Skip to content

feat: merge upstream v3.1.2 with sing-box egress integration - #1

Merged
xiaocongyu66 merged 1210 commits into
mainfrom
merge-upstream
Aug 17, 2026
Merged

feat: merge upstream v3.1.2 with sing-box egress integration#1
xiaocongyu66 merged 1210 commits into
mainfrom
merge-upstream

Conversation

@xiaocongyu66

Copy link
Copy Markdown
Owner

Summary

Merge upstream v3.1.2 (1188 commits) into fork while preserving all fork-specific features.

Upstream updates (v3.0.3 → v3.1.2)

  • Citation/render fixes for web gateway
  • Bot-risk Build scheduling exclusion
  • Media image ingest improvements
  • Various bug fixes and refactors

Fork features preserved

  • sing-box egress (vendored, 906 files in third_party/)
  • Prompt cache affinity (session seed, turn linkage, Redis hot cache)
  • Reasoning replay (session persistence)
  • Segmented selector (large pool optimization)
  • FlareSolverr integration (Cloudflare clearance)
  • Cloudflare R2 media storage + admin files page
  • Proxies admin page (multi-scope, batch import, UA pool)
  • Console provider (quota rotation, model pre-registration)
  • DB buffer (bulk ops optimization)
  • Statsig fingerprint (pure-Go local implementation)
  • Custom API key headers
  • Anti-bot stack (WARP + Privoxy + FlareSolverr docker-compose)
  • Client analytics (dashboard RPM/TPM, audit details)
  • Anthropic Messages at /Anthropic/messages

Build

  • go build ./cmd/grok2api passes ✅
  • Dockerfile updated with SINGBOX_TAGS
  • go.mod includes sing-box replace directive

chenyme and others added 30 commits July 24, 2026 16:47
feat: 创作控制台聊天支持单条消息重生成/修改/删除与停止生成
gpt-5.4 → grok-4.5
gpt-5.5 → grok-4.5
并与发现/目录产生的 grok-4.5 → grok-4.5 共存。
仍保持 对外名 public_id 全局唯一;重复创建同一个 gpt-5.5 继续 409。
…user

Map definitive upstream dead-account signals to provider.ErrUnauthorized so
import identity sync and Web quota refresh persist reauthRequired (UI: 失效)
and drop accounts from scheduling.

- Session Parse: status=blocked (no identity) → ErrUnauthorized
- Web rate-limits: HTTP 403 body with blocked-user / user is blocked → ErrUnauthorized
- Keep generic missing-identity and non-blocked 403 as non-invalidating failures
- Add sessionidentity Parse tests and Web quota blocked/generic 403 tests
Classify HTTP 403 by response body before egress retry. When body contains
blocked-user or user is blocked, mark reauthRequired and rotate accounts;
other 403s keep egress retry without account penalty.
Treat session status blocked/unauthenticated before accepting identity
fields. On Web chat and quota 403, classify blocked-user body before
Statsig invalidation retry so definitive ban signals are not dropped.
…lidation

feat(account): 完善 SSO 失效——补齐 403 正文明确封号(导入 / 额度 / Web && Console 对话)
Classify Grok Build 403/429 failures so request-level safety denials
and free-usage / Team RPS limits no longer mis-invalidate accounts or
block failover.

- Treat SAFETY_CHECK_TYPE_* / usage-guidelines 403 as request-scoped
- Require explicit access-denied text for permanent account denial
- Rotate free-usage-exhausted even when X-Should-Retry is false
- Parse Build Team+Model RPS metadata with a 2s default cool-down
- Keep previous_response_id pinned to the original account

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… modelRouteID parameter for improved routing candidate selection
放宽「同一 Provider + 同一 upstream 只能有一条路由」的限制,使管理端可创建:
feat: implement batch quota reset functionality for Build accounts
feat: updated egress binding  UI
feat: introduce webVisibleStreamPhase to manage client-visible output and suppress late reasoning
Allow routing.maxAttempts to be set above 10 so large account pools can
retry across more candidates in a single request. Keep the existing
minimum of 1 and update frontend validation/UI to match.
Expose effort-suffixed model names (e.g. grok-4.5-low) only for keys with allowModelAliases enabled, using each model's real supported reasoning levels.
Allow single and batch account deletion to also remove linked
Web/Build/Console peers resolved only from binding tables
(Web↔Build, Web↔Console; Build↔Console two-hop via Web without
deleting intermediate Web unless targeted).

