Skip to content

Releases: zhanghaojie513/waygate-open

v1.6.29 — 补上遗漏的两个导入脚本

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 12:21

v1.6.29 — 补上遗漏的两个导入脚本

v1.6.28 还是不能用

v1.6.28 修了数据目录、UI 按钮、文案覆盖、推送脚本打包 —— 但漏了服务端真正调用的两个脚本:

server/tools/minimax-import-credential.mjs
server/tools/qoder-import-credential.mjs

它们不在 files 白名单里,npm 用户点「从本机客户端读取」只会得到
「导入脚本不存在(部署未带 tools/ 目录?)」。

验证(这次是真跑,不是看代码)

从 tarball 装到临时目录 → 起服务 → 新建 MiniMax 提供商 → 点 import-local:

阶段 结果
导入前 anthropic configured=false / 未配置
导入 ok=true, outcome=imported
导入后 anthropic configured=true / mmor••••AjkQ

教训

files 白名单是手写清单:改了调用方("要跑哪个脚本")就必须同步清单。
以后每新增一个 this.toolsPath('X'),都要确认 X 已在 files 里。

v1.6.28 — 修「从本机客户端读取」四个真问题

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 09:32

v1.6.28 — 修「从本机客户端读取」四个真问题

用户问:「开源版本地启动,为什么还报读不到客户端登录态?」—— 查证后是四个独立缺陷。

① 凭证写到了服务看不到的目录(最严重)

run() 传给导入脚本的 RELAY_DATA_DIR 回落到 server/../data(包根下),
而 npm 形态下服务端的数据目录是 ~/.waygate/open(由 bin 注入)。

后果:按钮报「导入成功」,控制台却仍是「未配置」—— 凭证写进了一个服务根本不读的地方。

修法:改用服务端自己的 resolveDataDir(),两者同源。
实测:导入后 configured 由 false 变 true,mask 正确显示。

② WorkBuddy 不该有「从本机客户端读取」按钮

它走 OAuth,本机没有可读的登录态文件 —— 按钮对它永远只会失败。
后端文案也过时(「用静态 API 密钥,在配置里更换」—— ck_ 早退役,界面没有那个入口)。
修法:UI 对 openai 协议不显示该按钮;后端文案改为指向「重新导入授权」。

③ 前端把后端的原因覆盖了

不管后端说什么,一律替换成「读不到客户端登录态(远程部署的正常情形)」——
对本地启动的用户是误导。修法:原文照显示,只在真需要跨机推送时补命令。

④ npm 包里没有推送脚本

files 白名单没有 server/tools,分离部署的用户照提示敲命令会 file not found。
修法:把 import-credential-push.mjs + lib/read-client-credential.mjs 打进包。

⑤ 顺带:MiniMax 提示分情况

不再一口咬定「分离部署」,改为先问「客户端是不是就在这台机器上(只是没登录过)」,
再说跨机推送那条路。

验证

真机跑通完整链路:新建 MiniMax 提供商 → import-local → configured=true。
server 765 全绿;web typecheck + lint 全绿。

v1.6.27 — 重启后仍能识别默认口令

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 08:58

v1.6.27 — 重启后仍能识别默认口令

真实缺陷(用户提问「别人安装使用会出现这个问题吗」——会)

首次启动(waygate)→ 重启 → 登录页不再显示口令,但口令其实还是 waygate。
用户只能靠记忆或翻旧终端,否则根本不知道该输什么。

根因

判断标记只在「首次生成」时置位;重启走「读数据库」分支,标记被重置为 false。
而数据库的 source='generated' 同时表示「内置默认 waygate」与「随机生成的 16 位」——
靠它判断会把早先随机生成过口令的用户误判成「还在用默认值」,
于是登录页显示一个输进去必然报错的 waygate。

改法:自证式判定

启动装载完哈希后,直接验一次 waygate 是否匹配(scryptSync,实测 ~67ms)。
验得过就是默认值、验不过就不是 —— 没有歧义,也不依赖任何来源标记。

场景 结果
重启后库里仍是 waygate ✅ true,登录页继续显示
库里是随机 16 位(即使 source=generated) ✅ false,不显示错的
用户改密 ✅ 重新自证,自然变 false
坏哈希 ✅ false(宁可不显示,也不显示错的)

附带一层保险:用户无法主动把口令改回 waygate —— 密码策略下限是 8 位,
而 waygate 只有 7 位。

验证

首次启动 → 打印口令;重启 → hint 仍返回 waygate 且登录成功;
server 759 → 765(新增 6 个自证用例)。

v1.6.26 — 启动器不再谎报口令

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 08:23

v1.6.26 — 启动器不再谎报口令

用户实际问题

登录页输入 waygate 报「管理口令不正确」—— 因为终端那句「管理口令 waygate(默认…)」是错的。

根因:启动器无条件打印注入的默认口令,但服务端的装载优先级是
env hash > 数据库 > 文件 > 首次生成。库里早有 10-16 随机生成的口令时,
注入的 waygate 根本不会被采用 —— 等于告诉用户一个无效口令。

