Commit Graph
51 Commits
Author SHA1 Message Date
ZyyandCodex 56451601fb feat(observability): enrich error request traces
Expose request, client, model, transport, and account facts in operations errors and surface them in the error table and detail view.

Co-authored-by: Codex <noreply@openai.com>
2026-08-31 10:57:53 +08:00
ZyyandCodex a62bb196f7 fix(accounts): proxy profile avatars through backend
Co-authored-by: Codex <noreply@openai.com>
2026-08-31 09:56:23 +08:00
ZyyandCodex c46910df22 fix(observability): restore direct page navigation
Co-authored-by: Codex <noreply@openai.com>
2026-08-31 04:09:31 +08:00
ZyyandCodex 2231fee768 perf(observability): narrow usage and ops read models
Separate Usage list and detail reads, use keyset paging with first-page totals, push Ops predicates into source branches, and merge repeated account and diagnostics aggregates. Apply the shared per-query PostgreSQL budget, coalesce identical Dashboard windows, and preserve the existing IP, User-Agent, and latency detail surface.

Co-authored-by: Codex <noreply@openai.com>
2026-08-31 02:40:40 +08:00
ZyyandCodex a2e60c1c6e refactor(admin): page account read models in PostgreSQL
Move account, account-group, and client-key filtering, stable ordering, counts, and current-page membership reads into PostgreSQL. Keep Redis cooldown and lease enrichment in the Admin application boundary, share stable page state in the UI, and supervise client-key last-used flushing through the host worker lifecycle.

Co-authored-by: Codex <noreply@openai.com>
2026-08-31 02:40:40 +08:00
ZyyandCodex a268f5ca66 fix(observability): restore WebSocket usage records
Co-authored-by: Codex <noreply@openai.com>
2026-08-30 22:40:16 +08:00
ZyyandCodex d4855cca9c feat(observability): expose runtime pressure insights
Co-authored-by: Codex <noreply@openai.com>
2026-08-30 00:46:01 +08:00
ZyyandCodex 4830ef093b refactor(architecture): remove obsolete compatibility scaffolding
Remove orphaned fixtures, unused capability and resource branches, and stale credential APIs.

Retire legacy Usage metadata fallbacks and record the completed cleanup.

Co-authored-by: Codex <noreply@openai.com>
2026-08-29 22:08:34 +08:00
ZyyandCodex ad20064d15 fix(admin): unify control-plane error responses
Co-authored-by: Codex <noreply@openai.com>
2026-08-29 20:22:14 +08:00
ZyyandCodex 57422275bb feat(accounts): add official profile statistics
Co-authored-by: Codex <noreply@openai.com>
2026-08-29 02:36:45 +08:00
ZyyandCodex ca527d5833 fix(accounts): use personal usage reports only
Remove the workspace token-breakdown probe and its dedicated statistics mode so usage aggregation always uses the personal model-credit and token-total reports.

Drop the invariant mode field from provider projections, the admin response, and the account usage UI.

Co-authored-by: Codex <noreply@openai.com>
2026-08-26 11:31:55 +08:00
ZyyandCodex 5d97086511 feat(accounts): add official usage statistics
Fetch Codex cycle usage in the provider, calculate model and daily Token costs with the shared OpenAI pricing rules, and expose the result through the admin API.

Add the account usage statistics modal, structured loading state, and feature-scoped quota components.

