Commit Graph
3646 Commits
Author SHA1 Message Date
erio 72c836141e feat(notify): add percentage threshold type for balance low notification
- Add threshold_type field (fixed/percentage) to system and user settings
- Add total_recharged field to users table, auto-incremented on balance credit
- Percentage mode: effective threshold = total_recharged × percentage / 100
- User-level threshold_type inherits from system default when not set
- Update admin settings UI with radio selector (fixed amount / percentage)
- Migration: 102_add_balance_notify_threshold_type.sql
2026-04-12 13:53:02 +08:00
erio f059ad02be chore: bump version to 0.1.110.8 2026-04-12 13:18:30 +08:00
erio 9d3376cbdb Merge branch 'worktree-feature+balance_notify' into release/custom-0.1.110
# Conflicts:
#	backend/internal/handler/admin/setting_handler.go
#	backend/internal/service/domain_constants.go
#	backend/internal/service/setting_service.go
#	backend/internal/service/settings_view.go
2026-04-12 13:17:28 +08:00
erio 21e6d68925 feat(websearch): settings UI overhaul and quota improvements
- Remove Priority field, auto load-balance by quota remaining
- Replace QuotaRefreshInterval (daily/weekly/monthly) with SubscribedAt
  (subscription date, monthly lazy refresh via Redis TTL)
- Add collapsible provider cards, API key show/copy, usage progress bar
- Add test endpoint (POST /web-search-emulation/test) bypassing quota
- Wire WebSearchManagerBuilder on startup (was never called before)
- Fix nextMonthlyReset day-of-month overflow (Jan 31 → Feb 28)
- Fix non-deterministic sort in selectByQuotaWeight
- Map ProxyID in builder for provider-level proxy tracking
- Fix frontend timezone drift in subscribed_at date picker
- Fix provider deletion index shift for expandedProviders state
2026-04-12 13:11:46 +08:00
erio 48488652f2 fix(notify): per-recipient timeout and return user on email removal
- Use per-recipient context timeout in sendEmails to prevent later
  recipients from failing due to shared timeout exhaustion
- Return updated user object from RemoveNotifyEmail handler for
  frontend state consistency (matching VerifyNotifyEmail pattern)
2026-04-12 12:50:27 +08:00
erio 10166c72e6 fix(notify): address review findings - accountCost formula, dedup, refactor
- Fix accountCost calculation in finalizePostUsageBilling to match
  postUsageBilling (always multiply by AccountRateMultiplier)
- Use strings.EqualFold for email dedup in collectBalanceNotifyRecipients
- Extract CheckAccountQuotaAfterIncrement into smaller functions:
  buildQuotaDims + asyncSendQuotaAlert (< 30 lines each)
- Add "not splittable" comments for HTML template functions
- Extract QuotaNotifyToggle.vue sub-component to reduce
  QuotaLimitCard.vue from 404 to 339 lines
2026-04-12 12:48:17 +08:00
erio 8f93b69584 feat(notify): add balance low & account quota notification system
- User balance low notification: email alert when balance drops below
  configurable threshold (user email + verified extra emails)
- Account quota notification: broadcast email to admin-configured
  recipients when daily/weekly/total quota usage exceeds alert threshold
- Admin settings: global enable/disable, default threshold, quota
  notification email list (Email Settings tab)
- User profile: enable/disable, custom threshold, add/remove extra
  notification emails with verification code flow
- Account quota: per-dimension alert toggle and threshold in quota
  control card
- Trigger logic: first-crossing only (old >= threshold && new < threshold
  for balance; old < threshold && new >= threshold for quota), naturally
  prevents duplicate notifications without Redis dedup
2026-04-12 02:48:57 +08:00
erio 6f24322ee6 chore: bump version to 0.1.110.7 2026-04-12 02:27:19 +08:00
erio d65efd6f5c fix(websearch): improve isProxyError detection and add manager tests
- Add TLS error detection to isProxyError (RecordHeaderError, handshake)
- Case-insensitive error string matching
- Add 19 unit tests for: isProviderAvailable, resolveProxyID,
  isProxyError, isProxyAvailable, selectByQuotaWeight, newHTTPClient
