Commit Graph
1310 Commits
Author SHA1 Message Date
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 a91e06b228 feat(settings): add payment config guide link in payment settings header 2026-04-11 20:46:47 +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 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
erio 6d7e0642a0 chore: remove unused decodeURLValue and clean up formatting 2026-04-11 16:29:51 +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 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 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 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 7547ea9f4e fix(payment): include RECHARGING in result page success states
The PaymentResultView only checked COMPLETED and PAID status, but orders
in RECHARGING state (balance being applied after payment) were incorrectly
shown as failed.
2026-04-10 16:23:23 +08:00
erio 0113bf60fd feat(payment): renewal modal, clean confirm card, platform color refresh
- Replace gradient header in subscription confirm with clean card layout
  matching sub2apipay design (platform accent text instead of full gradient)
- Add renewal plan selection modal: when group has multiple plans show
  picker, single plan skips directly to payment method selection
- Restyle SubscriptionsView with platform-specific colors (badge, border,
  button) instead of hardcoded purple
- Update platformColors to match sub2apipay style (transparent badges,
  subtle borders with /20 opacity)
2026-04-10 16:12:28 +08:00
erio 9df96a45c7 feat(payment): redesign Stripe popup to match sub2apipay clean card style
Replace purple gradient header with clean white card layout, method-specific
colored amount text and spinner, larger card and spinner sizes.
2026-04-10 15:50:28 +08:00
erio cd1bbebb77 feat(payment): subscription renewal UI, payment button colors, QR branding, refund day deduction
- Add btn-alipay/btn-wxpay CSS classes; confirm button color follows payment method
- Subscription confirm header uses platform gradient (Anthropic orange, Gemini blue, etc.)
- Subscription confirm page shows plan details (rate, limits, validity)
- SubscriptionPlanCard: show "Renew" button when user has active subscription
- SubscriptionsView: add renewal button on active subscription cards
- QR code display: brand-color border + center logo overlay (Alipay blue, WeChat green)
- StripePaymentView: WeChat QR green border + logo, Alipay spinner brand color
- Backend: fix subscription refund to deduct days (ExtendSubscription -days or Revoke)
- Backend: rollback subscription days on gateway failure
2026-04-10 10:42:06 +08:00
IanShaw027 b6bc042302 fix(frontend): 升级 axios 修复审计高危漏洞 2026-04-10 09:28:32 +08:00
erio db139191e3 fix(payment): critical audit fixes for security, idempotency and correctness
Backend fixes:
- #1: doSub subscription idempotency via audit log check
- #2: markFailed only when status=RECHARGING (prevents overwriting COMPLETED)
- #3: ExpireTimedOutOrders checks upstream payment before expiring
- #4: Public verify endpoint for payment result page (no auth required)
- #5: EasyPay QueryOrder returns amount, confirmPayment handles zero amount
- #6: WxPay notifyUrl priority: request-first, config-fallback
- #7: EasyPay remove double URL decode in VerifyNotification
- #8: checkPaid/cancelUpstreamPayment use order's provider instance
- #9: Amount NaN/Inf/negative validation in order creation and refund
- #10: Refund amount comparison uses tolerance instead of float64 ==
- #11: Skip balance deduction on retry when previous rollback failed
- #12: checkPaid logs fulfillment errors instead of silently ignoring
- #13: WxPay certSerial added to required config fields

Frontend fixes:
- Payment result page no longer requires authentication
- Public verify API fallback for expired sessions
2026-04-10 02:23:19 +08:00
erio 72b77306da fix(admin): reload provider list after save to get correct data format
UpdateProvider API returns raw DB entity (encrypted config, string types),
but frontend needs ProviderInstanceResponse (decrypted, array types).
Reload full list after save to ensure correct data and sort order.
2026-04-10 01:28:54 +08:00
erio e45c774ab9 fix(payment): refresh provider registry on config changes
- Call RefreshProviders after Create/Update/Delete provider instance
- Call RefreshProviders after saving payment settings
- Auto-save settings when provider dialog saves
- Fixes webhook signature verification using stale pkey
2026-04-10 00:50:12 +08:00
erio 087cd72371 style(admin): widen time unit select, shorten cancel limit label 2026-04-10 00:19:32 +08:00
erio 7617ed56d3 style(admin): cancel rate limit inline with toggle, greyed when off 2026-04-10 00:13:16 +08:00
erio 83643f2dde style(admin): cancel rate limit as toggle switch, config in single row 2026-04-10 00:03:54 +08:00
erio a6728b9b69 style(admin): move cancel rate limit checkbox inline with pending orders row 2026-04-09 23:58:52 +08:00
erio 62e9453ddc refactor(frontend): extract shared OrderTable component
- Create OrderTable.vue with shared cell rendering (ID, order number,
  amount, payment method, status badge, created time)
- Accepts showUser prop to conditionally show user_email column
- Actions column uses scoped slot for view-specific buttons
- UserOrdersView and AdminOrdersView both use OrderTable
- Removes duplicated DataTable cell templates from both views

chore: bump version to 0.1.108.144
2026-04-09 23:49:47 +08:00
erio 753a87dee3 feat(admin): add user info and keyword search to admin order list
Backend:
- Add Keyword field to OrderListParams
- AdminListOrders supports keyword search on out_trade_no, user_email, user_name
- PaymentOrder already has user_email/user_name/user_notes fields (no join needed)