Co-authored-by: Codex <noreply@openai.com>
2026-08-26 00:46:53 +08:00
ZyyandCodex 94f298927d feat(openai): add active quota reset credits
Co-authored-by: Codex <noreply@openai.com>
2026-08-21 00:33:21 +08:00
ZyyandCodex 3be827204f fix(openai): keep image routes model-agnostic
Co-authored-by: Codex <noreply@openai.com>
2026-08-20 19:05:14 +08:00
ZyyandCodex cd89e2e8fc fix(admin): align quota metadata and usage layout
Co-authored-by: Codex <noreply@openai.com>
2026-08-20 15:14:28 +08:00
ZyyandCodex 056561de41 refactor(frontend): clarify component boundaries
Co-authored-by: Codex <noreply@openai.com>
2026-08-17 15:33:36 +08:00
ZyyandCodex 65645c7403 fix(accounts): gate quota recovery and add manual reset
Co-authored-by: Codex <noreply@openai.com>
2026-08-13 22:43:03 +08:00
ZyyandCodex 71159d5633 refactor(account-groups): remove unused members endpoint
Co-authored-by: Codex <noreply@openai.com>
2026-08-13 17:28:43 +08:00
ZyyandCodex 07acc67ce6 feat(frontend): add account group management
Co-authored-by: Codex <noreply@openai.com>
2026-08-13 16:58:36 +08:00
ZyyandCodex 2b8b3de0e4 refactor(accounts): unify five-state account status
Co-authored-by: Codex <noreply@openai.com>
2026-08-12 23:50:31 +08:00
ZyyandClaude Fable 5 330b222359 feat(accounts): separate rate-limited status into Redis cooldown
429 临时限流从 quota 快照分离为 Redis 冷却(ProviderCooldownPort):
- apply_rate_limit_429 只写 Redis(put_if_later,不缩短已有冷却),不再合成 quota 窗口,额度重置时间不被 429 污染
- 调度选择时排除冷却中的账号,到期自动恢复;诊断请求绕过
- 状态派生分离:rate_limited_until 存在 → 限流中;quota_limit_reached → 配额耗尽
- store 层(账号列表/筛选 + dashboard poolSummary)注入 cooldown 端口,精确区分限流中与配额耗尽,"正常"筛选不再混入限流中
- wire 透传 rate_limited_until,前端状态弹窗改为状态卡片(icon 块 + 状态名 + 原因/到期明细),BasePopover 加 hover delay
- 更新 429 相关测试断言,新增配额耗尽映射测试

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 00:39:38 +08:00
ZyyandClaude Opus 4.8 8e2edb680d feat(accounts): converge status classification and persist upstream errors
Unify account status derivation in gateway-admin via AccountStatusSignals,
removing the duplicated rules in store and use_case. AccountStatus now has
five operational classes (normal/quota_exhausted/rate_limited/disabled/error),
with AccountErrorReason carrying the concrete cause.

Add provider_accounts.last_error_message, written by record_failure with the
raw upstream error and cleared on recovery to ready. The admin error badge
shows the cause and upstream text on hover.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 21:23:28 +08:00
ZyyandCodex 00879be47d fix(accounts): separate rate-limited account status
Co-authored-by: Codex <noreply@openai.com>
2026-08-03 17:01:23 +08:00
ZyyandClaude Fable 5 df83ffdafb refactor(quota): split quota module and align scheduling/display semantics
Split credential/quota.rs into quota/{mod,snapshot,recovery}.rs with
corresponding test modules. Snapshot aggregation is snapshot-level:
top-level limit_reached/allowed and any window used>=100 count as
exhaustion, scheduling signals survive limit-only windows, and window
rolling is O(1) arithmetic.

402 recovery uses the pre-write confirmed reset (old reset elapsed plus
fresh snapshot not exhausted, or explicit allowed=true) instead of the
new snapshot's future reset, fixing the worker recovery deadlock.
Scheduling projection TTL is capped at the nearest active reset so
cache expiry never outlives the limit.

Admin derives seven mutually exclusive statuses (Active/RateLimited/
QuotaExhausted/Expired/Invalid/Disabled/Banned) from availability plus
snapshot-level quota.limitReached; Unknown maps to invalid. Dashboard
metrics are mutually exclusive (rate_limited disjoint from active),
ignore reset-expired windows, and cover additional rate limits.

xAI: bare 402 writes a short account cooldown instead of persisting
QuotaExhausted; ModelQuotaExhausted keeps model scope; runtime cooldown
survives credential rotation; account deletion clears all account and
model-scoped cooldown keys via new ProviderCooldownPort::clear_all.

Migration 0002 is frozen in the sha256 manifest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 03:04:43 +08:00
ZyyandClaude Fable 5 cf03c56cfa refactor(quota): separate rate limiting from account availability
Remove the persistent Cooldown state and cooldown_until/availability_reason
columns; rate limiting (429/503) now lives entirely in provider quota data
with projected window rolling, while availability carries only terminal or
intervention-required states (QuotaExhausted for 402, worker auto-recovers
on quota reset). xAI migrated to the same model (runtime cooldown via Redis,
no persistent state). Frontend derives 限流中 from quota window limitReached.

Align quota window parsing with the official codex schema: drop the invented
monthly_limit/spend_control windows, add the top-level code_review_rate_limit
window, prefer upstream limit_name for display labels, and keep duration
guessing only for grouping.

