sususu98
|
3abd0b0f36
|
fix: 编辑Console账户表单前先读取maxConcurrentTasks并显示,防止每次编辑Console账户并发限制都被重置
|
2025-10-27 16:35:27 +08:00 |
|
sususu98
|
1458d609ca
|
feat: 为 Claude Console 账户添加并发控制机制
实现了完整的 Claude Console 账户并发任务数控制功能,防止单账户过载,提升服务稳定性。
**核心功能**
- 🔒 **原子性并发控制**: 基于 Redis Sorted Set 实现的抢占式并发槽位管理,防止竞态条件
- 🔄 **自动租约刷新**: 流式请求每 5 分钟自动刷新租约,防止长连接租约过期
- 🚨 **智能降级处理**: 并发满额时自动清理粘性会话并重试其他账户(最多 1 次)
- 🎯 **专用错误码**: 引入 `CONSOLE_ACCOUNT_CONCURRENCY_FULL` 错误码,区分并发限制和其他错误
- 📊 **批量性能优化**: 调度器使用 Promise.all 并行查询账户并发数,减少 Redis 往返
**后端实现**
1. **Redis 并发控制方法** (src/models/redis.js)
- `incrConsoleAccountConcurrency()`: 增加并发计数(带租约)
- `decrConsoleAccountConcurrency()`: 释放并发槽位
- `refreshConsoleAccountConcurrencyLease()`: 刷新租约(流式请求)
- `getConsoleAccountConcurrency()`: 查询当前并发数
2. **账户服务增强** (src/services/claudeConsoleAccountService.js)
- 添加 `maxConcurrentTasks` 字段(默认 0 表示无限制)
- 获取账户时自动查询实时并发数 (`activeTaskCount`)
- 支持更新并发限制配置
3. **转发服务并发保护** (src/services/claudeConsoleRelayService.js)
- 请求前原子性抢占槽位,超限则立即回滚并抛出专用错误
- 流式请求启动定时器每 5 分钟刷新租约
- `finally` 块确保槽位释放(即使发生异常)
- 为每个请求分配唯一 `requestId` 用于并发追踪
4. **统一调度器优化** (src/services/unifiedClaudeScheduler.js)
- 获取可用账户时批量查询并发数(Promise.all 并行)
- 预检查并发限制,避免选择已满的账户
- 检查分组成员时也验证并发状态
- 所有账户并发满额时抛出专用错误码
5. **API 路由降级处理** (src/routes/api.js)
- 捕获 `CONSOLE_ACCOUNT_CONCURRENCY_FULL` 错误
- 自动清理粘性会话映射并重试(最多 1 次)
- 重试失败返回 503 错误和友好提示
- count_tokens 端点也支持并发满额重试
6. **管理端点验证** (src/routes/admin.js)
- 创建/更新账户时验证 `maxConcurrentTasks` 为非负整数
- 支持前端传入并发限制配置
**前端实现**
1. **表单字段** (web/admin-spa/src/components/accounts/AccountForm.vue)
- 添加"最大并发任务数"输入框(创建和编辑模式)
- 支持占位符提示"0 表示不限制"
- 表单数据自动映射到后端 API
2. **实时监控** (web/admin-spa/src/views/AccountsView.vue)
- 账户列表显示并发状态进度条和百分比
- 颜色编码:绿色(<80%)、黄色(80%-100%)、红色(100%)
- 显示"X / Y"格式的并发数(如"2 / 5")
- 未配置限制时显示"并发无限制"徽章
|
2025-10-21 13:43:57 +08:00 |
|
shaw
|
abef8a4e31
|
feat: claude账号新增保存claude的uuid
|
2025-10-19 17:15:31 +08:00 |
|
shaw
|
05f4454c10
|
feat: apikey显示最后调度的账号
|
2025-10-17 19:44:40 +08:00 |
|
AAEE86
|
8f58fe6264
|
feat: 账号使用趋势增加对Droid账户的支持
|
2025-10-16 23:01:06 +08:00 |
|
shaw
|
994e474155
|
fix: 修复批量编辑apikey模式无法选择oai账号
|
2025-10-16 14:48:15 +08:00 |
|
shaw
|
2f0839c7da
|
feat: 合并 PR #578 并接入统一定价服务
|
2025-10-16 14:12:25 +08:00 |
|
AAEE86
|
d3cf66e2c0
|
Update AccountsView.vue
移除 overflow-x: auto
|
2025-10-16 11:13:23 +08:00 |
|
liangjie.wanglj
|
b9d2e855f3
|
claude console类型中增加claude-haiku-4-5-20251001、GLM、Kimi、Qwen模型支持;增加计费消息通知;Claude console 及 ccr模型匹配大小写不敏感
|
2025-10-16 09:53:42 +08:00 |
|
AAEE86
|
914c1b6120
|
Merge branch 'main' into new
|
2025-10-15 23:38:18 +08:00 |
|
AAEE86
|
8ab3c76c6f
|
feat: 新增 API Key 筛选和搜索功能
- 筛选key,新增支持筛选正常和异常状态的key
- 搜索key,新增支持模糊/精确搜索key
- 删除key,新增支持一键删除所有异常状态的key或者删除所有key
- 导出key,新增支持一键导出所有异常状态的key或者导出所有key
|
2025-10-15 15:35:59 +08:00 |
|
shaw
|
92712277db
|
feat: droid的apikey页面增加一键复制全部
|
2025-10-14 20:44:14 +08:00 |
|
mrlitong
|
cd5df4f76b
|
Merge remote-tracking branch 'upstream/main' into feature/account-subscription-expiry-check
|
2025-10-14 08:04:12 +00:00 |
|
Wesley Liddick
|
4b3ffa4136
|
Merge pull request #561 from AAEE86/new
feat: 添加Droid账户API Key管理功能
|
2025-10-14 14:34:07 +08:00 |
|
shaw
|
dfea5fe534
|
docs: 更新gemini配置教程
|
2025-10-14 11:40:07 +08:00 |
|
shaw
|
914142541a
|
Revert "fix: 修复账户到期时间的时区偏差问题"
This reverts commit 46ba514801.
|
2025-10-14 11:29:33 +08:00 |
|
mrlitong
|
ba60a2dcbb
|
fix: 修复自定义过期时间的时区解析问题
修复 datetime-local 输入框在不同浏览器中时区解析不一致的问题。
## 问题
- datetime-local 返回无时区信息的字符串 (如: 2025-12-31T23:59)
- new Date(string) 在不同浏览器中解析行为不一致
- 部分浏览器错误地将其解释为 UTC,导致时区偏移
## 解决方案
- 手动解析日期时间字符串的各个部分
- 使用 Date 构造函数明确创建本地时间对象
- 统一转换为 UTC ISO 字符串存储
- 添加日期有效性验证和错误处理
## 影响范围
- 仅影响自定义过期时间设置功能
- 确保用户设置的时间与存储/显示一致
- 提升跨浏览器兼容性
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-14 02:52:18 +00:00 |
|
litongtongxue
|
1e7465e533
|
feat: 为所有账户服务添加订阅过期检查功能
完成账户订阅到期时间功能的核心调度逻辑实现。
## 实现范围
✅ 已添加订阅过期检查的服务(5个):
- Gemini 服务:添加 isSubscriptionExpired() 函数及调度过滤
- OpenAI 服务:添加 isSubscriptionExpired() 函数及调度过滤
- Droid 服务:添加 _isSubscriptionExpired() 方法及调度过滤
- Bedrock 服务:添加 _isSubscriptionExpired() 方法及调度过滤
- Azure OpenAI 服务:添加 isSubscriptionExpired() 函数及调度过滤
## 核心功能
- 账户调度时自动检查 subscriptionExpiresAt 字段
- 过期账户将不再被系统调度使用
- 未设置过期时间的账户视为永不过期(向后兼容)
- 使用 <= 比较判断过期(精确到过期时刻)
- 跳过过期账户时记录 debug 日志便于排查
## 技术实现
- 统一的实现模式:过期检查函数 + 账户选择逻辑集成
- 不影响现有功能,完全向后兼容
- 业务字段 subscriptionExpiresAt 与技术字段 expiresAt(OAuth token过期)独立管理
## 相关文档
参考 account_expire_bugfix.md 了解问题背景和实现细节
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-14 02:42:03 +00:00 |
|
AAEE86
|
8dd07919f4
|
fix: 修复 API Key 管理界面按钮的点击事件逻辑
|
2025-10-14 10:34:38 +08:00 |
|
AAEE86
|
582348d615
|
fix: 修正删除API Key时更新数据的字段名称
|
2025-10-14 10:09:47 +08:00 |
|
AAEE86
|
38c61e1018
|
refactor: 优化API Key状态过滤逻辑,增强代码可读性
|
2025-10-14 09:37:46 +08:00 |
|
AAEE86
|
e051ade27e
|
feat: 按最新使用时间排序API Keys
|
2025-10-14 01:05:22 +08:00 |
|
AAEE86
|
ea3ad2157f
|
fix: 优化API Key错误状态码的显示方式
|
2025-10-14 00:53:19 +08:00 |
|
DokiDoki1103
|
46ba514801
|
fix: 修复账户到期时间的时区偏差问题
修复了在编辑账户到期时间时,保存后显示时间相差8小时的问题。
问题原因:
- datetime-local 输入框的值使用 new Date(string) 解析时
- 部分浏览器会错误地将其解释为 UTC 时间
- 导致保存和显示时出现时区转换不一致
解决方案:
- 手动解析日期时间字符串的各个部分
- 使用 Date 构造函数明确创建本地时间对象
- 然后统一转换为 UTC ISO 字符串存储
- 确保时区转换的一致性
修改文件:
- web/admin-spa/src/components/accounts/AccountExpiryEditModal.vue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-13 19:04:11 +08:00 |
|
AAEE86
|
1f9afc788b
|
feat: 添加Droid账户API Key管理功能
(cherry picked from commit 0cf3ca6c7eafcf28a2da7e8bfd6814b4883bb752)
|
2025-10-13 18:24:49 +08:00 |
|
jft0m
|
96eca07ff2
|
Merge branch 'Wei-Shaw:main' into main
|
2025-10-13 11:32:02 +08:00 |
|
Wesley Liddick
|
2215b0acd8
|
Merge pull request #555 from DokiDoki1103/fix/ccr-account-modal-dark-theme [skip ci]
fix: 修复 CCR 账户弹窗暗黑主题失效问题
|
2025-10-13 11:25:33 +08:00 |
|
shaw
|
f302c94d3c
|
docs: 移除claude code使用droid api相关文档
|
2025-10-13 10:51:06 +08:00 |
|
shaw
|
cea6f976b9
|
fix: 修复批量编辑模式下专属账号修改的问题
|
2025-10-13 09:16:13 +08:00 |
|
jft0m
|
44a7a61f14
|
Merge branch 'Wei-Shaw:main' into main
|
2025-10-12 22:51:22 +08:00 |
|
jft0m
|
ad64bd3c51
|
feat: 改善登录表单的可访问性和自动填充支持
- 为所有表单字段添加 id 和 name 属性
- 添加 autocomplete 属性支持浏览器自动填充
- 使用 for 属性正确关联 label 和 input
- 优化代码格式符合 Prettier 规范
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-12 14:50:07 +00:00 |
|
shaw
|
692abbc4f8
|
Merge branch 'fix/remove-horizontal-scrollbar-accounts-page' into dev
|
2025-10-12 21:00:24 +08:00 |
|
DokiDoki1103
|
a2844e802a
|
fix: 修复 CCR 账户弹窗暗黑主题失效问题
- 为全局 modal 和 modal-content 添加暗黑模式样式
- 在 CcrAccountForm 组件中使用 Tailwind 暗黑模式类替代 scoped style
- 优化关闭按钮在暗黑模式下的显示效果
此修复确保 CCR 账户添加/编辑弹窗在暗黑模式下正确显示深色背景和样式,与其他界面元素保持一致的用户体验。
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-12 20:59:41 +08:00 |
|
DokiDoki1103
|
e6d9a46b98
|
fix: 移除账户管理页面的横向滚动条
- 移除 .table-container 的 overflow-x: auto 样式
- 清理重复的样式定义
- 修复账户管理页面在某些情况下出现不必要横向滚动条的问题
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-12 20:49:00 +08:00 |
|
shaw
|
2fa1b0b1dc
|
fix: 优化创建apikey成功弹窗
|
2025-10-12 19:59:01 +08:00 |
|
shaw
|
40b7c68694
|
fix: 修复账号过期时间的一系列bug
|
2025-10-12 18:35:05 +08:00 |
|
shaw
|
a3dacbccd0
|
refactor: 编辑账户时隐藏过期时间表单,使用独立编辑弹窗
## 问题分析
编辑账户时显示过期时间表单存在以下问题:
1. **相对时间 vs 绝对时间冲突**:
- 下拉框提供相对时间选项(30天、90天等)
- 实际存储的是绝对时间(如 2025-02-15)
- 过了1天后,无法准确对应原来的"30天"选项
2. **用户体验混乱**:
- 设置了30天过期,编辑时下拉框显示"永不过期"
- 无法准确回显用户当初的选择
- 容易误导用户
3. **功能重复**:
- 已有独立的AccountExpiryEditModal弹窗专门编辑过期时间
- 该弹窗使用绝对时间显示,更清晰准确
## 解决方案
仅在编辑模式下隐藏过期时间表单:
- 创建账户时:保留过期时间表单(相对时间设置合理)
- 编辑账户时:隐藏过期时间表单,引导用户使用独立的编辑弹窗
## 实现细节
在两处过期时间表单添加 v-if="!isEdit" 条件:
- 第645行:OAuth添加方式的表单
- 第2116行:手动添加方式的表单
## 用户流程改进
- 创建账户:可以快速选择相对过期时间(30天、90天等)
- 编辑账户:在列表中点击"编辑到期时间"按钮 → 使用独立弹窗编辑
- 弹窗优势:显示当前绝对过期时间、支持快捷延期、实时预览新时间
文件: web/admin-spa/src/components/accounts/AccountForm.vue:645,2116
|
2025-10-12 14:04:16 +08:00 |
|
shaw
|
62e457932e
|
fix: 修复账户编辑时过期时间不回显的问题
## 问题描述
在账户编辑页面,虽然过期时间已保存并在列表中正确显示,但点击编辑时:
- expireDuration 和 customExpireDate 字段为空
- 导致过期时间选择器显示为空白状态
## 根本原因
AccountForm.vue 的 form 初始化时:
- expiresAt 正确读取了 props.account?.expiresAt
- 但 expireDuration 和 customExpireDate 都初始化为空字符串
- 缺少从 expiresAt 反向初始化这两个字段的逻辑
## 修复方案
修改 form 初始化逻辑(第 3443-3457 行):
- expireDuration: 如果存在 expiresAt,设置为 'custom'
- customExpireDate: 如果存在 expiresAt,转换为 datetime-local 格式 (YYYY-MM-DDTHH:mm)
- expiresAt: 保持原有逻辑不变
## 技术细节
使用 IIFE (立即执行函数) 在 reactive 对象初始化时计算初始值:
```javascript
expireDuration: (() => {
if (props.account?.expiresAt) return 'custom'
return ''
})()
```
## 测试验证
- ✅ 编辑已设置过期时间的账户,过期时间正确回显
- ✅ 编辑未设置过期时间的账户,显示为永不过期
- ✅ AccountExpiryEditModal 组件已有正确的初始化逻辑,无需修改
文件: web/admin-spa/src/components/accounts/AccountForm.vue:3443-3457
|
2025-10-12 13:56:26 +08:00 |
|
shaw
|
a84f344df6
|
Merge PR #541: 添加账户订阅到期时间管理功能 + 修复核心过期检查逻辑
## 原PR功能
- ✅ 后端添加subscriptionExpiresAt字段支持
- ✅ 前端提供到期时间设置界面(快捷选项 + 自定义日期)
- ✅ 账户列表显示到期状态(已过期🔴/即将过期🟠/永不过期⚪)
- ✅ 新增AccountExpiryEditModal.vue编辑弹窗组件
- ✅ 支持创建和更新账户时设置到期时间
- ✅ 完整支持暗黑模式
## 🔧 关键修复(本次提交)
原PR缺少核心过期检查逻辑,过期账户仍会被调度使用。本次合并时添加了:
1. **新增isAccountNotExpired()方法**:
- 检查账户subscriptionExpiresAt字段
- 未设置过期时间视为永不过期
- 添加debug日志记录过期账户
2. **在selectAvailableAccount()中添加过期检查**:
- 过滤逻辑中集成this.isAccountNotExpired(account)
- 确保过期账户不被选择
3. **在selectAccountForApiKey()中添加过期检查**:
- 绑定账户检查中添加过期验证
- 共享池过滤中添加过期验证
## 🗑️ 清理工作
- 移除了不应提交的account_expire_feature.md评审文档(756行)
## 技术细节
- API层使用expiresAt,存储层使用subscriptionExpiresAt
- 存储格式:ISO 8601 (UTC)
- 空值表示:null表示永不过期
- 时区处理:后端UTC,前端自动转换本地时区
作者: mrlitong (原PR) + Claude Code (修复)
PR: https://github.com/Wei-Shaw/claude-relay-service/pull/541
|
2025-10-12 13:42:57 +08:00 |
|
shaw
|
8e415f8ff8
|
Merge PR #545: 常用模型增加deepseek-chat;修复修改时默认选择白名单
- Claude Console类型账户默认白名单模型增加deepseek-chat模型
- 修复白名单模式下的初始化逻辑:
* 白名单模式:正确设置allowedModels用于显示勾选的模型
* 同时保留modelMappings以便用户切换到映射模式时有初始数据
* 映射模式:只设置modelMappings,不填充allowedModels
- 增加代码注释,清晰说明不同模式的数据设置逻辑
作者: looksgood
PR: https://github.com/Wei-Shaw/claude-relay-service/pull/545
|
2025-10-12 13:34:10 +08:00 |
|
jft0m
|
44c6be129b
|
Merge branch 'Wei-Shaw:main' into main
|
2025-10-12 09:28:12 +08:00 |
|
litongtongxue
|
c8c337099e
|
Merge upstream/main into feature/account-expiry-management
解决与 upstream/main 的代码冲突:
- 保留账户到期时间 (expiresAt) 功能
- 采用 buildProxyPayload() 函数重构代理配置
- 同步最新的 Droid 平台功能和修复
主要改动:
- AccountForm.vue: 整合到期时间字段和新的 proxy 处理方式
- 合并 upstream 的 Droid 多 API Key 支持等新特性
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2025-10-12 00:55:25 +08:00 |
|
shaw
|
26894f485b
|
feat: droid账号增加apikey数量显示
|
2025-10-11 23:05:48 +08:00 |
|
shaw
|
0b2610842a
|
feat: droid apikey异常自动移除
|
2025-10-11 22:39:41 +08:00 |
|
shaw
|
53dee11a10
|
feat: droid的apikey模式适配多种更新方式
|
2025-10-11 22:15:38 +08:00 |
|
liangjie.wanglj
|
c81ec34ad8
|
常用模型增加deepseek-chat;修复修改时默认选择白名单
|
2025-10-11 18:53:41 +08:00 |
|
shaw
|
4a925e2f8b
|
docs: 更新droid部分内容
|
2025-10-11 12:37:37 +08:00 |
|
shaw
|
a6f5876eca
|
fix: 修复droid类型账号类型显示
|
2025-10-11 11:48:20 +08:00 |
|
shaw
|
6c2ef2eef3
|
fix: 修复droid账号更新丢失apikey的问题
|
2025-10-11 11:23:24 +08:00 |
|
shaw
|
19fa518e65
|
fix: 修复droid追加和代理代理IP提交异常的问题
|
2025-10-11 10:50:26 +08:00 |
|