Sakurasan
|
d357134e97
|
fix: 修 Docker 构建失败,compose 补上生产必需的 OT_JWT_COOKIE_SECURE
- pnpm 11 默认拒绝发布不足 1 天的依赖(供应链策略),锁文件里
tailwind v4 的 @csstools 传递依赖会踩中,导致镜像构建失败且
pnpm build 的 run 前自检(隐式 install)还会再次踩中。pnpm 11
该配置只认 pnpm-workspace.yaml(.npmrc/ENV 均不生效),在
web-builder 阶段写入 minimumReleaseAge: 0;frozen-lockfile +
--ignore-scripts 两道闸仍在,放开无风险
- config.validate 的生产 fail-fast 要求 refresh cookie 必须 Secure,
compose 漏配 OT_JWT_COOKIE_SECURE 导致新镜像启动即被拒绝
|
2026-10-30 02:20:57 +08:00 |
|
Sakurasan
|
854d0f5d8c
|
feat(web): 接入 ESLint 与 vitest,TrendChart hover 读数
- ESLint(flat config,vue essential + ts recommended)接入并清零:
webauthn.ts 标注为刻意的动态类型边界(文件级豁免),theme-init.js
修掉未用的 catch 变量
- vitest + jsdom 接入,build 前置跑测试;覆盖 format 工具、auth store
(token 只存内存、bootstrap 恢复、遗留键清理)、client.ts 401 拦截器
single-flight(自定义 axios adapter 模拟 401→refresh→重放)
- TrendChart:hover 命中区盖满槽位(窄条也可悬停),读数显示在头部行,
标签行联动高亮
- auth store bootstrap 顺手清理旧版 localStorage 遗留的 access token 键
|
2026-10-30 02:04:02 +08:00 |
|
Sakurasan
|
263bfb7845
|
chore: gofmt 对齐(远端提交带入的未格式化文件)
|
2026-10-30 01:42:54 +08:00 |
|
Sakurasan
|
dfe31b5b4f
|
fix(web): 仪表盘 curl 示例模型名改用真实可用模型
硬编码的 gpt-test 让快速开始示例照抄必失败。并发拉取 /user/models
取第一个可用模型,拿不到时退回占位符。
|
2026-10-30 01:42:24 +08:00 |
|
Sakurasan
|
7dce4cadde
|
test: keys CRUD 的 HTTP 级测试
覆盖完整生命周期(明文一次性返回、列表不泄漏明文、改配额、删除)
与用户隔离(跨用户 patch/delete 返回 404 不泄漏存在性)。
SessionAuth 以桩替换,专注 handler 语义。
|
2026-10-30 01:42:23 +08:00 |
|
Sakurasan
|
99829ef745
|
perf: 代理鉴权复用用户查询,last_used_at 按分钟节流
- Auth 加载的完整用户放进上下文,resolveUser 直接复用,省掉每请求
一次重复的 users 查询
- last_used_at 是纯展示字段,改为距上次更新满一分钟才写,高 QPS 下
每请求一次 DB 写降到每密钥每分钟至多一次
|
2026-10-30 01:42:23 +08:00 |
|
Sakurasan
|
9d3648ffe7
|
fix: 限流日计数与用户速率窗口的条目回收
reqDaily/tokDaily/userHits 此前只增不减:停用密钥与久未活动用户的
条目长期堆积。超过阈值时在代理热路径清扫——旧日期的日计数条目
(下次使用本就清零)与窗口内无命中的用户条目直接删除。
|
2026-10-30 01:42:22 +08:00 |
|
Sakurasan
|
bb20ebbed0
|
perf: 渠道 MaxConcurrency 改配置后排空热生效,无需重启
信号量条目带上容量,TryAcquire 发现容量变更且旧槽已排空时就地换新。
release 闭包持有旧 chan,换新后在途请求释放进旧槽是无害的。
|
2026-10-30 01:42:22 +08:00 |
|
Sakurasan
|
a3197e2146
|
fix: 记账同一 trace 防重复扣款
流水 ref_id 有唯一索引,但扣款本身没有:重试/重复 flush 场景下
同一 trace 会被重复扣钱。billUser 扣款前先查 ref_id 是否已存在。
在远端记账重写基础上合并防重检查与测试。
|
2026-10-30 01:21:43 +08:00 |
|
Sakurasan
|
6cb840718f
|
fix: Pick 限最高优先级层加权随机,接入绑定级权重,修 loadBound 顺序丢失
- Pick 只在最高 priority 层内加权随机:低优先级渠道此前可能在首选
渠道健康时被随机打中,priority 只体现在故障转移顺序上
- 均衡权重 = 绑定级 Weight × 渠道级 Weight:绑定表 weight 字段此前
存而不用;乘法合成使默认绑定权重 1 时等价纯渠道权重
- loadBound 原按绑定记录返回顺序输出候选,丢掉了 SQL 的 priority
ASC 排序,绑定渠道的故障转移顺序实际是随机的
- 新增两个测试锁定优先级层与权重语义
|
2026-10-30 01:21:41 +08:00 |
|
Sakurasan
|
57134d2af2
|
fix: 健康探测对 Anthropic 渠道补发 x-api-key 与 anthropic-version 头
官方 Anthropic API 只认 x-api-key,之前只发 Bearer 会让 Anthropic 渠道
持续探测失败被误进 cooldown、流量归零。两个认证头并存互不干扰。
|
2026-10-30 01:21:39 +08:00 |
|
Sakurasan
|
1f8af649ca
|
fix: 收尾 P2——登录恒定耗时、AdminUsage N+1、用量索引重塑与时区缝
- 登录失败路径补 argon2 恒定耗时校验(用户不存在/被禁用与密码错误的时序不可区分,抹掉用户名枚举面)
- AdminUsage 每行 2 次查询改批量预取(100 行分页省 200 次查询)
- usage_logs 补 key_id 索引与 (user,created)/(channel,created) 复合索引(schema v6);AutoMigrate 按名跳过已存在索引,旧库的复合索引需一次性删掉重建,用 system_configs 打标记防 PG 每次启动重演
- 用量统计默认窗口改 UTC(usage_daily 的 date 键是 UTC,非 UTC 服务器上图表窗口偏移一天)
- 注册 email 大小写归一;并发撞唯一索引回查后返回 409 而非 500
- PatchKey 的 name 校验与 CreateKey 对齐(1-64 字符),PATCH 不再能绕过
- TrendChart 条宽不超过槽位(点数多时不再互相重叠),超过 32 个点隐藏标签行
|
2026-10-29 03:05:56 +08:00 |
|
Sakurasan
|
4df2506a74
|
fix(web): access token 移出 localStorage;401 刷新 single-flight 并跳登录页
- access token 只存内存:XSS 拿不到持久凭据;刷新页面由 bootstrap 用 HttpOnly refresh cookie 静默换新;bootstrap 并发去重
- 并发 401 共享一次刷新(refresh 已是轮换式,各自刷新会互相踩);会话失效自动回登录页
- 防主题闪烁内联脚本挪到外部 theme-init.js(配合 CSP script-src 'self')
- 修 console 用量页与管理用户搜索的查询参数未编码;极小金额不再显示科学计数法;渠道表单数字输入清空后省略字段而非提交 0(权重 0 的渠道永远选不中)
- 改密成功后主动清会话回登录页(后端已递增 token_version,当前会话已作废)
|
2026-10-29 02:56:52 +08:00 |
|
Sakurasan
|
e3ff0d3329
|
security: 会话可撤销与认证面加固
- users 加 token_version(schema v4):改密/登出递增,该用户全部已发 access/refresh 立即作废;refresh 改轮换式换发新 cookie
- 邀请码改精确匹配 + 注册成功后消费(一码一用),修复子串匹配让任意后缀放行、可无限薅体验金
- 生产校验拦下 .env.example 占位密钥;OT_ENV 枚举校验(拼错不再静默跳过断言);生产强制 COOKIE_SECURE;非 development 拒绝默认密码播种管理员
- WebAuthn 会话启用过期校验 + 4096 容量上限(未认证 login/begin 可无限撑爆内存),begin/complete 挂登录级限速
- /api/v1 挂 1MB 请求体上限;login 先限 IP 桶再解析 body;全局安全响应头 + CSP
- 连接池配置(PG 30/SQLite 8);SQLite DSN 自动追加 WAL + busy_timeout(驱动只认 _pragma,旧注释的 _journal_mode 写法不生效)
|
2026-10-29 02:56:46 +08:00 |
|
Sakurasan
|
d6db0f8162
|
feat: 补齐三个方向的流式工具调用;Anthropic 上游走 x-api-key;禁用模型真正下架
- 流式转换补齐 chat→responses / responses→chat / messages→responses 的工具调用(此前只转文本,SDK 客户端拿不到 tool_calls);completed 事件携带完整 output 数组
- Anthropic 协议上游同时发 x-api-key(官方 API 不接受 API key 走 Bearer)并透传 anthropic-beta
- 请求侧校验模型存在且启用:禁用模型 404 model_not_found,不再只是从 /v1/models 消失、实际照发照扣费;空模型名 400
- 模型在请求中途被删时按 0 记账留痕,不再按硬编码示例价扣用户的钱
- finishUsage 新增一行式请求日志(trace/user/model/channel/tokens/cost/status/latency),记账是异步的,日志是唯一即时排障依据
|
2026-10-29 02:56:37 +08:00 |
|
Sakurasan
|
984a31cbc5
|
fix: 记账可靠性——关停排空队列、失败重试、扣费不再静默;余额改 SQL 原子递减
- Recorder.Close 改为停止接收+排空残留,channel 不再 close(杜绝 send-on-closed panic),Close 后的 Record 走同步落库
- flush 瞬时 DB 错误重试 3 次,不再整批丢弃;事务内扣费/流水/日聚合失败一律打日志,明细与扣费不再静默脱节
- 扣费与管理员调余额改 SQL 侧原子加减(SQLite 驱动不支持 FOR UPDATE,读-改-写并发会丢扣费);调余额 ref_id 改纳秒不再撞唯一索引
- 最后一个启用的管理员不可被降级/禁用(管理面锁死后 reset-admin-password 救不回)
|
2026-10-29 02:56:31 +08:00 |
|
Sakurasan
|
7c597a6aa0
|
fix: 补上漏掉的 schema 版本号,修好渠道添加模型失败
c39c3e7 给 Model 加了 cache_write_price/context_length/supports_* 等列
但没递增 schemaVersion,user_version>=2 的库直接跳过 AutoMigrate,
models 表缺新列导致 Create 失败、渠道管理添加模型报缺列错误。
bump 到 3 触发一次迁移补齐列。
|
2026-10-28 15:40:03 +08:00 |
|
Sakurasan
|
75c8ecd519
|
fix: 列表页卡片与表格的切换点抬到 lg,补上用户管理的移动端视图
手机上"溢出屏幕"的两个真因(375 / 769 / 1100 三档实测):
- 卡片↔表格切换卡在 md(768px),而侧栏也在 768 出现,吃掉 224px 加 48px 内边距后
内容区只剩 495px,渠道表自然宽 1097px —— 横屏手机、小平板、分屏(768~1023)
整张表被塞进 495px 的盒子里横向滚。改为 lg(1024px) 起才用表格;769px 实测
可见表格数为 0、docSW 等于视口宽。
- 用户管理页只有 720px 的表格、没有卡片回退,手机上只能横向滑整张表。
补移动端卡片(用户名/邮箱、角色与状态、ID/余额/注册时间、编辑与调余额),
表格改 hidden lg:block;1100px 实测 client=826 / scroll=826,铺满不滚。
- 顺带修掉上次改动留下的挤列问题:渠道表"近N小时"列被表格自动布局压到 95px
(min-w 只约束整表、不保证单列),四个指标折成 4 行。该列加 min-w-[190px]、
指标拆两行,并把 Key 并入名称行、启用并入健康行,8 列减到 6 列
(colspan 同步 7→6),自然宽 1125 → 1053。
编辑渠道弹窗 375px 下无溢出元素。遗留:渠道表在 1024~1325 视口仍需容器内横向滚动
(6 列数据表的固有行为,不动整页),卡片列表在 640~1023 仍是单列。
|
2026-10-19 09:25:52 +08:00 |
|
Sakurasan
|
c39c3e7da4
|
feat: 补齐上游细节、渠道观测与模型定价元数据
- 上游 429 的 Retry-After 转成渠道冷却时长(夹在 10 分钟内;比默认值短则不缩短,
否则 1s 就把坏渠道放回轮转)。失败计数改由 proxyOne 就地报——只有它读得到响应头。
- 故障转移时间预算 OT_PROXY_FAILOVER_BUDGET(默认 30s):只约束第二个及以后的渠道,
首个不受限(长回答本就要跑几分钟),但坏渠道不再把客户端拖到 N×timeout。
- 流式空闲心跳 OT_PROXY_STREAM_HEARTBEAT(默认 15s):补一行 SSE 注释 `: ping`,
防止 nginx/Cloudflare 的空闲超时掐掉长思考。心跳与正文共用一把写的锁,
gin 的 ResponseWriter 不是并发安全的;注释行不进转换也不计费。
- 渠道观测:GET /api/v1/admin/channels/stats?window=5m|1h|6h|24h|7d 聚合请求量、
成功率、P50/P95/max 延迟、成本与 top_errors;分位只取成功样本,canceled(客户端
主动断开)不计入渠道错误率。渠道页桌面表格加「近N小时」列、移动端加同内容条,
顶部可切窗口。
- 修一个让统计瞎掉的归因问题:全部渠道失败时 recordError 传的是 nil,
usage_logs 里 channel_id=0,这类失败在渠道维度完全看不见。改为归到最后一个
真正试过的渠道。
- 模型定价与元数据:Model 新增 cache_write_price(0 则回退输入价×1.25,可显式配
Anthropic 1h 的 ×2)、context_length 与 supports_tools/vision/reasoning;
finishUsage 走 CacheWritePriceOr()。/v1/models 叠加用户与密钥白名单过滤
(原来会把限制外的模型名直接泄漏在列表里)并返回元数据,价格不外泄。
- /v1/models 的 Anthropic 分支原是死代码:协议只按路径判,而两种客户端共用这个路径。
改为按 x-api-key / anthropic-version 头判,OpenAI SDK 从不发这两个头,互不影响。
- NewGateway 的十个位置参数换成 Options 结构体(三个 Duration 两个 int,传错编译期发现不了)。
新增 6 个用例:Retry-After 两种写法与夹顶、重试预算截止、空闲心跳出帧、
/v1/models 过滤与双形状、缓存写价两条路径、失败归因。
|
2026-10-17 04:09:39 +08:00 |
|
Sakurasan
|
ad10bdc400
|
security: 补上认证面与输入边界的四处防护
链路功能已经跑通,缺的是边界。这几处默认值都是仓库里公开已知的,忘配就等于没有认证。
- 认证端点限速:/auth/login、/auth/register 此前完全没接限速器(Limiter 只挂在代理
Auth 上),爆破与批量建号零成本。新增 AllowWindow 滑动窗口,登录按「单 IP」和
「单 IP×账号」两个桶(默认 30/min、10/min),注册按 IP(5/min)且在 argon2 之前拦,
避免光靠建号请求打满 CPU;超限返回 429 + Retry-After。
- 生产启动断言:env=production 时拒绝默认 OT_JWT_SECRET、缺失或短于 16 字节的
OT_MASTER_KEY(缺失时 NewEncryptor 会用 sha256("") 派生,渠道密文可被公开还原)、
默认管理员密码;一次列全所有问题,不再改一个试一个。development 不拦。
- 请求体上限:parseBody 原来全量 io.ReadAll 且全项目没有一处 MaxBytesReader,
合法密钥可把任意大 body 整份压进内存再转发。/v1 组挂 BodyLimit(默认 32MB,
OT_PROXY_MAX_BODY_MB),超限按客户端协议返回 413 request_too_large 并点名上限。
- CORS:不再无条件反射 Origin + Allow-Credentials: true——那唯一挡住跨站凭据读取的
是 refresh cookie 的 SameSite=Lax,改成 None 就立刻变成窃取面。改为显式白名单,
空白名单完全不发跨域头(同源部署与 vite proxy 本来就不需要),通配 * 不配凭据;
允许头补上 X-Api-Key / Anthropic-Version / OpenAI-*,否则浏览器里跑官方 SDK 预检会挂。
- 配套 OT_SERVER_TRUSTED_PROXIES:不配置就不信 X-Forwarded-For(防伪造头绕过 IP 限速)。
顺手删掉 .env.example 末尾重复的 OT_PROXY_LOG_RAW 段。
|
2026-10-17 03:25:30 +08:00 |
|
Sakurasan
|
d4c5263f1e
|
feat: 运行期渠道冷却可见并可手动恢复
运行期冷却只存在网关进程内存里,DB 的 health_status 看不见它:渠道被踢到
30s 冷却后,管理后台仍显示 healthy,模型也照常出现在 /v1/models,但请求
返回 503 no_channel,管理员只能去翻日志。
- channel.Service 增 RuntimeState(连续失败次数 + 冷却剩余)与 ClearRuntime;
Gateway 包装出 ChannelRuntime / RecoverChannel 供管理端调用。
- GET /api/v1/admin/channels 每项返回 runtime_fails 与 cooldown_seconds。
- 新增 POST /api/v1/admin/channels/:id/recover:清运行期冷却与失败计数,并把
探测写的 health_status 置回 healthy;不改 enabled,上游若真挂着,下一次探测
或再连续 3 次请求失败会重新把它踢掉。
- 渠道页健康列下方显示「冷却中 Ns」/「连续失败 n/3」,仅在冷却或探测不健康时
出现「立即恢复」按钮(卡片与桌面表格两套布局都覆盖)。
仍未处理:冷却到期是裸恢复、没有 half-open 试探;计数是进程内的,多实例各自
为战,要共享得等 Redis 那一步。
|
2026-10-17 01:19:03 +08:00 |
|
Sakurasan
|
e865f69a41
|
fix: 修掉模型调用链路上的四处失效逻辑
- 超时:NewGateway 里 gw_timeout*time.Second 把已是 Duration 的值二次换算,
int64 溢出后无论 OT_PROXY_TIMEOUT 填多少都等于没有超时,渠道 timeout_ms
也从没被读过。现在非流式用 context deadline 约束整段时长,流式只约束首包
(Transport.ResponseHeaderTimeout),正文不限时长,长回答不会被砍。
- 断连:上游请求改用 NewRequestWithContext 绑定客户端 context,客户端断开即
取消上游并记 canceled,不再空转生成继续付费;PATCH 已写 200 头后不再往
响应里追加错误体。
- 白名单:APIKey.AllowedModels 以前只存不用,现在 Auth 注入 context 并参与
判定(用户黑名单 > 密钥白名单 > 用户白名单 > 全局)。
- 选路:模型已有渠道绑定时只用绑定渠道,都不可用直接 503 no_channel,不再
把请求发给不认识它的渠道;新增运行期健康(连续 3 次网络错误/超时/429/5xx
进 30s 冷却,成功清零),与 60s 一次的 /models 探测互补。
- 密钥 API:PATCH 回显更新后的完整对象;限额填 0 统一视为不限制(原来
token 配额存 0 会让密钥第一次请求就被 429 打死,而请求配额存 0 又等于
不限制,两个字段语义相反);前端编辑框总是提交白名单,清空能真的取消。
测试:新增 proxy 链路集成测试(超时生效、流式不被截断、断连取消并记账、
密钥白名单 403、连续 429 后候选剔除)与 channel 用例(绑定模型不退全局、
冷却阈值与到期恢复、成功清零)。
|
2026-10-16 19:15:51 +08:00 |
|
Sakurasan
|
d911881499
|
feat: add reset-password CLI command for any user
|
2026-09-07 02:33:11 +08:00 |
|
Sakurasan
|
2e3bb22f81
|
fix: use weighted random pick for load balancing instead of sequential iteration
|
2026-09-02 17:32:12 +08:00 |
|
Sakurasan
|
923ac79039
|
删除请求超时
|
2026-09-02 13:08:32 +08:00 |
|
Sakurasan
|
6d951a0d61
|
fix: sync schemaVersion to 2 matching production
|
2026-08-31 18:16:19 +08:00 |
|
Sakurasan
|
1f5f60e905
|
fix: move timeout migration outside schema version check
|
2026-08-31 18:01:33 +08:00 |
|
Sakurasan
|
c6a4fcfbbc
|
fix: migrate existing channels timeout_ms to 300000
|
2026-08-31 17:47:52 +08:00 |
|
Sakurasan
|
5cb428bba9
|
feat: increase default timeout to 5 minutes
|
2026-08-31 16:56:18 +08:00 |
|
Sakurasan
|
658a9cb580
|
fix: SQLite 迁移加版本锁,消除每次启动全量重建表
GORM sqlite AutoMigrate 对已有表判定不收敛(实测已迁移库再跑
仍触发 12 次表重建),SQLite 无在线 ALTER,每次重建走
CREATE __temp + INSERT SELECT + DROP 全表拷贝;usage_logs 含
raw_request/raw_response 大文本,一轮 40~80s,生产每次重启
重演导致启动数分钟。
- 新增 schemaVersion 常量,PRAGMA user_version 记录已迁移版本
- 版本达标跳过 AutoMigrate 秒开;旧库首次升级迁移一次写版本
- postgres 不受影响(支持 ALTER,保持原行为)
- 维护约定:改表结构须递增 schemaVersion
|
2026-08-29 12:46:52 +08:00 |
|
Sakurasan
|
3a836bf0e9
|
fix: curl 示例复制按钮逃逸到页头叠加在退出按钮上
上轮移动端修复误删容器 relative,absolute 按钮向上冒泡定位到
页面顶端。加回 relative 使按钮回到代码块右上角。
|
2026-08-28 21:22:40 +08:00 |
|
Sakurasan
|
faf38e2fd3
|
fix: 修复移动端仪表盘横向溢出
375px 视口下页面被撑到 763px:快速开始卡片的 curl 示例 <pre>
固有宽度沿 flex/grid 链层层撑破祖先(子项默认 min-width:auto
不可收缩,overflow-x-auto 形同虚设)。
- ShellLayout:flex-1 容器与 main 加 min-w-0 切断宽度传播(所有页面受益)
- DashboardView:快速开始卡片各块加 min-w-0,pre 的边框/背景
移入 overflow-hidden 容器、自身横滚
Playwright 实测 375px 视口滚动宽度 763 → 375,与视口齐平
|
2026-08-28 20:12:08 +08:00 |
|
Sakurasan
|
d8257df100
|
fix: messages 流式缓存场景 token 记账错乱
qwen/dashscope 等上游 messages 流式的 usage 语义:
- message_start.usage.input_tokens = 总输入
- message_delta.usage.input_tokens = 非缓存输入(缓存部分单列
cache_read/cache_creation 字段),是最终计费口径
原 usageSink 字段级合并中 delta 的 input 覆盖 start 的 input,
总输入丢失(31790 → 8);缓存写也未参与计费。
- push:带 cache_* 字段的 usage 视为最终口径,整体替换 sink
- finishUsage:缓存写按 1.25× 输入价计费(Anthropic 5m 口径);
落库 input_tokens 存总量(含缓存读/写)便于对账
- 估算兜底条件排除已有缓存计数的请求
- 回归测试:缓存写/缓存命中/chat 末块合并不回归
|
2026-08-28 18:11:24 +08:00 |
|
Sakurasan
|
cd015d370c
|
fix: handle zero channel_id in admin usage logs
|
2026-08-28 16:55:08 +08:00 |
|
Sakurasan
|
939a98d389
|
feat: show channel name in admin usage logs
|
2026-08-28 16:40:23 +08:00 |
|
Sakurasan
|
0b31cc209e
|
fix: chat→responses 转换 input 始终输出数组
单条消息时原逻辑把 input 塌缩成单个对象,火山方舟等上游只接受
[]*InputItem 数组,直接 400(Mismatch type)。chat/messages 经
vole 渠道转换因此全挂。改为恒为数组,三种协议全矩阵实测恢复。
|
2026-08-27 09:57:48 +08:00 |
|
Sakurasan
|
305b3ed731
|
refactor: 删除无用的模型展示名(display_name)字段
该字段仅存取、从不展示:管理列表只渲染 name,/v1/models 与用户侧
均不返回它。与渠道绑定 upstream_model 的名字映射职责重叠且悬空。
- store.Model 结构体、admin CRUD、seed 数据移除 display_name
- 前端编辑弹窗输入框、表单状态、types.ts 同步移除
- 本地库已 ALTER TABLE DROP COLUMN;生产残留列无害
|
2026-08-27 09:57:30 +08:00 |
|
Sakurasan
|
79545aa48e
|
fix: 兼容上游 SSE data: 后无空格格式,流式记账不再 0 消耗
火山方舟等上游流式返回 data:{...}(data: 后无空格),原解析只认
'data: '(带空格),导致 content 文本与 usage 全部漏解析:
- sseContentText 抽成 sseDataPayload,统一处理 data: 前缀
(支持带/不带空格 + event:+data: 多行块)
- scanUsage 复用 sseDataPayload
- convert/stream.go parseLine 也支持 data:{ 无空格
- 新增回归测试覆盖无空格/带空格/多行块三种形态
|
2026-08-27 01:24:30 +08:00 |
|
Sakurasan
|
d818cf3b4c
|
refactor: 命令树移入 internal/cli,去掉 DefaultRun 注入
- cmd/server/cmd → internal/cli,与 internal/api、internal/proxy 平级
- serve() 移入 cli 包作为默认子命令,main.go 退化为纯入口
- 消除 cmd/cmd 冗余层级和 main → cmd 的回调注入
|
2026-08-26 18:14:08 +08:00 |
|
Sakurasan
|
98f296101e
|
refactor: 改用 Cobra 命令行框架,reset-admin-password 带交互提示
- root.go 作为 Cobra 入口,DefaultRun 由 main 注入 serve()
- reset_admin.go 改为 Cobra 子命令,支持 --user/--password 参数
- 交互式:多管理员时选择目标、密码支持手动输入或随机生成(term.ReadPassword 不回显)
- 帮助输出自动生成,无需手写 Usage
- 删除旧的 flag 实现
|
2026-08-26 18:03:03 +08:00 |
|
Sakurasan
|
2983c89b42
|
feat: 新增 reset-admin-password 命令行重置管理员密码
- cmd/server 子命令分发:reset-admin-password 不启动服务
- -password 留空随机生成 16 位(去除易混淆字符),打印一次
- -user 指定目标管理员,仅匹配 role=admin
- 密码长度校验 8-72 与 API 一致,argon2id 参数取自配置
- Makefile 增加 make reset-admin-password 入口
|
2026-08-26 15:57:04 +08:00 |
|
Sakurasan
|
a45a6e16bd
|
fix: API Key 前缀调整为 sk-ot-
|
2026-08-26 15:57:04 +08:00 |
|
Sakurasan
|
c78a473e59
|
feat: API Key 前缀改为 sk-ot
- apikey 包 prefix 常量 sk- → sk-ot(生成/校验/展示前缀统一驱动)
- 鉴权错误提示同步更新为 sk-ot 格式
- 测试断言改用常量,避免硬编码长度
- 前端 curl 示例与 README/PLANNING 文档同步
|
2026-08-25 00:34:50 +08:00 |
|
Sakurasan
|
f7a5741b33
|
fix: 模型列表仅显示已启用渠道中的模型
|
2026-08-22 14:19:45 +08:00 |
|
Sakurasan
|
daf6b8c66b
|
fix: 获取模型列表时过滤已禁用渠道的绑定
|
2026-08-22 13:26:17 +08:00 |
|
Sakurasan
|
8430ecc6c6
|
fix: use inline style for enabled channel highlight
|
2026-08-22 12:21:48 +08:00 |
|
Sakurasan
|
4aa8b79156
|
fix: use bg-accent-soft for enabled channel highlight
|
2026-08-22 12:17:45 +08:00 |
|
Sakurasan
|
94fd7fd40a
|
feat: add highlight for enabled channels
|
2026-08-22 12:09:33 +08:00 |
|
Sakurasan
|
048de4c9a8
|
feat: add enable/disable toggle for channels
|
2026-08-22 02:12:10 +08:00 |
|
Sakurasan
|
781f1b9f83
|
添加 OT_PROXY_LOG_RAW 到 .env.example
|
2026-08-21 11:21:19 +08:00 |
|