2026-04-12 02:20:02 +08:00
erio e869c26789 fix: gofmt websearch manager 2026-04-12 01:55:00 +08:00
erio 4e5072df3c feat(websearch): proxy failover, timeout, quota-weighted load balancing
- Use proxyutil.ConfigureTransportProxy for unified proxy protocol support
  (HTTP/HTTPS/SOCKS5/SOCKS5H), replacing ad-hoc HTTP-only proxy code
- Proxy errors return ErrProxyUnavailable → gateway triggers account switch
  via UpstreamFailoverError instead of fallback to direct connection
- Timeout: proxy dial 3s, TLS handshake 3s, data transfer 60s
- Mark proxy unavailable for 5 minutes in Redis on connectivity failure
- Quota-weighted load balancing: providers with quota_limit>0 are selected
  by remaining quota (weighted random); quota_limit=0 providers treated as
  0% weight and placed last
2026-04-12 01:48:06 +08:00
erio 6986546d06 chore: bump version to 0.1.110.6 2026-04-12 01:06:31 +08:00
erio 0622fc71ee merge: integrate websearch emulation feature from worktree branch
Merge worktree-feature+websearch_support into release/custom-0.1.110.
Resolved conflicts in channel repo/service/handler/frontend (both
features_config and account_stats_pricing fields kept).
Fixed ProxySelector missing proxies prop in SettingsView.
2026-04-12 01:00:14 +08:00
erio 4d9d48fade feat(channels): add custom account stats pricing rules
Allow channels to configure independent model pricing for account
statistics cost calculation, decoupled from user billing.

Backend:
- Migration 101: channels.apply_pricing_to_account_stats toggle,
  channel_account_stats_pricing_rules/model_pricing tables,
  usage_logs.account_stats_cost column
- resolveAccountStatsCost: match rules by group/account, then channel
  pricing, fallback to original formula when unconfigured
- Integrate into both GatewayService.recordUsageCore and
  OpenAIGatewayService.RecordUsage
- Update 8 account stats SQL queries to use
  COALESCE(account_stats_cost, total_cost) * account_rate_multiplier
- 23 unit tests for matching, pricing lookup, and cost calculation

Frontend:
- Channel edit dialog: toggle + custom rules UI with group/account
  multi-select and pricing entry cards
- API types and i18n (zh/en)
2026-04-12 00:31:57 +08:00
erio f3d2c1931c fix(lint): resolve depguard violation — remove redis import from service layer
Service layer must not import redis directly (depguard rule). Replace
*redis.Client field with WebSearchManagerBuilder callback injected by
the infra layer. Also fix remaining errcheck in manager_test.go.
2026-04-12 00:28:21 +08:00
erio 6df42dd4bd fix(lint): resolve golangci-lint errcheck and gofmt issues
- Add errcheck handling for w.Write, json.Encode in test handlers
- Use defer func() { _ = resp.Body.Close() }() pattern
- Use safe two-return type assertions in websearch_config.go
- Fix gofmt alignment in setting_service.go struct fields
2026-04-12 00:17:52 +08:00
erio 15452fdacf fix(test): add web_search_emulation_enabled to API contract test
The settings API response now includes the new field; update the
expected snapshot in TestAPIContracts to match.
2026-04-12 00:09:28 +08:00
erio c2deb0939d feat(gateway): add web search emulation for Anthropic API Key accounts
Inject web search capability for Claude Console (API Key) accounts that
don't natively support Anthropic's web_search tool. When a pure
web_search request is detected, the gateway calls Brave Search or Tavily
API directly and constructs an Anthropic-protocol-compliant SSE/JSON
response without forwarding to upstream.

Backend:
- New `pkg/websearch/` SDK: Brave and Tavily provider implementations
  with io.LimitReader, proxy support, and Redis-based quota tracking
  (Lua atomic INCR + TTL, DECR rollback on failure)
- Global config via `settings.web_search_emulation_config` (JSON) with
  in-process cache + singleflight, input validation, API key merge on
  save, and sanitized API responses
- Channel-level toggle via `channels.features_config` JSONB column
  (DB migration 101)
- Account-level toggle via `accounts.extra.web_search_emulation`
- Request interception in `Forward()` with SSE streaming response
  construction using json.Marshal (no manual string concatenation)
- Manager hot-reload: `RebuildWebSearchManager()` called on config save
  and startup via `SetWebSearchRedisClient()`
- 70 unit tests covering providers, manager, config validation,
  sanitization, tool detection, query extraction, and response building