Frontend:
- Replace inline status badge with OrderStatusBadge component
- Replace user_id column with user_email (shows email, fallback to username, with notes)
- Keyword search matches order number and user info

chore: bump version to 0.1.108.143
2026-04-09 23:41:59 +08:00
erio e25e7b3f2d fix(admin): fix refund dialog amount for REFUND_REQUESTED, improve button styles
- Don't treat refund_amount as "already refunded" in REFUND_REQUESTED status
  (it's the requested amount, not actually refunded)
- Pre-fill refund amount with user's requested amount
- Show "already refunded" only for PARTIALLY_REFUNDED/REFUNDED orders
- Change action buttons from stacked icon+text to compact inline style
2026-04-09 22:07:06 +08:00
erio 66cd16fce3 fix: remove unused canRefund, fix TS type assertions 2026-04-09 21:49:05 +08:00
erio cc858c3cc9 feat(admin): enhance refund workflow to match sub2apipay
Admin order list:
- Add REFUND_REQUESTED "approve refund" button with amount badge
- Add REFUND_FAILED "retry refund" button
- Add missing status filters (REFUND_REQUESTED, REFUND_FAILED)
- Order detail dialog: show refund request info + audit logs

Admin refund dialog:
- Show refund request info card (violet) when user requested
- Display user balance with insufficient balance warning
- Add "no deduction" info when deduct_balance unchecked
- Add force refund checkbox (shown when requireForce=true)
- Add warning display prop
- Pre-fill reason from user's refund request
- Default deduct_balance to true

chore: bump version to 0.1.108.141
2026-04-09 21:47:39 +08:00
IanShaw027 2b70d1d332 merge upstream main into fix/bug-cleanup-main 2026-04-09 21:35:48 +08:00
erio ceee2d0584 fix: audit fixes - magic strings to constants, frontend any/catch, LB tests
Backend:
- Define OrderTypeBalance/Subscription, EntityStatusActive, DeductionType*,
  NotificationStatus* constants in payment/types.go
- Replace all magic strings in payment_order, payment_fulfillment, payment_refund
- Add local constants in easypay.go (tradeStatusSuccess, signTypeMD5)
- Add 27 unit tests for load balancer (filterByLimits, pickLeastAmount,
  getInstanceChannelLimits, startOfDay)

Frontend:
- Remove all `any` types in SettingsView.vue (18 catch blocks + 1 payload)
- Fix bare catch blocks in PaymentResultView, PaymentView
- Add `unknown` type annotation to all catch blocks

chore: bump version to 0.1.108.140
2026-04-09 21:29:49 +08:00
erio 8808910ee7 fix(frontend): unify currency to $ and add order number to admin orders
- Replace all ¥ / &yen; with $ across all payment views and components
- Add out_trade_no column to admin order list table
- Add order number field to admin order detail dialog

chore: bump version to 0.1.108.138
2026-04-09 21:14:57 +08:00
Wesley Liddick bbc79796dc Merge pull request #1529 from IanShaw027/feat/group-messages-dispatch-redo
feat: 为openai分组增加messages调度模型映射并支持instructions模板注入
2026-04-09 21:14:38 +08:00
erio b25d7f3179 fix(frontend): restore RechargeSubscriptionIcon for purchase menu
chore: bump version to 0.1.108.135
2026-04-09 19:01:34 +08:00
erio 766f9fc590 fix: cast platform to string to fix TS2345 2026-04-09 18:48:42 +08:00
erio 05ce6d6bc0 feat(admin): add platform colors to plan edit group selector
chore: bump version to 0.1.108.134
2026-04-09 18:46:58 +08:00
erio acb86102f4 feat(admin): color plan names by group platform
chore: bump version to 0.1.108.133
2026-04-09 18:33:36 +08:00
erio 4bacf47e45 fix(admin): only show subscription-type groups in plan group selector 2026-04-09 18:19:31 +08:00
IanShaw027 5f8e60a1b7 feat(table): 表格排序与搜索改为后端处理 2026-04-09 18:14:28 +08:00
IanShaw027 66e15a54a4 fix(export): 导出逻辑与当前筛选条件对齐 2026-04-09 18:14:28 +08:00
IanShaw027 ad80606a44 feat(settings): 增加全局表格分页配置,支持自定义 2026-04-09 18:14:28 +08:00
IanShaw027 d8fa38d55a fix(account): 修复账号管理中的状态筛选 2026-04-09 18:14:28 +08:00
erio 3ce57cade8 fix(payment): use Stripe built-in QR dialog for WeChat Pay
Remove handleActions:false and custom QR rendering. Let Stripe's
native QR dialog handle WeChat Pay display in the popup window.
2026-04-09 18:04:04 +08:00
erio ae1709a616 fix(payment): use normal style for order number column 2026-04-09 17:49:09 +08:00
erio 3098651bdd fix(payment): show order number as separate column in order list 2026-04-09 17:43:42 +08:00
erio 49a36e55a9 feat(payment): show out_trade_no in order list 2026-04-09 17:34:23 +08:00