hrz
|
8f2dda09cf
|
Bump to 0.9.8 (#3469)
v0.9.8
|
2026-10-23 18:54:05 +08:00 |
|
hrz
|
d4ff9c5c17
|
修掉通讯录的两处越权(读 + 写),并补上三处空指针 (#3460)
* 读取设备通讯录先验设备归属
登录用户传任意 MAC 就能读到别人设备通讯录里的备注和称呼。归属判断收进一个方法,读取通讯录、改别名、改权限都走它,不属于当前用户的设备一律按查不到处理。
* 通讯录存别名不再空指针
对方设备没登记时取备注会直接崩,整条权限授予请求跟着挂掉。取不到就退回尾号称呼,呼叫时主叫没登记也不再崩,顺手删掉一行调试打印。
* 解绑先验归属,通讯录别名不再落空
解绑接口原来不核对设备归属,谁知道对方的设备 id 就能把那台设备的通讯录清空,设备本身倒是因为带了用户条件没删掉。现在先看归属,不是自己的直接不动。
设备登记了但用户没起名时,别名会落成空,缓存刷新把整条跳过,对方再也呼不过来。改成和呼叫那处一样,两级判空都取不到才退回尾号称呼。顺带加了一条回填,把写进去的空值补上。
呼叫那条测试原来会真发请求也没验到东西,改成桩掉网关直接看发出去的称呼。
* 通讯录空别名兜底,撞名加后缀
缓存拼表之前,空别名先用尾号称呼顶上,不再整条跳过,用户没起名的设备也能被呼到。
昵称在同一个人的通讯录里是索引,两台撞名时后写的会盖掉先写的,按昵称呼会呼错设备。加后缀区分,规则和存表时那套一致。取名靠先后,而查询不带排序,所以先按地址排一遍,同样的数据每次刷新结果一样。
数据库没有排序保证,去重全靠顺序,所以这里先排再拼。迁移脚本不用动,运行时的兜底能管住它没覆盖到的行。
* 通讯录取名两条路径对上了
后缀原来只写进缓存,接口直查库返回原值,同一份数据给的是两个名字。
用户照控制台看到的名字呼叫,命中的不是同一台设备。
把取名抽成一个方法,两边都走一遍。顺带把权限位排到地址前面,
撞名时能呼的那台先拿原名,反过来用户怎么点都只会说没权限。
迁移取末两位时改成跟着小写化,和运行期算出的是同一个称呼。
* 同一个人被拆成两本通讯录,一台设备消失
两条记录的归属地址只差大小写时,会被算成两个人,各拿一个同名,
写进同一本时后者盖掉前者,一台设备就从缓存里消失了。
把归属地址归一抽成一个方法,算称呼、写缓存、查缓存都走它。
* 通讯录接口按最近改过的排前,这个约定有用例钉住
智控台页面是按对方地址把备注合进去的,接口返回顺序它并不关心,
所以现在这么排对界面没有效果。
用例留着是防它被当无用代码删掉,删了会有用例报出来。
* 迁移串到别人的私名,撞车的组改走尾号称呼
通讯录回填名字时,设备表里同一个 MAC 有两行(同一台被两个用户各登记一次),
MySQL 自己挑一行填进去,跟这行属于谁无关。改成只有一台时才取智控台名字,
多台就退回按 MAC 末两位算的称呼。名字照样填上,缓存照样刷新,对方还是呼得到。
补了 12 条在真库上跑的用例,另配一条排查重复 MAC 的语句。
* 去掉走不到的分支和没人用的桩,补上末尾换行
getUser() 取不到 subject 或 principal 时返回的是空对象,不是 null,
user == null 走不到,删掉;用例改成桩空对象,测真正的匿名那条路。
归属判断挪进 service 之后,controller 层四处 SecurityUser 的桩没人用了,删掉。
四个文件末尾少了换行,补上。另加一条用例钉住判重分组的比较规则:
只折叠大小写,不折叠分隔符。
* 移除回填通讯录别名的迁移,运行时已经兜住了
这个迁移是本 PR 带进来的。它要把空别名刷成称呼,可运行时的兜底已经做了一样的事,
而且覆盖得更宽:那边连纯空格、地址为空和不足两位的都管。删掉它,功能不受影响。
删它有两条理由。一是重复。二是它按 MAC 去设备表取名字,
而一个 MAC 在设备表里可能有多行——同一台设备被两个用户各登记一次就能造出来,
这时候取到的是别人给自己设备起的名字。写在这里,是怕后来的人以为这个坑不存在。
* 归属校验撞到重复 MAC 不再报错
库里同一 MAC 可能有两行只差大小写,selectOne 会抛 TooManyResultsException,把读通讯录接口整个带崩。改成 selectList 按 id 取第一条做归属校验,撞行时正常返回,不再报错。
|
2026-10-23 17:43:05 +08:00 |
|
wengzh
|
3709540efd
|
Merge pull request #3445 from xinnan-tech/fix/huoshan-double-stream-4-bugs-y15
huoshan_double_stream 修 4 个会话协议与监听竞态 bug
|
2026-10-23 17:37:05 +08:00 |
|
wengzh
|
333050ae2e
|
Merge pull request #3464 from xinnan-tech/chore/bump-deps-20261023
chore(deps): 批量升级 15 个依赖,适配 mcp 2.x
|
2026-10-23 17:05:05 +08:00 |
|
Sakura-RanChen
|
95ce49ffc9
|
删除 benchmark/ 下 3438~3441 回归验证脚本
四处修复均已验证收敛,脚本不进 CI、裸跑依赖 manager-api,保留仅为仓库噪声;后续若再动 huoshan_double_stream 时以 pytest 覆盖
|
2026-10-23 17:04:52 +08:00 |
|
Sakura-RanChen
|
be75e7bd39
|
chore(deps): 批量升级 15 个依赖,适配 mcp 2.x
源 PR: #3426 #3427 #3428 #3429
剔除 4 项:
- edge-tts 7.3.1->7.2.8 是降级
- powermem >=1.1.7 要求 Python>=3.11
- openai 3.29.0 与 powermem 冲突(powermem 要求 openai<3.0.0)
- ruamel.yaml 0.19.1 与 hyperpyyaml 冲突
mcp 2.x 适配: streamablehttp_client 更名为 streamable_http_client,headers/timeout
改由 http_client 承载,产出从 3 元组变 2 元组,ProgressFnT 移到 mcp.shared.dispatcher
|
2026-10-23 15:15:50 +08:00 |
|
hrz
|
24fbf7eee2
|
登录 token 12h 静默失效补 silent refresh 接口 #3392 (#3402)
* 登录 token 12h 静默失效补 silent refresh 接口 #3392
方案 A:后端 POST /xiaozhi/user/refresh(anon),旧 token 校验通过后强制覆盖为新 token 字符串,旧 token 在 DB 查不到即失效。前端 httpRequest 在 sendRequest 入口检查 token 剩余有效期,剩 1h 内触发 silent refresh(独立 fly 实例 + 单飞锁),成功后 setToken 替换并自动继续发送当前请求,失败走 clearAuth 跳登录。
* refreshToken 改 CAS 防并发 race + 拆前端副作用 #3392
P1:SysUserTokenDao 新增 refreshTokenCAS,条件 UPDATE(oldToken + 未过期 + userId),受影响 0 行抛 TOKEN_INVALID;refreshToken 改调它,避免读-改-写 race。P2:refreshToken 加 @Transactional;httpRequest.getTokenExpireAt 内的 localStorage.setItem 挪到独立 persistTokenExpireAt,由 shouldRefresh 入口调用。
* getTokenExpireAt 改读 localStorage 与持久化同源 #3392
pr01 三改:原代码 getTokenExpireAt 读 store(state.token 缓存),与 persistTokenExpireAt 写 localStorage 不同源,导致 _localStoredAt 缺失 → NaN → shouldRefresh 永 false → silent refresh 永不触发。修复:getTokenExpireAt 改读 localStorage,persistTokenExpireAt 同步刷 store,保证两端一致。e2e 已验证:注入 expire=1800 token → reload → role-config mount 触发 sendRequest → Network 抓到 POST /user/refresh 200 → localStorage token 被替换为新 12h token(含 _localStoredAt)。
* 应用启动同步 localStorage token 到 store #3392
PR #3402 扩展:守卫放行后首次 API 请求时,vuex state.token 还是 null,httpRequest 读 store 取不到 Authorization 头,会被后端 401 → clearAuth 跳登录。在 main.js 应用启动阶段就把 localStorage 里的 token commit 进 store,避免 race。不动 refresh 链路与其它业务文件。
|
2026-10-23 09:47:41 +08:00 |
|
 hrzandSakura-RanChen
|
fdf280f84a
|
模板 GET 入口迁回 AgentTemplateController #3395 (#3401)
* 模板 GET 入口迁回 AgentTemplateController #3395
根因:AgentController 已存在 GET /agent/template/templateList,AgentTemplateController 缺显式 GET,于是路由虽通却跨 controller 暴露模板数据,且职责错位。修复:删 AgentController.templateList,同名 @GetMapping(无 path)落到 AgentTemplateController,权限 normal、orderByAsc sort、复用现有 service.list。验证:spring-boot 启动期无 Ambiguous;/agent/template、/page、/{id} 三路由均被 Shiro 一致拦截,权限/路径正确。
* 补 P2 注释说明 normal 权限反直觉是有意保留 #3395
在 getAgentTemplates 上方加 2 行注释,说明单独 normal 权限是为保持原行为契约(普通用户也能查可用模板),与类级 superAdmin 故意分离;非疏忽。无逻辑变更。
* 去除未使用引用
---------
Co-authored-by: Sakura-RanChen <1908198662@qq.com>
|
2026-10-22 11:42:48 +08:00 |
|
wengzh
|
498191519c
|
Merge pull request #3452 from xinnan-tech/py-test-wakeup
Py test wakeup
|
2026-10-22 11:08:38 +08:00 |
|
wengzh
|
f614489d81
|
Merge pull request #3454 from xinnan-tech/web-test-json
Web test json
|
2026-10-20 15:44:16 +08:00 |
|
Sakura-RanChen
|
6f958ee4a6
|
fix: 新增模型页面dict字段错误解析
|
2026-10-20 15:34:40 +08:00 |
|
TXyy2023
|
b226ee5430
|
fix(manager-web): decode stored dictionaries before editing (#3450)
|
2026-10-20 11:53:02 +08:00 |
|
Sakura-RanChen
|
9c30b5e035
|
文件直接写入wav,无需经过二次编解码
|
2026-10-20 10:45:31 +08:00 |
|
TXyy2023
|
d531d04281
|
fix(tts): handle retained audio files in wakeup cache (#3451)
|
2026-10-20 10:00:20 +08:00 |
|
Sakura-RanChen
|
d8f8a4a083
|
- 取消屏障保证:新连接创建前 _cancel_monitor_task 已等旧监听任务完全退出,
旧任务不可能读新连接或误关新连接(check_huoshan_3440 动态断言覆盖)
- mismatch 分支仅保留纯跳过,删除旧会话结束事件的复位遗留,
activate_session 写入点收敛到会话生命周期(start / matched 结束 / close)
- 删除 _session_start_future 启动确认机制:start_session 发送即返回,
SessionFailed 由 monitor 记 error 并复位 activate_session,无挂起风险
- 回归脚本同步调整:3438 重写为新行为断言,3440 用屏障断言替换 snapshot 断言
|
2026-10-19 17:52:25 +08:00 |
|
hrz
|
6840210ea8
|
check_huoshan_3439 改 FIRST 分支行为断言
原 test 用正则 grep 源码验存在性,pr02 复评指出这样测不到实际调用。
改成起后台线程跑真 tts_text_priority_thread、构造 FIRST 消息入队、
run_coroutine_threadsafe patch 成立即完成的 future,最后断言
reset_stream_state 与 opus_encoder.reset_state 各被调一次。
|
2026-10-17 07:57:30 +08:00 |
|
hrz
|
0a54124d0d
|
huoshan_double_stream 修 3 处复评反馈
init 漏写 _pending_prefix 字段、start_session 用已弃用的
get_event_loop、finish_session 留着多余的 getattr 兜底。补字段、
换 get_running_loop、去兜底,3 处都修了。
|
2026-10-17 07:57:26 +08:00 |
|
hrz
|
ddc441bc59
|
补 huoshan_double_stream 4 bug 复现脚本
四个独立脚本各覆盖一个 issue:start_session 等 future 确认、句尾残留与编码器
冲刷、monitor snapshot 隔离、parser_response 四处协议解析。共享 _huoshan_mock
构造一个绕开父类 init 的假 provider 实例。
|
2026-10-17 07:39:51 +08:00 |
|
hrz
|
9b7fb3e826
|
parser_response 四处二进制协议解析修正
serialization_method 错用掩码当移位数恒 0,改成 >>4;message_type 写
== FULL or AUDIO_ONLY_RESPONSE 优先级下恒真,改 in (...);offset 硬编码 4 在
header_size>1 全错位,改成 header_size * 4;SessionCanceled 漏进协议分支被
else 误读,补进统一解析。
|
2026-10-17 07:39:51 +08:00 |
|
hrz
|
a6cdbf9410
|
监听任务用 snapshot 隔离跨连接
旧 monitor 循环直接 self.ws.recv(),连接重建后旧任务读新下行;finally 无条件
关 self.ws 误关新连接。改成入口绑 monitor_ws / monitor_task,recv 用 snapshot;
旧 session 事件 continue 不再 reset 当前;finally 判 id 相同才关 ws / 清引用。
|
2026-10-17 07:39:51 +08:00 |
|
hrz
|
75fd5d8cc3
|
句尾替换词残留先发 + 会话结束冲刷编码器
旧 finish_session 不发 _pending_prefix 残留,句尾替换词被扣时整段丢;monitor / to_tts
收 SessionFinished 不调 is_end=True 冲刷 opus 编码器,每句固定丢尾。改成
finish_session 开头先发残留,monitor / to_tts 调 is_end=True 冲刷,FIRST 同步重置。
|
2026-10-17 07:39:51 +08:00 |
|
hrz
|
6fe5630346
|
TTS 会话等 SessionStarted 确认
旧逻辑 start_session 发完 StartSession 即返回;服务端鉴权失败或 14s 内 26005 时
文本线程继续给死会话发文本,整轮无声。改成末尾 await 一个 future:monitor 读到
SessionStarted set True、读到 SessionFailed set False,超时报错让文本线程感知。
|
2026-10-17 07:39:50 +08:00 |
|
hrz
|
eb9dc8ca0f
|
把 pydub 探针绑到当前解释器同目录的完整版 ffmpeg (#3444)
edge_tts 升 7.3.1;edge.py 撤 WSS_URL patch 改默认
(4.36 跑默认 URL 稳定)。util.py 加 PATH 临时注入,
绕开 Mac 上 Trae CN 注入的精简版 ffmpeg/ffprobe,
让 pydub 拿 conda env 完整版。引用计数加锁防多线
程串。
|
2026-10-15 15:43:39 +08:00 |
|
wengzh
|
27399a2fb6
|
Merge pull request #3430 from xinnan-tech/py-text-test
Py text test
|
2026-10-14 14:11:53 +08:00 |
|
wengzh
|
7c43ecfcb5
|
Merge pull request #3434 from xinnan-tech/py-test-asr
fix: SenseVoice 日语识别结果按词带空格 (#3412)
|
2026-10-14 11:54:39 +08:00 |
|
korexil
|
0be634c627
|
fix: SenseVoice 日语识别结果按词带空格 (#3412)
SenseVoice 识别日语时偶尔按词输出空格(如「今日 の こと を 少し 長め に」),
这些空格会原样进入对话历史并交给 LLM。lang_tag_filter 现在去掉两个
中日文字符之间的空格,韩文、英文的词间空格保持不变。
|
2026-10-14 10:32:56 +08:00 |
|
Sakura-RanChen
|
932962e8d3
|
补充注释说明,调整测试样例
|
2026-10-14 10:10:28 +08:00 |
|
wengzh
|
60c2a7ee17
|
Merge pull request #3431 from xinnan-tech/py-content-text
Py content text
|
2026-10-13 17:13:42 +08:00 |
|
Sakura-RanChen
|
a01f0aa29b
|
去除没必要的测试,上游为str不需要防御性增加
|
2026-10-13 16:54:42 +08:00 |
|
korexil
|
4445aa7510
|
fix: FunASR 识别结果以 JSON 原样进入对话历史 (#3411)
FunASR 返回 {"content","language","emotion"} 时,startToChat 只在含 speaker
字段时才解包,否则整段 JSON 字符串会作为用户消息交给 LLM 并写入对话历史。
现在没有 speaker 时只取 content。
|
2026-10-13 16:44:13 +08:00 |
|
wengzh
|
dc86a780a2
|
Merge pull request #3418 from xinnan-tech/py-test
Py test
|
2026-10-13 15:47:30 +08:00 |
|
Sakura-RanChen
|
a5e47f2c4e
|
补充字符,调整字符判断
|
2026-10-13 15:29:28 +08:00 |
|
Sakura-RanChen
|
2057b99aeb
|
迁移测试用例,优化相关注释
|
2026-10-13 14:31:21 +08:00 |
|
wengzh
|
7957817a72
|
Merge pull request #3425 from xinnan-tech/chore/dependabot-monthly-groups
Dependabot 改月度更新并按用途分组
|
2026-10-13 11:41:15 +08:00 |
|
hrz
|
a6eeb107f4
|
fix(deps): 补 dependabot ignore portalocker
requirements.txt 把 portalocker 锁在 3.x,4.x 与 qdrant-client<1.20 的
portalocker<4.0 冲突 (PR #3360)。Dependabot 默认推 4.x 升级会破约束。
依 openrz 评审 P1 在 ignore 列表追加 portalocker 一项。
|
2026-10-13 11:28:37 +08:00 |
|
wengzh
|
847337cabb
|
Merge pull request #3419 from xinnan-tech/fix/3391-route-guard-whiteList
fix(router): 路由守卫改 anon 白名单反向匹配
|
2026-10-13 11:15:15 +08:00 |
|
Sakura-RanChen
|
b8f23ffa66
|
调整相关代码
|
2026-10-13 10:40:47 +08:00 |
|
lww9029
|
dc581d7185
|
fix: 修复登录状态下还能访问白名单路由问题
|
2026-10-13 10:36:25 +08:00 |
|
hrz
|
741ec299c0
|
fix(tts): edge-tts 失声改走 msedgeservices (#3420)
* fix(tts): edge-tts 失声改走 msedgeservices
微软 2026-10 起对 legacy 消费者接口返回 403,
edge-tts 7.2.8 仍走 speech.platform.bing.com 走不通。
上游 PR rany2/edge-tts#491 切到 api.msedgeservices.com 修好,
但 7.2.8 仍是 PyPI 最新版本。
仓库在 edge.py 顶部临时把 WSS_URL 顶住,等 7.2.9 出了删掉。
* fix(tts): patch 还要写 communicate.WSS_URL
edge-tts 7.2.8 仍指 legacy bing 接口,10 月起微软 403。
上游 PR #491 已切到 msedgeservices.com,7.2.9 才进 PyPI,先顶住。
上次只改 constants.WSS_URL 不够,communicate 用 from import 是模块局部名,
LEGB 找不到新值。这次同时改 communicate.WSS_URL 才生效。
|
2026-10-13 09:58:30 +08:00 |
|
hrz
|
505925fb21
|
Dependabot 改月度更新并按用途分组
原本每周跑一次会刷很多零碎 PR,看着烦。改成每月一次,并把第三方 AI 服务、本地模型、网络栈拆成几组聚一起,每组出一个 PR 就行。被锁住的 torch/numpy/websockets 几个直接忽略掉,免得它推升级 PR 进来。
|
2026-10-13 09:34:02 +08:00 |
|
hrz
|
4aa63baf75
|
fix(router): 路由守卫改 anon 白名单反向匹配
业务路由越加越多,原来硬编码的 8 项守卫名单跟不上了,
未登录直接进十来个业务页看到骨架再被踢,体感抖。
守卫改成只对登录、注册、找回密码、根路径这四页放行,其余一律查 token。
顺手把 9 处没人读的 meta.requiresAuth 和 meta.title 死字段删了。
|
2026-10-12 18:02:36 +08:00 |
|
korexil
|
70ab19d23f
|
fix: TTS 分句在引号内切开句子 (#3413)
_get_segment_text 会在引号内的标点处切分(如「わぁ!」って、“好!”然后),
把引号拆到两段里,或留下只有「。」的片段。新增 _quote_safe_cut:切分点后的
右引号与句末标点一并带走;位于未闭合引号内或右引号后句子仍在继续时,顺延到
下一个标点。不含引号的文本切分结果不变。
|
2026-10-12 16:26:40 +08:00 |
|
Sakura-RanChen
|
e5f326285e
|
update: 优化client 生命周期对齐业务请求——重试内连接复用、锁外构造、safe_close 可打断重试
|
2026-10-12 15:42:51 +08:00 |
|
hrz
|
4576e391bb
|
fix(ci): 阿里云 PyPI 镜像 metadata 缺失回退官方源 (#3417)
基镜像构建挂了——日志显示 pip 在装 requirements.txt 阶段退出码 1,
罪魁是阿里云 pypi 镜像对 mcp==1.22.0 的元数据文件 404。
装包那行加 --extra-index-url https://pypi.org/simple,
主源没货时自动去官方源捞。
|
2026-10-12 10:28:35 +08:00 |
|
Yanhan Ruan
|
ef1d24e40d
|
fix(server): 修复临时事件循环结束后 HTTP 客户端未释放的问题 (#3416)
|
2026-10-12 10:00:28 +08:00 |
|
wengzh
|
c30c40bf56
|
Merge pull request #3415 from xinnan-tech/chore/bump-deps-20261010065106-1659
chore(deps): 批量升级 4 个允许的依赖
|
2026-10-10 15:24:17 +08:00 |
|
Sakura-RanChen
|
199c4ce365
|
chore(deps): batch bump 允许升级的依赖
|
2026-10-10 14:53:30 +08:00 |
|
hrz
|
a6cd755cf2
|
聊天记录弹框底部不再留大量空白 (#3410)
弹框本身和 body 用 !important 撑到视口(body 顶开 size="large" 默认多扣的 56px footer 高度)。body 的高度由 flex: 1 自动撑满,max-height 只用来顶开原来的 950px 上限。
|
2026-10-09 17:24:39 +08:00 |
|
hrz
|
23d0e64d9d
|
召回测试弹框与切片弹框样式对齐 (#3409)
召回测试弹框宽度从 900px 调到 1200px 并启用大弹框样式,高度、上下间距与切片弹框保持一致。结果区域改用 flex 填充而不是写死的 400px 高度。
|
2026-10-09 17:18:06 +08:00 |
|
hrz
|
96c224c4e4
|
切片和聊天记录弹框统一为大弹框样式 (#3407)
知识库查看切片弹框加 size="large",聊天记录弹框去掉旧样式覆盖并把 body 改成 flex 列布局,底部下载按钮不再绝对定位,两个弹框跟历史版本对齐。
|
2026-10-09 17:02:49 +08:00 |
|