改法

启动器按「数据目录里有没有 relay.db」区分:

场景 输出
首次启动 管理口令 waygate(默认,建议登录后改掉)
库已存在 管理口令 沿用已有口令(忘记可在控制台重置:设置 → 管理口令)
显式 --password 如实打印「(你指定)」

明文我们不知道(也不该知道)—— 指向重置路径比编一个值有用。

登录页提示按要求改成按钮下方一行:本机默认口令:waygate。

验证

  • 全新目录:打印 waygate;bootstrap-hint 返回 waygate;用它登录成功
  • 同目录二次启动:打印「沿用已有口令」;bootstrap-hint 返回 false
  • server 759 全绿;web typecheck + lint 全绿

v1.6.25 — 登录页预填内置默认口令

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 07:41

v1.6.25 — 登录页预填内置默认口令

问题

本机启动时(CLI 在回环绑定时注入默认口令 waygate),这个口令只出现在终端输出里,
登录页的输入框只有占位符 —— 用户得切回终端翻。

改法

新增 GET /api/auth/bootstrap-hint,登录页加载时预填:

已填入本机默认口令 waygate —— 直接点「进入控制台」即可。
登录后请到「设置 → 管理口令」改掉它。

两条安全约束

  1. 改密即失效 —— 用户在控制台换过口令后,接口立刻返回 defaultInUse:false,
    绝不会再把 waygate 摆在输入框里
  2. 只对回环开放 —— 用真实 TCP 对端判定(忽略 XFF)。若实例被 --host 0.0.0.0
    暴露到公网,这个接口不会告诉任何人默认口令

waygate 本身是公开值(README / 启动日志 / 源码里都有),交给前端不增加暴露面;
页面显示的是「本机默认口令」,不是用户自定的秘密。

验证

场景 结果
首次启动 + 回环 ✅ 返回 {"defaultInUse":true,"password":"waygate"},登录成功
改密后 ✅ 立刻 {"defaultInUse":false,"password":null}
非回环 ✅ false(不返回明文)
自定口令 / 随机生成 / 库内已有 ✅ 全 false

server 754 → 759(新增 5 个判据用例);web typecheck + lint + build 全绿。

v1.6.24 — 默认端口不可用时自动改用可用端口

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 06:56

v1.6.24 — 默认端口不可用时自动改用可用端口

问题

npx waygate-open 直接启动失败:

端口 8787 无权绑定(EACCES)。

v1.6.23 加了预检(提示比堆栈友好),但只是提示然后退出 —— 用户仍要手动加 --port。
而 8787 落在 Windows 系统预留段(Hyper-V / WSL / Docker 申请的排除区间,实测 8691–8790)
不是个别环境。「装完直接 npx 就能跑」是本地工具的底线。

改法(与 core 0.2.10 / 三个独立工具对齐)

  • 没显式指定 --port / RELAY_PORT 时,默认端口不可用就往后找一个能用的
    (从 8791 起,最多 20 个),并如实告知:
默认端口 8787 在本机不可用(多半是 Windows 系统预留段),已自动改用 8791。
  · 想固定下来:加 `--port 8791`,或设 RELAY_PORT=8791;
  · 查预留段:netsh interface ipv4 show excludedportrange protocol=tcp
  • 显式指定了却绑不上 → 原样报错,不偷改(部署脚本里的固定端口不能被换掉)

验证

场景 结果
npx waygate-open(8787 在保留段) ✅ 自动用 8791,healthz 200
--port 8787 ✅ 原样报 EACCES 提示
--port 8795 ✅ 用 8795,无「自动改用」提示

v1.6.23 — 端口预检

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 19 Oct 02:50

v1.6.23 — 端口预检

问题

npx waygate-open 在部分 Windows 机器上启动失败:

ERROR [NestApplication] Error: listen EACCES: permission denied 127.0.0.1:8787

Nest 全部模块都初始化成功,只有最后 bind 失败,然后抛一屏原始堆栈。

真因

netstat 看不到 8787 被占用 —— 但 netsh interface ipv4 show excludedportrange protocol=tcp
显示 8691–8790 是系统预留段(Hyper-V / WSL / Docker 向 usermode 申请的排除区间)。
落在里面的端口 bind 恒 EACCES,且没有任何进程可见。对用户来说完全反直觉。

改法

启动前先试绑一次,把失败翻译成能直接照做的中文提示:

情况 提示内容
EACCES 点明可能是 Windows 预留段、给出查预留段的命令、给出可用端口示例(--port 8791)、setx RELAY_PORT 常驻写法
EADDRINUSE 换端口 + 查占用者(netstat -ano | findstr :PORT / lsof -i :PORT)
端口越界 直接说范围 1–65535

不改默认端口 8787:它是产品约定(README / .env.example / 服务端兜底三处一致),
本机撞上预留段属环境问题,靠提示引导换端口更合适。

验证

三种失败分支逐个实测通过;空闲端口(8791)预检放行且服务正常启动(healthz 200);
--help 不触发预检;node --check 语法通过。

