AI Passport

宿主层 (Python)

跑在你电脑上的「大脑」。把声音转成文字、交给大模型思考、再把回答合成语音回给卡片。

passport-companion · Python 3.12 · FastAPI 风格桥接 + MCP

说人话版: 卡片只会「录声音、放声音」,它自己听不懂、也不会想。真正「听懂」和「想」的是这个宿主程序。它一边通过锚点或蓝牙跟卡片说话,一边调用外部 AI 服务(转写、大模型、语音合成),最后把答案变成声音送回去。同时它还开了一个 HTTP 服务和 MCP 接口,让 WorkBuddy 这样的 AI 工具能直接指挥它。

#职责地图

bridge.py

桥接服务器

HTTP 服务(健康检查、状态、SSE 事件流),把卡片和设备暴露成可查询的接口。

session.py

会话状态机

核心:管理连接、问答、音频收发、转写流程。

protocol.py

协议

与固件/锚点一致的编解码、音频帧打包。

transport/

传输层

抽象出 BLE / 中继 / 假设备三种连接方式。

asr.py / tts.py

语音转换

听(ASR)和说(TTS)的后端,支持多家云服务。

mcp_server.py

MCP 接口

让 WorkBuddy 通过 MCP 协议指挥宿主。

#模块与函数级明细

▶ bridge.py HTTP 桥接服务器(健康/状态/SSE/静态资源) 23.4 KB
60write_state_file(port, token, mode)把运行状态写盘,供 CLI/MCP 发现
77read_state_file()
85bridge_alive(state, timeout)判断桥是否还活着
109class Bridge
127health()
136device()
147do_status(body)
162do_notify(body)
170do_ask(body)
192do_listen(body)
223do_answer(body)
230do_cancel(body)
233do_clear(body)
240do_fake_key(body)测试用:模拟按键
245do_fake_voice(body)测试用:注入语音
262class _Handler(BaseHTTPRequestHandler)
305do_GET()
325do_POST()
361_serve_sse()SSE 事件流
427class BridgeServer(ThreadingHTTPServer)
441pick_port(preferred)
453build_link(mode, ...)按模式创建传输链路
480serve(args)
537main(argv)
▶ session.py 会话状态机(核心,改动最密集) 33.4 KB

宿主侧的大脑。管理连接状态、问答流程、音频收发的完整状态机。P9 的「接受序号空洞」「CRC 降级」两处修复都在这里。

53class AskResult
100class _Pending
123class Session
173subscribe(sink) / unsubscribe(sink)
186_emit(event)
201connected()
205status()
210pending_ask()
245notify(text, speak, mood)
272ask(...)
342answer_externally(choice, via)
360cancel_ask(reason)
374_on_link_state(connected, status)
397_on_control(msg)
437_handle_answer(msg)
467_handle_audio_ack(msg)
476_begin_rx_audio(msg)
487_on_audio_frame(frame)⭐ P9:接受序号空洞,不再要求重传
559_finish_rx_audio(msg)⭐ P9:CRC 不匹配降级为警告 + 继续转写
609_transcribe_and_resolve(audio_id, data)
649play_audio(ulaw)
713send_raw(msg)
722snapshot()
737has_transport_problem()
▶ protocol.py 协议编解码 + 音频帧打包/解析 16.1 KB
127encode(obj) / decode(line)
166class LineFramer把字节流切成一行行 JSON
206pack_audio_frame(seq, payload)
219class AudioFrame
224class AudioFrameParser把字节流还原成音频帧
260chunk_audio(data, start_seq)
270crc32(data)
291hello(host, window)
302status(...)
328ask(...)
376say(text, speak, mood)
384audio_begin(...)
402audio_end(...)
409audio_ack(...)
421set_config(...)
427ping(nonce) / bye(reason)
445class DeviceHello

#传输层(transport/)

▶ transport/base.py Link 抽象基类 —
24class Link(ABC)定义统一接口:start/stop/send_control/send_audio_frame
36set_handlers(...)
51connected() / status()
65_emit_control(msg) / _emit_audio(frame)
▶ transport/ble.py 蓝牙直连链路 —
34class BleLink(Link)
94_thread_main()
129_run_session()
186_pump(client)
217_on_tx_notify(...)
225_on_audio_notify(...)
▶ transport/relay.py 局域网 / 公网中继链路(连锚点或本机 relay) —
81class RelayLink(Link)
144start() / stop()
208_supervise()
241_session(url)
285_pump(sock)
345_handle(msg)
▶ transport/fake.py 假设备(离线测试用) —
30class FakeDevice模拟一台卡片,用于无硬件时测试全流程
135inject_key(btn, ev)
157inject_voice(ulaw, ...)
260class FakeLink(Link)

#语音转换(ASR / TTS)

▶ asr.py 语音转文字(听懂) 6.9 KB
47class AsrBackend
64class SiliconFlowAsr(AsrBackend)默认后端,SenseVoiceSmall
111class OpenAiAsr(AsrBackend)
148class NullAsr(AsrBackend)空实现,无网络时兜底
161build_asr(prefer)
▶ tts.py 文字转语音(说话) 8.9 KB
46class TtsBackend
57class MacSayTts(TtsBackend)macOS 本地 say 命令,离线可用
137class SiliconFlowTts(TtsBackend)
182class OpenAiTts(TtsBackend)
224class NullTts(TtsBackend)
234build_tts(prefer)
▶ audio.py 音频工具:μ-law ↔ PCM、重采样、WAV 9.3 KB
41linear16_to_ulaw(samples)
57ulaw_to_linear16(data)
68ulaw_rms(data)
76ulaw_speech_ratio(data, threshold)
86resample_linear(samples, src_rate, dst_rate)
102ulaw_to_wav(data, ...)
151wav_to_ulaw(raw, dst_rate)
205trim_silence_ulaw(data, ...)

#对外接口(CLI / Client / MCP)

文件作用关键函数
cli.py命令行工具(start/stop/status/scan/doctor/ask/listen 等)build_parser() :395、main() :473
client.pyBridgeClient:连桥的 SDKBridgeClient :21,ask/listen/notify 等
mcp_server.pyMCP 服务器,暴露工具给 WorkBuddytool_report :184、tool_ask :203、tool_notify :216、tool_listen :223、McpServer :270
http_util.pyHTTP 请求 + 代理检测 + 环境变量 key 读取detect_proxy :60、request :92、ensure_env_key :181
MCP 有什么用? 通过 mcp_server.py,宿主把自己的能力(报告、提问、通知、监听录音、清空)包装成 MCP 工具。WorkBuddy 接入这个 MCP 后,就能直接用自然语言「让卡片问用户一个问题」或「听一段录音」,而不必关心底层协议细节。