Skip to content

内部开发指南

面向在源码里做二次开发的开发者。 不是用户手册 —— 这里讲的是数据流、机制与"别踩的坑"。来源:CLAUDE.md + 实测沉淀。


0. 一句话

Familiars = Electron(Vue3) 前端 → 本地 FastAPI bridge(127.0.0.1:18711) → OpenAI 兼容 LLM + 本地小模型 + 工具系统。后端单进程、Windows-first。

1. 核心数据流

Renderer ──window.familiars API──▶ main.js(preload / IPC)
                                      │ spawn

                            src.bridge.run (hypercorn HTTPS/2)
                                      │  X-Bridge-Token
                          ┌────────────┴──────────────┐
                          ▼                           ▼
              DialogueManager / ConversationSession   工具系统 ToolDispatcher
              (LLM tool-loop, MAX_TURNS=50)           │  ├─ security gate(风险分/审批)
                          │                           │  ├─ browser/shared-Chrome
                          ▼                           │  ├─ multimodal/vision
              MemoryWriter → workspace/               │  ├─ memory/tools
              (Scoping: dialogue/agent/user)          │  └─ broker / skill……
                          ▼                           ▼
                       SQLite (familiars.db, WAL)   workspace/ 文件树

2. Bridge 启动副作用顺序(重要!)

src/bridge/app.py 在 import 时按精确顺序做副作用,别乱改顺序

  1. pin WORKSPACE_ROUTE(仓库根)
  2. 主线程 pin CUDA(Windows WDDM 不允许 worker 线程首触 GPU)
  3. align_all_paths()(路径漂移自动对齐,必须在任何 DialogueManager 读对话前)
  4. import+mount 47 个路由
  5. CORS + BridgeTokenMiddleware
  6. startup hooks 顺序:broker_workshop bootstrap → anyio 线程限制器 → pool 看门狗 → 浏览器生命周期
  7. 模块级:杀孤儿 GPU 进程 → 预热 embedder/rembg/rewriter/最近的 agent DH → autorun 检查 → rehydrate 监控/cron/技能调度

3. 路径对齐机制(改路径别慌)

  • 仓库根漂移:启动时比较所有 dialogue.path 前缀与 repo_root(),漂移自动改写 dialogue.json + turn_*/plan.json + step_*.json,并记录到 workspace/.paths_aliases.json
  • 外部目录别名python -m src.tools.paths_migrate <old> <new> --record 一次性记录,之后每次开机回放;--dry-run 先预览,每个改动文件备份为 .bak_<ts>
  • 日志文件(.bridge.logaudit.log永不改写,保留真实历史。

4. 内存 / VRAM 约定

  • 单一 VRAM 准入闸(src/base/vram_gate.py:4 级优先级、3 级驱逐)。
  • MRU/参考上位回调用 DialogueManager.release_memory + ensure_dialogue_loaded(JIT,避免常驻几个亿 token 的 RSS)。
  • HTTP 端点:POST /api/agents/{id}/release-memoryGET /api/memory 观测。
  • 保持 on_evict 约定:凡持有显存/内存的对象都要实现 evict 回调,驱逐时可协作。

5. 工具系统

  • ToolDispatcher 默认注册 15 个工具实例(Daily/DailyMonitor/Base+InputController/Multimodal/Browser/Doc/Memory/System/User/UserSecret/Phone/Skill/SkillWatcher/Broker + 按需 run_call_conversation/ask_user_questions/bridge_call)。
  • 工具 schema 存 workspace/tools.json,按客户端 merge 到 src/models/clients/*_client.py
  • _CONSULT_TARGETS 仍会把 consult_doc 路由到 doc_tools —— 别删它在 base_client 里的映射。

6. 三大 agent 模型的接线

  • AssistantManager(agent 0 / 管理者)持 N 个 Assistant,跑独立的 MANAGER_MODEL 做摘要与人设演化。
  • ConversationSession + DialogueManager:LLM I/O 层,MAX_TURNS 不再是硬上限(有 turn-budget 升级器)。
  • AssistantRouter / TaskDecomposer:多 agent 分工。

7. 测试红线(每一条都踩过代价)

  1. 真 SQLiteFAMILIARS_DB_PATH=:memory:),不要 mock 仓库。
  2. Bridge-route 测试:恢复 sys.modules 捕获项;不要 reload 路由模块。
  3. Scratch agent 目录回 runs/
  4. 浏览器自动化走 familiars_cdp_port() 单一共享 Chrome。
  5. 新增日志要进 KNOWN_LOGSsrc/utils/framework_tools.py)—— manager 才能看到。

8. 常见坑(血泪)

说明
uvicorn src.bridge.app:app --reload丢 HTTP/2 + worker 线程 race 初始化 CUDA → 崩溃。用 python -m src.bridge.run
两个 router 同 prefix先注册的赢(broker_user vs user 曾碰撞)。加 prefix 路由前先想冲突
HKDF info 字符串b"familiars-secrets-v1" —— 轮换会失效所有 SECRET.json,须同时迁移
workspace/tools.json 里空 parameters会让 LLM 看不到该工具。给每个空 schema 加 reason+placeholder
贴一张"为啥不修"先查 audit.log.bridge.log,再怀疑代码 —— amend 前先看清事件流

9. 下一步

  • CLI 命令全表:../dev/cli.md
  • REST 面:../dev/api-bridge.md
  • 生态开发:../ecosystem/index.md(Recipe/Flow/Broker)

✨ Familiars · 多 Agent AI 桌面应用 —— 对话树记忆 · 长期记忆 · 工具系统 · 数字人 · Broker 生态