Commit Graph

1305 Commits

Author SHA1 Message Date
fawney19
d735b6316f feat: 引入 Rust executor/gateway sidecar 及 Python 侧双后端适配
- 新增 Rust workspace crates: aether-contracts, aether-executor, aether-gateway
- aether-executor: 支持 Unix Socket/TCP 双传输模式,处理同步/流式上游请求
- aether-gateway: 作为本地主入口代理,集成 /api/internal/gateway/resolve 认证预解析
- Python 侧新增 ExecutionPlan 契约和 RustExecutorClient,各 handler 支持
  executor_backend=rust 时将可序列化请求转发给 Rust executor 执行
- 重构 dev.sh 支持 executor/gateway 进程编排与生命周期管理
- 新增 internal gateway 路由,提供 resolve/passthrough 端点
- handler 层(chat/cli/video/endpoint_checker 等)全面适配 Rust executor 回退逻辑
- pipeline 层支持 trusted auth context 跳过重复认证
- 新增 Rust CI workflow 及对应测试用例
2026-03-21 12:57:09 +08:00
fawney19
46737d32f8 feat: 引入 status_snapshot 统一 provider key 状态管理
- 新增 StatusSnapshot 模型,聚合 OAuth / 账号 / 配额三维状态
- 新增 StatusSnapshotStore 负责快照的持久化与查询
- 重构 response_builder / endpoint_models,基于 snapshot 输出状态字段
- 前端抽取 providerKeyStatus / oauthRefreshFeedback 工具函数,
  统一 PoolManagement、ProviderDetailDrawer、BatchDialog 的状态展示
- errorParser 增加已知 OAuth 错误的友好提示
- refresher 适配 snapshot 写入,account_state 扩展状态分类
- 新增 alembic 迁移及存量数据回填脚本
- 补充前后端单元测试
v0.6.3
2026-03-20 19:16:52 +08:00
fawney19
25d38ae632 feat(oauth): 账号封禁前置 OAuth 验证、抽取 provider_context、完善账号状态分类
- 新增 verify_oauth_before_account_block:在标记账号封禁前先尝试刷新 token,
  区分 OAuth 过期与真正的账号级封禁,避免误标
- 抽取 provider_context.py 统一解析 provider_type,解决 ORM detached 访问问题
- account_state 新增 workspace_deactivated 分类和 auto-removable 状态集合,
  补充中文验证关键词匹配
- OAuth refresh 成功后仅清除可恢复的 token 错误,不再自动清除账号级 block
- deploy.sh 依赖指纹改用纯 shell 实现,移除对 Python tomllib 的依赖
- 前端 Pool 管理页面新增筛选和批量操作优化
- 补充对应测试用例
2026-03-20 16:50:59 +08:00
fawney19
aa83b4a7a7 fix: 加固续租失败处理、verify_auth 异常捕获及调度器注册追踪
- task_coordinator: 续租连续失败 5 次后主动触发 lock_lost 回调,失败间加指数退避
- proxy_nodes: lock_lost 回调由 lambda 改为具名 async 函数,确保异步停止逻辑正确执行
- provider_ops: 将 prepare_verify_config 纳入外层 try,捕获 ValueError 并返回失败响应
- maintenance_scheduler: 用 _registered_job_ids 动态追踪已注册任务,stop 时按列表清理
- stats_aggregator: 内联 _do_aggregate 为 for/range(2) 循环,消除内嵌函数
2026-03-20 01:22:07 +08:00
fawney19
913ce2dbcb Merge pull request #252 from AAEE86/nn
fix(startup): 收口 leader 失锁后的后台任务
2026-03-20 01:13:01 +08:00
fawney19
cae5e520ac fix(frontend): 修复 restoreOriginalPlaceholder 递归调用、优化日志参数格式,补全 tsconfig lib 配置 v0.6.2 2026-03-20 01:06:15 +08:00
fawney19
772f2ea601 fix(vertex): SA 认证注入代理配置,细化 token 获取异常处理
- _auth_service_account 接收 endpoint 参数,通过 _get_proxy_config 解析代理
- vertex_auth 区分 TimeoutException/RequestError/通用异常,提供可读错误信息
- 新增测试覆盖代理传递和超时场景
2026-03-20 00:49:44 +08:00
fawney19
28fa03451c feat(provider): 模型测试支持自定义请求头,优化对话框布局与并发策略
- 前后端新增 request_headers 字段,测试时可自定义额外请求头
- ModelTestDialog 拆分为请求头/请求体并排双栏布局,增加格式化与重置按钮
- 区分 Pool 托管(并发5)和单 Key Provider(并发1)的测试并发数
- JsonImportInput 新增 multiple prop 支持单文件模式
- KeyFormDialog Service Account 输入改用 JsonImportInput,支持拖拽导入
2026-03-20 00:24:56 +08:00
fawney19
6984984c22 feat(provider): 重构模型测试对话框,加固 Vertex AI 传输层
模型测试:
- 将消息输入替换为完整 JSON 请求体编辑器,支持格式化和校验
- 新增端点选择面板,测试前可选择目标端点
- 新增调试检查器,可查看每次尝试的请求/响应头和体
- 结果视图改用 HorizontalRequestTimeline 组件展示请求追踪
- endpoint_checker 返回完整调试数据,通过 candidate extra_data 持久化