- Preview counts after checkbox selection (POST deletion-preview)
- Delete re-resolves targets; empty targets keep legacy root-only
- DeleteManyWithLinked: lock roots, expand links, media check,
  and delete in one transaction (avoid resolve/delete TOCTOU)
- Single delete: missing root 404; non-empty malformed body 400
- UI: linked options, select-all, spinner counts, no fake +0 on
  preview failure; batch API forwards linkedDeleteTargets
- Status cleanup / autoClean / reauth propagation unchanged
Build and Console account tabs gain webLinked/webUnlinked filtering
resolved from binding tables; grok_web keeps its six existing values.
Per-provider validation rejects cross-pool values with 400. Covered by
validation matrix, repository count, and combined-filter tests.
Cleanup can now delete linked Web/Build/Console peers resolved from
binding tables, with COUNT-based preview in the dialog.

- Repository: RootGroups/PeerProviders in the resolution, shared
  deleteLinkedGroupsTx helper, cursor-paged DeleteAccountStatusBatchWithLinked,
  CountCleanupWithLinked for preview
- Media semantics: single delete still rejects the whole operation;
  batch delete and cleanup skip the blocked root group and report skipped
- Counts now derive from rows actually deleted instead of the planned set
- Cross-pool deletes invalidate every provider's candidate cache
- UI: per-status counts, smooth-expanding linked block, warning that linked
  accounts may be healthy, preview failure blocks confirm, toasts report
  linked/skipped; provider switch resets cleanup dialog state
- Drop the now-unused DeleteAccountStatusBatch
buddhism5080 and others added 7 commits August 7, 2026 17:51
When no page/source title is known, use "1"/"2"/… instead of the URL.
Match non-stream chat: attach xAI tool usage next to citations on the
finish_reason chunk before [DONE].
…tion