Also fix: account directory degrades one failing quota to an empty projection
instead of failing the whole page; dashboard rate_limited bucket SQL; fake
store Mutex re-entrancy deadlock; remove dead tokenRefreshing field.

Migration 0002 drops cooldown columns and rewrites the availability CHECK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 00:13:56 +08:00
zyycnandCodex 365d389a14 refactor(frontend): phase system-update state and clear remaining any
system-update now uses a discriminated phase union so mutually exclusive
operation states cannot be expressed together; connection-test event shapes
and cost chart points are typed instead of any.

Co-authored-by: Codex <noreply@openai.com>
2026-08-02 01:25:53 +08:00
zyycnandCodex e79d57eaf9 refactor(frontend): normalize usage records into a single view model
Components now consume `UsageViewModel` produced by `normalizeUsageRecord`;
metadata fallback exists only in the normalizer. Also complete the typed
request params for ops errors so the usage module stays build-clean.

Co-authored-by: Codex <noreply@openai.com>
2026-08-02 01:25:50 +08:00
zyycnandClaude Fable 5 7ed2a6668a feat(usage): mark attempt list as best-effort observations
Decide attempt facts are best-effort (adr-002), not authoritative history:
- Usage detail response exposes attemptsComplete: false
- frontend labels the attempt chain as best-effort
- architecture.md documents the semantics

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 00:31:39 +08:00
zyycnandClaude Fable 5 3c4ac99ae4 feat(api): type request params across admin API modules
Replace data: object with precise parameter types derived from call sites,
using type inference (Omit/union) over bulk interface declarations where
possible. Covers accounts, api-keys, usage, system, auth, dashboard,
settings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 00:08:52 +08:00
zyycnandClaude Fable 5 dfedb5069d feat(backup): add S3-compatible PostgreSQL backups with expiry TTL
Implement end-to-end backup to S3-compatible object storage (Cloudflare R2):
admin settings UI, scheduled and manual jobs, records, retention and expiry,
download via presigned URL, and delete convergence.

- gateway-admin: backup model, schedule/retention policy, daemon worker,
  storage identity lock and audit
- gateway-store: pg_dump staging, S3 client with probe, backup repository
- gateway-api: backup settings/records/create/download/delete routes
- migrations: fold expiry TTL into 0003_s3_backup.sql (single migration)
- frontend: S3 storage, schedule and records cards under settings/backup

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 22:12:23 +08:00
zyycnandCodex 01b4029998 feat(observability): polish usage detail and error diagnostics
Show attempt chains and P95 latency, surface client status/component/endpoint, and remove unused dashboard summary fields.

Co-authored-by: Codex <noreply@openai.com>
2026-07-31 22:28:24 +08:00
zyycnandCodex f583e50e88 feat(observability): snapshot provider account identity for history
Persist provider account name, email, and authentication kind at write time so request, attempt, and error views survive account deletion; add stable diagnostic keys with display-name resolution (account email/name, API key name); count only errored requests in failure diagnostics.

Co-authored-by: Codex <noreply@openai.com>
2026-07-31 21:25:38 +08:00
zyycnandCodex f5c1d773d7 fix(accounts): use current credential revisions
Load the current credential revision server-side for reauthorization and manual refresh so background token refreshes do not make admin mutations fail stale client fences.

Co-authored-by: Codex <noreply@openai.com>
2026-07-28 13:04:12 +08:00
ZyyandCodex 45903b684b fix(admin): remove config revision fences from API writes
Operator mutations no longer require callers to carry configRevision values through accounts, client keys, provider credentials, or settings. The store and admin use cases now apply current state directly, which removes stale-revision failures from normal create, update, and delete flows.

xAI Responses catalog entries now let the upstream validate feature support instead of rejecting requests locally when optional catalog metadata is absent, matching the Build routing behavior used by grok2api.

Co-authored-by: Codex <noreply@openai.com>
2026-07-27 11:30:59 +08:00
zyycnandClaude 2366f66f33 refactor(web): type the API layer end to end
Make request generic so the axios envelope is unwrapped as a typed value,
and thread the known response shapes through every api module and their
call sites so a wire rename surfaces as a compile error instead of silent
any. Type-only: no runtime or visual change.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-27 01:52:00 +08:00
zyycnandCodex 70f8afb122 refactor(gateway): remove provider instance layer
Collapse routing, health, circuit state, account pools, and admin APIs onto the fixed OpenAI and xAI Provider boundary while keeping credential runtime state account-scoped.