Frontend:
- Settings → Gateway tab: Web Search Emulation config card with global
  toggle, provider list (add/remove, API key, priority, quota, proxy)
- Channels → Anthropic tab: web search emulation toggle with global
  state linkage (disabled when global off)
- Account Create/Edit modals: web search emulation toggle for API Key
  type with Toggle component
- Full i18n coverage (zh + en)
2026-04-12 00:02:26 +08:00
erio 473746a09d chore: bump version to 0.1.110.5 2026-04-11 20:58:12 +08:00
erio 1ed3b4bd8e feat(settings): add EasyPay provider recommendation link below enabled providers 2026-04-11 20:57:36 +08:00
erio 59b2c9a424 docs: align English ZPay referral description with Chinese version 2026-04-11 20:52:12 +08:00
erio aed7d2e5e3 docs: clarify ZPay referral code belongs to Sub2ApiPay author @touwaeriol 2026-04-11 20:48:44 +08:00
erio a91e06b228 feat(settings): add payment config guide link in payment settings header 2026-04-11 20:46:47 +08:00
erio 98837e454c docs: show ZPay URL explicitly in parentheses 2026-04-11 20:39:28 +08:00
erio 3a44a9ba64 docs: move ZPay recommendation to overview section 2026-04-11 20:35:57 +08:00
erio 6294e36de0 docs: add ZPay referral recommendation to EasyPay section 2026-04-11 20:30:50 +08:00
erio d707f3c22e fix(docs): correct webhook paths and provider config in payment guide
- Fix webhook URLs: /payment/webhook/<provider> not /payment/<provider>/notify
- Remove notifyUrl/returnUrl from provider config tables (auto-generated by UI)
- Adjust wxpay publicKeyId/certSerial to match frontend optional marking
2026-04-11 20:15:59 +08:00
erio 27e2a51f31 docs: add built-in payment guide and update README ecosystem section
- Add docs/PAYMENT.md and docs/PAYMENT_CN.md with full payment configuration guide
- Mark Sub2ApiPay as deprecated (strikethrough) in all 3 READMEs, link to built-in payment docs
- Add built-in payment system to features list
2026-04-11 19:54:25 +08:00
erio 0401b77204 fix: resolve TS errors from upstream merge
- Fix ApiResponse cast to Record<string,unknown> via double assertion
- Add missing default_mapped_model to editForm reactive (lost in merge)
2026-04-11 19:09:31 +08:00
erio 6c96aaec8c chore: bump version to 0.1.110.4 2026-04-11 19:03:34 +08:00
erio 94d91d69a9 chore: clean up sora_client_enabled and purchase_subscription residuals
- Remove sora_client_enabled from PublicSettings type and store defaults
- Remove purchase_subscription form defaults and save payload from SettingsView
- Remove dead 'data' tab type from SettingsTab union
2026-04-11 18:55:32 +08:00
erio 989c5faad5 Merge remote-tracking branch 'upstream/main' into release/custom-0.1.110
# Conflicts:
#	.github/audit-exceptions.yml
#	backend/cmd/server/VERSION
#	backend/go.sum
#	backend/internal/handler/admin/setting_handler.go
#	backend/internal/handler/dto/settings.go
#	backend/internal/repository/channel_repo.go
#	backend/internal/service/channel_service.go
#	backend/internal/service/setting_service.go
#	backend/internal/service/settings_view.go
#	frontend/src/api/admin/settings.ts
#	frontend/src/stores/app.ts
#	frontend/src/types/index.ts
#	frontend/src/views/admin/SettingsView.vue
2026-04-11 18:41:54 +08:00
erio f18d4ebbba chore: remove all sora dead code and fork-specific sora_client_enabled
Upstream removed sora feature (090_drop_sora.sql) but left i18n keys
and wire.go references. Clean up:
- Remove entire sora i18n block from en.ts and zh.ts (~190 lines)
- Remove sora nav key and unused 'data' settings tab key
- Remove sora_client_enabled from settings (fork-specific)
- Remove SoraMediaCleanupService from wire.go
2026-04-11 18:13:38 +08:00
erio d3d3a55f1f fix(payment): propagate reason/metadata in API error responses
The API client's error interceptor was dropping the reason and metadata
fields from backend error responses. This caused PaymentView to miss
specific error codes (TOO_MANY_PENDING, CANCEL_RATE_LIMITED) and fall
back to generic error messages.
2026-04-11 17:52:15 +08:00
erio dc31732b7a fix(deps): upgrade axios to 1.15.0 to fix GHSA-fvcv-3m26-pcqx 2026-04-11 16:46:26 +08:00
Wesley Liddick 1ef3782dd4 Merge pull request #1538 from IanShaw027/fix/bug-cleanup-main
fix: 修复多个 UI 和功能问题 - 表格排序搜索、导出逻辑、分页配置和状态筛选
2026-04-11 16:29:55 +08:00
erio 6d7e0642a0 chore: remove unused decodeURLValue and clean up formatting 2026-04-11 16:29:51 +08:00
erio a5a5d93de7 chore: bump version to 0.1.110.3 2026-04-11 16:10:09 +08:00
erio d60015f1d1 revert(payment): remove active upstream sync, keep webhook-only approach
Reverts the sync polling mechanism that queried upstream providers on
each frontend poll. Keep the Stripe expiresAt countdown fix.
2026-04-11 16:10:09 +08:00
erio 017f23bfa3 chore: bump version to 0.1.110.2 2026-04-11 15:46:43 +08:00
erio 576c34bbf7 fix(payment): add active upstream sync to polling and fix Stripe countdown
- Add POST /payment/orders/:id/sync endpoint that queries upstream
  provider on each poll, complementing webhooks for timely payment
  detection when webhooks are delayed or unreachable