Vertex AI:
- 改进上下文检测逻辑,不再仅依赖 provider_type,支持从 base_url 推断
- Service Account 密钥现支持自动拉取模型(使用 auth_config 而非 api_key)
- 移除 Gemini Developer API 回退,API Key 仅走 Express 模式
- 端点表单为 Vertex AI 显示格式特定的默认路径模板
- 密钥格式校验仅在 auth_type/api_formats 变更时执行

其他:
- 禁用 ClaudeCode 提供商类型创建入口
- Dialog 组件新增 closeOnBackdrop 属性
2026-03-19 23:52:17 +08:00
AAEE86
1209c835c7 fix(startup): 收口 leader 失锁后的后台任务
- 为后台调度器注册失锁回调并只在 stop 成功后清空生命周期引用
- 停止调度器时移除定时 job,补充启动与任务协调器回归测试
- 降低多 worker 下重复调度风险,保持停机收口与统计聚合回归一致
2026-03-19 22:26:51 +08:00
fawney19
e4ebd5cca1 refactor(oauth): LinuxDo 备用端点回退、Basic Auth 认证,修复 session 外访问 ORM 对象
- LinuxDo provider: token/userinfo 请求增加 backup 端点自动回退
- LinuxDo provider: token 请求改用 HTTP Basic Auth 认证
- 授权 URL 构建: scope 为空时不再发送该参数
- OAuthService: 引入 OAuthAuthenticatedUser 快照,避免 DB session 关闭后访问 ORM 对象
- OAuthService: _handle_login_sync 设置 expire_on_commit=False 防止属性过期
- 新增 LinuxDo provider 单元测试(Basic Auth、端点回退)
- 新增 _handle_login_sync 返回快照的集成测试
2026-03-19 20:32:33 +08:00
fawney19
f573110725 fix(frontend): 用 CSS text-security 替代 password 输入框,简化配额进度条 UI
- Input 组件 masked 模式改用 WebkitTextSecurity: disc 替代 type=password,
  避免浏览器密码管理器自动填充干扰
- LoginDialog/UserFormDialog/Settings/ProxyNodes 密码字段统一迁移到 masked 属性
- PoolManagement 配额进度条布局从 grid 改为 flex,移除未使用的
  getQuotaProgressDisplayClass/getQuotaProgressTooltip 函数

Close #249
Co-authored-by: AAEE86 <ppk0227@hotmail.com>
2026-03-19 20:04:56 +08:00
fawney19
a8620e133a fix(kiro): 加固 Kiro adapter 错误处理与请求构建逻辑
- 提取 request.py 统一 URL/headers/payload 构建,消除 handler_adapter_base 与 envelope 的重复逻辑
- 新增 error_enhancer 模块,分类 HTTP 状态码与连接错误,增强上游错误诊断信息
- envelope 实现 extract_error_text / on_http_status / on_connection_error,透传错误上下文到 eventstream rewriter
- KiroRequestContext 扩展错误状态字段,支持网络诊断信息传递
- provider_oauth_utils 改用 importlib 动态加载,避免 core 层对 services 的静态依赖
- idc auth_method 下跳过 profileArn,修复 usage 查询参数

Closes #247

