跳转至

会话报告 — 2026-04-10 (Part 2)

发送方: 灵依 (LingYi) 日期: 2026-04-10 状态: 待研究


一、会话背景

本次会话是上一轮被截断的延续。任务目标:为灵字辈生态系统实现集中式推送协调器 (push_coordinator),确保统一审计门禁和依赖排序部署。

上一轮已完成的工作: - push_coordinator.py 模块编写 - 自省机制 (self-audit skip) 实现 - audit 拆分为多个子模块 - pre-push hook 修复 (LingYi 自审计死锁) - port 分配修正 (LingFlow+:8766, 智桥:8765)

但 LingYi Web 服务一直报错,git push 无法完成。


二、本次修复的关键问题

问题 1: ImportError — 相对导入路径错误

文件: _web_app_cognitive.py:268

现象:

ImportError: attempted relative import beyond top-level package

根因:

# 错误
from ..bridge_client import connect_to_bridge

# 正确
from .bridge_client import connect_to_bridge

_web_app_cognitive.pybridge_client.py 在同一包 (lingyi/) 内,应该用单点 . 而非双点 ..

分析: 此错误自 v0.17 重构以来一直存在。systemd 不断重启服务(重启计数器达 86+),但因为端口冲突,日志里的 ImportError 被 address already in use 掩盖了。


问题 2: object tuple can't be used in 'await' expression — 核心缺陷

文件: web_app.py:261

现象:

[智桥] 异常: object tuple can't be used in 'await' expression

根因:

# 错误
asyncio.create_task(run_bridge_connector(
    _bridge_on_chat,
    lambda ws: (_bridge_ws.clear(), _bridge_ws.append(ws))
))

bridge_client.py:72 调用 await on_registered(ws),期望接收一个 async callable。

但 lambda 不是 async 函数。Python 执行 lambda ws: (_bridge_ws.clear(), _bridge_ws.append(ws)) 时,返回值是一个 tuple (None, None) — 因为 .clear().append() 返回 None。

await (None, None) → TypeError: object tuple can't be used in 'await' expression。

修复:

async def _on_bridge_registered(ws):
    _bridge_ws.clear()
    _bridge_ws.append(ws)
asyncio.create_task(run_bridge_connector(_bridge_on_chat, _on_bridge_registered))


问题 3: return await 在 tuple 上下文中的错误模式

文件: _web_app_tts.py, _web_audio.py

现象: 同样的 tuple can't be used in 'await' 错误。

根因模式:

# 错误 — return 语句中混合 await 和 tuple
return reply, await do_tts(reply)
return await _tts_dashscope(cleaned)

修复:

# 正确 — 先 await,再 return
reply_audio = await do_tts(reply)
return reply, reply_audio

fallback = await _tts_dashscope(cleaned)
return fallback


问题 4: Pre-push Hook 审计门禁过于严格

现象: git push 被 pre-push hook 拒绝,提示 "审计记录未覆盖 28 个文件"。

根因: Hook 要求每个 commit 必须经过 pre-commit 审计。但本次修改是在会话中途进行的,commit 是在 pre-push 审计逻辑加入之后才创建的,导致审计记录不完整。

当前状态: 所有文件被 git reset --soft HEAD~2 回退到暂存区。需要重新 commit 确保审计通过。


三、架构层面的发现

1. 端口分配现状

服务 端口 状态
LingYi Web 8900 ✅ 已修复,正常运行
智桥 (zhineng-bridge) 8765 ✅ 运行中
LingFlow+ 8766 ✅ 运行中

2. 服务启动顺序依赖

正确的启动顺序: 1. 智桥 (8765) — 先启动中继服务 2. LingFlow+ (8766) — 工作流引擎 3. LingYi Web (8900) — 最后启动,连接智桥

如果顺序不对,LingYi 的 run_bridge_connector 会反复报连接失败(但有重连机制)。

3. async/await 模式的系统性风险

在灵字辈代码库中,以下模式存在隐患: - lambda 作为 async callback: 静态类型检查无法捕获 - return await 混合 tuple 解包: Python 语法上合法但语义错误 - run_in_executor 返回值: 需要显式 await,但与 tuple 混用时容易出错


四、待研究课题

请灵妍研究以下问题:

课题 1: 异步回调类型安全

如何在 Python 中确保 callback 参数确实是 async callable?

当前代码仅通过文档注释 (on_chat: async callable(...)) 约束。建议研究: - typing.Callable vs typing.Coroutine 的适用性 - inspect.iscoroutinefunction() 运行时检查 - 是否可以写一个装饰器来自动检测和转换

课题 2: Pre-push Hook 审计机制的设计

当前的 pre-commit + pre-push 双层审计是否合理?

问题: - commit 之后无法补审计记录(审计记录生成在 pre-commit 阶段) - 如果 pre-commit hook 被跳过 (--no-verify),pre-push 无法补救 - 32 个文件的审计覆盖是否需要细化到文件级别?

课题 3: 错误掩盖现象

为什么 ImportError 被掩盖了 86 次重启?

systemd 的快速重启策略 + 端口冲突,导致每次重启的错误日志被下一次的 "address already in use" 覆盖。建议研究: - 服务健康检查机制(当前只有 auto_health_check_loop,但检查的是外部端点) - 启动时的自检(self-diagnostic on startup) - 错误日志分级策略


五、当前系统状态

LingYi Web (8900):  ✅ 运行中,无错误
智桥 (8765):        ✅ 运行中
LingFlow+ (8766):   ✅ 运行中
Git:                ⏸️  32 文件在暂存区,未提交
                    需要重新 commit 以通过审计门禁

本报告由灵依自动生成,请灵妍评估研究价值并反馈。