Remove configurable provider-instance and routing-catalog persistence, use fixed official endpoints in provider adapters, align account routes and frontend contracts, and mirror provider tests under their source modules.

Co-authored-by: Codex <noreply@openai.com>
2026-07-25 00:33:12 +08:00
zyycnandCodex 75773a4608 refactor: migrate to multi-provider gateway architecture
Rebuild the backend as the frozen gateway workspace with a single PostgreSQL schema, provider-owned OpenAI and xAI boundaries, and mirrored domain tests.

Restore the admin product contracts for accounts, model catalogs, usage observability, billing details, and provider-scoped settings without compatibility shims.

Co-authored-by: Codex <noreply@openai.com>
2026-07-25 00:33:11 +08:00
ZyyandCodex 76b81a6ceb refactor(frontend): simplify client architecture
Remove frontend schemas and tests, keep API modules as thin GET/POST adapters, and replace manual SSE and browser helpers with existing VueUse and utility primitives.

Reorganize feature helpers, move unauthorized handling into an app plugin, align the admin key removal route, and satisfy the enabled accessibility rules.

Co-authored-by: Codex <noreply@openai.com>
2026-07-17 11:44:04 +08:00
zyycnandCodex 29c8b679ba refactor(architecture): complete dependency boundary audit
Harden WebSocket ownership and capacity semantics, split the transport into focused modules, and move admin queries, quota observations, and upstream adapters behind explicit consumer-owned ports.

Parse frontend payloads at the API boundary, centralize SSE and store ownership, add latest-request-wins queries with inferred view types, and enforce dependency direction through lint and AST tests.

Co-authored-by: Codex <noreply@openai.com>
2026-07-17 09:03:33 +08:00
zyycnandCodex 4091a0c2d8 feat(proxy): prefer passive upstream state refresh
Remove request-path quota probes and consume account, request, and rate-limit facts from normal upstream responses, including 429 active-limit metadata.

Refresh model catalogs only at startup, on x-models-etag changes, or through the explicit account model refresh control in the connection test dialog.

Co-authored-by: Codex <noreply@openai.com>
2026-07-17 02:12:16 +08:00
Zyy 2d9510d9e3 feat: improve usage insights and dashboard trends 2026-07-13 19:09:22 +08:00
zyycnandCodex f1872df293 fix: reload after updated service is ready
Track the target update version and poll the version endpoint through process replacement. Reload as soon as the new backend is ready without requiring the browser to observe a brief shutdown window.

Co-authored-by: Codex <noreply@openai.com>
2026-07-13 07:54:18 +08:00
zyycnandCodex 28b89200f7 feat: refine admin workflows and proxy telemetry
Improve account and API key filtering, sorting, responsive layouts, table loading, usage reporting, and billing semantics across the admin interface.

Remove obsolete compact-route handling, normalize model metadata, and add process-wide draining for HTTP streams and WebSockets during restart.

Co-authored-by: Codex <noreply@openai.com>
2026-07-13 00:57:26 +08:00
zyycnandCodex 203fc1b03e fix: harden persistence and runtime boundaries
Co-authored-by: Codex <noreply@openai.com>
2026-07-12 10:07:21 +08:00
zyycnandCodex 3c33e93da9 fix: unify pagination and error contracts
Co-authored-by: Codex <noreply@openai.com>
2026-07-11 13:58:41 +08:00
ZyyandCodex 45e4b36225 refactor: complete postgresql redis migration
Co-authored-by: Codex <noreply@openai.com>
2026-07-10 19:00:14 +08:00
zyycnandCodex 73658238e5 fix: refine admin usage reporting
Co-authored-by: Codex <noreply@openai.com>
2026-07-05 16:25:01 +08:00
zyycnandCodex a12c61b4f4 fix: stabilize system update restart
Co-authored-by: Codex <noreply@openai.com>
2026-07-04 14:18:45 +08:00
zyycnandCodex 4f35230ab7 fix: refine system update workflow
Co-authored-by: Codex <noreply@openai.com>
2026-07-04 12:38:29 +08:00
ZyyandCodex 112bd76f66 refactor: address audit findings
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Zyy <No Email>
2026-07-03 18:20:05 +08:00