fix(web): Web 上游搜索引用对齐(mgw render_citation → 客户端 citations)
- Integrate third_party/sing-box transport modules
- Add egress platform/sharelink/singbox registry
- Add account bulk_buffer/preselect/sso_dedup
- Add response_cache retry_status and merge repro tests
- Fix account/redis interface incompatibility with upstream v3.1.2
- Add Docker publish workflow and CodeQL config
- Update Dockerfile and go.mod/go.sum
# Conflicts:
#	.dockerignore
#	.github/workflows/codeql.yml
#	.github/workflows/ghcr-image.yml
#	.github/workflows/stale.yml
#	.gitignore
#	Dockerfile
#	Makefile
#	README.md
#	VERSION
#	backend/README.md
#	backend/docs/docs.go
#	backend/docs/swagger.json
#	backend/docs/swagger.yaml
#	backend/go.mod
#	backend/internal/app/application.go
#	backend/internal/app/console_routes_test.go
#	backend/internal/app/startup.go
#	backend/internal/app/startup_test.go
#	backend/internal/application/account/console_quota_test.go
#	backend/internal/application/account/conversion_test.go
#	backend/internal/application/account/credential_refresh_test.go
#	backend/internal/application/account/credential_scheduler.go
#	backend/internal/application/account/export_test.go
#	backend/internal/application/account/quota_refresh_test.go
#	backend/internal/application/account/quota_test.go
#	backend/internal/application/account/service.go
#	backend/internal/application/account/web_console_sync_test.go
#	backend/internal/application/accountsync/service.go
#	backend/internal/application/accountsync/service_test.go
#	backend/internal/application/audit/service.go
#	backend/internal/application/audit/service_test.go
#	backend/internal/application/clientkey/cache.go
#	backend/internal/application/clientkey/service.go
#	backend/internal/application/clientkey/service_test.go
#	backend/internal/application/dashboard/service.go
#	backend/internal/application/dashboard/service_test.go
#	backend/internal/application/egress/service.go
#	backend/internal/application/egress/service_test.go
#	backend/internal/application/gateway/attempt.go
#	backend/internal/application/gateway/attempt_test.go
#	backend/internal/application/gateway/failure.go
#	backend/internal/application/gateway/failure_test.go
#	backend/internal/application/gateway/image.go
#	backend/internal/application/gateway/model_alias_test.go
#	backend/internal/application/gateway/prompt_cache.go
#	backend/internal/application/gateway/prompt_cache_test.go
#	backend/internal/application/gateway/selector.go
#	backend/internal/application/gateway/selector_plan.go
#	backend/internal/application/gateway/selector_segmented_active.go
#	backend/internal/application/gateway/selector_test.go
#	backend/internal/application/gateway/service.go
#	backend/internal/application/gateway/service_test.go
#	backend/internal/application/gateway/timing.go
#	backend/internal/application/gateway/timing_test.go
#	backend/internal/application/gateway/video.go
#	backend/internal/application/gateway/video_test.go
#	backend/internal/application/media/service.go
#	backend/internal/application/media/service_test.go
#	backend/internal/application/model/service.go
#	backend/internal/application/model/service_test.go
#	backend/internal/application/quotarecovery/service.go
#	backend/internal/application/quotarecovery/service_test.go
#	backend/internal/application/settings/service.go
#	backend/internal/application/settings/service_test.go
#	backend/internal/application/updatecheck/service_test.go
#	backend/internal/domain/account/account.go
#	backend/internal/domain/account/account_test.go
#	backend/internal/domain/audit/audit.go
#	backend/internal/domain/audit/pricing.go
#	backend/internal/domain/audit/pricing_test.go
#	backend/internal/domain/clientkey/client_key.go
#	backend/internal/domain/dashboard/dashboard.go
#	backend/internal/domain/egress/egress.go
#	backend/internal/domain/inference/response.go
#	backend/internal/domain/media/asset.go
#	backend/internal/domain/media/job.go
#	backend/internal/domain/model/model.go
#	backend/internal/domain/settings/settings.go
#	backend/internal/infra/config/config.go
#	backend/internal/infra/config/config_test.go
#	backend/internal/infra/egress/buildclient.go
#	backend/internal/infra/egress/buildclient_test.go
#	backend/internal/infra/egress/manager.go
#	backend/internal/infra/egress/manager_test.go
#	backend/internal/infra/egress/sticky_retry.go
#	backend/internal/infra/egress/sticky_retry_test.go
#	backend/internal/infra/egress/tlsclient.go
#	backend/internal/infra/egress/trace.go
#	backend/internal/infra/media/local_store.go
#	backend/internal/infra/persistence/relational/account_repository.go
#	backend/internal/infra/persistence/relational/audit_repository.go
#	backend/internal/infra/persistence/relational/audit_repository_test.go
#	backend/internal/infra/persistence/relational/client_key_repository.go
#	backend/internal/infra/persistence/relational/client_key_repository_test.go
#	backend/internal/infra/persistence/relational/console_provider_test.go
#	backend/internal/infra/persistence/relational/dashboard_repository.go
#	backend/internal/infra/persistence/relational/dashboard_repository_test.go
#	backend/internal/infra/persistence/relational/database.go
#	backend/internal/infra/persistence/relational/egress_repository.go
#	backend/internal/infra/persistence/relational/egress_sort_test.go
#	backend/internal/infra/persistence/relational/list_filter_repository_test.go
#	backend/internal/infra/persistence/relational/mapping.go
#	backend/internal/infra/persistence/relational/media_repository.go
#	backend/internal/infra/persistence/relational/media_repository_test.go
#	backend/internal/infra/persistence/relational/model_capability_repository_test.go
#	backend/internal/infra/persistence/relational/model_public_id.go
#	backend/internal/infra/persistence/relational/model_repository.go
#	backend/internal/infra/persistence/relational/models.go
#	backend/internal/infra/persistence/relational/postgres_integration_test.go
#	backend/internal/infra/persistence/relational/repository_test.go
#	backend/internal/infra/persistence/relational/response_repository.go
#	backend/internal/infra/persistence/relational/response_repository_test.go
#	backend/internal/infra/persistence/relational/schema.go
#	backend/internal/infra/persistence/relational/schema_console_upgrade_test.go
#	backend/internal/infra/persistence/relational/settings_repository_test.go
#	backend/internal/infra/provider/cli/adapter.go
#	backend/internal/infra/provider/cli/adapter_test.go
#	backend/internal/infra/provider/cli/billing.go
#	backend/internal/infra/provider/cli/billing_test.go
#	backend/internal/infra/provider/cli/egress.go
#	backend/internal/infra/provider/cli/fallback.go
#	backend/internal/infra/provider/cli/import.go
#	backend/internal/infra/provider/cli/normalize.go
#	backend/internal/infra/provider/cli/normalize_test.go
#	backend/internal/infra/provider/cli/oauth.go
#	backend/internal/infra/provider/cli/oauth_test.go
#	backend/internal/infra/provider/cli/responses_advanced_test.go
#	backend/internal/infra/provider/cli/responses_codex_tools.go
#	backend/internal/infra/provider/cli/responses_codex_tools_test.go
#	backend/internal/infra/provider/cli/responses_compaction.go
#	backend/internal/infra/provider/cli/responses_compaction_forward.go
#	backend/internal/infra/provider/cli/responses_compaction_test.go
#	backend/internal/infra/provider/cli/responses_history.go
#	backend/internal/infra/provider/cli/responses_input.go
#	backend/internal/infra/provider/cli/responses_reasoning_recovery.go
#	backend/internal/infra/provider/cli/responses_reasoning_recovery_test.go
#	backend/internal/infra/provider/cli/responses_response.go
#	backend/internal/infra/provider/cli/responses_tool_declarations.go
#	backend/internal/infra/provider/cli/responses_tool_state.go
#	backend/internal/infra/provider/cli/responses_tool_types.go
#	backend/internal/infra/provider/cli/responses_tools_test.go
#	backend/internal/infra/provider/cli/video.go
#	backend/internal/infra/provider/console/adapter.go
#	backend/internal/infra/provider/console/catalog.go
#	backend/internal/infra/provider/console/console_test.go
#	backend/internal/infra/provider/console/definition.go
#	backend/internal/infra/provider/console/import.go
#	backend/internal/infra/provider/console/normalize.go
#	backend/internal/infra/provider/conversation/chat_request.go
#	backend/internal/infra/provider/conversation/conversation_test.go
#	backend/internal/infra/provider/conversation/messages_request.go
#	backend/internal/infra/provider/conversation/messages_response.go
#	backend/internal/infra/provider/conversation/messages_stream.go
#	backend/internal/infra/provider/conversation/request.go
#	backend/internal/infra/provider/conversation/response.go
#	backend/internal/infra/provider/conversation/stream.go
#	backend/internal/infra/provider/definition.go
#	backend/internal/infra/provider/definition_contract_test.go
#	backend/internal/infra/provider/import_json.go
#	backend/internal/infra/provider/import_json_test.go
#	backend/internal/infra/provider/provider.go
#	backend/internal/infra/provider/web/adapter.go
#	backend/internal/infra/provider/web/attachments.go
#	backend/internal/infra/provider/web/catalog.go
#	backend/internal/infra/provider/web/chat.go
#	backend/internal/infra/provider/web/image.go
#	backend/internal/infra/provider/web/import.go
#	backend/internal/infra/provider/web/import_test.go
#	backend/internal/infra/provider/web/protocol_test.go
#	backend/internal/infra/provider/web/quota.go
#	backend/internal/infra/provider/web/quota_test.go
#	backend/internal/infra/provider/web/sso_build.go
#	backend/internal/infra/provider/web/statsig.go
#	backend/internal/infra/provider/web/statsig_test.go
#	backend/internal/infra/provider/web/tools.go
#	backend/internal/infra/provider/web/tools_test.go
#	backend/internal/infra/provider/web/upstream_test.go
#	backend/internal/infra/provider/web/video.go
#	backend/internal/infra/runtime/memory/quota_queue.go
#	backend/internal/infra/runtime/memory/quota_queue_test.go
#	backend/internal/infra/runtime/memory/store.go
#	backend/internal/infra/runtime/memory/store_test.go
#	backend/internal/infra/runtime/redis/response_cache.go
#	backend/internal/infra/runtime/redis/store.go
#	backend/internal/infra/runtime/redis/store_integration_test.go
#	backend/internal/infra/security/cipher.go
#	backend/internal/infra/security/cipher_test.go
#	backend/internal/infra/security/token.go
#	backend/internal/pkg/batch/executor.go
#	backend/internal/pkg/batch/executor_test.go
#	backend/internal/pkg/neterror/classify.go
#	backend/internal/pkg/neterror/classify_test.go
#	backend/internal/pkg/resultcache/cache.go
#	backend/internal/pkg/resultcache/cache_test.go
#	backend/internal/repository/account.go
#	backend/internal/repository/dashboard.go
#	backend/internal/repository/egress.go
#	backend/internal/repository/errors.go
#	backend/internal/repository/list.go
#	backend/internal/repository/media.go
#	backend/internal/repository/model.go
#	backend/internal/repository/response.go
#	backend/internal/repository/runtime.go
#	backend/internal/transport/http/account/handler.go
#	backend/internal/transport/http/account/handler_test.go
#	backend/internal/transport/http/adminauth/handler.go
#	backend/internal/transport/http/audit/handler.go
#	backend/internal/transport/http/audit/handler_test.go
#	backend/internal/transport/http/clientkey/handler.go
#	backend/internal/transport/http/dashboard/handler.go
#	backend/internal/transport/http/dashboard/handler_test.go
#	backend/internal/transport/http/egress/handler.go
#	backend/internal/transport/http/inference/handler.go
#	backend/internal/transport/http/inference/handler_test.go
#	backend/internal/transport/http/inference/model_list_test.go
#	backend/internal/transport/http/inference/prompt_cache.go
#	backend/internal/transport/http/inference/prompt_cache_test.go
#	backend/internal/transport/http/media/dto.go
#	backend/internal/transport/http/media/handler.go
#	backend/internal/transport/http/media/handler_test.go
#	backend/internal/transport/http/middleware/auth.go
#	backend/internal/transport/http/middleware/auth_test.go
#	backend/internal/transport/http/middleware/concurrency.go
#	backend/internal/transport/http/middleware/request.go
#	backend/internal/transport/http/middleware/request_test.go
#	backend/internal/transport/http/model/handler.go
#	backend/internal/transport/http/model/handler_test.go
#	backend/internal/transport/http/server.go
#	backend/internal/transport/http/settings/handler.go
#	backend/internal/transport/http/settings/security_test.go
#	backend/internal/transport/http/swagger_annotations.go
#	config.example.yaml
#	docker-compose.yml
#	docker/entrypoint.sh
#	frontend/package.json
#	frontend/pnpm-lock.yaml
#	frontend/src/app/app-shell.tsx
#	frontend/src/app/deferred-pages.tsx
#	frontend/src/app/router.tsx
#	frontend/src/components/ui/dropdown-menu.tsx
#	frontend/src/components/ui/input.tsx
#	frontend/src/components/ui/select.tsx
#	frontend/src/components/ui/table.tsx
#	frontend/src/components/ui/tabs.tsx
#	frontend/src/components/ui/textarea.tsx
#	frontend/src/entities/model/model-api.ts
#	frontend/src/entities/model/types.ts
#	frontend/src/features/accounts/account-quota.tsx
#	frontend/src/features/accounts/accounts-api.ts
#	frontend/src/features/accounts/accounts-page.tsx
#	frontend/src/features/audits/request-audit-detail-dialog.tsx
#	frontend/src/features/audits/request-audits-api.ts
#	frontend/src/features/audits/request-audits-page.tsx
#	frontend/src/features/client-keys/client-keys-api.ts
#	frontend/src/features/client-keys/client-keys-page.tsx
#	frontend/src/features/creative-console/creative-console-api.ts
#	frontend/src/features/creative-console/creative-console-page.tsx
#	frontend/src/features/dashboard/dashboard-api.ts
#	frontend/src/features/dashboard/dashboard-page.tsx
#	frontend/src/features/docs/api-docs-page.tsx
#	frontend/src/features/media/gallery-page.tsx
#	frontend/src/features/media/media-api.ts
#	frontend/src/features/media/types.ts
#	frontend/src/features/media/video-gallery-page.tsx
#	frontend/src/features/models/models-page.tsx
#	frontend/src/features/settings/settings-api.ts
#	frontend/src/features/settings/settings-model.ts
#	frontend/src/features/settings/settings-page.tsx
#	frontend/src/features/settings/use-settings.ts
#	frontend/src/features/system/version-update.tsx
#	frontend/src/index.css
#	frontend/src/shared/api/client.ts
#	frontend/src/shared/api/decoder.ts
#	frontend/src/shared/clipboard.ts
#	frontend/src/shared/components/data-table-filters.tsx
#	frontend/src/shared/components/date-time-picker.tsx
#	frontend/src/shared/components/page-header.tsx
#	frontend/src/shared/components/pagination.tsx
#	frontend/src/shared/components/period-selector.tsx
#	frontend/src/shared/components/site-footer.tsx
#	frontend/src/shared/i18n/index.ts
#	frontend/src/shared/lib/format.ts
#	frontend/src/shared/lib/period.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd88685d08

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return "", ErrSecretUnavailable
}
raw, err := s.cipher.DecryptAAD(value.EncryptedSecret, security.ClientKeyAAD(value.Prefix))
raw, err := s.cipher.Decrypt(value.EncryptedSecret)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore AAD-bound client key decryption

