-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
新功能:自定义透传渠道(CustomPass) #1454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: alpha
Are you sure you want to change the base?
新功能:自定义透传渠道(CustomPass) #1454
Conversation
This commit introduces the CustomPass channel, a new transparent proxy channel that allows for seamless integration with various upstream APIs. It supports both synchronous direct pass-through and asynchronous task processing, along with comprehensive pre-charging and billing mechanisms. Key features implemented: - Synchronous and asynchronous modes for API requests. - Automatic configuration discovery for various project types and database setups. - Intelligent task analysis to identify database-dependent operations. - Data-driven decision making with contextual analysis. - Full-stack task support, from data analysis to code implementation. - Extensibility for custom data type support. - Auto-configuration discovery for different project types and database settings. - Handles a wide range of tasks including data analysis, function creation, problem diagnosis, performance optimization, and business insights. This implementation lays the foundation for a powerful and flexible API gateway system.
… functionality This commit introduces the Stripe payment gateway as a new option for users to top up their accounts. It includes: - New controller (`controller/topup_stripe.go`) for handling Stripe requests, including amount validation, payment initiation, and webhook processing. - Adaptation of existing payment logic (`common/constants.go`, `model/option.go`, `model/user.go`) to support Stripe configuration and user data updates. - Updates to settings (`setting/payment.go`, `setting/payment_stripe.go`) to include Stripe-specific configurations like API keys, webhook secrets, price IDs, unit prices, and minimum top-up amounts. - Routing configuration (`router/api-router.go`) to expose the new Stripe endpoints. - Webhook handling (`controller/topup_stripe.go`) for processing payment events from Stripe, including session completion and expiration, to update user quotas and top-up statuses. - New constants in `common/constants.go` for top-up statuses. - New hashing functions in `common/hash.go` for generating HMAC SHA256 signatures, likely used for Stripe webhook verification. Additionally, this commit includes a significant number of changes to the frontend (web directory) to support the new features, including: - New components for Stripe payment integration. - Updates to README files to reflect licensing changes and add partner information. - Refactoring of existing components and hooks to support new features and improve code quality. - Addition of video generation endpoints and related DTOs. - Enhancements to existing channel types and constants. - Refinements to logging and caching mechanisms.
…n support This commit introduces several enhancements to the CustomPass channel, focusing on refining the two-request flow for synchronous and asynchronous operations and adding support for model-specific configurations. Key changes include: - **Refined Two-Request Flow:** - The `ExecuteTwoRequestFlow` function now handles both billing and non-billing models uniformly, simplifying the request processing logic. - Usage data is now prioritized from the real request response if available, falling back to the precharge response. This ensures more accurate billing and logging. - Debug logging has been improved for better visibility into the request and response flows, especially for usage data. - Error handling and refund logic have been improved for failed real requests or invalid responses. - **Model Configuration Support:** - The `custompass/adaptor.go` and related files now correctly handle different upstream URLs for async submission endpoints (`/submit`). - The `custompass_billing.go` and `custompass_precharge.go` services have been updated to correctly fetch model ratios and apply completion ratios for more accurate quota calculations. - The `IsModelUsageBasedBilling` function now correctly checks for the presence of model ratios. - **API and UI Improvements:** - The `CLAUDE.md` documentation has been updated to reflect configuration changes. - The `new-api` file has been removed. - `middleware/distributor.go` is updated to correctly parse CustomPass URLs. - `async_adaptor.go` now uses the two-request flow for task submission and simplifies task creation logic. - `dto.go` and `polling_service.go` have minor updates for validation and logging. - `sync_adaptor.go` is refactored to use the unified `ExecuteTwoRequestFlow`. - `custompass_auth.go` updates `BuildUpstreamHeaders` to accept `channel` directly and enhances `GetCustomTokenHeader` to consider channel-specific settings. - `custompass_billing.go` now correctly uses model ratios. - `custompass_precharge.go` introduces `calculateTokenBasedQuotaWithCompletionRatio` for more accurate precharge calculations and improves logging. - `service/quota.go` is updated to correctly use model ratios. - `start.sh` comments out the `SQLITE_PATH` export. - `web/src/components/common/logo/CustomPassIcon.js` adds a new icon component. - `web/src/components/table/channels/modals/EditChannelModal.jsx` updates the help text for the custom token header and adds priority clarification. - `web/src/components/table/mj-logs/MjLogsColumnDefs.js` and `web/src/components/table/task-logs/TaskLogsColumnDefs.js` include minor adjustments for rendering. - `web/src/helpers/render.js` adds the `CustomPassIcon` to channel rendering.
- Adds support for the Vidu channel, including its integration into the relay and task systems. - Introduces a new `ChannelTypeVidu` constant and corresponding configuration in `constant/channel.go`. - Implements the `TaskAdaptor` for Vidu in `relay/channel/task/vidu/adaptor.go`. - Updates `relay/relay_adaptor.go` to recognize and utilize the Vidu task adaptor. - Enhances error handling across various modules by consistently using `types.NewOpenAIError` or similar specific error types for better clarity and consistency. - Refactors `service/error.go` to improve error type management and introduce `InitOpenAIError`. - Updates `types/error.go` to correctly expose and utilize error types. - Modifies `controller/relay.go` to correctly retrieve error types using `err.GetErrorType()`. - Adjusts `middleware/distributor.go` to provide more specific error messages when channels are unavailable. - Updates `controller/task_video.go` to correctly check for successful response from JSON unmarshalling. - Improves Ollama adaptor to handle Claude requests and stream options correctly. - Fixes stream handling in `relay/channel/openai/relay-openai.go` to prevent potential issues with empty data. - Updates `relay/channel/siliconflow/adaptor.go` to correctly handle Claude requests and other modes. - Corrects `relay/helper/stream_scanner.go` to properly handle the end of stream data. - Updates frontend constants and modal logic for channel management. - Adjusts channel indexing in `constant/channel.go` to accommodate the new Vidu channel.
- Add new channel type 53 for CustomPass. - Refactor `start.sh` to include mock server functionality: - Add `-m` or `--mock` flag to start a mock server. - Implement port conflict detection and resolution for the mock server. - Support starting `test/mock_server.py` using `uv` or `python`. - Add `relay/channel/custompass/helper.go` with `GetEffectiveUserRatio` functions. - Add `verify_billing_fix.md` documentation for CustomPass billing logic verification. - Update `web/src/components/table/channels/modals/EditChannelModal.jsx` to use the new channel type ID (53) and adjust UI elements accordingly. - Update `web/src/helpers/render.js` to map the new channel type to its icon.
This commit introduces significant enhancements to the CustomPass billing system, focusing on accurate context propagation and handling of various billing scenarios. Key changes include: - **Introduction of `model.BillingInfo` struct**: This new struct stores detailed billing context, including ratios, prices, and billing modes, per task. - **Propagation of `BillingInfo`**: The `BillingInfo` is now generated during precharge and stored in `model.Properties` for tasks, ensuring that downstream processes (like task polling) have access to the correct billing parameters. - **Refined Precharge Logic**: The `ExecutePrecharge` function in `custompass_precharge.go` has been refactored to generate and return comprehensive `BillingInfo`. It now correctly handles free, usage-based, and fixed-price models, incorporating group ratios and special user group ratios. - **Updated Two-Request Flow**: The `ExecuteTwoRequestFlow` and related functions in `adaptor.go` and `async_adaptor.go` are updated to pass the `BillingInfo` from precharge to the `Task` properties. - **Improved Task Polling Settlement**: The `performTaskSettlement` and `performFailedTaskSettlement` functions in `custompass_task_polling.go` now prioritize using the `BillingInfo` stored within the task's properties for calculating settlement amounts, ensuring consistency and accuracy, especially for asynchronous tasks. This also includes backward compatibility for cases where `BillingInfo` might not be available. - **Fixed Price Billing Adjustment**: In `custompass_billing.go`, the fixed price billing calculation now correctly applies group and user ratios for consistency with other billing modes. The settlement logic for fixed price models has also been clarified to avoid redundant calculations. - **Error Handling and Logging**: Enhanced logging throughout the billing and precharge modules provides better visibility into the process and aids in debugging. These changes collectively improve the robustness and accuracy of the CustomPass billing system, particularly for asynchronous tasks and diverse billing models.
WalkthroughThis change set introduces the "CustomPass" channel, a fully transparent API proxy supporting both synchronous and asynchronous task modes with advanced billing, authentication, configuration, and error handling. It includes backend implementation (Go), frontend UI integration (React), extensive documentation, configuration management, deployment scripts, and a robust error and logging system. Numerous new files and modifications span core logic, service layers, web UI, and operational tooling. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API_Server
participant CustomPassAdaptor
participant AuthService
participant PrechargeService
participant BillingService
participant UpstreamAPI
participant DB
Client->>API_Server: POST /pass/{model}
API_Server->>CustomPassAdaptor: HandleRequest(context)
CustomPassAdaptor->>AuthService: ValidateUserToken(token)
AuthService->>DB: Query user info
AuthService-->>CustomPassAdaptor: user
CustomPassAdaptor->>PrechargeService: ExecutePrecharge(user, model, usage)
PrechargeService->>DB: Lock & deduct quota
PrechargeService-->>CustomPassAdaptor: PrechargeResult
CustomPassAdaptor->>UpstreamAPI: Send API request (with headers)
UpstreamAPI-->>CustomPassAdaptor: UpstreamResponse
CustomPassAdaptor->>BillingService: ProcessSettlement(user, model, precharge, usage)
BillingService->>DB: Settle/refund as needed
BillingService-->>CustomPassAdaptor: OK
CustomPassAdaptor-->>API_Server: Response
API_Server-->>Client: API result
sequenceDiagram
participant Client
participant API_Server
participant CustomPassAsyncAdaptor
participant AuthService
participant PrechargeService
participant BillingService
participant UpstreamAPI
participant DB
participant PollingService
Client->>API_Server: POST /pass/{model}/submit
API_Server->>CustomPassAsyncAdaptor: SubmitTask(context)
CustomPassAsyncAdaptor->>AuthService: ValidateUserToken(token)
AuthService->>DB: Query user info
AuthService-->>CustomPassAsyncAdaptor: user
CustomPassAsyncAdaptor->>PrechargeService: ExecutePrecharge(user, model, usage)
PrechargeService->>DB: Lock & deduct quota
PrechargeService-->>CustomPassAsyncAdaptor: PrechargeResult
CustomPassAsyncAdaptor->>UpstreamAPI: Submit async task
UpstreamAPI-->>CustomPassAsyncAdaptor: TaskSubmitResponse
CustomPassAsyncAdaptor->>DB: Insert task record
CustomPassAsyncAdaptor-->>API_Server: Response (task_id)
API_Server-->>Client: task_id
Note over PollingService,UpstreamAPI: Periodic polling
PollingService->>UpstreamAPI: Query task status
UpstreamAPI-->>PollingService: TaskInfo
PollingService->>BillingService: ProcessSettlement(user, model, precharge, usage)
BillingService->>DB: Settle/refund as needed
BillingService-->>PollingService: OK
PollingService->>DB: Update task status
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120+ minutes
Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
为 custompass 渠道添加了对自定义认证令牌的支持。 在提交任务时,将用户令牌 (userToken) 和自定义头密钥 (customHeaderKey) 包装在任务属性的输入字段中。 在轮询任务状态时,服务现在会根据用户令牌对任务进行分组,并为每个令牌组单独向其上游 API 发送查询请求,确保在请求头中正确地传递自定义令牌。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 43
🧹 Nitpick comments (26)
relay/channel/baidu_v2/adaptor.go (1)
46-54
: Simplify API-key parsing & remove unreachable branch
strings.Split
will always return at least one element, solen(keyParts) == 0
is impossible.
UsingSplitN
also avoids an unnecessary allocation for keys that never contain a second part.
Finally, the nestedif
can be flattened for clarity.- keyParts := strings.Split(info.ApiKey, "|") - if len(keyParts) == 0 || keyParts[0] == "" { + keyParts := strings.SplitN(strings.TrimSpace(info.ApiKey), "|", 2) + if keyParts[0] == "" { return errors.New("invalid API key: authorization token is required") } - if len(keyParts) > 1 { - if keyParts[1] != "" { - req.Set("appid", keyParts[1]) - } - } + if len(keyParts) == 2 && keyParts[1] != "" { + req.Set("appid", keyParts[1]) + }Minor, but this shaves a tiny amount of work on every request and removes dead code, improving readability and maintainability.
setting/console_setting/validation.go (4)
123-132
: Runstrings.TrimSpace
on free-text fields before validation
route
,description
(and latercategoryName
,slug
, …) are accepted verbatim. Trailing/leading spaces will silently consume quota in the length checks and may cause subtle mismatches when these values are used as keys in other parts of the system.Consider trimming once right after the type assertion:
- route, ok := apiInfo["route"].(string) + route, ok := apiInfo["route"].(string) if !ok || route == "" { return fmt.Errorf("第%d个API信息缺少线路描述字段", i+1) } + route = strings.TrimSpace(route)Apply the same pattern to
description
,categoryName
,slug
, etc.
262-290
: Slug validation should normalise to lower-case for consistencyYou accept mixed-case slugs (
"My-Group"
), but later comparisons (nameSet[slug]
, URL paths, DB keys) frequently rely on a single canonical form. Converting to lower-case before the regex & duplication checks avoids future collisions:- slug, ok := group["slug"].(string) + slug, ok := group["slug"].(string) if !ok || slug == "" { return fmt.Errorf("第%d个分组缺少Slug字段", i+1) } + slug = strings.ToLower(strings.TrimSpace(slug))
33-41
:url.Parse
result is discarded; rely on it instead of the custom regexThe handcrafted
urlRegex
is complex and easy to miss edge cases (IDNs, IPv6 literals, etc.). Sincenet/url
already performs full RFC-compliant parsing, consider:
- Drop the regex entirely.
- Use
u, err := url.ParseRequestURI(urlStr)
and validateu.Scheme
is http/https.Benefits: simpler code, fewer false positives/negatives, easier maintenance.
43-51
: Add early return for empty content incheckDangerousContent
Currently, an empty string goes through the full loop. A fast-path micro-optimisation improves readability and eliminates needless work:
func checkDangerousContent(content string, index int, itemType string) error { + if content == "" { + return nil + } lower := strings.ToLower(content)web/src/components/table/mj-logs/MjLogsColumnDefs.js (1)
51-53
: Consider import consistency.The
Video
icon is separated from the main icon import group. While functionally correct, it's inconsistent with the existing pattern. Consider keeping all lucide-react imports grouped unless there's a specific technical reason for separation.import { Palette, ZoomIn, Shuffle, Move, FileText, Blend, Upload, Minimize2, RotateCcw, PaintBucket, Focus, Move3D, Monitor, UserCheck, HelpCircle, CheckCircle, Clock, Copy, FileX, Pause, XCircle, Loader, AlertCircle, - Hash + Hash, + Video } from 'lucide-react'; -import { Video } from 'lucide-react';middleware/distributor.go (1)
140-152
: CustomPass routing logic looks good, but remove debug print statement.The implementation correctly handles CustomPass request routing by extracting the model name from the URL path and setting the appropriate relay mode. The logic to preserve the full model path including suffixes like
/submit
is important for async mode handling.However, remove the debug print statement before production deployment:
- // Debug log - fmt.Printf("DEBUG: CustomPass URL=%s, extracted model=%s\n", c.Request.URL.Path, modelRequest.Model)model/ability.go (1)
332-339
: Consider logging when fallback to default group occurs.The function logic is correct, but it might be helpful to log when the fallback to "default" group happens for debugging purposes, especially since this affects billing calculations in CustomPass.
func GetModelPrimaryGroup(modelName string) string { groups, err := GetModelGroups(modelName) if err != nil || len(groups) == 0 { + common.SysLog(fmt.Sprintf("GetModelPrimaryGroup: No groups found for model %s, using default group. Error: %v", modelName, err)) return "default" // fallback to default group } return groups[0] // return the first group as primary }
CLAUDE.md (1)
18-18
: Consider hyphenating compound adjective.The static analysis tool suggests using a hyphen for the compound adjective "Full Stack" when it modifies the following noun.
-### Full Stack +### Full-Stack.claude/commands/README.md (1)
16-18
: Add language specification to fenced code blocks for proper syntax highlighting.The markdown linter indicates that code blocks should have a language specified.
-``` +```bash /ask-with-data <您的问题或任务>-``` +```text 用户任务 → Claude Code → /ask-with-data 命令 → 分析任务需求 → 自动发现数据库 → 查询相关数据 → 基于数据上下文执行任务 → 提供完整解决方案Also applies to: 113-117
service/quota.go (1)
575-576
: Consider using English for debug log prefixes for consistency.The debug logs use Chinese prefix "[CustomPass-Debug]" which might be inconsistent with other logging in the codebase. Consider using English for better consistency and searchability.
- common.SysLog(fmt.Sprintf("[CustomPass-Debug] 模型使用量计费检查 - 模型: %s, 有比率配置: %t, 比率值: %.6f", + common.SysLog(fmt.Sprintf("[CustomPass-Debug] Model usage billing check - model: %s, has ratio config: %t, ratio value: %.6f", modelName, hasRatio, ratio))Apply similar changes to other debug log messages in this file for consistency.
Also applies to: 582-583, 595-595, 599-600, 608-609, 613-614, 621-621, 627-628
service/custompass_auth.go (1)
168-174
: Remove unused duplicate functionThe
getCustomTokenHeaderFromEnv
function duplicates logic already inGetCustomTokenHeader
and is never used.relay/channel/custompass/sync_adaptor.go (1)
99-100
: Remove unnecessary empty lineThere's an unnecessary empty line between reading the request body and using the two-request flow.
- - // Use the common two-request flow for all requestscc_launcher.sh (1)
320-340
: Remove unused duration parameterThe
duration
parameter inshow_loading
function is never used.# 显示loading动画 show_loading() { local message="$1" - local duration="$2" - local pid="$3" + local pid="$2" local spinner="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"relay/channel/custompass/error_handler.go (1)
170-243
: Consider documenting string-matching limitationsThe error detection helpers rely on string matching which can be fragile. Consider adding a comment explaining this limitation and potential for false positives.
Add a comment before the helper functions:
// Error classification helper functions // Note: These functions use string matching as a fallback when proper error types // are not available. This approach may have false positives if error-like strings // appear in user data. Consider migrating to typed errors where possible. func isTimeoutError(err error) bool {docs/custompass/DEPLOYMENT.md (2)
812-821
: Enhance SSL/TLS security configuration.The current SSL configuration is good but can be improved with additional security headers and modern TLS practices.
Add these security enhancements:
# SSL配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; + ssl_session_timeout 1d; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; # 安全头 add_header Strict-Transport-Security "max-age=63072000" always; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + add_header Content-Security-Policy "default-src 'self';" always;
546-552
: Add additional systemd security hardening.The current security settings are good, but additional hardening options can further improve security.
Add these hardening options:
# 安全设置 NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/opt/newapi/logs +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true +RestrictNamespaces=true +LockPersonality=true +MemoryDenyWriteExecute=true +RestrictRealtime=true +RestrictSUIDSGID=true +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERMrelay/channel/custompass/logger.go (1)
208-252
: Use strings.Builder for efficient string concatenation.Multiple string concatenations in a loop can be inefficient. Use
strings.Builder
for better performance.func (l *CustomPassLogger) buildLogMessage(operation string, entry *LogEntry) string { - msg := fmt.Sprintf("CustomPass %s", operation) + var builder strings.Builder + builder.WriteString(fmt.Sprintf("CustomPass %s", operation)) if entry.UserID > 0 { - msg += fmt.Sprintf(", UserID: %d", entry.UserID) + builder.WriteString(fmt.Sprintf(", UserID: %d", entry.UserID)) } // ... continue for other fields ... - return msg + return builder.String() }service/custompass_billing.go (1)
194-206
: Consider using decimal arithmetic for financial calculations.While the current implementation uses
math.Round
to mitigate floating-point precision issues, consider using a decimal library for more accurate financial calculations.For production systems handling financial calculations, consider using a decimal arithmetic library like
shopspring/decimal
to avoid floating-point precision issues:import "github.com/shopspring/decimal" // Use decimal for precise calculations promptCost := decimal.NewFromInt(int64(usage.GetInputTokens())).Mul(decimal.NewFromFloat(modelRatio)) completionCost := decimal.NewFromInt(int64(usage.GetOutputTokens())).Mul(decimal.NewFromFloat(modelRatio * completionRatio)) totalCost := promptCost.Add(completionCost) finalAmount := totalCost.Mul(decimal.NewFromFloat(groupRatio)).Mul(decimal.NewFromFloat(userRatio)) finalQuota := finalAmount.Round(0).IntPart()start.sh (2)
326-326
: Declare and assign backup_script variable separately.Shellcheck warning about variable declaration masking return values.
- local backup_script="${CURRENT_SCRIPT}.backup.$(date +%Y%m%d_%H%M%S)" + local backup_script + backup_script="${CURRENT_SCRIPT}.backup.$(date +%Y%m%d_%H%M%S)"
636-690
: Excellent script organization and command-line interfaceThe main function provides a comprehensive command-line interface with clear help documentation and proper error handling. The overall script organization with logical function grouping makes it maintainable and extensible.
Consider addressing the shellcheck warnings about variable declaration and assignment separation (SC2155) for better shell scripting practices, though they don't affect functionality:
# Instead of: local pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1) # Use: local pid pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1)CustomPass开发文档.md (1)
35-35
: Add language specifiers to fenced code blocks for better syntax highlighting.Multiple code blocks are missing language specifiers, which affects readability.
For example, change:
-``` +```textOr use appropriate language like
bash
,json
,http
where applicable.Also applies to: 202-202, 320-320, 372-372, 883-883, 943-943
relay/channel/custompass/adaptor.go (1)
47-113
: Consider implementing or documenting stub methodsThe adaptor contains many stub methods that return
nil
or empty values. If these methods are part of a required interface but not used by CustomPass, consider:
- Adding comments to indicate they are intentionally unimplemented
- Returning appropriate errors if they should not be called
- Implementing them if they will be needed
Additionally,
GetModelList()
returns hardcoded model names which should likely be replaced with dynamic configuration.func (a *Adaptor) GetModelList() []string { - // Return available models for CustomPass - return []string{"custom-model-1", "custom-model-2"} + // TODO: Implement dynamic model retrieval from configuration or channel settings + // For now, return empty list or fetch from channel configuration + return []string{} }service/custompass_task_polling.go (2)
902-904
: Consider passing context through polling serviceThe function creates a mock
gin.Context
for the billing service. Consider refactoring to pass a proper context through the polling service chain for better request tracing and cancellation support.Would you like me to suggest a refactoring to properly propagate context through the polling service?
983-984
: Clarify deprecation status of performFailedTaskSettlementThe comment indicates this function is "kept for backward compatibility but should not be used for new failure handling". Consider:
- Adding a
@deprecated
tag in the comment- Logging a warning when this function is called
- Document the migration path to
processFailedTaskDirectRefund
// performFailedTaskSettlement performs settlement for failed tasks with zero usage (full refund) -// This function is kept for backward compatibility but should not be used for new failure handling +// @deprecated: This function is kept for backward compatibility but should not be used for new failure handling. +// Use processFailedTaskDirectRefund instead for direct refund without settlement. func (s *TaskPollingService) performFailedTaskSettlement(localTask *model.Task) { + common.SysLog("[DEPRECATED] performFailedTaskSettlement called - consider using processFailedTaskDirectRefund").kiro/specs/custompass-channel/design.md (1)
740-747
: Add language specifier to code blockThe code block is missing a language specifier for proper syntax highlighting.
-``` +```text 模型配置说明: - 同步模型:直接透传,立即返回结果 - 异步模型:模型名称需以 /submit 结尾,如 custom-image-gen/submit - 支持混合配置:可同时配置同步和异步模型</blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used: CodeRabbit UI** **Review profile: CHILL** **Plan: Pro** <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between c5d97597c408ec72482792e1369dff41bf570371 and fef8d22e08021e32568e31f1c57c898d8870c9a4. </details> <details> <summary>⛔ Files ignored due to path filters (1)</summary> * `go.sum` is excluded by `!**/*.sum` </details> <details> <summary>📒 Files selected for processing (66)</summary> * `.claude/commands/README.md` (1 hunks) * `.claude/commands/ask-with-data.md` (1 hunks) * `.gitignore` (1 hunks) * `.kiro/specs/custompass-channel/design.md` (1 hunks) * `.kiro/specs/custompass-channel/requirements.md` (1 hunks) * `.kiro/specs/custompass-channel/tasks.md` (1 hunks) * `CLAUDE.md` (1 hunks) * `CustomPass开发文档.md` (1 hunks) * `cc_launcher.sh` (1 hunks) * `common/api_type.go` (1 hunks) * `common/utils.go` (1 hunks) * `constant/api_type.go` (1 hunks) * `constant/channel.go` (2 hunks) * `constant/task.go` (1 hunks) * `controller/custompass.go` (1 hunks) * `controller/ratio_config.go` (1 hunks) * `controller/ratio_sync.go` (1 hunks) * `controller/task.go` (1 hunks) * `controller/uptime_kuma.go` (5 hunks) * `docs/custompass/API.md` (1 hunks) * `docs/custompass/CONFIGURATION.md` (1 hunks) * `docs/custompass/DEPLOYMENT.md` (1 hunks) * `docs/custompass/README.md` (1 hunks) * `docs/custompass/TROUBLESHOOTING.md` (1 hunks) * `dto/ratio_sync.go` (1 hunks) * `go.mod` (2 hunks) * `main.go` (1 hunks) * `middleware/auth.go` (1 hunks) * `middleware/distributor.go` (1 hunks) * `middleware/stats.go` (2 hunks) * `model/ability.go` (1 hunks) * `model/task.go` (2 hunks) * `relay/channel/baidu_v2/adaptor.go` (1 hunks) * `relay/channel/custompass/adaptor.go` (1 hunks) * `relay/channel/custompass/async_adaptor.go` (1 hunks) * `relay/channel/custompass/constants.go` (1 hunks) * `relay/channel/custompass/dto.go` (1 hunks) * `relay/channel/custompass/error_handler.go` (1 hunks) * `relay/channel/custompass/errors.go` (1 hunks) * `relay/channel/custompass/helper.go` (1 hunks) * `relay/channel/custompass/logger.go` (1 hunks) * `relay/channel/custompass/polling_service.go` (1 hunks) * `relay/channel/custompass/sync_adaptor.go` (1 hunks) * `relay/channel/mokaai/constants.go` (1 hunks) * `relay/constant/relay_mode.go` (1 hunks) * `relay/custompass_handler.go` (1 hunks) * `relay/relay_adaptor.go` (2 hunks) * `router/relay-router.go` (1 hunks) * `service/custompass_auth.go` (1 hunks) * `service/custompass_billing.go` (1 hunks) * `service/custompass_config.go` (1 hunks) * `service/custompass_config_summary.md` (1 hunks) * `service/custompass_config_watcher.go` (1 hunks) * `service/custompass_precharge.go` (1 hunks) * `service/custompass_task_polling.go` (1 hunks) * `service/quota.go` (3 hunks) * `setting/console_setting/validation.go` (1 hunks) * `setting/ratio_setting/expose_ratio.go` (1 hunks) * `start.sh` (1 hunks) * `verify_billing_fix.md` (1 hunks) * `web/src/components/common/logo/CustomPassIcon.js` (1 hunks) * `web/src/components/table/channels/modals/EditChannelModal.jsx` (6 hunks) * `web/src/components/table/mj-logs/MjLogsColumnDefs.js` (1 hunks) * `web/src/components/table/task-logs/TaskLogsColumnDefs.js` (4 hunks) * `web/src/constants/channel.constants.js` (1 hunks) * `web/src/helpers/render.js` (2 hunks) </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>🧠 Learnings (7)</summary> <details> <summary>middleware/stats.go (2)</summary> Learnt from: feitianbubu PR: QuantumNous/new-api#1228 File: router/main.go:28-36 Timestamp: 2025-06-15T12:38:11.806Z Learning: gin.Context implements context.Context interface since Gin v1.8.0, providing the methods Deadline(), Done(), Err(), and Value(). When using Gin v1.8.0 or later, gin.Context can be passed directly to functions expecting context.Context without needing to extract c.Request.Context(). Learnt from: feitianbubu PR: QuantumNous/new-api#1228 File: router/main.go:28-36 Timestamp: 2025-06-15T12:38:11.806Z Learning: gin.Context implements context.Context interface since Gin v1.8.0, providing the methods Deadline(), Done(), Err(), and Value(). When using Gin v1.8.0 or later, gin.Context can be passed directly to functions expecting context.Context without needing to extract c.Request.Context(). </details> <details> <summary>verify_billing_fix.md (1)</summary> Learnt from: 9Ninety PR: QuantumNous/new-api#1273 File: relay/channel/gemini/relay-gemini.go:97-116 Timestamp: 2025-06-21T03:37:41.726Z Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior. </details> <details> <summary>relay/channel/custompass/helper.go (1)</summary> Learnt from: 9Ninety PR: QuantumNous/new-api#1273 File: relay/channel/gemini/relay-gemini.go:97-116 Timestamp: 2025-06-21T03:37:41.726Z Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior. </details> <details> <summary>relay/channel/custompass/constants.go (1)</summary> Learnt from: 9Ninety PR: QuantumNous/new-api#1273 File: relay/channel/gemini/relay-gemini.go:97-116 Timestamp: 2025-06-21T03:37:41.726Z Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior. </details> <details> <summary>relay/custompass_handler.go (1)</summary> Learnt from: 9Ninety PR: QuantumNous/new-api#1273 File: relay/channel/gemini/relay-gemini.go:97-116 Timestamp: 2025-06-21T03:37:41.726Z Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior. </details> <details> <summary>service/quota.go (1)</summary> Learnt from: 9Ninety PR: QuantumNous/new-api#1273 File: relay/channel/gemini/relay-gemini.go:97-116 Timestamp: 2025-06-21T03:37:41.726Z Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior. </details> <details> <summary>relay/channel/custompass/adaptor.go (1)</summary> Learnt from: 9Ninety PR: QuantumNous/new-api#1273 File: relay/channel/gemini/relay-gemini.go:97-116 Timestamp: 2025-06-21T03:37:41.726Z Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior. </details> </details><details> <summary>🧬 Code Graph Analysis (17)</summary> <details> <summary>common/api_type.go (2)</summary><blockquote> <details> <summary>constant/channel.go (1)</summary> * `ChannelTypeCustomPass` (53-53) </details> <details> <summary>constant/api_type.go (1)</summary> * `APITypeCustomPass` (33-33) </details> </blockquote></details> <details> <summary>controller/ratio_config.go (2)</summary><blockquote> <details> <summary>setting/ratio_setting/expose_ratio.go (1)</summary> * `IsExposeRatioEnabled` (15-17) </details> <details> <summary>setting/ratio_setting/exposed_cache.go (1)</summary> * `GetExposedData` (35-55) </details> </blockquote></details> <details> <summary>relay/relay_adaptor.go (2)</summary><blockquote> <details> <summary>constant/api_type.go (1)</summary> * `APITypeCustomPass` (33-33) </details> <details> <summary>relay/channel/adapter.go (1)</summary> * `Adaptor` (13-29) </details> </blockquote></details> <details> <summary>controller/ratio_sync.go (4)</summary><blockquote> <details> <summary>dto/ratio_sync.go (5)</summary> * `UpstreamRequest` (10-14) * `UpstreamDTO` (3-8) * `TestResult` (17-21) * `DifferenceItem` (27-31) * `SyncableChannel` (33-38) </details> <details> <summary>model/channel.go (1)</summary> * `GetChannelsByIds` (822-826) </details> <details> <summary>common/logger.go (2)</summary> * `LogError` (68-70) * `LogWarn` (64-66) </details> <details> <summary>setting/ratio_setting/exposed_cache.go (1)</summary> * `GetExposedData` (35-55) </details> </blockquote></details> <details> <summary>setting/console_setting/validation.go (1)</summary><blockquote> <details> <summary>setting/console_setting/config.go (1)</summary> * `GetConsoleSetting` (37-39) </details> </blockquote></details> <details> <summary>controller/task.go (3)</summary><blockquote> <details> <summary>constant/task.go (3)</summary> * `TaskPlatformKling` (8-8) * `TaskPlatformJimeng` (9-9) * `TaskPlatformCustomPass` (10-10) </details> <details> <summary>controller/task_video.go (1)</summary> * `UpdateVideoTaskAll` (18-25) </details> <details> <summary>common/logger.go (1)</summary> * `SysLog` (50-53) </details> </blockquote></details> <details> <summary>web/src/helpers/render.js (1)</summary><blockquote> <details> <summary>web/src/components/common/logo/CustomPassIcon.js (1)</summary> * `CustomPassIcon` (23-46) </details> </blockquote></details> <details> <summary>model/ability.go (1)</summary><blockquote> <details> <summary>model/main.go (1)</summary> * `DB` (63-63) </details> </blockquote></details> <details> <summary>relay/channel/custompass/helper.go (4)</summary><blockquote> <details> <summary>service/custompass_billing.go (1)</summary> * `CustomPassBillingService` (15-45) </details> <details> <summary>setting/ratio_setting/group_ratio.go (1)</summary> * `GetGroupGroupRatio` (76-89) </details> <details> <summary>common/logger.go (1)</summary> * `SysLog` (50-53) </details> <details> <summary>model/user.go (1)</summary> * `GetUserById` (224-236) </details> </blockquote></details> <details> <summary>main.go (2)</summary><blockquote> <details> <summary>service/custompass_task_polling.go (1)</summary> * `GetTaskPollingService` (134-143) </details> <details> <summary>common/logger.go (1)</summary> * `SysError` (55-58) </details> </blockquote></details> <details> <summary>model/task.go (1)</summary><blockquote> <details> <summary>model/main.go (1)</summary> * `DB` (63-63) </details> </blockquote></details> <details> <summary>web/src/components/table/channels/modals/EditChannelModal.jsx (1)</summary><blockquote> <details> <summary>web/src/components/table/channels/modals/EditTagModal.jsx (4)</summary> * `inputs` (73-73) * `handleInputChange` (77-129) * `customModel` (65-65) * `addCustomModels` (263-297) </details> </blockquote></details> <details> <summary>relay/custompass_handler.go (9)</summary><blockquote> <details> <summary>types/error.go (9)</summary> * `NewAPIError` (75-81) * `NewErrorWithStatusCode` (179-190) * `ErrorCodeInvalidRequest` (36-36) * `ErrorCodeGetChannelFailed` (45-45) * `ErrorCodeReadRequestBodyFailed` (56-56) * `ErrorCode` (33-33) * `ErrorCodeInsufficientUserQuota` (71-71) * `ErrorCodeDoRequestFailed` (44-44) * `ErrorCodeBadResponse` (63-63) </details> <details> <summary>model/channel.go (1)</summary> * `GetChannelById` (313-328) </details> <details> <summary>constant/channel.go (1)</summary> * `ChannelTypeCustomPass` (53-53) </details> <details> <summary>common/logger.go (1)</summary> * `LogInfo` (60-62) </details> <details> <summary>relay/channel/custompass/async_adaptor.go (1)</summary> * `NewAsyncAdaptor` (43-52) </details> <details> <summary>common/gin.go (1)</summary> * `GetRequestBody` (15-27) </details> <details> <summary>relay/channel/custompass/dto.go (1)</summary> * `TaskQueryRequest` (129-131) </details> <details> <summary>relay/channel/custompass/sync_adaptor.go (1)</summary> * `NewSyncAdaptor` (36-45) </details> <details> <summary>relay/channel/custompass/errors.go (6)</summary> * `CustomPassError` (26-31) * `ErrCodeInvalidRequest` (11-11) * `ErrCodeInsufficientQuota` (12-12) * `ErrCodeTimeout` (16-16) * `ErrCodeUpstreamError` (13-13) * `ErrCodeSystemError` (17-17) </details> </blockquote></details> <details> <summary>controller/custompass.go (2)</summary><blockquote> <details> <summary>common/logger.go (2)</summary> * `LogInfo` (60-62) * `LogError` (68-70) </details> <details> <summary>relay/custompass_handler.go (1)</summary> * `CustomPassHelper` (17-139) </details> </blockquote></details> <details> <summary>service/custompass_config_watcher.go (2)</summary><blockquote> <details> <summary>service/custompass_config.go (3)</summary> * `CustomPassConfigService` (52-59) * `CustomPassConfig` (15-42) * `NewCustomPassConfigService` (74-80) </details> <details> <summary>common/logger.go (2)</summary> * `SysLog` (50-53) * `SysError` (55-58) </details> </blockquote></details> <details> <summary>service/custompass_config.go (2)</summary><blockquote> <details> <summary>relay/channel/custompass/dto.go (2)</summary> * `CustomPassConfig` (193-208) * `CustomPassStatusMapping` (157-161) </details> <details> <summary>common/logger.go (1)</summary> * `SysError` (55-58) </details> </blockquote></details> <details> <summary>relay/channel/custompass/logger.go (3)</summary><blockquote> <details> <summary>common/logger.go (3)</summary> * `LogInfo` (60-62) * `LogError` (68-70) * `LogWarn` (64-66) </details> <details> <summary>common/constants.go (1)</summary> * `RequestIdKey` (128-128) </details> <details> <summary>common/json.go (1)</summary> * `Marshal` (20-22) </details> </blockquote></details> </details><details> <summary>🪛 Gitleaks (8.27.2)</summary> <details> <summary>verify_billing_fix.md</summary> 36-37: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (curl-auth-header) </details> <details> <summary>docs/custompass/README.md</summary> 53-54: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (curl-auth-header) --- 68-69: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (curl-auth-header) </details> <details> <summary>docs/custompass/TROUBLESHOOTING.md</summary> 126-127: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (curl-auth-header) --- 155-156: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (curl-auth-header) </details> </details> <details> <summary>🪛 LanguageTool</summary> <details> <summary>CLAUDE.md</summary> [uncategorized] ~18-~18: If this is a compound adjective that modifies the following noun, use a hyphen. Context: ...ix**: `cd web && bun run lint:fix` ### Full Stack - **Build and run**: `make all` (builds... (EN_COMPOUND_ADJECTIVE_INTERNAL) </details> <details> <summary>.claude/commands/README.md</summary> [uncategorized] ~70-~70: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:可行"地"解决 Context: ...于真实数据而非假设 - **个性化建议**: 针对您项目的具体情况 - **可行的解决方案**: 结合代码和数据的实用建议 - **量化的洞察**: 具体的数字和... (wb4) </details> <details> <summary>docs/custompass/CONFIGURATION.md</summary> [uncategorized] ~501-~501: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:适当"地"并发 Context: ...## 1. 生产环境配置 - 使用合理的轮询间隔(30-60秒) - 设置适当的并发限制 - 配置完整的状态映射 - 启用监控和日志记录 - 设置合理的超时时间... (wb4) </details> <details> <summary>docs/custompass/API.md</summary> [uncategorized] ~250-~250: 您的意思是“"不"扣”? Context: ...根据实际usage计算最终费用 4. **多退少补**: 退还多扣的quota或补扣不足的quota 5. **记录日志**: 记录详细的消费日志 ## 错误处... (BU) </details> <details> <summary>CustomPass开发文档.md</summary> [uncategorized] ~124-~124: 您的意思是“"不"扣”? Context: ...:计算预扣费与实际费用的差额 5. **用户余额调整**:退还多扣的quota或补扣不足的quota 6. **任务状态更新**:更新任务状态为已结算 7. **... (BU) --- [uncategorized] ~155-~155: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:合理"地"锁 Context: ...行级锁**:对用户记录使用行级锁,防止并发修改余额 - **锁超时**:设置合理的锁超时时间(建议5秒),避免长时间等待 - **死锁检测**:数据库层面的死锁检... (wb4) --- [uncategorized] ~456-~456: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:正确"地"查询 Context: ...CustomPass系统在查询异步任务状态时,需要根据模型名称和任务ID构建正确的查询URL。系统会自动处理模型名称的转换和URL拼接。 **URL构建步骤**... (wb4) --- [uncategorized] ~469-~469: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:固定"地"查询 Context: ...渠道配置的基础URL作为前缀 - 拼接处理后的模型名称 - 添加固定的查询路径 `/task/list-by-condition` - 最终格式... (wb4) --- [uncategorized] ~484-~484: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:好"地"查询 Context: ...送**: - 使用HTTP POST方法发送查询请求 - 携带构建好的查询数据和请求头 - 设置适当的超时时间,避免长时间等待 #### 3.... (wb4) --- [uncategorized] ~1271-~1271: 您的意思是“"不"全”? Context: ...费 **倍率设定**:参考6.7.1节价格计算示例 - 模型倍率: 2.0 - 补全倍率: 1.5 - 用户分组倍率: 0.8 **计费计算**:基于系统内置基... (BU) --- [uncategorized] ~1277-~1277: 您的意思是“"不"全”? Context: ... - 提示单价 = 1.0 × 2.0 = 2.0 quota/token - 补全单价 = 1.0 × 2.0 × 1.5 = 3.0 quota/token ... (BU) --- [uncategorized] ~1362-~1362: 您的意思是“"不"全”? Context: ...## 6.4.3 异步任务计费 **倍率设定**: - 模型倍率: 1.0 - 补全倍率: 1.0 - 用户分组倍率: 0.9 ```json // 1. Cu... (BU) --- [uncategorized] ~1443-~1443: 您的意思是“"不"全”? Context: ... - **模型倍率**: 针对特定模型设置的倍率,影响该模型的基础价格 - **补全倍率**: 针对输出token的额外倍率,通常大于1.0 - **用户分组倍率... (BU) --- [uncategorized] ~1519-~1519: 您的意思是“"不"扣”? Context: ... `users.quota` 字段上进行临时扣除 - 最终结算时根据实际消费进行补扣或退还 - 所有预扣费和最终结算的详细信息记录在 `logs` 表中 ###... (BU) --- [uncategorized] ~1555-~1555: 您的意思是“"不"全”? Context: ...设模型custom-text-pro的倍率配置为: - 模型倍率: 2.0 - 补全倍率: 1.5 - 用户分组倍率: 0.8 基于系统内置基础价格: - 系统... (BU) --- [uncategorized] ~1669-~1669: 您的意思是“"不"全”? Context: ...atio`: 模型分组倍率 - `completion_ratio`: 补全倍率 - `model_price`: 模型固定价格 - `user_... (BU) </details> <details> <summary>.kiro/specs/custompass-channel/requirements.md</summary> [uncategorized] ~118-~118: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:合理"地"默认 Context: ...ER_KEY环境变量 7. WHEN 环境变量未配置 THEN 系统应该使用合理的默认值 (wb4) </details> </details> <details> <summary>🪛 markdownlint-cli2 (0.17.2)</summary> <details> <summary>.claude/commands/README.md</summary> 16-16: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 113-113: Fenced code blocks should have a language specified (MD040, fenced-code-language) </details> <details> <summary>CustomPass开发文档.md</summary> 35-35: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 202-202: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 320-320: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 372-372: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 883-883: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 943-943: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1231-1231: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1237-1237: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1249-1249: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1255-1255: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1408-1408: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1409-1409: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1414-1414: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1415-1415: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1421-1421: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1422-1422: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1428-1428: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1429-1429: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1433-1433: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1434-1434: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1450-1450: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1451-1451: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1455-1455: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1456-1456: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1475-1475: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1481-1481: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1563-1563: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1564-1564: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1569-1569: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1570-1570: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 1577-1577: Emphasis used instead of a heading (MD036, no-emphasis-as-heading) --- 1578-1578: Fenced code blocks should have a language specified (MD040, fenced-code-language) </details> <details> <summary>.kiro/specs/custompass-channel/design.md</summary> 740-740: Fenced code blocks should have a language specified (MD040, fenced-code-language) </details> </details> <details> <summary>🪛 Shellcheck (0.10.0)</summary> <details> <summary>cc_launcher.sh</summary> [warning] 101-101: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 102-102: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 114-114: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 115-115: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 118-118: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 119-119: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 140-140: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 141-141: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 153-153: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 154-154: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 157-157: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 158-158: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 222-222: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 272-272: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 322-322: duration appears unused. Verify use (or export if used externally). (SC2034) --- [warning] 351-351: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 483-483: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 488-488: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 496-496: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 532-532: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 793-793: This pattern always overrides a later one on line 793. (SC2221) --- [warning] 793-793: This pattern never matches because of a previous pattern on line 793. (SC2222) --- [warning] 797-797: This pattern always overrides a later one on line 797. (SC2221) --- [warning] 797-797: This pattern never matches because of a previous pattern on line 797. (SC2222) --- [warning] 801-801: This pattern always overrides a later one on line 801. (SC2221) --- [warning] 801-801: This pattern never matches because of a previous pattern on line 801. (SC2222) --- [warning] 869-869: This pattern always overrides a later one on line 869. (SC2221) --- [warning] 869-869: This pattern never matches because of a previous pattern on line 869. (SC2222) </details> <details> <summary>start.sh</summary> [warning] 101-101: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 103-103: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 104-104: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 146-146: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 326-326: Declare and assign separately to avoid masking return values. (SC2155) --- [warning] 384-384: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. (SC2164) --- [warning] 605-605: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. (SC2164) </details> </details> </details> <details> <summary>🔇 Additional comments (86)</summary><blockquote> <details> <summary>relay/channel/mokaai/constants.go (1)</summary> `9-10`: **LGTM! Good code hygiene.** Adding the trailing newline improves file formatting consistency and follows standard practices. </details> <details> <summary>controller/uptime_kuma.go (1)</summary> `34-154`: **LGTM! Clean formatting improvements.** The whitespace and indentation adjustments improve code readability while maintaining all existing functionality. The formatting changes follow Go conventions consistently. </details> <details> <summary>relay/constant/relay_mode.go (1)</summary> `54-54`: **Ignore Path2RelayMode for CustomPass mapping** The CustomPass routes are already handled via the Gin router, middleware distributor, and controller—no updates to `Path2RelayMode` are needed: • router/relay-router.go: registers `POST "/pass/*model"` → `controller.RelayCustomPass` • middleware/distributor.go: checks `strings.HasPrefix(path, "/pass/")`, extracts model, and sets `c.Set("relay_mode", "custompass")` • controller/custompass.go: trims `/pass/`, detects async `/submit`, and dispatches to the CustomPass handler Since all `/pass/` URL patterns map correctly to `RelayModeCustomPass` via this flow, you can ignore the suggestion to modify `Path2RelayMode`. > Likely an incorrect or invalid review comment. </details> <details> <summary>.gitignore (1)</summary> `14-16`: **LGTM! Appropriate build artifact ignores.** The additions properly ignore development artifacts (`test`, `.eslintcache`) and build outputs (`new-api`) that align with the new CustomPass infrastructure. </details> <details> <summary>dto/ratio_sync.go (1)</summary> `4-38`: **LGTM! Proper Go formatting with tabs.** The indentation change from spaces to tabs aligns with Go formatting standards (`gofmt` conventions) and improves consistency across the codebase. </details> <details> <summary>relay/relay_adaptor.go (2)</summary> `15-15`: **LGTM: Import properly placed** The custompass import is correctly positioned alphabetically within the imports section, following Go conventions. --- `100-101`: **LGTM: Consistent integration pattern** The CustomPass adapter integration follows the same pattern as other channel adapters, maintaining consistency with the existing codebase structure. </details> <details> <summary>web/src/constants/channel.constants.js (1)</summary> `162-166`: **LGTM: Channel option properly configured** The CustomPass channel option is correctly added with value 53, following the established pattern of other channel entries. The Chinese label '自定义透传渠道' (Custom Pass-through Channel) appropriately describes the channel's purpose and is consistent with other localized channel names. </details> <details> <summary>middleware/stats.go (1)</summary> `21-21`: **LGTM: Code formatting improvements** The changes are purely cosmetic, removing trailing whitespace and adding proper file ending. No functional changes affect the middleware's connection tracking logic. Also applies to: 26-26, 41-41 </details> <details> <summary>setting/ratio_setting/expose_ratio.go (1)</summary> `8-8`: **LGTM: Formatting standardization** The changes standardize indentation from spaces to tabs and add proper file ending, following Go formatting conventions. No functional changes to the atomic boolean operations. Also applies to: 12-12, 16-17 </details> <details> <summary>go.mod (1)</summary> `53-53`: **LGTM! Standard testing dependencies added.** The three new indirect dependencies (`github.com/davecgh/go-spew`, `github.com/pmezard/go-difflib`, and `github.com/stretchr/objx`) are standard components of the testify testing framework, commonly used for test assertions, pretty printing, and diff generation in Go projects. Also applies to: 83-83, 85-85 </details> <details> <summary>constant/channel.go (2)</summary> `53-53`: **LGTM! New CustomPass channel type constant added.** The addition follows the established pattern with a unique integer value (53) for the new channel type. --- `112-112`: **LGTM! User-configurable base URL for CustomPass.** The empty string entry with the descriptive comment correctly indicates that CustomPass channels require user-provided base URLs, which aligns with the customizable nature of this channel type. </details> <details> <summary>common/utils.go (1)</summary> `260-285`: **LGTM! Code formatting standardized.** The indentation has been standardized to use tabs instead of spaces, improving code consistency. The function logic remains unchanged. </details> <details> <summary>common/api_type.go (1)</summary> `66-67`: **LGTM! CustomPass channel type mapping added.** The new case correctly maps `ChannelTypeCustomPass` to `APITypeCustomPass`, following the established pattern for channel type to API type conversions. </details> <details> <summary>router/relay-router.go (1)</summary> `93-99`: **LGTM! CustomPass routing integration added.** The new `/pass` route group properly integrates the CustomPass channel into the API gateway with: - Appropriate middleware stack (TokenAuth, Distribute) consistent with other relay routes - Flexible `/*model` pattern supporting dynamic model names - Clean integration with the existing routing structure </details> <details> <summary>web/src/helpers/render.js (2)</summary> `58-58`: **LGTM: Clean import addition for CustomPass icon support** The import statement correctly adds the `CustomPassIcon` component that will be used for channel type 53. --- `417-418`: **LGTM: Proper integration of CustomPass channel icon** The implementation correctly follows the established pattern for channel icons, returning the `CustomPassIcon` component with the consistent `iconSize` parameter for channel type 53. </details> <details> <summary>controller/ratio_config.go (2)</summary> `3-8`: **LGTM: Clean import formatting** The import statement formatting improvements enhance code readability without affecting functionality. --- `10-24`: **LGTM: Consistent code formatting** The indentation and formatting improvements maintain the same logic while enhancing code readability. The function continues to properly check ratio exposure settings and return appropriate responses. </details> <details> <summary>middleware/auth.go (1)</summary> `249-252`: **LGTM: Proper token extraction for CustomPass support** The token extraction logic correctly: - Removes both "Bearer " and "sk-" prefixes consistently with existing patterns - Stores the full token in context at the appropriate point in the authentication flow - Follows the established middleware pattern for context data storage This enhancement properly supports the CustomPass authentication requirements. </details> <details> <summary>constant/task.go (1)</summary> `8-10`: **LGTM: Clean addition of new task platform constants** The new `TaskPlatform` constants are properly defined following the established naming convention and typing patterns. The `TaskPlatformCustomPass` constant correctly integrates with the broader CustomPass feature implementation. </details> <details> <summary>main.go (1)</summary> `110-115`: **LGTM: Proper CustomPass task polling service initialization** The service startup implementation correctly: - Retrieves the singleton service instance using the established pattern - Handles errors appropriately with consistent logging via `common.SysError` - Places the initialization in the correct location alongside other task services - Maintains non-blocking behavior suitable for the main initialization flow The integration aligns well with the broader CustomPass feature architecture. </details> <details> <summary>web/src/components/common/logo/CustomPassIcon.js (1)</summary> `23-46`: **LGTM! Clean icon component implementation.** The component is well-structured and follows React best practices. The SVG icon is properly sized and wrapped in the Semi UI Icon component. </details> <details> <summary>controller/task.go (1)</summary> `78-83`: **Good platform-specific handling for new task platforms.** The explicit handling of `TaskPlatformKling`, `TaskPlatformJimeng`, and `TaskPlatformCustomPass` is well-implemented. The CustomPass case correctly acknowledges that tasks are managed by the dedicated polling service, preventing unnecessary "unknown platform" warnings while maintaining system clarity. </details> <details> <summary>controller/ratio_sync.go (1)</summary> `1-475`: **Formatting changes only - no functional impact.** This file contains exclusively formatting changes (indentation and whitespace adjustments). All function logic, control flow, and behavior remain identical. No functional review required. </details> <details> <summary>web/src/components/table/task-logs/TaskLogsColumnDefs.js (3)</summary> `89-89`: **Function signature updated correctly for enhanced rendering.** The addition of the `record` parameter to `renderType` enables platform-specific rendering logic, which is properly utilized for CustomPass support. --- `116-123`: **Excellent CustomPass UI integration with consistent styling.** The CustomPass-specific rendering logic is well-implemented: - Uses consistent purple color and Sparkles icon across type and platform rendering - Shows the full model name for CustomPass types, which provides valuable information to users - Maintains proper conditional logic without affecting existing functionality Also applies to: 148-153 --- `291-291`: **Function call updated correctly to pass record parameter.** The call to `renderType` now properly includes the `record` parameter, enabling the new CustomPass-specific rendering functionality. </details> <details> <summary>model/ability.go (1)</summary> `322-330`: **LGTM! Well-implemented database query function.** The function correctly uses parameterized queries to prevent SQL injection and handles the enabled filter appropriately. The use of `DISTINCT` ensures no duplicate groups are returned. </details> <details> <summary>relay/channel/custompass/helper.go (1)</summary> `31-40`: **LGTM! Robust error handling and fallback logic.** The function properly handles user lookup failures and provides a sensible default ratio of 1.0. The logging helps with debugging and the delegation to `GetEffectiveUserRatio` maintains consistency. </details> <details> <summary>service/custompass_config_summary.md (1)</summary> `1-135`: **Excellent comprehensive documentation!** This documentation provides thorough coverage of the CustomPass configuration system including environment variables, validation rules, hot reload capabilities, and usage examples. The performance benchmarks and testing coverage information add valuable context for users and developers. </details> <details> <summary>.kiro/specs/custompass-channel/tasks.md (1)</summary> `1-138`: **Well-structured implementation plan with clear task breakdown.** The task list provides comprehensive coverage of the CustomPass implementation with clear requirement mappings and completion tracking. The organization by functional areas (authentication, billing, configuration, etc.) makes it easy to track progress and dependencies. </details> <details> <summary>model/task.go (2)</summary> `54-70`: **Well-designed billing context integration.** The addition of the optional `BillingInfo` field to the `Properties` struct is well-implemented: - Uses pointer with `omitempty` for backward compatibility - Comprehensive billing context fields with clear naming - Appropriate field types for different data (ratios, prices, modes) - Proper documentation with Chinese comments This design effectively supports the CustomPass billing requirements outlined in the PR objectives. --- `355-383`: **Solid task status update implementation.** The `UpdateTaskStatus` function is well-implemented with good practices: - Proper input validation (empty taskID handling) - Comprehensive status mapping covering various upstream status formats - Correct GORM usage with `Updates()` and proper field updates - Consistent timestamp management with `updated_at` - Appropriate error handling The status mappings align well with the CustomPass channel requirements for handling diverse upstream API status formats. </details> <details> <summary>.claude/commands/ask-with-data.md (3)</summary> `1-35`: **Excellent documentation and command structure.** The command documentation is comprehensive and well-structured: - Clear YAML frontmatter with appropriate tool permissions - Informative description of the assistant's capabilities - Practical usage examples covering various scenarios - Professional documentation that guides users effectively --- `51-74`: **Well-designed keyword detection system.** The keyword detection logic is thoughtfully implemented: - Effective case-insensitive regex matching - Good multilingual support (English and Chinese) - Logical keyword grouping for different query types - Reasonable fallback to general overview when no keywords are detected This approach should handle most user queries effectively while providing relevant database context. --- `76-106`: **Solid SQL query execution with good error handling.** The query execution logic is well-implemented: - Proper database file existence checks before executing queries - Good error handling with informative fallback messages - SQL queries are safe (no user input injection risks) - Queries are well-designed for their analytical purposes - Appropriate use of SQLite3 CLI with error redirection The predefined queries effectively support the various analysis scenarios outlined in the documentation. </details> <details> <summary>CLAUDE.md (3)</summary> `5-50`: **Comprehensive and accurate development guidance.** The development commands and architecture overview are well-documented: - Complete coverage of both backend (Go) and frontend (React) workflows - Accurate build commands and development server instructions - Clear architectural layer separation and component descriptions - Relevant key concepts that align with the system's design This documentation effectively guides developers through the codebase structure and development processes. --- `51-80`: **Accurate database and configuration documentation.** The database and configuration sections provide valuable information: - Correct database support details (SQLite default, MySQL/PostgreSQL production) - Relevant environment variables for development setup - Logical file organization structure - Helpful file references with specific line numbers for navigation The configuration guidance aligns well with the system's architecture and deployment requirements. --- `82-89`: **Good development principles aligned with PR objectives.** The development principles emphasize important practices: - Non-intrusive development approach for CustomPass features - Focus on maintaining compatibility with existing functionality - Clear context about current CustomPass development focus These principles align well with the PR objectives of implementing CustomPass as an independent, fully backward-compatible feature. </details> <details> <summary>docs/custompass/README.md (3)</summary> `1-47`: **Excellent comprehensive documentation structure.** The feature overview and quick start guide are well-crafted: - Clear explanation of CustomPass as a transparent API proxy - Comprehensive feature list aligning with the PR objectives - Practical step-by-step setup instructions - Good explanation of sync vs async model naming conventions The documentation effectively introduces users to the CustomPass functionality and provides actionable setup guidance. --- `48-77`: **Clear and practical usage examples.** The API usage examples are well-designed: - Proper curl syntax with correct HTTP headers and JSON structure - Good demonstration of both synchronous and asynchronous usage patterns - Realistic example data that illustrates the differences between modes - Appropriate use of placeholder credentials for documentation Note: The static analysis warnings about authorization tokens are false positives - these are documentation examples with placeholder values, not actual credentials. --- `78-100`: **Well-organized documentation structure and clear architecture overview.** The documentation structure is comprehensive and user-friendly: - Complete cross-references to related documentation files - Clear architecture diagram illustrating the request flow - Appropriate support channels and troubleshooting resources - Good integration with the broader documentation ecosystem The simple ASCII diagram effectively communicates the system's request processing flow including precharge, upstream interaction, and billing settlement. </details> <details> <summary>relay/channel/custompass/constants.go (3)</summary> `3-18`: **Well-defined channel constants with reasonable defaults.** The channel definition and default configuration are well-structured: - Clear channel name that aligns with the feature branding - Appropriate empty model list for a dynamically configured channel - Reasonable default values for timeouts, concurrency, and polling intervals - Self-documenting constant names with clear purposes The default values appear well-balanced for production use while allowing for customization through environment variables. --- `20-31`: **Consistent and clear environment variable naming.** The environment variable keys follow good conventions: - Consistent `CUSTOM_PASS_` prefix for easy identification and namespacing - Complete coverage of all configurable default values - Clear, descriptive names that match their corresponding constants - Good organization separating operational and status mapping variables This design enables flexible configuration while maintaining clear naming standards. --- `33-38`: **Comprehensive status mappings for upstream API compatibility.** The default status mappings are well-designed for broad API compatibility: - Logical grouping into success, failure, and processing states - Comprehensive coverage of common status variations from different APIs - Good handling of edge cases (e.g., "not_found" as failure, "submitted" as processing) - Flexible string slice format allows for easy extension and customization These mappings should effectively handle status translation from diverse upstream APIs while providing clear categorization for the system's internal processing. </details> <details> <summary>docs/custompass/API.md (1)</summary> `1-583`: **Excellent API documentation!** The CustomPass API documentation is comprehensive, well-structured, and includes: - Clear explanations of sync/async modes - Detailed request/response formats - Authentication mechanisms - Billing models and flows - Error handling with examples - Best practices with code samples in multiple languages - Monitoring and debugging guidance This provides excellent developer experience for API consumers. </details> <details> <summary>relay/channel/custompass/sync_adaptor.go (2)</summary> `122-247`: **Well-implemented response processing with comprehensive error handling** The response processing logic is thorough: - Properly handles error cases with refunds - Includes fallback logic for price data retrieval - Comprehensive consumption logging for monitoring - Correct settlement logic for billing differences --- `250-272`: **Good defensive programming for test environments** The method properly handles the case where the database might be nil in test environments, and provides a reasonable heuristic for determining billing requirements. </details> <details> <summary>docs/custompass/CONFIGURATION.md (1)</summary> `501-501`: **Current Chinese grammar is correct** The phrase "设置适当的并发限制" is grammatically correct. Here "适当的" (appropriate) modifies the noun phrase "并发限制" (concurrency limit), not a verb, so "的" is the correct particle to use. </details> <details> <summary>relay/channel/custompass/polling_service.go (5)</summary> `64-134`: **Well-structured service initialization with proper configuration loading** The polling service initialization properly: - Loads and validates configuration from environment variables - Sets appropriate HTTP client timeout - Initializes concurrency control with semaphore - Creates necessary service dependencies --- `305-347`: **Robust batch processing with proper error isolation** The channel task processing correctly: - Validates channel status before processing - Groups tasks by model for efficient batch queries - Continues processing other batches even if one fails - Properly handles disabled channels Good design choice to isolate batch failures. --- `349-496`: **Complex but well-implemented task querying logic** The implementation effectively handles: - Token extraction from task properties with error handling - Efficient grouping by client token - Proper URL construction for model-specific endpoints - Comprehensive debug logging for troubleshooting - Correct header management for authentication The complexity is justified by the need to handle different authentication contexts. --- `620-685`: **Correct and resilient billing settlement implementation** The task completion handling excellently: - Calculates actual usage-based billing with proper ratios - Gracefully handles billing calculation errors without failing completion - Performs accurate settlement between precharge and actual amounts - Includes comprehensive debug logging for troubleshooting - Updates task records with actual quota Good design choice to continue task completion even if billing operations fail. --- `220-239`: **Proper concurrent processing with semaphore control** The implementation correctly manages concurrency: - Processes channels in parallel with proper synchronization - Semaphore prevents resource exhaustion - Proper error isolation between channels - Clean goroutine lifecycle management </details> <details> <summary>relay/channel/custompass/error_handler.go (3)</summary> `48-83`: **Comprehensive error classification with proper fallback** The error classification effectively: - Covers all major error categories - Uses proper error unwrapping with errors.Is - Delegates to specialized handlers for complex error types - Provides sensible fallback to system error --- `246-272`: **Robust panic recovery with proper error handling** The panic recovery implementation: - Handles all panic types appropriately - Includes request context for debugging - Returns structured error responses - Properly aborts request processing Excellent defensive programming practice. --- `284-313`: **Comprehensive upstream error handling with detailed context** The upstream error handler excellently: - Maps all common HTTP status codes to appropriate error types - Preserves upstream response body for debugging - Provides clear error messages in Chinese - Maintains proper error categorization </details> <details> <summary>relay/channel/custompass/logger.go (1)</summary> `139-145`: **Well-implemented security practice for header logging.** The code properly redacts sensitive authentication headers before logging, which is a good security practice. </details> <details> <summary>start.sh (6)</summary> `636-681`: **Well-structured main function with comprehensive command handling.** The main function properly parses arguments and dispatches to appropriate handlers. Good use of case statement and error handling. --- `89-108`: **Well-implemented port checking utilities** The port checking and process information functions are properly implemented with good error handling and appropriate use of system tools like `lsof` and `ps`. The null redirects prevent unwanted output while maintaining functionality. --- `110-210`: **Excellent port conflict resolution system** The port conflict handling is comprehensive and user-friendly, providing multiple resolution options with clear prompts. The intelligent port scanning, graceful process termination, and input validation demonstrate good design practices. --- `248-336`: **Good script management utilities with safety features** The script synchronization functions include proper safety checks, backup mechanisms, and clear user feedback. The decision to disable auto-update prevents unwanted overwrites during development. --- `444-466`: **Well-integrated service startup function** The service startup function effectively combines environment setup, port conflict resolution, and service execution with appropriate fallbacks and error handling. --- `510-634`: **Consistent mock server implementation** The mock server functionality follows the same patterns as the main service, with appropriate port conflict handling, flexible execution options, and clear user feedback. The URL output is particularly helpful for development. </details> <details> <summary>CustomPass开发文档.md (1)</summary> `1-1950`: **Comprehensive and well-structured CustomPass development documentation.** This documentation provides excellent coverage of: - System architecture with clear flow diagrams - Detailed billing mechanisms with calculation examples - Comprehensive error handling strategies - Complete API specifications - Configuration management with hot reload support The documentation will be invaluable for developers implementing and maintaining the CustomPass channel. </details> <details> <summary>.kiro/specs/custompass-channel/requirements.md (1)</summary> `1-118`: **Well-structured requirements document with clear acceptance criteria.** The requirements document effectively captures all aspects of the CustomPass channel: - Clear user stories for each feature - Comprehensive WHEN/THEN acceptance criteria - Covers all major functionality: sync/async modes, precharge, billing, auth, polling, error handling, and configuration - Testable and measurable criteria This provides an excellent foundation for development and testing. </details> <details> <summary>relay/channel/custompass/dto.go (2)</summary> `9-108`: **Well-designed DTOs with comprehensive validation and compatibility support.** The UpstreamResponse and Usage structs are excellently designed: - Flexible code type handling for different upstream APIs - Smart message retrieval with fallback - Comprehensive token usage tracking with compatibility fields - Thorough validation ensuring data integrity Great attention to API compatibility and error handling. --- `192-337`: **Robust configuration management and utility functions.** The configuration structures and utility functions demonstrate good practices: - Sensible default values for all configuration parameters - Comprehensive validation with clear error messages - Proper error wrapping maintaining error context - Clean separation of concerns The code is production-ready with excellent error handling. </details> <details> <summary>service/custompass_precharge.go (1)</summary> `119-324`: **Excellent implementation of precharge with comprehensive safeguards.** The ExecutePrecharge method demonstrates production-quality code: - Detailed logging for debugging and audit trails - Per-user locking prevents race conditions - Comprehensive input validation - Smart retry mechanism for transient failures - Clear separation of billing modes - Proper error handling with meaningful error codes The implementation is robust and production-ready. </details> <details> <summary>relay/channel/custompass/adaptor.go (4)</summary> `164-276`: **Well-implemented two-request mode with proper fallback logic** The implementation correctly handles the two-request flow with: - Proper validation of precharge response - Smart fallback to precharge usage when real response lacks usage data - Appropriate refund handling on failure - Comprehensive debug logging for troubleshooting --- `278-382`: **Comprehensive handling of different billing modes** The single request mode implementation correctly handles all billing scenarios: - Proper validation of usage data for usage-based models - Appropriate fixed-price billing with minimal usage - Free model support without charges - Good error handling and logging --- `412-505`: **Robust HTTP request implementation** The upstream request handling is well-implemented with: - Proper timeout context (30s) - Comprehensive header management - Detailed request/response logging for debugging - Proper error wrapping with CustomPassError - Response validation --- `507-529`: **Good handling of test and production environments** The billing check implementation: - Properly handles nil DB in test environments - Uses reasonable heuristic for test mode (models with "free" in name) - Correctly queries ability table in production - Appropriate error handling </details> <details> <summary>service/custompass_task_polling.go (3)</summary> `255-309`: **Excellent timeout handling with comprehensive refund logic** The timeout detection and handling implementation: - Properly detects tasks exceeding 1-hour timeout - Correctly marks tasks as failed with detailed timeout information - Implements refund logic consistent with the billing system - Good logging for audit trail --- `400-495`: **Efficient task batching with proper token handling** The channel task processing: - Smart grouping by model and client token for optimal batch queries - Correctly extracts and uses client-specific headers - Proper error handling for each batch - Good separation of concerns --- `581-716`: **Clever two-pass processing ensures accurate refunds** The implementation uses a smart two-pass approach: 1. First pass handles failed tasks immediately to preserve original quota for refunds 2. Second pass handles other status updates and successful completions This design prevents any potential issues with quota modifications affecting refund amounts. </details> <details> <summary>.kiro/specs/custompass-channel/design.md (2)</summary> `170-204`: **Excellent transaction boundary design for precharge** The precharge service implementation shows proper database transaction handling: - User record locking to prevent race conditions - Proper rollback on errors - Clear step-by-step processing - Atomic operations for quota management --- `483-510`: **Well-designed Usage structure with good compatibility** The Usage structure design: - Handles multiple token naming conventions (prompt_tokens vs input_tokens) - Includes validation logic - Supports advanced billing features (cache hits, multi-modal tokens) - Provides compatibility methods for different formats </details> <details> <summary>web/src/components/table/channels/modals/EditChannelModal.jsx (6)</summary> `1099-1126`: **Excellent implementation of CustomPass-specific UI elements** The informational banner and custom token header field are well-implemented, following established patterns in the codebase. The banner provides clear guidance on CustomPass features, and the input field includes appropriate help text explaining environment variable precedence. --- `1229-1229`: **Correct conditional exclusion for CustomPass** Properly excludes CustomPass (type 53) from the generic API configuration section, following the established pattern for other specialized channel types. --- `1266-1278`: **Well-implemented CustomPass API configuration** The upstream API address field is properly implemented with required validation, clear placeholder text, and helpful guidance. This follows the established pattern for specialized channel configurations. --- `1295-1310`: **Excellent user guidance for CustomPass model configuration** The informational banner provides clear, actionable guidance on CustomPass model configuration, explaining the distinction between synchronous and asynchronous models and the naming convention requirements. This significantly improves the user experience. --- `1363-1363`: **Good contextual customization for model input field** The conditional placeholder and help text provide CustomPass-specific guidance while maintaining compatibility with other channel types. The examples clearly demonstrate the naming conventions for synchronous and asynchronous models. Also applies to: 1371-1371 --- `1402-1419`: **Valuable configuration precedence documentation** The banner effectively explains CustomPass configuration priority rules, helping users understand how environment variables, channel settings, and defaults interact. This in-context documentation significantly improves usability. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
!echo "🔍 Auto-discovering database configuration..." && \ | ||
DB_TYPE="" && DB_CONNECTION="" && \ | ||
if [ -f "config.yaml" ] || [ -f "config.yml" ]; then echo "📁 Found YAML config file"; fi && \ | ||
if [ -f "config.json" ]; then echo "📁 Found JSON config file"; fi && \ | ||
if [ -f ".env" ]; then echo "📁 Found .env file"; source .env 2>/dev/null; fi && \ | ||
if [ -f "application.properties" ]; then echo "📁 Found Spring properties file"; fi && \ | ||
if [ -f "go.mod" ]; then echo "📁 Found Go project"; fi && \ | ||
if [ -f "data/new-api.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./data/new-api.db"; \ | ||
elif [ -f "database.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./database.db"; \ | ||
elif [ -f "app.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./app.db"; \ | ||
else DB_TYPE="sqlite"; DB_CONNECTION="./data/new-api.db"; fi && \ | ||
echo "✅ Database type: $DB_TYPE" && echo "✅ Connection: $DB_CONNECTION" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve database discovery robustness.
The database discovery logic has some limitations:
- Hardcoded SQLite paths may not work in all environments
- Always defaults to
./data/new-api.db
even if the file doesn't exist - Limited to SQLite despite checking for other config file types
Consider enhancing the discovery logic:
-if [ -f "data/new-api.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./data/new-api.db"; \
-elif [ -f "database.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./database.db"; \
-elif [ -f "app.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./app.db"; \
-else DB_TYPE="sqlite"; DB_CONNECTION="./data/new-api.db"; fi && \
+for db_path in "./data/new-api.db" "./database.db" "./app.db"; do \
+ if [ -f "$db_path" ]; then DB_TYPE="sqlite"; DB_CONNECTION="$db_path"; break; fi; \
+done && \
+if [ -z "$DB_CONNECTION" ]; then echo "❌ No SQLite database found"; exit 1; fi && \
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
!echo "🔍 Auto-discovering database configuration..." && \ | |
DB_TYPE="" && DB_CONNECTION="" && \ | |
if [ -f "config.yaml" ] || [ -f "config.yml" ]; then echo "📁 Found YAML config file"; fi && \ | |
if [ -f "config.json" ]; then echo "📁 Found JSON config file"; fi && \ | |
if [ -f ".env" ]; then echo "📁 Found .env file"; source .env 2>/dev/null; fi && \ | |
if [ -f "application.properties" ]; then echo "📁 Found Spring properties file"; fi && \ | |
if [ -f "go.mod" ]; then echo "📁 Found Go project"; fi && \ | |
if [ -f "data/new-api.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./data/new-api.db"; \ | |
elif [ -f "database.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./database.db"; \ | |
elif [ -f "app.db" ]; then DB_TYPE="sqlite"; DB_CONNECTION="./app.db"; \ | |
else DB_TYPE="sqlite"; DB_CONNECTION="./data/new-api.db"; fi && \ | |
echo "✅ Database type: $DB_TYPE" && echo "✅ Connection: $DB_CONNECTION" | |
!echo "🔍 Auto-discovering database configuration..." && \ | |
DB_TYPE="" && DB_CONNECTION="" && \ | |
if [ -f "config.yaml" ] || [ -f "config.yml" ]; then echo "📁 Found YAML config file"; fi && \ | |
if [ -f "config.json" ]; then echo "📁 Found JSON config file"; fi && \ | |
if [ -f ".env" ]; then echo "📁 Found .env file"; source .env 2>/dev/null; fi && \ | |
if [ -f "application.properties" ]; then echo "📁 Found Spring properties file"; fi && \ | |
if [ -f "go.mod" ]; then echo "📁 Found Go project"; fi && \ | |
for db_path in "./data/new-api.db" "./database.db" "./app.db"; do \ | |
if [ -f "$db_path" ]; then DB_TYPE="sqlite"; DB_CONNECTION="$db_path"; break; fi; \ | |
done && \ | |
if [ -z "$DB_CONNECTION" ]; then echo "❌ No SQLite database found"; exit 1; fi && \ | |
echo "✅ Database type: $DB_TYPE" && echo "✅ Connection: $DB_CONNECTION" |
🤖 Prompt for AI Agents
In .claude/commands/ask-with-data.md around lines 38 to 49, the database
discovery script currently hardcodes SQLite file paths and defaults to a path
even if the file does not exist, limiting robustness and flexibility. Update the
logic to dynamically detect existing database files rather than assuming
defaults, verify file existence before setting DB_CONNECTION, and consider
extending support beyond SQLite by parsing detected config files (YAML, JSON,
.env, etc.) to identify other database types and connection details. This will
make the discovery process more reliable and adaptable to different
environments.
cc_launcher.sh
Outdated
# 下载并更新脚本 | ||
update_script() { | ||
local script_path="$0" | ||
local temp_file=$(mktemp) | ||
|
||
print_info "正在下载最新版本..." | ||
|
||
# 下载最新版本到临时文件(带loading动画) | ||
local download_result=$(curl_with_loading "$REMOTE_SCRIPT_URL" "正在下载最新版本..." 10 30) | ||
|
||
if [[ -n "$download_result" ]]; then | ||
echo "$download_result" > "$temp_file" | ||
|
||
# 验证下载的文件是否是有效的 bash 脚本 | ||
if bash -n "$temp_file" 2>/dev/null; then | ||
# 获取原文件权限 | ||
local file_perms=$(stat -f "%A" "$script_path" 2>/dev/null || stat -c "%a" "$script_path" 2>/dev/null) | ||
|
||
# 原子操作:替换文件 | ||
if mv "$temp_file" "$script_path"; then | ||
# 恢复执行权限 | ||
chmod "$file_perms" "$script_path" 2>/dev/null || chmod +x "$script_path" | ||
print_success "脚本更新成功!" | ||
print_info "正在重新启动脚本..." | ||
echo "" | ||
|
||
# 重新启动脚本 | ||
exec "$script_path" "$@" | ||
else | ||
print_error "更新失败:无法替换脚本文件" | ||
rm -f "$temp_file" | ||
return 1 | ||
fi | ||
else | ||
print_error "更新失败:下载的文件不是有效的脚本" | ||
rm -f "$temp_file" | ||
return 1 | ||
fi | ||
else | ||
print_error "更新失败:无法下载最新版本" | ||
rm -f "$temp_file" | ||
return 1 | ||
fi | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add integrity verification for auto-updates
The auto-update mechanism downloads and executes scripts from a remote URL without integrity verification. This poses a security risk if the remote server is compromised.
Add checksum verification:
# 下载并更新脚本
update_script() {
local script_path="$0"
local temp_file=$(mktemp)
+ local checksum_url="${REMOTE_SCRIPT_URL}.sha256"
print_info "正在下载最新版本..."
+ # Download checksum first
+ local expected_checksum=$(curl -s "$checksum_url" | cut -d' ' -f1)
+ if [ -z "$expected_checksum" ]; then
+ print_error "无法获取校验和"
+ return 1
+ fi
+
# 下载最新版本到临时文件(带loading动画)
local download_result=$(curl_with_loading "$REMOTE_SCRIPT_URL" "正在下载最新版本..." 10 30)
if [[ -n "$download_result" ]]; then
echo "$download_result" > "$temp_file"
+ # Verify checksum
+ local actual_checksum=$(sha256sum "$temp_file" | cut -d' ' -f1)
+ if [ "$actual_checksum" != "$expected_checksum" ]; then
+ print_error "校验和验证失败"
+ rm -f "$temp_file"
+ return 1
+ fi
+
# 验证下载的文件是否是有效的 bash 脚本
if bash -n "$temp_file" 2>/dev/null; then
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
# 下载并更新脚本 | |
update_script() { | |
local script_path="$0" | |
local temp_file=$(mktemp) | |
print_info "正在下载最新版本..." | |
# 下载最新版本到临时文件(带loading动画) | |
local download_result=$(curl_with_loading "$REMOTE_SCRIPT_URL" "正在下载最新版本..." 10 30) | |
if [[ -n "$download_result" ]]; then | |
echo "$download_result" > "$temp_file" | |
# 验证下载的文件是否是有效的 bash 脚本 | |
if bash -n "$temp_file" 2>/dev/null; then | |
# 获取原文件权限 | |
local file_perms=$(stat -f "%A" "$script_path" 2>/dev/null || stat -c "%a" "$script_path" 2>/dev/null) | |
# 原子操作:替换文件 | |
if mv "$temp_file" "$script_path"; then | |
# 恢复执行权限 | |
chmod "$file_perms" "$script_path" 2>/dev/null || chmod +x "$script_path" | |
print_success "脚本更新成功!" | |
print_info "正在重新启动脚本..." | |
echo "" | |
# 重新启动脚本 | |
exec "$script_path" "$@" | |
else | |
print_error "更新失败:无法替换脚本文件" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
else | |
print_error "更新失败:下载的文件不是有效的脚本" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
else | |
print_error "更新失败:无法下载最新版本" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
} | |
# 下载并更新脚本 | |
update_script() { | |
local script_path="$0" | |
local temp_file=$(mktemp) | |
local checksum_url="${REMOTE_SCRIPT_URL}.sha256" | |
print_info "正在下载最新版本..." | |
# Download checksum first | |
local expected_checksum=$(curl -s "$checksum_url" | cut -d' ' -f1) | |
if [ -z "$expected_checksum" ]; then | |
print_error "无法获取校验和" | |
return 1 | |
fi | |
# 下载最新版本到临时文件(带loading动画) | |
local download_result=$(curl_with_loading "$REMOTE_SCRIPT_URL" "正在下载最新版本..." 10 30) | |
if [[ -n "$download_result" ]]; then | |
echo "$download_result" > "$temp_file" | |
# Verify checksum | |
local actual_checksum=$(sha256sum "$temp_file" | cut -d' ' -f1) | |
if [ "$actual_checksum" != "$expected_checksum" ]; then | |
print_error "校验和验证失败" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
# 验证下载的文件是否是有效的 bash 脚本 | |
if bash -n "$temp_file" 2>/dev/null; then | |
# 获取原文件权限 | |
local file_perms=$(stat -f "%A" "$script_path" 2>/dev/null || stat -c "%a" "$script_path" 2>/dev/null) | |
# 原子操作:替换文件 | |
if mv "$temp_file" "$script_path"; then | |
# 恢复执行权限 | |
chmod "$file_perms" "$script_path" 2>/dev/null || chmod +x "$script_path" | |
print_success "脚本更新成功!" | |
print_info "正在重新启动脚本..." | |
echo "" | |
# 重新启动脚本 | |
exec "$script_path" "$@" | |
else | |
print_error "更新失败:无法替换脚本文件" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
else | |
print_error "更新失败:下载的文件不是有效的脚本" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
else | |
print_error "更新失败:无法下载最新版本" | |
rm -f "$temp_file" | |
return 1 | |
fi | |
} |
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 483-483: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 488-488: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 496-496: Declare and assign separately to avoid masking return values.
(SC2155)
🤖 Prompt for AI Agents
In cc_launcher.sh around lines 480 to 523, the update_script function downloads
and replaces the script without verifying its integrity, which is a security
risk. To fix this, add a checksum verification step after downloading the script
and before replacing the original file. Fetch a trusted checksum (e.g., from a
separate secure URL or embedded signature), compute the checksum of the
downloaded file, and compare them. Only proceed with replacing the script if the
checksums match; otherwise, abort the update and clean up the temporary file.
cc_launcher.sh
Outdated
read -p "请输入完整的 Claude Code 启动命令: " custom_command | ||
|
||
if [[ -n "$custom_command" ]]; then | ||
print_info "执行自定义命令: $custom_command" | ||
eval "$custom_command" | ||
else | ||
print_error "命令不能为空,使用默认 YOLO 模式..." | ||
claude --dangerously-skip-permissions | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid using eval with user input
Using eval
to execute user-provided commands is a security risk as it can execute arbitrary code.
Instead of eval, execute the command directly:
if [[ -n "$custom_command" ]]; then
print_info "执行自定义命令: $custom_command"
- eval "$custom_command"
+ # Parse the command safely
+ $custom_command
else
Or better yet, validate the command first:
if [[ -n "$custom_command" ]]; then
+ # Validate that the command starts with 'claude'
+ if [[ ! "$custom_command" =~ ^claude[[:space:]] ]]; then
+ print_error "自定义命令必须以 'claude' 开头"
+ exit 1
+ fi
print_info "执行自定义命令: $custom_command"
- eval "$custom_command"
+ $custom_command
else
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
read -p "请输入完整的 Claude Code 启动命令: " custom_command | |
if [[ -n "$custom_command" ]]; then | |
print_info "执行自定义命令: $custom_command" | |
eval "$custom_command" | |
else | |
print_error "命令不能为空,使用默认 YOLO 模式..." | |
claude --dangerously-skip-permissions | |
fi | |
read -p "请输入完整的 Claude Code 启动命令: " custom_command | |
if [[ -n "$custom_command" ]]; then | |
# Validate that the command starts with 'claude' | |
if [[ ! "$custom_command" =~ ^claude[[:space:]] ]]; then | |
print_error "自定义命令必须以 'claude' 开头" | |
exit 1 | |
fi | |
print_info "执行自定义命令: $custom_command" | |
$custom_command | |
else | |
print_error "命令不能为空,使用默认 YOLO 模式..." | |
claude --dangerously-skip-permissions | |
fi |
🤖 Prompt for AI Agents
In cc_launcher.sh around lines 874 to 882, avoid using eval to execute user
input as it poses a security risk. Instead, execute the user-provided command
directly without eval by running it as a command string or array. Additionally,
implement validation to ensure the command is safe and allowed before execution
to prevent arbitrary code execution.
@@ -30,6 +30,7 @@ const ( | |||
APITypeXinference | |||
APITypeXai | |||
APITypeCoze | |||
APITypeCustomPass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
LGTM: Constant properly added to enumeration
The APITypeCustomPass
constant is correctly positioned in the iota-based enumeration, maintaining the sequential nature of the API type constants.
Please verify that the iota-generated value for APITypeCustomPass
matches the value 53
used in the frontend channel constants. Run this script to check the actual constant values:
🏁 Script executed:
#!/bin/bash
# Description: Verify the APITypeCustomPass constant value matches frontend expectations
# Expected: APITypeCustomPass should correspond to value 53 used in channel.constants.js
# Search for APITypeCustomPass usage and any value mappings
ast-grep --pattern 'APITypeCustomPass'
# Look for any constant-to-value mappings or tests that might reveal the actual values
rg -A 5 -B 5 "APITypeCustomPass|APIType.*53"
Length of output: 1583
🏁 Script executed:
#!/bin/bash
# Extract the iota-based enumeration from constant/api_type.go
sed -n '/^const (/,/^)/p' constant/api_type.go
Length of output: 638
Mismatch Detected: Back-end APITypeCustomPass = 29 vs Front-end Channel Constant = 53
I ran sed
on constant/api_type.go and confirmed that with iota starting at 0, APITypeCustomPass is assigned value 29—not 53. You’ll need to reconcile this with the front-end’s expectation.
• Option A: Explicitly assign
APITypeCustomPass = 53
and update subsequent constants (or switch to manual values)
• Option B: Adjust the front-end channel.constants.js to use 29
Please choose and implement the appropriate fix so both sides remain in sync.
🤖 Prompt for AI Agents
In constant/api_type.go at line 33, the constant APITypeCustomPass is assigned
the value 29 by iota, but the front-end expects it to be 53. To fix this
mismatch, explicitly assign APITypeCustomPass the value 53 in the Go file and
update any subsequent constants accordingly to maintain correct values, ensuring
both back-end and front-end constants are synchronized.
urlRegex = regexp.MustCompile(`^https?://(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(?:\:[0-9]{1,5})?(?:/.*)?$`) | ||
dangerousChars = []string{"<script", "<iframe", "javascript:", "onload=", "onerror=", "onclick="} | ||
validColors = map[string]bool{ | ||
"blue": true, "green": true, "cyan": true, "purple": true, "pink": true, | ||
"red": true, "orange": true, "amber": true, "yellow": true, "lime": true, | ||
"light-green": true, "teal": true, "light-blue": true, "indigo": true, | ||
"violet": true, "grey": true, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Lower-case color before lookup to avoid false negatives
At run-time front-end config values may arrive in mixed-case (e.g. "Blue"
), but the lookup in validColors
is case–sensitive. A single wrong-cased character will currently be rejected even though it is a legitimate color.
- if !validColors[color] {
+ if !validColors[strings.ToLower(color)] {
return fmt.Errorf("第%d个API信息的颜色值不合法", i+1)
}
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In setting/console_setting/validation.go around lines 14 to 21, the validColors
map lookup is case-sensitive, causing legitimate colors with different casing
(e.g., "Blue") to be rejected. To fix this, convert the input color string to
lower-case before checking its presence in the validColors map, ensuring
case-insensitive validation.
print_message $BLUE "设置环境变量..." | ||
|
||
# 设置SQLite数据库文件路径 | ||
# export SQLITE_PATH="../one-api.db" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove reference to undefined SQLITE_PATH variable.
The SQLITE_PATH export is commented out but is still referenced in the print statement, which will print an empty value.
Either uncomment the export or remove the print statement:
- # export SQLITE_PATH="../one-api.db"
+ export SQLITE_PATH="../one-api.db"
Or remove the print statement:
- print_message $YELLOW "SQLite数据库文件路径: $SQLITE_PATH"
Also applies to: 84-84
🤖 Prompt for AI Agents
In start.sh at lines 72 and 84, the print statements reference the SQLITE_PATH
variable which is commented out and thus undefined, resulting in empty output.
To fix this, either uncomment the export of SQLITE_PATH to define it properly or
remove the print statements that reference SQLITE_PATH to avoid printing an
empty value.
# 获取占用端口的进程信息 | ||
get_port_process_info() { | ||
local port=$1 | ||
local pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Declare and assign variables separately to avoid masking return values.
Shellcheck correctly identifies that declaring and assigning on the same line can mask command failures.
Apply these fixes:
- local pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1)
+ local pid
+ pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1)
- local process_name=$(ps -p $pid -o comm= 2>/dev/null)
- local process_args=$(ps -p $pid -o args= 2>/dev/null)
+ local process_name
+ local process_args
+ process_name=$(ps -p $pid -o comm= 2>/dev/null)
+ process_args=$(ps -p $pid -o args= 2>/dev/null)
And similarly for line 146:
- local pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1)
+ local pid
+ pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null | head -1)
Also applies to: 103-104, 146-146
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 101-101: Declare and assign separately to avoid masking return values.
(SC2155)
🤖 Prompt for AI Agents
In start.sh at lines 101, 103-104, and 146, the code declares and assigns
variables in the same line, which can mask command failures. To fix this,
separate the declaration and assignment by first declaring the variable without
assignment, then assign the command output on the next line. This ensures that
any command failure is not masked and can be properly detected.
print_message $BLUE "编译前端..." | ||
|
||
if [ -d "web" ]; then | ||
cd web |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for cd commands.
If cd
fails, the script continues execution in the wrong directory, which could cause unexpected behavior.
Use cd ... || return
pattern:
- cd web
+ cd web || return 1
- cd ..
+ cd .. || return 1
- cd test
+ cd test || return 1
- cd ..
+ cd .. || return 1
Also applies to: 418-418, 605-605, 633-633
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 384-384: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🤖 Prompt for AI Agents
In start.sh at lines 384, 418, 605, and 633, the cd commands lack error
handling, so if they fail, the script continues in the wrong directory. Update
each cd command to use the pattern cd <directory> || return to ensure the script
stops or returns on failure, preventing further execution in an incorrect
directory.
Fix directory changes without error checking
The cd
commands should include error handling to prevent script continuation if directory change fails.
Apply this fix:
- cd web
+ cd web || { print_message $RED "无法进入 web 目录"; return 1; }
- cd test
+ cd test || { print_message $RED "无法进入 test 目录"; return 1; }
Also applies to: 605-605
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 384-384: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🤖 Prompt for AI Agents
In start.sh at lines 384 and 605, the cd commands lack error checking, which can
cause the script to continue running even if the directory change fails. Modify
these cd commands to include error handling by appending '|| exit 1' after each
cd command to stop the script if the directory change is unsuccessful.
curl -X POST "http://localhost:3000/v1/chat/completions" \ | ||
-H "Authorization: Bearer sk-2LjhL4kdZMjxBVF4IJokP8rIdTwGWAdLBuIJci80PDxJ1m3c" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove or mask the authorization token in documentation.
The curl command contains a real authorization token that could compromise security if this documentation is shared publicly.
-curl -X POST "http://localhost:3000/v1/chat/completions" \
- -H "Authorization: Bearer sk-2LjhL4kdZMjxBVF4IJokP8rIdTwGWAdLBuIJci80PDxJ1m3c" \
+curl -X POST "http://localhost:3000/v1/chat/completions" \
+ -H "Authorization: Bearer sk-YOUR_API_KEY_HERE" \
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
curl -X POST "http://localhost:3000/v1/chat/completions" \ | |
-H "Authorization: Bearer sk-2LjhL4kdZMjxBVF4IJokP8rIdTwGWAdLBuIJci80PDxJ1m3c" \ | |
curl -X POST "http://localhost:3000/v1/chat/completions" \ | |
-H "Authorization: Bearer sk-YOUR_API_KEY_HERE" \ |
🧰 Tools
🪛 Gitleaks (8.27.2)
36-37: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🤖 Prompt for AI Agents
In verify_billing_fix.md around lines 36 to 37, the curl command includes a real
authorization token which poses a security risk. Replace the actual token with a
placeholder like "YOUR_API_KEY" or mask it to prevent exposing sensitive
credentials in the documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
// Usage represents token usage information (imported from custompass package) | ||
type Usage struct { | ||
PromptTokens int `json:"prompt_tokens"` | ||
CompletionTokens int `json:"completion_tokens"` | ||
TotalTokens int `json:"total_tokens"` | ||
InputTokens int `json:"input_tokens,omitempty"` | ||
OutputTokens int `json:"output_tokens,omitempty"` | ||
} | ||
|
||
// Validate validates the usage information | ||
func (u *Usage) Validate() error { | ||
if u.PromptTokens < 0 || u.CompletionTokens < 0 || u.TotalTokens < 0 { | ||
return errors.New("token数量不能为负数") | ||
} | ||
if u.TotalTokens != u.PromptTokens+u.CompletionTokens { | ||
return errors.New("总token数量与输入输出token数量之和不匹配") | ||
} | ||
return nil | ||
} | ||
|
||
// GetInputTokens returns compatible input token count | ||
func (u *Usage) GetInputTokens() int { | ||
if u.InputTokens > 0 { | ||
return u.InputTokens | ||
} | ||
return u.PromptTokens | ||
} | ||
|
||
// GetOutputTokens returns compatible output token count | ||
func (u *Usage) GetOutputTokens() int { | ||
if u.OutputTokens > 0 { | ||
return u.OutputTokens | ||
} | ||
return u.CompletionTokens | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate Usage struct definition.
The Usage struct is already defined in relay/channel/custompass/dto.go
. Having duplicate definitions can lead to maintenance issues and confusion.
Import and use the Usage struct from the custompass package:
+import (
+ "one-api/relay/channel/custompass"
+ // ... other imports
+)
-// Usage represents token usage information (imported from custompass package)
-type Usage struct {
- PromptTokens int `json:"prompt_tokens"`
- CompletionTokens int `json:"completion_tokens"`
- TotalTokens int `json:"total_tokens"`
- InputTokens int `json:"input_tokens,omitempty"`
- OutputTokens int `json:"output_tokens,omitempty"`
-}
-
-// Validate validates the usage information
-func (u *Usage) Validate() error {
- // ... validation code
-}
-
-// GetInputTokens returns compatible input token count
-func (u *Usage) GetInputTokens() int {
- // ... method code
-}
-
-// GetOutputTokens returns compatible output token count
-func (u *Usage) GetOutputTokens() int {
- // ... method code
-}
+// Use custompass.Usage instead
+type Usage = custompass.Usage
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Usage represents token usage information (imported from custompass package) | |
type Usage struct { | |
PromptTokens int `json:"prompt_tokens"` | |
CompletionTokens int `json:"completion_tokens"` | |
TotalTokens int `json:"total_tokens"` | |
InputTokens int `json:"input_tokens,omitempty"` | |
OutputTokens int `json:"output_tokens,omitempty"` | |
} | |
// Validate validates the usage information | |
func (u *Usage) Validate() error { | |
if u.PromptTokens < 0 || u.CompletionTokens < 0 || u.TotalTokens < 0 { | |
return errors.New("token数量不能为负数") | |
} | |
if u.TotalTokens != u.PromptTokens+u.CompletionTokens { | |
return errors.New("总token数量与输入输出token数量之和不匹配") | |
} | |
return nil | |
} | |
// GetInputTokens returns compatible input token count | |
func (u *Usage) GetInputTokens() int { | |
if u.InputTokens > 0 { | |
return u.InputTokens | |
} | |
return u.PromptTokens | |
} | |
// GetOutputTokens returns compatible output token count | |
func (u *Usage) GetOutputTokens() int { | |
if u.OutputTokens > 0 { | |
return u.OutputTokens | |
} | |
return u.CompletionTokens | |
} | |
// at the top of service/custompass_precharge.go, update your imports: | |
import ( | |
"one-api/relay/channel/custompass" | |
// … other imports … | |
) | |
// Replace the entire local Usage struct + its methods with a type alias: | |
// Use custompass.Usage instead | |
type Usage = custompass.Usage |
🤖 Prompt for AI Agents
In service/custompass_precharge.go lines 19 to 54, the Usage struct is
duplicated but already defined in relay/channel/custompass/dto.go. Remove the
entire Usage struct definition and its methods from this file. Instead, import
the Usage struct from the custompass package and update the code to use the
imported struct to avoid duplication and maintenance issues.
// contains checks if a string contains a substring (case-insensitive) | ||
func contains(s, substr string) bool { | ||
return len(s) >= len(substr) && | ||
(s == substr || | ||
len(s) > len(substr) && | ||
(s[:len(substr)] == substr || | ||
s[len(s)-len(substr):] == substr || | ||
indexOf(s, substr) >= 0)) | ||
} | ||
|
||
// indexOf returns the index of substr in s, or -1 if not found | ||
func indexOf(s, substr string) int { | ||
for i := 0; i <= len(s)-len(substr); i++ { | ||
if s[i:i+len(substr)] == substr { | ||
return i | ||
} | ||
} | ||
return -1 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use standard library string functions instead of custom implementations.
The custom contains
and indexOf
functions reinvent functionality that's already available in the standard library.
Replace with standard library functions:
-// contains checks if a string contains a substring (case-insensitive)
-func contains(s, substr string) bool {
- return len(s) >= len(substr) &&
- (s == substr ||
- len(s) > len(substr) &&
- (s[:len(substr)] == substr ||
- s[len(s)-len(substr):] == substr ||
- indexOf(s, substr) >= 0))
-}
-
-// indexOf returns the index of substr in s, or -1 if not found
-func indexOf(s, substr string) int {
- for i := 0; i <= len(s)-len(substr); i++ {
- if s[i:i+len(substr)] == substr {
- return i
- }
- }
- return -1
-}
+import "strings"
// In isRetryableError, replace:
-if contains(errStr, retryableErr) {
+if strings.Contains(strings.ToLower(errStr), strings.ToLower(retryableErr)) {
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In service/custompass_precharge.go around lines 710 to 728, the custom contains
and indexOf functions duplicate existing standard library functionality. Remove
these custom functions and replace their usage with strings.Contains for
substring checks and strings.Index for index retrieval, importing the "strings"
package if not already imported.
|
||
# start.sh - Go项目启动脚本 | ||
# 基准目录配置 | ||
BASE_DIR="/Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid hard-coding user-specific paths.
The BASE_DIR path is hard-coded to a specific user's home directory, which won't work on other systems.
Consider using environment variables or relative paths:
-BASE_DIR="/Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts"
+BASE_DIR="${SMART_SCRIPTS_DIR:-$HOME/.smart_scripts/new-api_scripts}"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
BASE_DIR="/Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts" | |
BASE_DIR="${SMART_SCRIPTS_DIR:-$HOME/.smart_scripts/new-api_scripts}" |
🤖 Prompt for AI Agents
In start.sh at line 5, the BASE_DIR is hard-coded to a specific user's absolute
path, which reduces portability. Replace this with a dynamic approach by using
environment variables like $HOME or use relative paths based on the script's
location to ensure the script works across different user environments.
🛠️ Refactor suggestion
Consider making BASE_DIR configurable
The hardcoded path /Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts
appears to be user-specific and may not work for other developers. Consider making this configurable via environment variable or detecting it dynamically.
-BASE_DIR="/Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts"
+BASE_DIR="${SCRIPT_BASE_DIR:-${HOME}/.local/share/new-api-scripts}"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
BASE_DIR="/Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts" | |
- BASE_DIR="/Users/zhao/Documents/workspace/coding/tools/smart_scripts/new-api_scripts" | |
+ BASE_DIR="${SCRIPT_BASE_DIR:-${HOME}/.local/share/new-api-scripts}" |
🤖 Prompt for AI Agents
In start.sh at line 5, the BASE_DIR variable is hardcoded to a user-specific
path, which limits portability. Modify the script to set BASE_DIR from an
environment variable if provided, falling back to a default or dynamically
detected path if not. This allows other developers to configure BASE_DIR without
changing the script.
很好,很强大,期待测试一下效果! |
很强大 希望作者能兼容根据json参数比如指定的视频时长计费,比如说fal渠道 |
This commit introduces significant enhancements to the custompass channel's billing and precharge logic. Key changes include: - **Comprehensive Billing Information Extraction:** The code now extracts and processes detailed billing information, including model prices, ratios, and group-specific multipliers, before making upstream requests. This ensures accurate precharge calculations. - **Robust Precharge Calculation:** The precharge amount is now calculated based on extracted billing information and user-specific ratios. Error handling is implemented for cases where essential billing data is missing. - **Two-Request Flow Enhancement:** The `executeTwoRequestFlow` function is refactored to more accurately handle scenarios where the upstream supports precharging. It now prioritizes using the actual usage from the second request for final billing, falling back to precharge usage if the second request's usage is unavailable. - **Precharge Validation and Refund:** Precharge execution is now conditional on the calculated amount being greater than zero. If the second business request fails, a refund mechanism for the precharged amount is implemented. - **Detailed Logging:** Extensive logging has been added to trace the billing information extraction, precharge calculation, and usage comparisons, aiding in debugging and understanding the flow. - **Error Handling Improvements:** More specific error codes and messages are returned for various failure scenarios, including missing billing information, precharge calculation failures, and upstream request errors. - **Billing Mode String Conversion:** A helper function `billingModeToString` is added for clearer logging and reporting of billing modes. - **Main Script Updates (`cc_launcher.sh`):** The launcher script has undergone extensive updates to improve user interaction, environment detection (Node.js, Claude Code CLI), and account management for Claude Code. This includes adding options for managing accounts, better error handling for installations, and refining the user prompts. These changes aim to provide a more accurate, robust, and user-friendly billing experience for the custompass channel.
This commit refactors the custompass channel to standardize billing calculations and logging by leveraging the `ModelPriceHelper`. Key changes include: - Replaced manual model price and ratio fetching with calls to `helper.ModelPriceHelper`. - Simplified `ExecuteTwoRequestFlow` by passing `relayInfo` to `ModelPriceHelper` for group ratio calculations. - Updated `ProcessResponse` in `sync_adaptor.go` to use `helper.HandleGroupRatio` for consistent group ratio calculations. - Improved logging to reflect the use of standard billing helpers and provide clearer debugging information. - Consolidated the logic for recording consume logs to use the `model.RecordConsumeLogParams` struct.
- Simplified billing checks by removing the `checkModelBilling` function and directly using `params.BillingService.DetermineBillingMode`. - Introduced `ErrCodeModelNotFound` for specific model not found scenarios, mapping it to a 404 HTTP status for clearer API responses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (6)
cc_launcher.sh (3)
21-23
: Repeat of SC2155: split declaration & assignmentDeclaring and assigning
response
on the same line hides the exit status ofcurl
, making failure detection unreliable. The same pattern recurs many times.- local response=$(curl -s --connect-timeout 10 --max-time 30 "$remote_url") + local response + response=$(curl -s --connect-timeout 10 --max-time 30 "$remote_url") + local curl_exit_code=$?
2094-2102
:eval
on user input allows arbitrary command execution
eval "$custom_command"
executes the raw string supplied by the user, reopening command-injection risk previously flagged.Use a safe exec pattern or validate the command strictly before execution.
1071-1139
: Add cryptographic integrity verification toupdate_script
The update routine still blindly replaces the local script with the downloaded bytes. File-size / syntax checks are insufficient against malicious replacement.
At minimum fetch a SHA-256 or GPG signature from a trusted channel, verify it locally, and abort on mismatch.Example patch skeleton:
- local download_result=$(curl_with_loading "$REMOTE_SCRIPT_URL" "正在下载最新版本..." 10 30 false) + local checksum_url="${REMOTE_SCRIPT_URL}.sha256" + local expected_sum + expected_sum=$(curl -s --connect-timeout 5 "$checksum_url" | cut -d' ' -f1) || { + print_error "无法获取校验和" + return 1 + } + + local download_result + download_result=$(curl_with_loading "$REMOTE_SCRIPT_URL" "正在下载最新版本..." 10 30 false) ... - echo "$download_result" > "$temp_file" + echo "$download_result" > "$temp_file" + local actual_sum + actual_sum=$(sha256sum "$temp_file" | cut -d' ' -f1) + if [[ "$actual_sum" != "$expected_sum" ]]; then + print_error "校验和不匹配,更新已中止" + rm -f "$temp_file" + return 1 + fi[security]
relay/channel/custompass/errors.go (1)
212-227
: Extract duplicated HTTP status mapping logic.The HTTP status mapping logic is duplicated in multiple functions. Extract it to a helper function to follow DRY principle.
service/custompass_precharge.go (2)
19-54
: Remove duplicate Usage struct definition.The Usage struct is already defined in
relay/channel/custompass/dto.go
. Having duplicate definitions can lead to maintenance issues and confusion.
714-732
: Use standard library string functions instead of custom implementations.The custom
contains
andindexOf
functions reinvent functionality that's already available in the standard library.
🧹 Nitpick comments (2)
relay/channel/custompass/errors.go (1)
111-208
: Consider reusing predefined error instances to reduce duplication.The factory functions duplicate the message and HTTP status mapping from the predefined error instances. Consider modifying the predefined instances with details instead of creating new ones.
func NewInvalidRequestError(details string) *CustomPassError { - return &CustomPassError{ - Code: ErrCodeInvalidRequest, - Message: "请求参数无效", - Details: details, - HTTPStatus: http.StatusBadRequest, - } + err := *ErrInvalidRequest // Create a copy + err.Details = details + return &err }relay/channel/custompass/adaptor.go (1)
433-435
: Consider making the request timeout configurable.The 30-second timeout is hardcoded but different models might need different timeouts based on their complexity.
+const defaultRequestTimeout = 30 * time.Second + // Create request with context -ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) +timeout := defaultRequestTimeout +if configTimeout := params.Channel.GetTimeout(); configTimeout > 0 { + timeout = time.Duration(configTimeout) * time.Second +} +ctx, cancel := context.WithTimeout(c.Request.Context(), timeout) defer cancel()
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
cc_launcher.sh
(1 hunks)relay/channel/custompass/adaptor.go
(1 hunks)relay/channel/custompass/errors.go
(1 hunks)relay/channel/custompass/sync_adaptor.go
(1 hunks)service/custompass_precharge.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- relay/channel/custompass/sync_adaptor.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: in relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the maxout...
Learnt from: 9Ninety
PR: QuantumNous/new-api#1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
Applied to files:
relay/channel/custompass/adaptor.go
🪛 Shellcheck (0.10.0)
cc_launcher.sh
[warning] 21-21: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 27-27: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 53-53: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 54-54: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 55-55: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 57-57: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 58-58: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 59-59: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 99-99: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 100-100: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 101-101: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 164-164: ShellCheck can't follow non-constant source. Use a directive to specify location.
(SC1090)
[warning] 543-543: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 544-544: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 556-556: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 557-557: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 560-560: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 561-561: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 582-582: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 583-583: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 595-595: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 596-596: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 599-599: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 600-600: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 664-664: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 773-773: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 844-844: duration appears unused. Verify use (or export if used externally).
(SC2034)
[warning] 884-884: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 906-906: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1074-1074: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1079-1079: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1087-1087: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1102-1102: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1105-1105: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1147-1147: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1235-1235: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1274-1274: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1280-1280: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1312-1312: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1314-1314: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1327-1327: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1349-1349: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1358-1358: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1474-1474: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1495-1495: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1499-1499: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1528-1528: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1532-1532: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1585-1585: Declare and assign separately to avoid masking return values.
(SC2155)
[warning] 1813-1813: This pattern always overrides a later one on line 1813.
(SC2221)
[warning] 1813-1813: This pattern never matches because of a previous pattern on line 1813.
(SC2222)
[warning] 1818-1818: This pattern always overrides a later one on line 1818.
(SC2221)
[warning] 1818-1818: This pattern never matches because of a previous pattern on line 1818.
(SC2222)
[warning] 1824-1824: This pattern always overrides a later one on line 1824.
(SC2221)
[warning] 1824-1824: This pattern never matches because of a previous pattern on line 1824.
(SC2222)
[warning] 1831-1831: This pattern always overrides a later one on line 1831.
(SC2221)
[warning] 1831-1831: This pattern never matches because of a previous pattern on line 1831.
(SC2222)
[warning] 1838-1838: This pattern always overrides a later one on line 1838.
(SC2221)
[warning] 1838-1838: This pattern never matches because of a previous pattern on line 1838.
(SC2222)
[warning] 1894-1894: This pattern always overrides a later one on line 1894.
(SC2221)
[warning] 1894-1894: This pattern never matches because of a previous pattern on line 1894.
(SC2222)
[warning] 1925-1925: This pattern always overrides a later one on line 1925.
(SC2221)
[warning] 1925-1925: This pattern never matches because of a previous pattern on line 1925.
(SC2222)
[warning] 1960-1960: This pattern always overrides a later one on line 1960.
(SC2221)
[warning] 1960-1960: This pattern never matches because of a previous pattern on line 1960.
(SC2222)
[warning] 2015-2015: This pattern always overrides a later one on line 2015.
(SC2221)
[warning] 2015-2015: This pattern never matches because of a previous pattern on line 2015.
(SC2222)
[warning] 2024-2024: This pattern always overrides a later one on line 2024.
(SC2221)
[warning] 2024-2024: This pattern never matches because of a previous pattern on line 2024.
(SC2222)
[warning] 2085-2085: This pattern always overrides a later one on line 2085.
(SC2221)
[warning] 2085-2085: This pattern never matches because of a previous pattern on line 2085.
(SC2222)
[warning] 2178-2178: This pattern always overrides a later one on line 2178.
(SC2221)
[warning] 2178-2178: This pattern never matches because of a previous pattern on line 2178.
(SC2222)
REMOTE_SCRIPT_URL="http://tfs.sthnext.com/cc/cc_launcher.sh" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use HTTPS for self-update endpoint
The launcher downloads and executes code from an unencrypted HTTP URL.
Man-in-the-middle tampering can lead to arbitrary code execution on every user’s machine. Switch to HTTPS or a similarly authenticated transport before production rollout.
[security]
🤖 Prompt for AI Agents
In cc_launcher.sh around lines 8 to 9, the REMOTE_SCRIPT_URL is set to use an
unencrypted HTTP URL, which poses a security risk due to potential
man-in-the-middle attacks. Update the REMOTE_SCRIPT_URL to use HTTPS instead of
HTTP to ensure encrypted and secure downloading of the script.
# 版本比较函数(语义化版本号比较) | ||
compare_versions() { | ||
local version1="$1" | ||
local version2="$2" | ||
|
||
# 检查输入是否为空或包含非版本号内容 | ||
if [[ -z "$version1" || -z "$version2" ]]; then | ||
return 0 # 如果有空值,认为相等 | ||
fi | ||
|
||
# 检查是否包含非版本号内容(如果包含空格或其他字符,可能是错误信息) | ||
if [[ "$version1" =~ [[:space:]] || "$version2" =~ [[:space:]] ]]; then | ||
return 0 # 如果包含空格,可能是错误信息,认为相等 | ||
fi | ||
|
||
# 移除可能的前缀字符(如 v) | ||
version1=$(echo "$version1" | sed 's/^[vV]//') | ||
version2=$(echo "$version2" | sed 's/^[vV]//') | ||
|
||
# 分割版本号 | ||
IFS='.' read -ra VER1 <<< "$version1" | ||
IFS='.' read -ra VER2 <<< "$version2" | ||
|
||
# 确保版本号数组长度一致,不足的补0 | ||
while [ ${#VER1[@]} -lt 3 ]; do VER1+=(0); done | ||
while [ ${#VER2[@]} -lt 3 ]; do VER2+=(0); done | ||
|
||
# 逐位比较 | ||
for i in {0..2}; do | ||
local v1=${VER1[i]:-0} | ||
local v2=${VER2[i]:-0} | ||
|
||
# 确保是数字 | ||
if ! [[ "$v1" =~ ^[0-9]+$ ]]; then v1=0; fi | ||
if ! [[ "$v2" =~ ^[0-9]+$ ]]; then v2=0; fi | ||
|
||
if [ "$v1" -gt "$v2" ]; then | ||
return 1 # version1 > version2 | ||
elif [ "$v1" -lt "$v2" ]; then | ||
return 2 # version1 < version2 | ||
fi | ||
done | ||
|
||
return 0 # version1 == version2 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate compare_versions
function – later definition silently overrides the first
compare_versions
is defined at Lines 39-91 and re-defined here. The earlier logic (and any callers loaded before this point) become unreachable or inconsistent.
Remove one definition or consolidate the two into a single, well-tested implementation.
[maintainability]
🤖 Prompt for AI Agents
In cc_launcher.sh between lines 974 and 1018, there is a duplicate definition of
the function compare_versions, which overrides the earlier one defined at lines
39-91, causing inconsistency and unreachable code. To fix this, remove one of
the compare_versions function definitions or merge their logic into a single,
well-tested implementation to ensure consistent behavior throughout the script.
func (a *Adaptor) Init(info *relaycommon.RelayInfo) { | ||
// CustomPass initialization logic | ||
} | ||
|
||
func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) { | ||
// CustomPass URL building logic | ||
return "", nil | ||
} | ||
|
||
func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error { | ||
// CustomPass header setup logic | ||
return nil | ||
} | ||
|
||
func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error) { | ||
// CustomPass request conversion logic | ||
return nil, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement the stub methods or document why they're not needed.
Several interface methods are returning nil/empty values. These should either be properly implemented or documented if they're intentionally left as no-ops.
Methods that need implementation:
Init
GetRequestURL
SetupRequestHeader
ConvertOpenAIRequest
🤖 Prompt for AI Agents
In relay/channel/custompass/adaptor.go around lines 48 to 65, the interface
methods Init, GetRequestURL, SetupRequestHeader, and ConvertOpenAIRequest are
currently stubs returning nil or empty values. You need to either implement the
full logic for these methods according to the CustomPass adaptor requirements or
add clear comments explaining why these methods are intentionally left as no-ops
to clarify their purpose and avoid confusion.
func (a *Adaptor) GetModelList() []string { | ||
// Return available models for CustomPass | ||
return []string{"custom-model-1", "custom-model-2"} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid hardcoding model names.
The model list should be dynamically retrieved from configuration or the CustomPass service rather than being hardcoded.
func (a *Adaptor) GetModelList() []string {
- // Return available models for CustomPass
- return []string{"custom-model-1", "custom-model-2"}
+ // TODO: Implement dynamic model retrieval from CustomPass configuration
+ // This should query the actual available models from the service
+ return []string{}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (a *Adaptor) GetModelList() []string { | |
// Return available models for CustomPass | |
return []string{"custom-model-1", "custom-model-2"} | |
} | |
func (a *Adaptor) GetModelList() []string { | |
// TODO: Implement dynamic model retrieval from CustomPass configuration | |
// This should query the actual available models from the service | |
return []string{} | |
} |
🤖 Prompt for AI Agents
In relay/channel/custompass/adaptor.go around lines 102 to 105, the GetModelList
method currently returns a hardcoded list of model names. Modify this method to
dynamically retrieve the model list from a configuration source or by querying
the CustomPass service, ensuring the list reflects the current available models
without hardcoding.
var prechargeAmount int64 = 0 | ||
var finalUsage *Usage = prechargeResp.Usage | ||
|
||
// 只有非免费的计费模式才需要计算预扣费 | ||
if billingMode != service.BillingModeFree { | ||
// 直接使用ModelPriceHelper计算的预消费配额 | ||
prechargeAmount = int64(priceData.ShouldPreConsumedQuota) | ||
|
||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] ===== 预扣费计算 =====")) | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 计费模式: %s", billingInfo.BillingMode)) | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 组倍率: %.6f", billingInfo.GroupRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 用户倍率: %.6f", billingInfo.UserGroupRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 使用标准ModelPriceHelper计算得出预扣费金额: %d (¥%.4f)", | ||
prechargeAmount, float64(prechargeAmount)/common.QuotaPerUnit)) | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] ====================")) | ||
} else { | ||
common.SysLog("[CustomPass-TwoRequest-Debug] 免费模型(BillingModeFree),无需计算预扣费") | ||
} | ||
|
||
|
||
// 使用prechargeResp的信息构建 返回参数 | ||
result = &TwoRequestResult{ | ||
Response: prechargeResp, | ||
PrechargeAmount: prechargeAmount, | ||
RequestCount: 1, | ||
PrechargeUsage: finalUsage, | ||
BillingInfo: billingInfo, | ||
} | ||
|
||
|
||
// 执行预扣费(只有金额大于0才执行) | ||
if prechargeAmount > 0 { | ||
serviceUsageForPrecharge := &service.Usage{ | ||
PromptTokens: prechargeResp.Usage.PromptTokens, | ||
CompletionTokens: prechargeResp.Usage.CompletionTokens, | ||
TotalTokens: prechargeResp.Usage.TotalTokens, | ||
InputTokens: prechargeResp.Usage.InputTokens, | ||
OutputTokens: prechargeResp.Usage.OutputTokens, | ||
} | ||
|
||
prechargeResult, _, err := params.PrechargeService.ExecutePrecharge(c, params.User, params.ModelName, serviceUsageForPrecharge) | ||
if err != nil { | ||
return nil, &CustomPassError{ | ||
Code: ErrCodeInsufficientQuota, | ||
Message: "预扣费执行失败", | ||
Details: err.Error(), | ||
} | ||
} | ||
// 使用实际扣除的金额 | ||
prechargeAmount = prechargeResult.PrechargeAmount | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 预扣费执行成功,实际扣除: %d (¥%.4f)", | ||
prechargeAmount, float64(prechargeAmount)/common.QuotaPerUnit)) | ||
} | ||
|
||
// Check if upstream returned precharge response | ||
|
||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 检查上游响应类型 - Type: %s, IsPrecharge: %t", | ||
prechargeResp.Type, prechargeResp.IsPrecharge())) | ||
|
||
// 如果需要进行第二次业务请求,将业务请求的结果返回出去 | ||
if prechargeResp.IsPrecharge() { | ||
common.SysLog("[CustomPass-TwoRequest-Debug] 上游支持预扣费,将发起两次请求") | ||
|
||
realResp, err := executeSecondBizRequest(c, params, prechargeResp) | ||
if err != nil { | ||
common.SysError(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 二次请求失败: %v", err)) | ||
// 记录错误信息到logs | ||
model.RecordConsumeLog(c, params.User.Id, model.RecordConsumeLogParams{ | ||
ChannelId: params.Channel.Id, | ||
PromptTokens: 0, | ||
CompletionTokens: 0, | ||
ModelName: params.ModelName, | ||
TokenName: c.GetString("token_name"), | ||
Quota: int(prechargeAmount), | ||
Content: "二次请求失败: " + err.Error(), | ||
}) | ||
|
||
// 退还预扣费 | ||
if prechargeAmount > 0 { | ||
common.SysLog(fmt.Sprintf("[CustomPass-TwoRequest-Debug] 退还预扣费: %d", prechargeAmount)) | ||
params.PrechargeService.ProcessRefund(params.User.Id, prechargeAmount, 0) | ||
} | ||
return nil, err | ||
} | ||
|
||
// 使用真实响应的usage(如果有) | ||
if realResp.Usage != nil { | ||
finalUsage = realResp.Usage | ||
common.SysLog("[CustomPass-TwoRequest-Debug] 使用真实响应的usage作为最终usage") | ||
} | ||
|
||
// 构建返回结果 | ||
result.Response = realResp | ||
result.RequestCount = 2 | ||
} | ||
|
||
// 返回结果 | ||
return result, nil | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Break down this complex function into smaller, manageable pieces.
This function is over 230 lines and handles multiple complex operations. Consider extracting logical sections into separate functions for better maintainability.
Suggested extraction:
- Free model handling (lines 122-148)
- Precharge request and validation (lines 170-193)
- Price calculation using ModelPriceHelper (lines 194-235)
- Precharge execution (lines 281-303)
- Second request handling (lines 311-345)
Example extraction:
func (a *Adaptor) handleFreeModel(c *gin.Context, params *TwoRequestParams) (*TwoRequestResult, error) {
// Extract lines 122-148
}
func (a *Adaptor) calculatePricing(c *gin.Context, relayInfo *relaycommon.RelayInfo, usage *Usage) (*model.BillingInfo, int64, error) {
// Extract price calculation logic
}
🤖 Prompt for AI Agents
In relay/channel/custompass/adaptor.go from lines 117 to 350, the
ExecuteTwoRequestFlow function is too large and complex, making it hard to
maintain. Refactor by extracting logical sections into smaller functions: one
for handling free models (lines 122-148), another for precharge request and
validation (lines 170-193), a third for price calculation using ModelPriceHelper
(lines 194-235), one for executing the precharge (lines 281-303), and another
for handling the second request (lines 311-345). Each extracted function should
encapsulate its respective logic and be called from the main function to improve
readability and maintainability.
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - 组倍率 (GroupRatio): %.6f", groupRatioInfo.GroupRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - 分组特殊倍率 (GroupSpecialRatio): %.6f", groupRatioInfo.GroupSpecialRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - 使用特殊倍率 (HasSpecialRatio): %t", groupRatioInfo.HasSpecialRatio)) | ||
} else { | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] GroupRatioInfo: 免费模型,未计算组倍率")) | ||
} | ||
|
||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 最终构建的BillingInfo:")) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - BillingMode: %s", billingInfo.BillingMode)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - GroupRatio: %.6f", billingInfo.GroupRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - UserGroupRatio: %.6f", billingInfo.UserGroupRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - ModelRatio: %.6f", billingInfo.ModelRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - CompletionRatio: %.6f", billingInfo.CompletionRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - ModelPrice: %.6f", billingInfo.ModelPrice)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] - HasSpecialRatio: %t", billingInfo.HasSpecialRatio)) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] =======================================")) | ||
|
||
|
||
// Calculate amount based on billing mode | ||
var amount int64 | ||
var err error | ||
|
||
if billingMode == BillingModeFree { | ||
amount = 0 | ||
common.SysLog("[CustomPass预扣费执行] 免费模型,预扣费金额为0") | ||
} else { | ||
// Use effective user ratio (group special ratio if exists, otherwise 1.0) | ||
effectiveUserRatio := 1.0 | ||
if hasGroupRatioInfo && groupRatioInfo.HasSpecialRatio { | ||
effectiveUserRatio = groupRatioInfo.GroupSpecialRatio | ||
} | ||
|
||
groupRatio := 1.0 | ||
if hasGroupRatioInfo { | ||
groupRatio = groupRatioInfo.GroupRatio | ||
} | ||
|
||
amount, err = billingService.CalculatePrechargeAmount(modelName, estimatedUsage, groupRatio, effectiveUserRatio) | ||
if err != nil { | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 预扣费计算失败: %v", err)) | ||
return nil, nil, err | ||
} | ||
} | ||
|
||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 预扣费计算完成 - 金额: %s", common.LogQuota(int(amount)))) | ||
|
||
if amount <= 0 { | ||
common.SysLog("[CustomPass预扣费执行] 预扣费金额为0,跳过扣费操作") | ||
return &PrechargeResult{ | ||
PrechargeAmount: 0, | ||
Success: true, | ||
}, billingInfo, nil | ||
} | ||
|
||
// Get user-specific lock to prevent concurrent operations | ||
userLock := s.getUserLock(user.Id) | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 获取用户锁 - 用户ID: %d", user.Id)) | ||
userLock.Lock() | ||
defer userLock.Unlock() | ||
|
||
// Execute precharge transaction with retry mechanism | ||
var result *PrechargeResult | ||
maxRetries := 3 | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 开始执行预扣费事务 - 最大重试次数: %d", maxRetries)) | ||
|
||
for i := 0; i < maxRetries; i++ { | ||
if i > 0 { | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 重试第 %d 次", i)) | ||
} | ||
|
||
result, err = s.executePrechargeTransaction(user.Id, amount) | ||
if err == nil { | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 预扣费事务执行成功 - 事务ID: %s, 金额: %s", | ||
result.TransactionID, common.LogQuota(int(result.PrechargeAmount)))) | ||
break | ||
} | ||
|
||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 预扣费事务执行失败: %v", err)) | ||
|
||
// Check if it's a retryable error | ||
if !s.isRetryableError(err) { | ||
common.SysLog("[CustomPass预扣费执行] 不可重试的错误,停止重试") | ||
break | ||
} | ||
|
||
// Wait before retry | ||
sleepTime := time.Duration(i+1) * 100 * time.Millisecond | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 等待 %v 后重试", sleepTime)) | ||
time.Sleep(sleepTime) | ||
} | ||
|
||
if err != nil { | ||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 预扣费最终失败 - 用户ID: %d, 错误: %v", user.Id, err)) | ||
return nil, nil, err | ||
} | ||
|
||
common.SysLog(fmt.Sprintf("[CustomPass预扣费执行] 预扣费执行完成 - 用户ID: %d, 金额: %s, 事务ID: %s", | ||
user.Id, common.LogQuota(int(result.PrechargeAmount)), result.TransactionID)) | ||
return result, billingInfo, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Break down this complex method into smaller, focused functions.
This method is over 200 lines long and handles multiple responsibilities including validation, billing mode determination, price calculation, and transaction execution. Consider extracting logical sections into separate methods.
Consider extracting these logical sections:
- Input validation (lines 125-152)
- Billing info construction (lines 154-242)
- Precharge amount calculation (lines 244-279)
- Transaction execution with retry (lines 281-324)
This would improve readability, testability, and maintainability.
🤖 Prompt for AI Agents
In service/custompass_precharge.go from lines 119 to 326, the ExecutePrecharge
method is too long and handles multiple responsibilities. Refactor by extracting
four focused helper methods: one for input validation (lines 125-152), one for
constructing billing info (lines 154-242), one for calculating the precharge
amount (lines 244-279), and one for executing the transaction with retry logic
(lines 281-324). Replace the corresponding code blocks in ExecutePrecharge with
calls to these new methods to improve readability, testability, and
maintainability.
功能概述
CustomPass 是一个全新的自定义透传渠道功能,支持将用户请求透传到自定义的AI服务端点,并提供完整的计费、监控和管理能力。该功能在不影响现有功能的前提下,为 New API 网关增加了高度可定制的渠道接入能力。
核心特性
🚀 渠道管理
💰 完整计费系统
🔄 双模式请求处理
📊 异步任务管理
🛡️ 安全与认证
技术架构
后端核心模块
前端集成
关键技术特性
🔧 双请求流程 (Two-Request Flow)
创新的双请求处理模式,同时支持同步和异步AI服务:
📈 智能计费引擎
🚦 高可用性设计
部署与配置
🛠️ 配置管理
📦 部署要求
影响范围
Summary by CodeRabbit
New Features
Documentation
Bug Fixes
Chores
.gitignore
.Style