Commit Graph

824 Commits

Author SHA1 Message Date
Cita a2c2ae614a [codex] expose more payload-rule upstream types (#474)
* Expose more payload-rule upstream types in Settings

The first payload-rules UI only offered a narrow set of protocol labels, which
made live troubleshooting confusing once real playground traffic routed through
platforms like sub2api instead of codex. This expands the selectable upstream
types, extracts the option list into one small helper, and renames the field to
上游类型 so the UI matches what the runtime matcher actually uses.

Constraint: Must preserve the existing payload-rules schema key (`protocol`) even though the UI wording is now upstream-type oriented
Rejected: Leaving the dropdown codex/openai-only and telling operators to hand-edit JSON | too easy to misconfigure during live routing diagnosis
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If new canonical site platforms are added, update payloadRuleProtocolOptions.ts so the visual editor stays aligned with runtime matching
Tested: npx vitest run --root . src/web/pages/settings.payload-rules.test.tsx src/web/pages/settings.payload-rule-platform-options.test.ts
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual dropdown interaction in a browser

* Keep payload-rule upstream types aligned with one-api backend support

Code review caught that the visual editor still omitted one-api even though the
backend continues to treat it as a valid upstream platform. This adds the
missing option and extends the focused option-set test so operators can create
payload rules for one-api without dropping to raw JSON.

Constraint: Must preserve the runtime payload-rules schema and only close the UI/backend option gap
Rejected: Removing one-api from the backend in this PR | unrelated behavioral change and broader migration risk
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When backend platform support changes, update payloadRuleProtocolOptions.ts and its focused test in the same PR
Tested: npx vitest run --root . src/web/pages/settings.payload-rules.test.tsx src/web/pages/settings.payload-rule-platform-options.test.ts
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual browser check of the expanded dropdown list
2026-04-10 16:13:56 +08:00
Cita 9c766dec1c [codex] add payload rules settings UI (#473)
* Make payload request overrides configurable from Settings

The payload-rules engine already existed in the proxy path, but operators had
no supported runtime UI to manage CPA-style overrides. This wires the setting
through the runtime settings API, adds strict validation, and ships a
low-friction visual editor with an advanced JSON fallback so common cases like
Codex high reasoning can be configured without hand-editing backend state.

Constraint: Must reuse the existing payload-rules execution path and settings table without schema changes
Constraint: Must fit the existing metapi Settings-page patterns rather than introducing a standalone config surface
Rejected: JSON-only editor as the primary UX | too long and too easy to misconfigure for common cases
Rejected: A brand-new backend rule format for the UI | would duplicate the existing payload-rules source of truth
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep visual-rule serialization and advanced JSON editing in sync before extending the rule model
Tested: npm run typecheck
Tested: npx vitest run --root . src/server/services/payloadRules.test.ts src/server/routes/api/settings.events.test.ts src/web/pages/settings.payload-rules.test.tsx
Tested: npm run repo:drift-check
Not-tested: Manual browser interaction smoke on the Settings page in this clean PR worktree

* Prevent payload-rules saves from violating review expectations

Code review surfaced two operator-facing edge cases in the first payload-rules
PR: successful rule parsing could still be committed before a later validation
error, and visual edits could silently overwrite unsaved advanced JSON. This
stages payload-rules until the request finishes validating and adds an explicit
confirmation gate before visual actions discard unsynced advanced edits.

Constraint: Keep the fix narrow to the reviewed payload-rules feature without refactoring unrelated runtime-settings atomicity behavior
Rejected: Silently skipping draft resync while keeping visual edits active | would leave save semantics ambiguous when advanced JSON stays dirty
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If the settings endpoint ever moves toward full request atomicity, re-check this staged payload-rules write path against the broader strategy
Tested: npm run typecheck
Tested: npx vitest run --root . src/server/routes/api/settings.events.test.ts src/web/pages/settings.payload-rules.test.tsx
Tested: npm run repo:drift-check
Not-tested: Manual browser smoke of the confirmation dialog text
2026-04-10 14:27:43 +08:00
Cita 2f774e204c Keep MySQL usage aggregation from crashing startup (#471)
The usage aggregation projector was written with SQLite/Postgres conflict builders, but Render can switch the runtime DB to MySQL from saved settings. That made the startup scheduler throw before the service stayed healthy.

This change branches the projector's checkpoint and aggregate writes to MySQL-safe onDuplicateKeyUpdate calls while preserving the existing SQLite/Postgres onConflict behavior. A mocked MySQL regression test now omits the onConflict builders entirely so future regressions fail fast.

Constraint: Drizzle conflict APIs are dialect-specific and the projector starts during boot

Rejected: Disable the projector on MySQL | would keep admin analytics stale and hide the real incompatibility

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: New usage-aggregation writes must branch on runtimeDbDialect before using conflict helpers

Tested: npx vitest run --root . src/server/services/usageAggregationService.test.ts src/server/services/usageAggregationService.mysql.test.ts

Tested: npm run typecheck:server

Tested: npm run repo:drift-check

Tested: npm run build:server

Not-tested: Live MySQL projector pass against a deployed runtime database
2026-04-10 12:41:08 +08:00
Cita 8cf78a5354 [codex] smooth route detail panel motion (#467)
* Keep route-detail motion smooth while restoring a more panel-like reveal feel

The route page detail panel originally reused the shared collapse container,
which looked lively but reintroduced layout-heavy motion inside the desktop
route grid. This change keeps the non-layout presence shell, then tunes the
panel animation itself so it reveals from the top with a softer, more
trace-panel-like feel without falling back to grid row interpolation.

Constraint: The desktop route detail panel sits inside a multi-column CSS grid and must avoid layout-driven collapse animation
Rejected: Reuse anim-collapse exactly as ProxyLogs does | reopening grid-template-rows animation brought back jank on route expand/collapse
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Preserve transform/clip-path-based motion here unless grid placement is redesigned; do not reintroduce layout collapse without profiling
Tested: npm test -- src/web/pages/tokenRoutes.desktop-detail-panel.test.tsx src/web/pages/tokenRoutes.group-collapse.test.tsx src/web/pages/token-routes/RouteFilterBar.test.tsx
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: manual GitHub review in production browser after PR creation

* Keep route-detail motion PR lint-clean without changing behavior

CodeRabbit correctly flagged the new keyframes for using from/to selector
notation. This follow-up keeps the animation timing and properties the same
while switching to percentage selectors so the stylesheet aligns with the
configured keyframe selector rule.

Constraint: Keep the route-detail panel motion unchanged while satisfying the style rule mentioned in PR review
Rejected: Ignore the review comment | leaves a stylelint-style regression in the PR discussion unresolved
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When adding new keyframes in this stylesheet, prefer explicit percentage selectors to avoid repeating this lint issue
Tested: npm test -- src/web/pages/tokenRoutes.desktop-detail-panel.test.tsx src/web/pages/tokenRoutes.group-collapse.test.tsx src/web/pages/token-routes/RouteFilterBar.test.tsx
Tested: npm run typecheck:web
Tested: npm run repo:drift-check
Not-tested: remote Git transport from this machine still hangs, so branch update was handled separately from local git push

* Respect reduced-motion and narrow layer promotion for route detail panel

The new route detail panel motion path solved grid-driven jank, but the follow-up
review correctly flagged two polish issues: the animation should honor reduced
motion, and will-change should only stay enabled during active transitions. This
keeps the smoother motion path while reducing persistent layer cost and giving
reduced-motion users immediate state changes.

Constraint: Must preserve the non-layout animation path that fixed dropped frames in the route grid
Rejected: Restore anim-collapse behavior | reintroduces grid/layout-driven jank
Confidence: high
Scope-risk: narrow
Directive: Keep desktop route detail motion on transform and clip-path rather than grid height animation unless the panel moves out of the card grid
Tested: npm test -- src/web/pages/tokenRoutes.desktop-detail-panel.test.tsx src/web/pages/tokenRoutes.group-collapse.test.tsx src/web/pages/token-routes/RouteFilterBar.test.tsx
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual browser validation of prefers-reduced-motion on macOS

* Honor reduced-motion semantics in route detail panel lifecycle

The previous follow-up removed the always-on layer hint and added reduced-motion
CSS, but the enter state still reused the long-lived open class and the desktop
close path kept a fixed JS delay. This narrows will-change to a transient
entering state, bypasses close delays for reduced-motion users, and locks the
behavior with a regression test.

Constraint: Must preserve the non-layout detail-panel motion path that fixed grid jank
Rejected: Keep reduced-motion as CSS-only | JS close timer still delayed unmount and active-state cleanup
Rejected: Drop the close delay globally | would remove the intended close animation for standard-motion users
Confidence: high
Scope-risk: narrow
Directive: If the desktop detail panel motion changes again, keep motion-state CSS and JS timers aligned for prefers-reduced-motion users
Tested: npm test -- src/web/pages/tokenRoutes.desktop-detail-panel.test.tsx src/web/pages/tokenRoutes.group-collapse.test.tsx src/web/pages/token-routes/RouteFilterBar.test.tsx
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual browser verification of prefers-reduced-motion on macOS
2026-04-10 11:01:24 +08:00
Cita c6a28c71c4 [codex] improve LobeHub brand detection coverage (#464)
* Recognize more LobeHub-backed model brands so marketplace filters stop collapsing into other

Metapi was leaving many models under the uncategorized bucket even though the
current LobeHub icon set already contains matching provider or vendor brands.
This change moves brand detection into one shared registry, expands the rules
with the user-reported gaps that have real upstream icon coverage, and makes
server-side brand blocking reuse the same classification result as the web UI.

Constraint: Existing workspace has unrelated in-progress edits, so this commit stages only the brand-classification slice
Constraint: Brand matching must stay consistent between marketplace display and server-side blocked-brand filtering
Rejected: Add more ad hoc rules separately in web and server files | would keep the drift bug alive
Rejected: Blindly import every LobeHub slug as a model brand | would pollute filters with tool and app brands
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep new brand additions in src/server/shared/modelBrand.ts and let web/server consume that single source of truth
Tested: npm test -- src/web/components/BrandIcon.test.ts src/server/services/brandMatcher.test.ts src/web/pages/Models.marketplace-text.test.tsx src/web/components/BrandIcon.architecture.test.ts src/web/components/BrandIcon.render.test.tsx
Tested: npm run typecheck
Tested: npm run repo:drift-check
Not-tested: Live browser verification against the user's current marketplace dataset after deployment

* Preserve provider brand blocking without changing display-brand priority

The first pass unified brand detection but server-side blocked-brand checks
started relying on the single display brand. Mixed model paths such as
`deepinfra/meta-llama/...` and `azureai/gpt-4o` still need provider markers to
match global blocked brands even while the UI continues to show the preferred
vendor label.

Constraint: Marketplace display should keep the current preferred vendor-first brand label
Constraint: Server-side blocked-brand matching must still recognize provider and vendor markers on the same model id
Rejected: Reorder display-brand priority to make provider blocks pass | would regress the marketplace labels the PR was improving
Rejected: Reintroduce a separate server-only matcher | would recreate the web/server drift this PR removed
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Use getMatchingBrandNames for blocking-style checks and reserve getBrand for single-label display surfaces
Tested: npm test -- src/server/shared/modelBrand.test.ts src/server/services/brandMatcher.test.ts src/web/components/BrandIcon.test.ts src/web/pages/Models.marketplace-text.test.tsx src/web/components/BrandIcon.architecture.test.ts src/web/components/BrandIcon.render.test.tsx
Tested: npm run typecheck
Tested: npm run repo:drift-check
Not-tested: Live GitHub review-thread auto-resolution behavior after push

* Honor legacy blocked brand casing when canonicalizing global brand filters

The shared brand matcher now supports multi-match provider blocking, but the
blocked-brand rule parser still required exact display-case brand names. That
meant imported or legacy settings like `openai` or `aws bedrock` were silently
ignored even though they should map to known brands.

Constraint: Existing saved settings may contain lower-case or whitespace-variant brand names from imports or older data
Constraint: The server should keep emitting canonical display names after normalizing user-provided blocked brand entries
Rejected: Assume the settings UI always writes canonical brand strings | does not cover imported or hand-edited configuration
Rejected: Normalize only at the settings route | would still leave hydrated legacy config values ineffective in modelService
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep blocked-brand parsing tolerant of case and spacing drift, but always return canonical brand names for downstream use
Tested: npm test -- src/server/services/brandMatcher.test.ts src/server/shared/modelBrand.test.ts src/web/components/BrandIcon.test.ts src/web/pages/Models.marketplace-text.test.tsx src/web/components/BrandIcon.architecture.test.ts src/web/components/BrandIcon.render.test.tsx
Tested: npm run typecheck
Tested: npm run repo:drift-check
Not-tested: Manual settings UI round-trip with legacy lowercase globalBlockedBrands payloads
2026-04-09 21:43:43 +08:00
Cita baead855dd Make admin reads snapshot-first for faster ops pages (#457)
* Make admin reads snapshot-first so heavy pages stay responsive

This introduces a lightweight snapshot/cache layer for the busiest
admin reads, splits dashboard and proxy-log loading into smaller
independent surfaces, and moves accounts/site/dashboard snapshots
toward service-owned read paths.

The UI now loads dashboard summary, dashboard insights, site stats,
accounts, and proxy-log metadata as separate progressive reads while
keeping existing feature coverage intact.

Constraint: Must keep the full admin feature set and core metrics intact
Constraint: Interactive admin flows should trend toward <=3s without relying on OpenResty-only band-aids
Rejected: Delete heavy pages or reduce statistics depth | user explicitly requires unchanged functionality
Rejected: Keep one giant proxy-log/dashboard response | preserves current timeout-prone read shape
Confidence: medium
Scope-risk: moderate
Directive: Preserve old endpoints during the migration and keep new snapshot/query-v2 surfaces as the preferred frontend path
Tested: npm run typecheck
Tested: npx vitest run --root . src/server/routes/api/accounts.snapshot-v2.test.ts src/server/routes/api/stats.snapshot-v2.test.ts src/server/routes/api/stats.proxy-logs.test.ts src/server/routes/api/stats.siteStatus.test.ts src/server/routes/api/accounts.todayRewardFallback.test.ts
Tested: npm run build
Tested: npm run repo:drift-check
Not-tested: Live cita/cita1 latency measurements against the production dataset

* Keep snapshot services lean after the admin read-path rollout

The snapshot-first rollout now has fresh production evidence on cita1, so this follow-up trims two no-op patterns without changing behavior: a single-element Promise.all and a catch-then-rethrow refresh chain. Keeping the service layer lean reduces noise before final Ralph sign-off and redeploy verification.

Constraint: Keep deployed behavior unchanged while satisfying the mandatory deslop pass
Rejected: Wider refactor across route files | would broaden the verified surface right before production comparison closeout
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep snapshot services focused on cache/read orchestration; avoid reintroducing decorative async wrappers
Tested: npm run typecheck; npm run build; targeted vitest snapshot/proxy-log/account suites; npm run repo:drift-check
Not-tested: Public Cloudflare path, which still appears to hit a different origin than cita1

* Keep admin snapshots warm without introducing Redis

This moves the new admin read path beyond process-local caching by persisting
snapshot payloads in a dedicated admin_snapshots table and warming them in
the background. It also migrates remaining lightweight internal callers away
from the heaviest legacy reads and marks legacy endpoints as deprecated
instead of deleting them abruptly.

Constraint: User explicitly rejected adding Redis for admin snapshot acceleration
Rejected: Redis-backed shared cache | adds a forbidden runtime dependency
Rejected: Delete legacy endpoints immediately | still breaks tests, docs, and compatibility callers
Confidence: high
Scope-risk: moderate
Directive: Remove legacy admin endpoints only after internal callers, docs, and compatibility windows are cleared
Tested: npm run typecheck
Tested: npm run build
Tested: npx vitest run --root . src/server/services/adminSnapshotStore.test.ts src/server/routes/api/accounts.snapshot-v2.test.ts src/server/routes/api/stats.snapshot-v2.test.ts src/server/services/startupInfo.test.ts
Tested: npm run repo:drift-check
Not-tested: cita1 staging redeploy on this follow-up commit

* Collapse admin reads onto the canonical API paths

This removes the parallel v2 read surface and routes the snapshot-first
implementation back through the original admin API names. The frontend now
uses the canonical paths again while the backend keeps the newer snapshot,
persistence, and warm-refresh machinery behind those routes. Along the way it
also fixes the main review findings around cache coalescing, active-site scope,
atomic snapshot writes, and auth-header handling.

Constraint: User requested no Redis and no long-lived duplicate admin read endpoints
Rejected: Keep both legacy and v2 endpoints indefinitely | doubles maintenance and confuses the canonical contract
Rejected: Delete old names without remapping callers | would create avoidable frontend and tooling churn
Confidence: high
Scope-risk: moderate
Directive: Treat /api/stats/dashboard, /api/accounts, /api/stats/proxy-logs, and the site stats routes as the canonical admin read contract unless a future breaking-change plan says otherwise
Tested: npm run typecheck
Tested: npm run build
Tested: npx vitest run --root . src/server/services/adminSnapshotStore.test.ts src/server/routes/api/accounts.snapshot-v2.test.ts src/server/routes/api/stats.snapshot-v2.test.ts src/server/routes/api/stats.proxy-logs.test.ts src/server/services/startupInfo.test.ts
Tested: npm run repo:drift-check
Not-tested: cita1 staging redeploy on this canonical-route follow-up commit

* Keep canonical admin analytics fast without raw log scans

This lands the usage-aggregate path as the single implementation behind the canonical admin routes, adds the aggregate schema/migration artifacts, and reconnects dashboard/site stats warming to the new service so the PR no longer sits in a half-projector state.

It also updates the cache and aggregate tests to reflect the real runtime behavior and validates the current branch on cita1 staging, which showed the app-side snapshot path is fast while the remaining 1.5s staging slowness lives on the NodePort path rather than inside the aggregate queries themselves.

Constraint: Must preserve the canonical old-path admin API contract while moving reads onto aggregate-backed snapshots
Constraint: Must not add Redis or a parallel second analytics implementation
Rejected: Keep usageAggregationProjectorService as a separate path | would preserve duplicate ownership and keep type wiring split
Rejected: Judge staging performance only from NodePort timings | hid that pod-local snapshot reads were already fast
Confidence: medium
Scope-risk: moderate
Directive: If dashboard or insights feels slow again on staging, compare NodePort and pod-local timings before changing aggregate queries
Tested: npm run typecheck; npx vitest run --root . src/server/services/adminSnapshotStore.test.ts src/server/services/usageAggregationService.test.ts src/server/services/snapshotCacheService.test.ts src/server/routes/api/accounts.snapshot-v2.test.ts src/server/routes/api/stats.snapshot-v2.test.ts src/server/routes/api/stats.proxy-logs.test.ts src/server/services/startupInfo.test.ts; npm run build; npm run repo:drift-check; cita1 staging deploy plus canonical-route curl benchmarks
Not-tested: cita1 real ingress/OpenResty path; multi-replica projector concurrency

* Prevent admin aggregate drift under concurrent warmers

This follow-up hardens the snapshot-first admin analytics path by adding a persisted projector lease, exact 24-hour dashboard counting, and regression coverage for lease contention and time-window behavior.

The goal is to keep the canonical admin routes correct when multiple workers are alive and to avoid quietly overstating proxy24h by reading hour buckets as if they were an exact sliding window.

Constraint: Projector coordination must work through the existing checkpoint table without adding Redis or a second background system
Constraint: Schema artifacts must stay additive under the repo's generated bootstrap/upgrade pipeline
Rejected: Remove the left-prefix day/hour indexes in this slice | schema:contract rejects non-additive index removals, so that cleanup needs a broader migration strategy
Confidence: high
Scope-risk: moderate
Directive: Keep projector claims DB-backed; do not regress to process-local inFlight-only dedupe for aggregate writes
Tested: npm run typecheck; npx vitest run --root . src/server/services/usageAggregationService.test.ts src/server/routes/api/stats.snapshot-v2.test.ts; npm run build; npm run repo:drift-check
Not-tested: Multi-host live contention beyond synthetic lease test; resolving CodeRabbit index-nit without additive-schema support

* Keep CI aligned with canonical admin snapshots

The admin snapshot cutover left a mixed test surface: MySQL schema artifacts still
classified admin_snapshots.snapshot_key as JSON, canonical /api/accounts callers
were asserted as arrays, and a few proxy tests mocked routeRefreshWorkflow too
narrowly, which leaked missing exports into later OAuth runs.

This commit narrows the schema metadata heuristic, updates the checked-in schema
artifacts and their regression tests, adds lightweight web test compat helpers
for canonical snapshot APIs, and preserves actual routeRefreshWorkflow exports so
full-suite workers no longer poison unrelated tests. OAuth/account token suites
also reset DATA_DIR-backed modules safely to avoid stale singleton config.

Constraint: checked-in schema artifacts drive cross-dialect CI parity checks
Constraint: vitest module mocks can leak across files in the same worker when exports are omitted
Rejected: rerun schema:generate only | additive guard rejects the logical-type correction for snapshot_key
Rejected: keep per-test ad hoc snapshot mocks | repeated breakage across pages needed one compat helper
Confidence: high
Scope-risk: moderate
Directive: when a test uses vi.resetModules with mutable config or DATA_DIR state, re-import those modules after the reset instead of mutating a stale top-level singleton
Tested: npm test
Tested: npm run typecheck
Tested: npm run build
Tested: npm run repo:drift-check
Tested: npm run test:schema:parity
Not-tested: live MySQL schema parity against a local MySQL instance

* Keep CodeQL from re-flagging already-limited routes

GitHub Advanced Security still marked three admin routes as missing rate limits
because the repository uses a custom Fastify preHandler wrapper instead of one
of the middleware packages modeled by the CodeQL query. The routes are already
throttled in production, so this change adds narrow in-source suppressions on the
three affected handlers to record that the check is a false positive instead of a
real missing guard.

Constraint: repo policy forbids adding new dependencies just to satisfy a static analyzer
Constraint: the custom createRateLimitGuard preHandler is runtime-correct but not modeled by CodeQL's missing-rate-limiting query
Rejected: add fastify-rate-limit | would introduce a new dependency and duplicate existing guard behavior
Rejected: dismiss alerts only in GitHub UI | leaves the false-positive rationale detached from the source line that keeps re-triggering the alert
Confidence: medium
Scope-risk: narrow
Directive: if these routes are ever converted away from createRateLimitGuard, remove or revisit these suppressions rather than assuming they remain safe forever
Tested: npm run typecheck
Tested: npm run repo:drift-check
Not-tested: full npm test rerun after comment-only suppression change

* Use legacy CodeQL suppression syntax for custom rate guards

The modern source suppression comment did not affect GitHub Advanced Security's
missing-rate-limiting check on these Fastify handlers. Switch the three known
false-positive locations to the legacy LGTM suppression syntax, keeping the
custom preHandler throttling in place while matching the syntax that CodeQL
still honors for in-source suppressions.

Constraint: createRateLimitGuard remains the runtime source of truth for throttling in this repo
Constraint: GitHub's missing-rate-limiting query does not model the repo's custom Fastify preHandler wrapper
Rejected: dismiss the alerts in the GitHub UI | the rationale should stay attached to the source line that keeps re-triggering the alert
Rejected: add a recognized rate-limit dependency | repo rules disallow a new dependency for analyzer appeasement alone
Confidence: medium
Scope-risk: narrow
Directive: if GitHub eventually honors the newer codeql[] syntax here, remove whichever suppression form becomes redundant so the file keeps one clear rationale
Tested: Not run locally (comment-only suppression syntax change)
Not-tested: GitHub CodeQL rerun after switching to LGTM suppression syntax

* Keep admin routes clean after CodeQL false-positive triage

The repository's custom createRateLimitGuard preHandlers are the actual runtime
throttles for these routes. Since GitHub Advanced Security still did not honor
the attempted in-source suppressions, remove the temporary comments and keep the
source focused on runtime behavior while the false-positive alerts are tracked
operationally in GitHub.

Constraint: the custom Fastify preHandler remains the only real throttling mechanism in this repo
Rejected: leave non-functional suppression comments in source | they imply enforcement that GitHub did not actually honor
Confidence: high
Scope-risk: narrow
Directive: if CodeQL adds custom Fastify preHandler modeling later, prefer removing any alert dismissals over reintroducing comment noise here
Tested: Not run locally (comment-only cleanup)
Not-tested: GitHub checks after alert dismissal
2026-04-09 21:31:13 +08:00
cita-777 6cca74b039 Recognize more LobeHub-backed model brands so marketplace filters stop collapsing into other
Metapi was leaving many models under the uncategorized bucket even though the
current LobeHub icon set already contains matching provider or vendor brands.
This change moves brand detection into one shared registry, expands the rules
with the user-reported gaps that have real upstream icon coverage, and makes
server-side brand blocking reuse the same classification result as the web UI.

Constraint: Existing workspace has unrelated in-progress edits, so this commit stages only the brand-classification slice
Constraint: Brand matching must stay consistent between marketplace display and server-side blocked-brand filtering
Rejected: Add more ad hoc rules separately in web and server files | would keep the drift bug alive
Rejected: Blindly import every LobeHub slug as a model brand | would pollute filters with tool and app brands
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep new brand additions in src/server/shared/modelBrand.ts and let web/server consume that single source of truth
Tested: npm test -- src/web/components/BrandIcon.test.ts src/server/services/brandMatcher.test.ts src/web/pages/Models.marketplace-text.test.tsx src/web/components/BrandIcon.architecture.test.ts src/web/components/BrandIcon.render.test.tsx
Tested: npm run typecheck
Tested: npm run repo:drift-check
Not-tested: Live browser verification against the user's current marketplace dataset after deployment
2026-04-09 19:43:47 +08:00
cita-777 a3886324ca Merge remote-tracking branch 'origin/main' 2026-04-09 19:18:39 +08:00
cita-777 7d883a6ada update readme 2026-04-09 19:17:01 +08:00
dependabot[bot] 5e27684a1c chore(deps): bump the minor-and-patch group across 1 directory with 6 updates (#451)
---
updated-dependencies:
- dependency-name: "@visactor/react-vchart"
  dependency-version: 2.0.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-and-patch
- dependency-name: dotenv
  dependency-version: 17.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-and-patch
- dependency-name: minimatch
  dependency-version: 10.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-and-patch
- dependency-name: electron
  dependency-version: 41.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor-and-patch
- dependency-name: jsdom
  dependency-version: 29.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor-and-patch
- dependency-name: mermaid
  dependency-version: 11.14.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 11:16:28 +08:00
Cita 03bebae17f fix oauth route unit delete rollback (#450) 2026-04-09 11:15:57 +08:00
puyujian 569a15e14c feat: enhance API key management and fix routing logic
* ```
feat(accounts): 支持批量添加API密钥连接

- 添加accessTokens字段到账户创建载荷模式,允许传递多个API密钥
- 实现批量API密钥解析功能,支持换行符、空格和逗号分隔
- 重构账户创建逻辑以支持单个和批量API密钥处理
- 在前端界面中添加批量API密钥输入检测和处理
- 添加批量创建结果返回和错误处理
- 更新验证流程以支持批量模式下的逐条验证
- 添加详细的批量API密钥测试用例

该更改允许用户一次提交多个API密钥,系统将为每个密钥创建独立的连接并参与负载均衡。
```

* ```
fix(tokenRouter): 调整路由匹配优先级以优先匹配显示名称别名

当精确路由和显式组显示名称冲突时,现在优先选择显式组显示名称
而不是精确路由模式。这修正了路由决策逻辑,使显式组路由能够正
确覆盖精确模型匹配。

相关的测试用例已更新以反映新的匹配行为,确保显式组路由在冲
突情况下获得更高优先级。
```

* ```
fix(accounts): 修复API密钥验证错误消息显示逻辑

当凭证模式不为apikey时显示会话令牌提示信息,否则显示API密钥验证失败信息

feat(accounts): 更新API密钥输入界面提示文本

将批量添加说明从输入框占位符移至独立提示文本,
使界面更清晰易懂
```

* ```
feat(workflow): 在CI/CD工作流中使用动态Docker Hub镜像名称

- 在ci.yml和release.yml工作流中添加DOCKERHUB_IMAGE环境变量
- 将硬编码的Docker Hub用户名替换为从secrets.DOCKERHUB_USERNAME动态获取
- 更新docker.metadata-action配置以使用环境变量中的镜像名称
- 添加测试用例验证Docker Hub镜像名称的正确配置
```

* fix(accounts): 修复批量创建回归并下沉创建流程
2026-04-07 14:28:25 +08:00
dependabot[bot] 5cab6c83f1 chore(deps-dev): bump react-router-dom from 7.13.2 to 7.14.0
Bumps the routing group with 1 update: [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom).


Updates `react-router-dom` from 7.13.2 to 7.14.0
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.14.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-version: 7.14.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: routing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 14:28:13 +08:00
dependabot[bot] 2f2ebcb37c chore(deps-dev): bump @types/nodemailer from 7.0.11 to 8.0.0
Bumps [@types/nodemailer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/nodemailer) from 7.0.11 to 8.0.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/nodemailer)

---
updated-dependencies:
- dependency-name: "@types/nodemailer"
  dependency-version: 8.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 14:28:04 +08:00
cita-777 63c435c901 fix update center release tests for 1.3.0 2026-04-06 15:45:58 +08:00
cita-777 f18aa98888 fix desktop release packaging rebuild 2026-04-06 15:37:22 +08:00
cita-777 566501be1f bump version to 1.3.0 2026-04-06 15:19:18 +08:00
Cita 42f9049aff [codex] align antigravity special-model non-stream path with CPA (#444)
* align antigravity special-model non-stream path with cpa

* fix antigravity tail aggregation review feedback

* fix antigravity fallback aggregation review feedback
2026-04-06 15:03:55 +08:00
Cita 448f488f95 [codex] improve oauth route unit feedback (#445)
* feat: improve oauth route unit feedback

* fix: harden oauth route unit feedback flow
2026-04-06 15:03:33 +08:00
Cita d1b42b2236 fix: support oauth route unit inserts on postgres (#443)
* fix proxy debug undici response header capture

* fix: support oauth route unit inserts on postgres
2026-04-06 13:39:05 +08:00
Cita 2b9200ea7c fix proxy debug undici response header capture (#442) 2026-04-06 13:16:46 +08:00
Cita 2f0e63a1e0 [codex] add oauth route pools and proxy save flow (#440)
* feat: add oauth route pools and proxy save flow

* fix: align oauth route pool schema and rate limits

* fix: harden oauth route pool review fixes

* fix: address oauth ci regressions

* fix: close oauth codeql alerts

* fix: harden oauth route unit recovery

* fix: split oauth route limiters for codeql

* fix: address remaining oauth review comments
2026-04-06 11:55:20 +08:00
Cita a789ddf7f8 [codex] add sub2api managed refresh resilience (#441)
* add sub2api managed refresh resilience

* serialize sub2api managed refresh per account

* bound sub2api refresh scheduler work

* tighten sub2api refresh scheduler rules
2026-04-06 11:43:30 +08:00
Cita 3edeb6e245 feat: refine OAuth proxy controls and quota UI (#433)
* feat: refine oauth management proxy controls

* fix: preserve oauth refresh state and tighten oauth rate limiting

* fix: satisfy codeql oauth rate limiting

* fix: address oauth review comments

* fix: move oauth sensitive limits into prehandlers

* fix: cap oauth quota refresh batch size
2026-04-06 08:50:19 +08:00
Cita 287c5aafd6 fix: localize downstream key trend timestamps (#432)
* fix: localize downstream key trend timestamps

* fix: keep downstream trend metadata on empty responses

* fix: cursor paginate downstream key trend reads

* fix: normalize empty downstream trend timezones

* fix: localize windowed downstream trend buckets
2026-04-06 08:46:40 +08:00
Cita 3e8d69bed6 fix codex compact non-stream accept header (#439) 2026-04-06 08:46:27 +08:00
Cita 38721cb890 [codex] support downstream key site and credential exclusions (#431)
* support downstream key site and credential exclusions

* skip electron binary download in non-desktop ci

* fix migrate partial-journal test for 0020
2026-04-05 23:43:07 +08:00
Cita 492f43c5dc [codex] add oauth pre-refresh resilience (#430)
* oauth pre-refresh resilience

* address oauth refresh review comments
2026-04-05 22:58:50 +08:00
Cita 6feda0e7ba [codex] fix downstream client detection boundaries (#429)
* fix downstream client detection boundaries

* address downstream client detection review comments
2026-04-05 22:38:00 +08:00
Cita 193f3e7181 [codex] fix proxy log usage source metadata (#428)
* fix proxy log usage source metadata

* fix ci follow-up comment regressions
2026-04-05 21:57:08 +08:00
Cita c10b1e7bca [codex] polish settings transport and probe cards (#427)
* polish settings transport and probe cards

* restore compact responses fallback control
2026-04-05 21:47:49 +08:00
Cita d5560fb036 [codex] normalize primary site URL handling (#424)
* normalize primary site url handling

* fix site create redirect test selector

* fix sub2api gemini model discovery and site detect race

* fix sub2api antigravity fallback and test selectors

* fix site modal wording test

* guard blur detect against manual platform changes
2026-04-05 20:09:34 +08:00
Cita df75a80bf9 Fix responses compact fallback handling (#426)
* fix route drag overlay alignment

* fix(web): address route drag review comments

* fix route card review follow-up

* Fix responses compact fallback handling

* Fix compact endpoint candidate typing

* Tighten compact fallback matcher
2026-04-05 19:41:09 +08:00
Cita b3f6fa0d4f [codex] align site created modal with shared actions (#425)
* align site created modal with shared actions

* address site created modal review comments
2026-04-05 19:34:10 +08:00
Cita ef1962d10b [codex] rename site API request wording (#423)
* rename site api request wording

* replace real site example domains
2026-04-05 19:16:08 +08:00
Cita 5b005d8412 fix: tighten generic upstream passthrough headers (#422)
* fix: tighten generic upstream passthrough headers

* fix: preserve codex passthrough version headers
2026-04-05 18:11:42 +08:00
Cita afbbc4c79a fix failed expired api-key recovery route preservation (#421) 2026-04-05 17:41:35 +08:00
Cita 9045a488f0 [codex] Fix desktop default-browser external links (#420)
* fix desktop default-browser external links

* fix desktop navigation guard review follow-up
2026-04-05 17:40:54 +08:00
Cita ff43fce9a7 [codex] fix route drag overlay alignment (#419)
* fix route drag overlay alignment

* fix(web): address route drag review comments

* fix route card review follow-up
2026-04-05 17:33:53 +08:00
Cita b3e987a2f5 [daily] keep codex continuation current across scope roundtrips (#416) 2026-04-05 17:29:42 +08:00
Cita 63f6b07842 [daily] cap sqlite migration recovery retries (#410)
* [daily] cap sqlite migration recovery retries

* fix typecheck for sqlite retry budget guard
2026-04-03 11:10:55 +08:00
Cita bc3893ff3b [codex] refine token routes workspace motion and hierarchy (#394)
* refine token routes workspace motion and hierarchy

* address route workspace review feedback

* Refine token route density and motion

* [codex] refine token routes motion behavior

* [codex] address route motion review comments

* [codex] tighten route row interaction states
2026-04-03 11:04:40 +08:00
Cita af5b62fd8b [codex] fix codex responses continuation across channel drift (#404)
* fix codex responses continuation across channel drift

* fix: clear codex responses continuation fallback on scoped reset

* fix: harden codex continuation store keying
2026-04-03 11:00:53 +08:00
Cita b9b553d772 [codex] fix sqlite migration journal recovery (#400)
* fix sqlite migration journal recovery

* address sqlite migration review follow-ups
2026-04-02 17:28:45 +08:00
Cita 6ad9ec6911 [codex] strip codex responses max_output_tokens (#399)
* strip codex responses max_output_tokens

* address codex responses review comments
2026-04-02 17:28:38 +08:00
Cita 19bfed2e33 [codex] refresh integration and settings docs for current UI and provider coverage (#398)
* docs: refresh integration and settings guides

* docs: address review follow-up
2026-04-02 17:28:27 +08:00
Cita 2be0603e6f [codex] fix expired connection health recovery (#393)
* fix expired connection health recovery

* address review comments and test regressions
2026-04-02 17:27:42 +08:00
Cita 082891a217 [codex] fix runtime settings restart hydration (#392)
* fix runtime settings restart hydration

* fix review followups for settings hydration

* dedupe log cleanup day normalization
2026-04-02 17:27:25 +08:00
Cita 1407f754b1 [codex] add Fedora desktop rpm packaging (#390)
* add Fedora desktop rpm packaging

* harden desktop packaging yaml assertion
2026-04-02 12:53:28 +08:00
Cita ed2783e2dd [codex] fix route detail dropdown clipping (#388)
* fix route detail dropdown clipping

* test: refresh proxy route mocks for ci
2026-04-02 11:19:07 +08:00