Co-authored-by: AAEE86 <ppk0227@hotmail.com>
2026-03-19 13:54:40 +08:00
RWDai
ddd6adbcf7 feat(provider): support custom prompts for model tests (#242) 2026-03-19 13:11:54 +08:00
fawney19
b570aaac48 fix: 补全 OpenAI 工具参数 schema 中缺失的 properties 字段
OpenAI API 要求 type=object 的 schema 节点必须声明 properties,
否则会拒绝请求。在 request_from_internal 出口处对工具参数 schema
进行深拷贝并递归补全缺失的空 properties,不影响内部表示。
v0.6.1
2026-03-19 02:36:22 +08:00
fawney19
086efe6efe refactor(usage-queue): ACK 后立即删除消息,清理 consumer 元数据
- 消费成功/移入 DLQ 后立即 XDEL,避免主流 Redis 保留已入库历史
- 缩小 usage_queue_stream_maxlen 默认值:200000 -> 2000(仅作短暂缓冲)
- 启动时清理 pending=0 且长期闲置的旧 consumer(防 consumer group 元数据累积)
- 停机时主动 XGROUP DELCONSUMER 移除自身
- 移除 cache_fingerprint 模块及其对 telemetry/recording_helpers 的引用
- 同步更新相关测试,验证 xdel 调用及 consumer 生命周期行为
2026-03-19 02:09:09 +08:00
fawney19
56f3c95763 fix: 统一 input_context_expr 计算口径,移除按 api_format 分支的 CASE 逻辑
input_context_expr() 原先按 OpenAI/Gemini 和 Claude 分支计算输入上下文,
现统一为 input_tokens + cache_read_input_tokens,与 usage 表展示口径一致。
同步更新 admin 和 user_me 路由中的缓存命中率注释,并新增单元测试。
2026-03-19 01:35:00 +08:00
fawney19
8a6a961900 feat: 增强 OAuth 标识展示与 Codex 调试日志
- 优化 OAuth badge 支持 account_id/account_user_id,tooltip 展示完整身份信息
- 重构池管理额度进度条布局,倒计时独立展示并增加样式区分
- Codex 插件增加 token 解析快照日志,便于排查 OAuth 透传问题

Closes #245
Co-Authored-By: kayphoon <109347466+Kayphoon@users.noreply.github.com>
2026-03-19 00:50:18 +08:00
kayphoon
6e55968487 feat: Codex account_name 透传并优化池列表 OAuth 标识与额度重置倒计时展示
(cherry picked from commit 1b9176fc4a)
2026-03-18 23:58:42 +08:00
fawney19
8d8cddcef6 fix(replay): rerun model mapping on replay target 2026-03-18 23:54:19 +08:00
RWDai
b90d5095f1 Fix replay fallback when model mapping is missing 2026-03-18 23:54:19 +08:00
RWDai
a4505b1281 Fix usage replay model remapping 2026-03-18 23:54:19 +08:00
fawney19
1d72a8f9c1 feat: 流式空闲超时、健康监控查询优化、限流桶内存上限与维护清理修复
Close #233

Co-authored-by: AAEE86 <ppk0227@hotmail.com>

- cli_monitor_mixin: 引入 STREAM_IDLE_TIMEOUT_SECONDS(可通过环境变量配置),
  流传输开始后若超出空闲窗口无新 chunk 则提前取消并返回 504,避免长时间挂起
- stream_context: 新增 managed_recorded_bodies 上下文管理器,确保 chunks 在
  telemetry 完成后及时释放;stream_telemetry 使用该接口统一管理 response body 构建
- health endpoint: 将状态聚合改为 GROUP BY 直接统计,事件列表按 api_format
  单独查询,避免单次 limit 拉取大量记录导致的遗漏与性能问题;同时过滤不活跃
  provider/endpoint,与公开健康接口保持一致
- endpoint health service: 修正时间线数据按 endpoint_id 而非 key_id 聚合
- token_bucket: 引入 max_buckets/bucket_expiry 上限与定时清理,防止内存无限增长;
  修复 refill_rate=0 时 get_reset_time 除零异常;新增 _is_unlimited_rate_limit 判断
- maintenance_scheduler: 调整清理顺序(先删整行再按窗口清理),新增 newer_than
  边界参数,避免同一行在同一轮中被重复改写
- sync_execute: 新增 create_pending_usage 开关,允许已预创建记录的调用方跳过重复创建
- quota_reader / provider_ops balance: 小幅修复与健壮性提升
- Dockerfile: 添加 MALLOC_ARENA_MAX=2 环境变量以降低 gunicorn worker RSS
- 补充相关测试覆盖
2026-03-18 23:38:26 +08:00
fawney19
3d5b6141a5 feat(codex): 引入 upstream_headers hook 机制,为 Codex 注入 session/conversation/account headers
- 新增 upstream_headers.py:可注册 provider+endpoint 维度的 extra headers 构建 hook
- Codex openai:cli 注入 session_id + conversation_id(由 prompt_cache_key sha256 派生)
- Codex openai:compact 注入 chatgpt-account-id(来自 auth_config)+ session_id,不注入 conversation_id
- 修复 prompt_cache:compact 格式现统一为 codex 策略,不再跳过注入
- chat_handler_base / cli_request_mixin 均在 extra_headers 阶段调用 build_upstream_extra_headers
2026-03-18 20:43:14 +08:00
fawney19
203cd5a9d5 fix(redis): 按事件循环隔离 Redis 连接,防止子线程 asyncio.run 导致连接泄漏
RedisClientManager 新增 _redis_by_loop 字典,按 event loop id 维护独立连接,
避免 usage consumer 在 asyncio.to_thread + asyncio.run 场景下复用主循环连接。

同步重构 consumer_streams 的写库路径:_apply_record_event 统一走
record_usage_batch,_apply_streaming_event 改为 to_thread 执行同步 DB 操作,
移除冗余的 session 传递和手动 rollback 逻辑。
2026-03-18 17:56:48 +08:00
fawney19
696ec65175 refactor(normalizer): 移除 request key reorder 机制,保持自然插入顺序
移除 OpenAI/OpenAI CLI normalizer 中的 _reorder_request_prefix_keys 及
基类 _reorder_request_keys 死代码,request_from_internal 直接返回构建
顺序的 dict,测试同步更新为验证自然插入顺序。
2026-03-18 14:01:56 +08:00
fawney19
cbb66a5667 refactor(task): 引入 MutableRequestBodyState 替代 request_body_ref 字典容器
将请求体可变状态从 {"body": dict} 字典容器重构为独立的
MutableRequestBodyState 类,统一管理 original_body / current_body /
build_attempt_body / rectify 等语义,消除各层通过 ref["body"] 间接
读写的隐式约定。

- 新增 src/services/task/request_state.py 定义 Protocol 与实现
- handler/executor/mixin 层改用 request_state 参数传递
- error_handler/state_transition 通过 request_state 判断整流状态
- 新增 request_state 单元测试与 chat/cli 请求体隔离测试
2026-03-18 13:43:39 +08:00
fawney19
53ef35ec80 refactor(cli): 提取 _build_upstream_request 统一流式/非流式的上游请求构建逻辑
将 cli_stream_mixin 和 cli_sync_mixin 中重复的上游请求构建代码
(provider behavior / stream policy / envelope / auth / RequestBuilder / URL 构建)
提取到 cli_request_mixin._build_upstream_request,返回 CliUpstreamRequestResult dataclass。
2026-03-18 13:13:47 +08:00
fawney19
1af3067303 refactor(codex): 移除 envelope/request_patching 层,用 context var 统一 compact 状态判断
- 删除 CodexOAuthEnvelope 和 request_patching 模块,Codex 不再需要 envelope 层
- 移除 _aether_compact 请求体内部标记,改用 is_codex_compact_request() 集中查询
- 简化 OpenAI CLI adapter,移除 Codex 专用的 get_cli_extra_headers/build_test_request_body 逻辑
- 移除 Codex behavior variant 注册(same_format/cross_format)
- normalizer patch_same_format_request 对 codex 变为 no-op
- 更新相关测试适配新的架构
2026-03-18 12:35:57 +08:00
fawney19
d026398bab refactor(body-rules): 移除 protected_body_keys 机制,允许 body_rules 自由修改所有请求体字段
删除 get_cache_sensitive_protected_body_keys 函数及相关常量、_is_protected_path
辅助函数,从 apply_body_rules、RequestBuilder、ProviderRequestResult 等处移除
protected_body_keys 参数,更新所有调用点和测试用例。
v0.6.0
2026-03-18 10:52:07 +08:00
fawney19
684689a82b fix(usage): session touch 独立提交避免行锁阻塞 & 管理员页面顺序加载降低并发压力
后端: 将 session touch 的 commit 从请求事务中分离,防止管理员 usage
页面的长查询持有 user_sessions 行锁阻塞后续请求。touch_session 改为
返回 bool 以支持按需提交。

前端: 管理员 Usage 页面将并行 API 调用改为顺序加载,优先显示记录表格,
统计面板在后台异步刷新,避免瞬时并发打满后端 worker。loadRecords 支持
传入 dateRange 参数确保时间范围一致性。
2026-03-18 00:13:28 +08:00
github-actions[bot]
eeb5f41bad chore(proxy): update download links for proxy-v0.2.5 2026-03-17 14:23:27 +00:00
fawney19
7180eaea88 chore: bump aether-proxy version to 0.2.5 proxy-v0.2.5 2026-03-17 22:16:47 +08:00
fawney19
7cb204f18a chore: bump aether-hub version to 0.2.0 hub-v0.2.0 2026-03-17 22:15:07 +08:00
fawney19
0342f609d0 feat(tunnel): 请求体流式传输 & OpenAI CLI 请求 key 排序优化
Hub 端:
- open_local_stream 不再接收 body 参数,改为通过 push_local_request_body 分块推送
- 请求体按 32KB 分帧发送,避免大请求一次性压缩和传输
- local_relay 改为流式解析 envelope 和转发请求体

Proxy 端:
- stream_handler 改为流式传输请求体到上游,不再预先收集完整 body
- upstream_client 请求体类型从 Full<Bytes> 改为 UnsyncBoxBody 以支持流式传输
- dispatcher 将 StreamEnd/StreamError 事件转发给 stream handler

Python 端:
- hub_transport relay envelope 改为异步生成器流式发送
- 提取 reorder_openai_cli_request_prefix_keys 为公共函数
- Codex passthrough 路径也应用稳定的前缀 key 排序
2026-03-17 22:07:09 +08:00
fawney19
59840fa419 feat(docker): 支持通过 GITHUB_MIRROR 参数加速 hub 二进制下载
Dockerfile.app.local 新增 GITHUB_MIRROR 构建参数,deploy.sh
新增 --mirror 选项,国内服务器可指定镜像代理地址加速下载。
2026-03-17 20:43:14 +08:00
fawney19
d390d46ee8 feat(docker): Dockerfile.app.local 支持本地 hub 二进制文件
将 aether-hub tar.gz 放到项目根目录即可跳过 GitHub 下载,
解决国内服务器构建时 GitHub 访问慢的问题。
2026-03-17 20:37:09 +08:00
fawney19
37eada9682 chore: bump aether-hub version to 0.1.9 hub-v0.1.9 2026-03-17 20:26:29 +08:00
fawney19
73a5325a38 refactor(hub): 用本地 HTTP relay 替代 Worker WebSocket 长连接
Hub 数据面改为 /local/relay/{node_id} HTTP 端点,Worker 通过本机
HTTP 请求转发 tunnel 帧,不再维护 /worker WebSocket 长连接。

Hub 侧:
- 新增 control_plane.rs: Hub 通过 HTTP 回调 Aether app 处理心跳 ACK 和节点状态变更
- 新增 local_relay.rs: 接收本地 HTTP 请求,在 Hub 内部打开 LocalStream 并透传到 proxy
- 移除 worker_conn.rs 及 Worker WebSocket 处理逻辑
- 简化 protocol.rs: 移除 NODE_STATUS 帧类型,抽取通用 encode_frame/decode_payload

Python 侧:
- 删除 tunnel_manager.py 及其 WebSocket 连接管理器 (HubConnectionManager)
- 简化 hub_transport.py 为 HTTP relay 调用
- 新增 src/api/internal/hub.py 接收 Hub 控制面回调 (heartbeat/node-status)
- hub_config.py 移除 WebSocket 相关配置,改为 HTTP relay URL
- service.py 新增 update_tunnel_status 方法
- 删除 src/api/admin/proxy_tunnel.py (旧管理接口)
- proxy_node 缓存 TTL 从 15s 降至 3s 加速状态感知
2026-03-17 20:22:12 +08:00
fawney19
460eb5434d fix(proxy-resolver): 将 resolve_ops_proxy_config 改为异步调用避免阻塞事件循环
在 anyrouter/nekocode/sub2api/yescode 架构及 service.py 中,
将同步的 resolve_ops_proxy_config 替换为 resolve_ops_proxy_config_async,
通过 asyncio.to_thread 包装避免同步 DB 查询阻塞事件循环。
2026-03-17 18:06:15 +08:00
fawney19
8a21cb9a55 chore: bump aether-hub version to 0.1.8 hub-v0.1.8 2026-03-17 17:32:01 +08:00
fawney19
d0df52ce35 fix(hub): worker 断连时向 proxy 端发送 STREAM_ERROR 防止流阻塞
将 unregister_worker 中的 stream 清理逻辑提取为 cancel_streams_for_worker
方法,与 cancel_streams_for_proxy 形成对称设计。worker 断连时主动通知
proxy 端终止相关 stream,防止 proxy 的 stream handler 永久阻塞等待请求体。
添加单元测试覆盖该场景。
2026-03-17 17:29:12 +08:00
fawney19
c1ed42fd3a feat(body-rules): 支持按 provider_type 覆盖 cache-sensitive 保护字段集合
Codex 通过 OpenAI CLI/Compact 格式转发时,endpoint body_rules 需要能
修改 instructions/input/tools 等 prompt 字段。新增 provider_type 维度的
保护集合映射,Codex 场景仅保护 prompt_cache_key,其余 prompt 字段交由
body_rules 自由调整。
2026-03-17 17:09:39 +08:00
fawney19
c4bb6b8161 feat(auth): 重构认证系统,引入 session 会话管理
- 新增 user_sessions 数据库表及 Alembic 迁移
- 实现 SessionService 会话生命周期管理(创建/刷新/撤销/清理)
- 认证流程改用 refresh token cookie + access token 双令牌模式
- 前端实现自动静默刷新、跨标签页同步及设备指纹
- 用户设置页新增会话管理和密码修改功能
- 管理员用户管理新增强制登出和会话查看
- 密码策略增强,支持强度校验和泄露检测
- OAuth 登录流程适配新会话机制
- 新增完整的单元测试和 API 测试覆盖

Closes #232

Co-authored-by: LewisPen <LewisPen@nyadoo.com>
2026-03-17 16:34:09 +08:00
fawney19
d480aa11f3 fix(request-body): 使用 deepcopy 防止请求体在处理流程中被意外修改
handler 基类和格式转换 registry 中,原始请求体通过浅拷贝或直接引用传递,
导致下游处理(模型映射、格式转换、重试整流)可能修改原始数据,
影响后续重试或并发请求的正确性。统一改用 copy.deepcopy 隔离副本。
2026-03-17 13:23:02 +08:00
fawney19
d63d5eff85 fix(nginx): 统一所有 location 块的 CF 头剥离,补充 proxy_hide_header 防止响应泄露 2026-03-17 11:33:43 +08:00
fawney19
5dae2a4792 fix(normalizer): 移除 Claude system 中的 billing header 2026-03-17 11:10:04 +08:00
fawney19
dcbd7dc219 feat(normalizer): 稳定请求体字段顺序以提升 prompt cache 命中率
在 FormatNormalizer 基类新增 _reorder_request_keys 方法,OpenAI/OpenAI CLI
normalizer 各自定义前缀字段顺序(model, tools, messages / model, instructions,
tools, input),确保静态字段前置、动态内容后置。同时调整 OpenAI CLI 中
instructions 字段的构建位置使其在 input 之前。
2026-03-17 10:26:57 +08:00
fawney19
2dcf8b8414 refactor(prompt-cache): 移除 client_family 命名空间拆分,统一缓存 key 提升复用率
不再按 User-Agent 客户端类型拆分 prompt cache namespace,
所有客户端共享同一缓存 key,版本升级至 v3。
2026-03-17 09:49:35 +08:00
fawney19
438f16094f refactor(stream): 将不完整流 token 估算逻辑收敛到 StreamContext
- 新增 has_partial_response / ensure_estimated_output_tokens / should_estimate_incomplete_tokens 方法
- CancelledError 路径在归因前即补充 output_tokens,确保日志包含估算值
- CLI Handler 和 Chat Handler 的兜底估算统一使用 should_estimate_incomplete_tokens
- 移除 cli_monitor_mixin 和 stream_telemetry 中重复的条件判断
- 新增对应单元测试
2026-03-17 03:37:06 +08:00