- Fix Stripe payment countdown: pass expires_at to PaymentStatusPanel
  instead of empty string (was falling back to hardcoded 30 minutes)
- Idempotent: toPaid uses atomic UPDATE WHERE status=PENDING, so
  concurrent webhook + sync calls won't double-credit
2026-04-11 15:46:28 +08:00
erio 75deeb6e17 docs: update CLAUDE.md with correct PR and release workflows
- Release flow: start from our release branch, merge upstream in (not reverse)
- PR flow: base on upstream/main, cherry-pick from release, never merge PR into release
- Add forbidden files list, PR checklist, reverse sync instructions
- Add feat/* branch to branch strategy table
2026-04-11 14:50:07 +08:00
erio b3d4ea5aa6 chore: bump version to 0.1.110.1 2026-04-11 14:49:36 +08:00
erio b5b5e35757 refactor(payment): code standards fixes and file organization
Cherry-picked from PR branch (feat/payment-system-v2).
- Use payment.Type* constants instead of magic strings in factory
- Add wxpay success response constants
- Add validity unit constants (week/month)
- Add constants for easypay popup mode
- Split payment_order.go into payment_order_lifecycle.go
- Extract shared order utilities to orderUtils.ts
- Improve admin order components to use shared utilities
- Removed duplicate migration (097 already exists)
2026-04-11 13:24:17 +08:00
erio f4e4b1539b feat(payment): add H5/mobile payment support
Cherry-picked from PR branch (feat/payment-system-v2).
- EasyPay: parse payurl2 for H5 mobile links, prefer on mobile
- EasyPay: add device=mobile for popup mode on mobile
- Backend: expand isMobile() to detect iPad/iPod
- Frontend: auto-redirect on mobile instead of popup
- Frontend: fallback to redirect when popup blocked
- Stripe: use mobile_web client for WeChat Pay on mobile
- StripePopup: typed interface, extractApiErrorMessage
2026-04-11 13:22:12 +08:00
IanShaw027 f480e57344 fix: align table defaults and preserve sidebar svg colors 2026-04-10 18:27:53 +08:00
IanShaw027 7dc7ff22d2 fix: preserve messages dispatch config in repository hydration 2026-04-10 18:13:18 +08:00
IanShaw027 67a05dfccd fix: honor table defaults and preserve dispatch mappings 2026-04-10 17:55:37 +08:00
erio 4a3383ecdd fix(payment): widen popup window to 1000px for Alipay+ checkout
Alipay+ checkout page needs ~960px to display QR code and order details
side by side. Previous 680px forced users to manually resize.
2026-04-10 16:45:47 +08:00
erio 9d4b02688f Revert "fix(payment): restore decodeURLValue in EasyPay webhook verification"
This reverts commit 1430c82078.
2026-04-10 16:43:21 +08:00