v1.6.22 — 更新截图与架构 / 功能图

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 17 Oct 17:18

v1.6.22 — 更新截图与架构 / 功能图

用户指出「README 中的图、架构图、功能图都没更新」—— 核实属实:docs/img/* 与两张 HTML 图
全部停在 2026-10-14,而之后界面改了多处(概览移除积分账本面板、行内去掉「重新导入授权」、
字号令牌、登录页棱镜重做)。

截图(6 张)

  • console-overview / console-usage / console-requests / intro:按新 UI 重拍
  • 新增 console-clients / console-keys / console-settings —— README 原本只展示 3 张,
    现在补齐提供商管理、API Keys、设置三页(与私有仓 2×2 布局一致)

架构图 / 功能图(两张 HTML)

同步新配色(iris 主题令牌),并补上本批新增内容:

位置 变更
架构图「容错」 断流重试 · 11128 渠道降级 · 渠道熔断(快速失败不占槽)
架构图「模型目录」 seed/upstream/observed/manual → 三家真拉取(WB / Qoder / MiniMax)· seed 回落 · observed 并入
功能图「运行保障」 新增渠道熔断条目(阈值 3 / 不占槽 / 只计渠道级信号)

验证

两张 HTML 的 <div> 开闭配对(46/46、2/2);SVG/XML 严格门禁通过;
note token 门禁 37/37;server 754 全绿。

v1.6.21 — 版本收口(README 同步到 npm 包页)

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 17 Oct 16:08

v1.6.21 — 版本收口(README 同步到 npm 包页)

本版无代码改动。

为什么发这一版

npm 的 README 是发布时快照:1.6.20 打包的是旧 README,之后补的文档只到了 GitHub
(npm 包页仍显示「只写了 npx」,且带着测试数 727、MiniMax「无清单端点」等过时表述)。

本版把完善后的 README 带进包

  • 全局安装与 npx 并列:npm install -g waygate-open(长期使用);固定版本写法
    npx waygate-open@1.6.21
  • 「第一步:导入客户端凭证」:三家授权方式对照表(WorkBuddy OAuth / MiniMax PKCE
    设备码 / Qoder PKCE)+ 设备码等待态说明 + 「服务端读不到本机登录态是正常情形」
  • 修正过时事实:测试数 727→754;MiniMax 目录「无清单端点」→ 真拉取
    /mavis/api/v1/models(旧结论测错了路径);Qoder 段去掉「积分账本并入概览」;
    RELAY_DATA_DIR 默认值补源码模式 / npm 模式的差异
  • 补充:11128 渠道熔断(阈值 3 / 冷却 30s 指数退避 / 只计渠道级信号的理由)、
    在途删除密钥不丢审计行、目录树补 channel-breaker.ts

验证

从 tarball 真装真跑:/healthz 报 1.6.21、/ 200;包内 README 已含
npm install -g waygate-open(本版唯一目的)。

v1.6.20 — 在途删除密钥不丢审计行 + 密钥弹窗显示名

Choose a tag to compare

@zhanghaojie513 zhanghaojie513 released this 17 Oct 15:11

v1.6.20 — 在途删除密钥不丢审计行 + 密钥弹窗显示名

与私有仓同步(v1.6.28)。

① 流式请求在途时密钥被删 → 整行审计丢失

请求还在飞、密钥先被删时,随后落库撞 key_id 外键(ON DELETE SET NULL 只清理删除那一刻
已存在的子行),整行审计(tokens / 积分 / 状态 / 耗时)被 FOREIGN KEY constraint failed 丢弃。

修法(writeLog):识别 FK 违例 → key_id 降级 NULL 重试一次,保住整行。

  • 保留 client_id / key_hint 文本快照(不改写成 unidentified,避免污染客户端排行)
  • note 追加 key_deleted_inflight 便于事后辨认
  • 聚合桶照常递增;用量缓存不再喂已不存在的 keyId

② 密钥弹窗「已选」列表显示提供商名称而非内部 id

v1.6.19 把绑定值从 name 改成 id 后,勾选区显示名字、下方「已选」却直接渲染 value
(p_default00 这类内部 id),两处对不上。现在提交值仍是 id(唯一键),只在显示时经
providerOptions 翻译回名字;旧名字值 / 已删除提供商回落原值,如实暴露孤儿绑定。

③ 「已选」列表字号对齐

.picked-item 此前没有 font-size,继承 body 的 16px;而勾选行 .pick-row 是 12.5px ——
同一个提供商名在「勾选区」和「已选区」一大一小。两块是同一条绑定的两种视图,统一字号。

④ note 映射补齐

  • breaker_open:文案改为「渠道熔断中(未发上游)」—— 原文案「稍后自动恢复」没点明本质
    (我们主动不发,而非上游拒绝)
  • key_deleted_inflight:新增映射 + 契约表登记

验证

server 750 → 754(新增 4 个在途删除用例)全绿;
web typecheck + lint(37/37 token 门禁)+ build 全绿。