When an operator reveals a key created by the previous release, its encrypted copy was sealed with security.ClientKeyAAD(prefix); this now calls the no-AAD decrypt path, so GCM authentication fails and the admin can no longer copy existing keys even though request authentication still works via the hash. Keep the AAD decrypt fallback for stored client-key ciphertexts before switching formats.

Useful? React with 👍 / 👎.

Comment on lines +507 to +508
if c.Media.Driver != "local" {
return errors.New("media.driver 当前仅支持 local")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve R2 media deployments

When media.driver: r2 is configured, validation now rejects it unconditionally, even though the example config still documents R2 and the R2 store code remains in the tree. Existing R2-backed deployments will fail during startup before storage can be initialized, so either keep r2 in MediaConfig/validation or provide a migration path.

Useful? React with 👍 / 👎.

Comment on lines +58 to +60
raw, ok := bearerToken(c.GetHeader("Authorization"))
if !ok {
raw = strings.TrimSpace(c.GetHeader("X-API-Key"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor configured API key headers

When an installation uses auth.apiKeyHeaders for clients or proxies that cannot set Authorization/X-API-Key, this fallback now ignores every configured custom header, so those requests authenticate with an empty key and fail with invalid_api_key. Preserve the configured header extraction in this path rather than limiting authentication to the two built-in headers.

Useful? React with 👍 / 👎.

@xiaocongyu66
xiaocongyu66 merged commit 22a551a into main Aug 17, 2026
11 checks passed
Link-Start pushed a commit to Link-Start/grok2api-sing_xiaocongyu66 that referenced this pull request Aug 18, 2026
admin: Token 列表分页上限扩展到 2000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.