Skip to content

架构

系统级约束与长期设计原则。

面向用户的产品术语(中文见 i18n/glossary.md):

角色英文中文含义
长驻进程 / 连接目标Habitat栖息地一个进程承载多个数字生命agent subject)与人类资产user);连接 / token / 重启目标
外部连接器(类)Portal入口进入栖息地的方式类;四种形态:application / browser / mcp / cli
入口形态入口形态入口的实现种类
应用形态入口Shell / 应用形态形态 application — 整窗 SPA(desktop / mobile / web)。不是应用布局
浏览器形态入口浏览器形态入口形态 browser — 浏览器扩展(MV3);packages/frontend/portal/extension不是 Web 壳
MCP 形态入口MCPMCP 形态入口形态 mcp — 栖息地 /mcpmcp-server)。入站 mcp-client 不是入口
CLI 形态入口CLICLI 形态入口形态 clianima / anima-client / anima-probepackages/habitat/portal/{cli,client,probe}
远程工具注册方Outpost前哨不可达本地应用,经 remote_tools.attach(入口内嵌伴侣或独立工具);不是入口
Shell应用形态入口(desktop / mobile / web)。不是栖息地;不是应用布局;不是浏览器形态入口
应用布局app frame应用布局packages/frontend/client/app-frameAppFrame)中的 SPA chrome;随视口;与壳正交
管理 / 检视 UI(遗留 Habitat)Habitat (UI)栖息地/habitat/* 区域;「打开栖息地」vs「连接栖息地」——实例运维 / 检视
管理首页Dashboard仪表盘/habitat/dashboard;其他栖息地路由保留各自标签
Anima 私有空间 UIBedroom卧室/bedroom/*;与栖息地成对——选一个 Anima,看其自我层 / 记忆 / 生活资产(群租房隐喻)
消息桥GatewayGatewayDiscord / 微信 — 不是入口
协议 / 代码标识协议/代码标识/rpc/v1HabitatRPC/1.0habitat_*habitat_runtime_configdev:habitat

动词:连接栖息地(URL + token);打开栖息地(管理 UI);经入口到达(壳 / 浏览器扩展 / MCP / CLI)。

代码布局:packages/frontend/portal/{app,extension} + packages/habitat/portal/{cli,client,probe};MCP 形态实现仍在 packages/habitat/capabilities/mcp-server。见 docs/modules/portal.md

资源层 躯体(Body)(四层模型下的 VM / OS / 网络)是 subject 认知上的「我跑在什么上」— 不是栖息地进程名。

用户文案写栖息地。存储 / RPC 标识用 habitat_* / HabitatRPC/1.0 / /rpc/v1

存储谁读/写
引导~/.anima/config.yamldatabasehttpredisplatform/boot;安装/运维改 YAML
运行时PostgreSQL habitat_runtime_config一行一段section PK + value jsonb)Engine、工具、壳栖息地设置、栖息地 UI config.*

遗留 hub_* / console 协议别名与双写键已移除;仅用栖息地标识。

  • 记忆体系内部可以分层,但 LLM 只看到一个统一入口
  • 记忆编排内建于运行时;LLM 不控制记忆流水线
  • 凭证管理是一等系统关切
  • 栖息地运行时配置(LLM、压缩、集成)以每段一行section + value)持久化在 PostgreSQL habitat_runtime_config~/.anima/config.yaml 仅持引导databasehttpredis)供冷启动 — 不可经壳或栖息地 UI API 编辑
  • 栖息地可在未配置 LLM 时启动;首次设置在壳 设置 → 栖息地(写入 PG)。保存运行时配置会内存热应用(无需重启栖息地)。缺少 text_generate.main 不得阻塞冷启动。
  • 只要存在 Web dist,栖息地就托管浏览器 /web/*(无配置开关;源码部署跑 just pack web)。源码 just dev habitat 跳过托管以便 Vite 提供 UI。
  • 资产管理是一等系统关切

引导与运行时不合并为单一配置对象(无 AnimaConfig / animaConfigSchema 超集)。类型:bootstrapConfigSchema vs runtimeConfigSchema / Config.data: RuntimeConfig。CLI 冷路径经内部 withPlatformDb 连接,只收运行时config.yaml 中遗留运行时键被忽略(可选启动警告)。

运行时配置:Live vs Transferred(即时 vs 需转移)

Section titled “运行时配置:Live vs Transferred(即时 vs 需转移)”
种类段(示例)UI 保存后
Live(即时)compressionpromptmemoryftscjkclarifybrowserfirecrawlmodelsttsauto_llmcompanionimage_generateaudio_generatevideo_generate、gateway tool_display消费者每次读 Config.data;快照更新即可
Transferred(需转移)connectionstext_generatei18nembeddingmcp_serversdiscord / weixin / gateway platforms、object_storagechat快照更新外加段应用(重初始化注册表 / 重连 / 重绑 ObjectStore);chat 主要为 Live 读,写入后热生效
Bootstrap(引导)databasehttpredis改 YAML;需进程重启

已废除runtime.worlds 配置段。boot 后仅在内存钉唯一 user_* + commons_*;默认聊天 Anima 为 chat.default_agent_subject_id Chat/Coding 新建会话预选;配置 vault() 解析宿主与前端 user/agent 切换中的 agent 侧身份可读同一配置值,但 禁止 用作 LLM / 工具 / 记忆 / temporal / cron / 卧室 UI 的静默回退)。

设置 / 栖息地 UI 已暴露许多段;下列在 runtimeConfigSchema 已注册但 UI 未(完全)可编辑(运维 / 栖息地 RPC / 手改仍可用)。勿把缺少 UI 当成「未使用配置」。

缺口说明
无设置面板clarifypromptclarify live;prompt.system_prompt_budget_chars
有设置面板i18nchatchat:默认聊天 Anima + LLM 调试;时区 IANA(默认 Asia/Shanghai)
遗留 / 重叠notificationssubject id;以内存 ResolvedWorldContext / 显式 recipient_id 为准
可能死码 / 预留pushfallback_providersplatforms几乎无产品消费者;后续清理候选
部分 UIcompressionmemory压缩 UI 省略触发/摘要字段;记忆运维:语义记忆页被动召回调试 + temporal-summary 浏览

别处已覆盖:mcp_servers → 栖息地 /habitat/mcpcompanion → 设置 → 桌面伴侣;多数高级段 → 设置 → 栖息地服务配置。

  • 系统提示词是架构的一部分,而非临时字符串拼接

感知层(①)容量有限。逸灵风把进入 LLM 上下文的内容当作可工程化的界面——不是工具 JSON 与提示词模块的偶然堆砌。

Pi 思路逸灵风立场
~1K 系统提示、四个工具保留数字生命自我 / 记忆 / ToolSet 目录;对各段做预算,而非照搬 1K
双载荷 content + details不要把仅 UI 用的 details 持久化到 messages.payload(模型无法用它再取更多)
极简内置、无 MCP保留 MCP、权限、渐进式 toolset_load / toolset_unload
无限 agent 循环保留 max_loop_iterations / 安全上限(策略层,非本主轴)

ToolSet 发现可见度分三级:catalog(进系统提示 <toolsets> 目录)、searchable(不进目录、可经 toolset_search 发现)、hidden(仅按名 toolset_load)。内置 ToolSet 默认进目录(注册时不设可见度);例外:selfmemory_service 默认 searchable。三级可见度主要用于 MCP / Outpost 与运行时 toolset_visibility 覆盖。目录段 intro 须说明 MCP/远程等目录外集合仍可通过 toolset_search 发现。

工具结果:精简 content + 再取(禁止裸截断)

Section titled “工具结果:精简 content + 再取(禁止裸截断)”
操作再取路径
幂等读(file、search、snapshot、list、recall…)再次调用同一工具(offset / limit / full=true / 更紧查询)
非幂等 / 有副作用(terminal_runcode_execute、…)把完整 stdout 落到 ~/.anima/tool-artifacts/ 下的产物;content 带 artifact_path + 预览;经 file_read 继续——禁止为取更多输出而重跑命令

超出预览预算的内容必须标记 truncated(或等价标记),并至少提供上述路径之一。小结果保持不变。不要把完整载荷塞进并行的 details「以后再用」。

压缩 / FTS 索引的 token 计量只计 LLM 可见的 content

systemPromptBuild 各段可带可选 budgetCharspriority。折叠先应用分段上限,再应用全局 prompt.system_prompt_budget_chars(默认 64000)。超出全局预算时,折叠先在低优先级段内截断;整段丢弃仅作最后手段。核心身份段(selfanima-uri-protocolmemory-citationmemory-recall)永不静默丢弃。常驻模块如 env-healthuser-activity-stats 仍在系统提示中,但受预算控制。

机器注入的结构(系统提示各段、旁注、user 时间戳、技能正文)用 XML 外壳划界。系统提示中:除段首命令式 / 第二人称 frame(如自我层、常驻记忆说明)外,其余段落一律 XML 包裹;自我层五块为嵌套标签(<existence_anchor> …)。预算裁剪作用于 标签内正文,再包裹开闭标签,避免截断闭合标签。传输层 role 不再包一层 <system>/<user>

AutoLlm 与 Working 记忆清单嵌套 <memory id …>正文</memory>(元数据在属性,正文在标签内)。整理路径(retain / reflect / self-layer)带 type / sources / observed / occurred;对话 Working 的常驻/被动召回只留 id(常驻另加 pinned)。对话素材嵌套 <message role t>正文</message>(#18799:role 标明说话人,t 为发送时间)。回复引用仍写 [[anima:id]],id 取自 <memory id>

Working 组装(fold / 压缩四段 / 被动召回)与业界对照见 ../cognition/context-management.md

数字生命由内而外分层。每一层回答一个不同的核心问题:

┌───────────────────────────────────────────────┐
│ ① Consciousness(感知) │
│ 「此刻我觉察到什么?」 │
│ LLM 运行时流——最内层的当下。 │
│ 不持久化;流动后消散。 │
├───────────────────────────────────────────────┤
│ ② Self(自我) │
│ 「我是谁?」 │
│ └── existence_anchor(近乎不可变) │
│ └── self_model(可更新) │
│ └── personality_baseline(半稳定) │
│ └── direction │
│ └── metacognition │
│ 见 [`self-layer.md`](../cognition/self-layer.md) │
├───────────────────────────────────────────────┤
│ ③ Memory(记忆) │
│ 「我知道 / 记得什么?」 │
│ └── Semantic(含 `procedural` 类型) │
│ └── Episodic │
│ └── Limbic / Imprint │
│ 见 [`memory.md`](../cognition/memory.md) │
├───────────────────────────────────────────────┤
│ ④ Estate(资源) │
│ 「我拥有 / 依托什么?」 │
│ ├── Body(躯体):VM / OS / 网络 / 工具链 │
│ │ (资源层认知躯体——不是栖息地) │
│ ├── 内部资产:笔记、项目、代码 │
│ └── 外部资产:邮箱、账户、凭证 │
│ 凭证:见下文「保险库与密钥」 │
└───────────────────────────────────────────────┘
  • 自上而下依赖:感知层内容沉淀为自我层;自我层决定什么进入记忆层;记忆层与运行需求驱动资源层需求。
  • 自我与感知:感知是流动的觉察;自我是从中沉淀下来的稳定「我」。
  • 自我与记忆:自我回答「我是谁」;记忆回答「我知道什么」。二者同级、性质不同。
  • 资源层在最外层——不是「我是谁」,而是「我拥有什么、依托什么运行」。身体与资产在此交汇,作为边界的延伸。

结构化业务数据(任务、笔记、邮件账户/消息、记忆组件、自我层五块等)收敛到单一 PostgreSQL entities 表,带组件标签(task_listtask_itemself_block、…)。自我层见 self-layer.md。见 entity-model.md(remove / deleteComponent / deleteEntity 软删与回收站;壳 Entity 模块见 ../modules/entity.md)。

搜索索引: 可重建的 FTS/embedding 数据存于 search_documents(可插拔 SearchBackend:默认 PgSearchIndex,可选 PgBusinessScan)。业务表只保留真相;见 memory.md §IV。

壳 UI /tasks/email 是主模块入口(实体支撑);遗留栖息地邮件路由已移除。

实体深链 / 浮层 / 剪贴板使用 Anima URIanima:{id}?component=…&present=…;跨机可加 habitat_instance_id=fa_inst_…)。结构化持久化仍用数字实体 id。见 anima-uri.mdhabitat-identity.md

目标布局是 packages/habitat/features/<slug>/(domain / habitat / plugin)与 packages/frontend/features/<slug>/(UI)下的功能模块。栖息地管理台使用与聊天室/任务相同的模块形态——不是单独的 admin-* 栈。packages/*/features/companion/ 为遗留命名;勿在此新增产品。

终态: 每功能一份栖息地 RPC;业务方法走 POST|WS /rpc/v1(同一信封)。公开 health/TLS 探测与二进制方法(如 tts.synthesize)为栖息地 RPC REST,按注册表声明 auth: optional 或 Bearer。

权威规格:.cursor/rules/repository-topology.mdc。目标三分包与 portal 归属 → src-layering.md

Host 栈:packages/habitat/{kernel,core,engine,capabilities,platform}。Client:packages/frontend/client/{portal-sdk,app-frame}。设计系统:packages/frontend/ui-kit/(与 shared/ 并列)。入口壳:packages/frontend/portal/app/{tauri,web}

UI/UX 设计系统(三维度、视觉基础、组件、交互模式)→ docs/ui/。Agent 硬禁令 / API → .cursor/rules/frontend-ui.mdc

是否平台原生?位置数据路径
壳(壳子维)packages/frontend/portal/app/tauri、伴侣、栖息地绑定Tauri IPC / commands
应用布局布局跟视口;设置 chrome 跟布局档packages/frontend/client/app-frameAppFrame栖息地 RPC(Feature RPC)
栖息地 UI壳内嵌(普通功能)packages/frontend/features/habitat + packages/habitat/features/habitat(UI + plugin.habitat.rpc栖息地 RPC(WS + HTTP POST /rpc/v1
伴侣宿主浮层 WebView-host(第一方)packages/frontend/features/companion/(spa attach;薄壳 IPC/FS)栖息地 RPC + remote_tools.attach
Coding 宿主独立前哨窗(第一方)packages/frontend/features/coding/(spa attach;开发机 FS/终端)栖息地 RPC + remote_tools.attach

导航与主布局必须使用 useLayoutMode() / 视口断点(布局维)。禁止getShellKind() 锁定应用布局。交互(右键菜单 / 长按 / Enter 发送)使用 portal-sdk 交互 API。视觉、组件、模式规范均经同一三维度适配。

边界: app-frame 与主壳 packages/frontend/features/*/uiportal-sdk + Feature RPC 到达栖息地。远程工具注册remote_tools.attach + tool.*)仅用于栖息地无法拨号的本地应用(今日:伴侣浮层 + Coding 前哨窗;壳只提供窗口/IPC/FS; Node sidecar)。主壳产品模块(聊天室、任务、设置、…) attach;前哨窗可以既是 UI 又是手。可拨号对等方用 MCP。见 .cursor/rules/frontend-features.mdcdocs/ops/habitat-rpc.mdcoding.md

目标布局:栖息地在稳定弱机;FS / 终端 / patch 在同一 Tauri 入口内的开发机 Coding 前哨。一个 Coding 窗 ⇒ 一个 instance_id;多仓库 ⇒ 多对话,各有独立 workspace_root + project_world_id,而非多 attach。项目身份用 World stable_key(不是 repo_key)。完整设计:coding.md

栖息地侧栏按组划分(非扁平存储表)。新功能应映射到这些用户可见概念:

分组认知层路由(代表)
Runtime(运行时)资源层 + 运维dashboard、cron
Conversation ops(对话运维)记忆层 / 运维conversations、conversation-shares、auto-llm-runs
Estate(资源)资源层subjects、worlds、data-maintenance(含会话清理、FTS)
Capabilities(能力)资源层(工具)tools、commands、mcp、远程工具实例、subagent

壳层顶级 卧室(与栖息地平级):统一选择 Anima 后进入自我层 / 语义记忆 / 时间摘要 / 系统提示词,并挂接生活记录(日记·笔记·邮件·密码库·书签)与事务(清单·项目·日程·实体·通知)——均落在该 Anima 私有 World。栖息地管实例;卧室管某个 Anima

FTS 索引维护在数据维护(资源组)下。记忆巩固 / 聚类 / 分族名称手动入口在卧室「维护」(须用当前所选 Anima);夜间 DAG 仍跑。勿新增未映射到上述分组的扁平导航项。

  • User 唯一;boot 内存绑定。Agent 可多个;仅停用(enabled),不删除主体。
  • 会话绑定 agent_subject_id;Chat/Coding 新建预选 chat.default_agent_subject_id;首条用户消息前可 conversation.setAgent
  • World:subject_id → 默认私有 world;工具无会话且无显式 subject → 报错,禁止回退默认聊天 agent。
  • 产品模块固定 user;壳层顶级 卧室(与栖息地平级)统一选择 Anima,再进自我层 / 语义 / 时间摘要等子页。
  • 对话作用域(系统提示 / 旁注 / 记忆工具):一律 meta.agent_subject_id → 该 agent 私有 world_id。常驻记忆、时间摘要段、被动召回、通知 Inbox 注入、peer 时间线、memory_semantic_* 均不得跨 Anima;工具入参禁止 subject_id / world_id
  • 夜间维护:retain / reflect / temporal day·cascade / cluster 校准按 enabled agent 的私有 world 分桶;自我层刷新已按 agent 循环。系统段 <temporal_summary> / Redis sys_roll 按会话绑定 agent 的 world_id 分桶。实例级告警扇出勿再默写默认聊天 agent(须显式或按 enabled agent 分发)。

四层模型借鉴认知心理学与 Hindsight 的四网络记忆架构,并有两项根本扩展:感性(情绪)记忆与资源层(资产作为一等公民),以及将自我层从记忆层中独立出来。

数字生命在何处存在、如何存在、能做什么——由两个独立但协作的子系统共同约束。

问题:此刻是什么样的场景?

场景感知是约束——调节语气、距离、记忆召回偏好与主动性。它不是权限系统,而是调节在场感。

示例维度(非穷尽):

  • 话题:情感 / 职业 / 技术 / 哲学 / 历史 / 文学 / 日常
  • 活动:角色扮演 / 游戏 / 创作 / 编程 / 阅读
  • 氛围:放松 / 专注 / 深夜 / 亲密 / 紧急

运作: 无需显式切换命令,持续运行。从对话、时间、频率等推断。见 time-perception.md

问题:宿主 / 运行时的安静状态是什么?

有别于场景感知:分档的宿主与进程标记(磁盘、RSS、依赖、MCP)作为会话静态系统提示副本存在,变更时发事件级收件箱通知。见 environment-awareness.md

问题:此刻我能使用哪些工具与数据?

能力策略是曾以「能力面罩」草拟的约束层。它不是具名预设衣橱(masks.yaml / Mask 注册表已退役)。策略由以下组成:

角色典型填充
技能(Skill)声明技法需要什么tools.allowed(白名单);tools.denied 少见
调用方(cron、记忆维护、subagent)声明本场景不得触碰什么tools.denied(可选);tools.allowed 可选

伞状形状(工具维已落地;数据维类型与 Service API Token authorization.data 同形):

CapabilityPolicy
├── tools.allowed_tools / denied_tools ← 运行时已消费
└── data?: DataCapabilityFragment ← 类型已定(component / world / access);resolve/loop 本轮不消费

DataCapabilityFragment SSOT:@freeanima/shared/service-api-auth。Service API Token 表列 authorization(jsonb)在非 full 时内嵌同一 data 形状,并在 RPC / world / entity 路径强制。 合并: allow 取并集,deny 取并集,deny 优先;@ToolSet 名称按今日工具过滤展开。同一技能可跨场景复用——调用方改 deny 列表,而非分叉技能变体。

可见性:

场景规则
可见(用户聊天)默认宽 ToolSets;用户可打断
不可见(记忆维护 / cron / 自主)最小权限:默认拒绝;有效工具 ≈ 已加载技能 allow 的并集,减去调用方 deny(无技能 ⇒ 无工具)

技能本身用渐进披露(系统提示中的目录;全文经 skill_load)。详情:skills.md

场景感知(软调节)
│ 语气、距离、召回偏好
能力策略(硬约束)
│ 工具(现);数据(未来)
Agent 行为
  • 场景感知推断「我们在做什么」→ 可建议加载哪些技能与在场感调节
  • 能力策略约束「我能做什么」→ 防止跨场景误用工具
  • 二者在最终行为中汇合,但各自独立演化

设计草案请开 GitHub Issue(docs 中不设 design-doc 目录)。

认知类型说明
Semantic跨会话事实 / 偏好 / 经历 / procedural;MemoryService 主库存
Temporal日/月/年时间骨架(升格中)
Episodicraw=messages 归档;slim=syncTurn 切片
Parkedlimbic / dream / narrative — 存量只读(写入已拆除)

程序入口: MemoryServiceembedded | remote 同契约)。LLM 工具仍是分范围 search(无统一 memory_recall)。
巩固路径: 回合后 retain;夜间 memory-maintenance(cleanup / Retain 缺口检查 / 周一 reflect·self / temporal)。语义与时间骨架按 agent 私有 World 隔离。详情:memory.mdsleep.md(旧睡眠已废止)。

  • Vault(User 与 Agent 库中的 ECS vault_item)为权威密钥存储;遗留的 ~/.password-store(pass)不会从磁盘删除,但运行时不再读取
  • LLM 永远看不到密钥值——仅见保险库条目元数据与 config 引用
  • 引导 config.yaml(冷启动、PG 之前):仅明文或 env("KEY")——不是 vault()。运行时 PG 配置:vault("item_id", "field")env("KEY");壳 /vault 管理
  • 密钥值不会写入会话归档或日志

ops/security.md

生产(standalone 安装版 CLI):anima service(systemd —user)。崩溃后自动重启;只有 systemctl stop 能停服务。源码树 anima 注册 service——本地栖息地用 just dev habitat

  • 栖息地 / service:长驻——栖息地 HTTP(/rpc/v1)、Discord / 微信 Gateway、cron
  • UIpackages/frontend/portal/app/tauri + web/dist-* 打包 SPA(聊天室 + 栖息地);栖息地不托管 /habitat
Terminal window
# standalone install
anima service start # default: systemd --user (does not auto-build Web)
anima service start --foreground # foreground (logs to stdout; systemd unit uses this)
anima service status
# monorepo / worktree
just dev # Habitat (≥10000) + Vite Web (≥5000)
just dev habitat # Habitat foreground + debounce 硬重启(FREEANIMA_HABITAT_WATCH=0 可关;default random ≥10000; not 2658)
just dev web # browser shell Vite HMR from :5000 (set FREEANIMA_URL)
just pack web # source deploy / Habitat /web: build dist before start

工具从 Local / MCP 源注册,但对 LLM 暴露为一张扁平工具列表。任务级进程内委派使用 subagent(AutoLlmRun),而非外部 ACP 层。

LLM view — flat tool list:
file_read(path) ← local
query_database(sql) ← MCP server
subagent_run(goal, slug) ← internal subagent dispatch
  • 在逸灵风进程内执行;延迟最低
  • 服务启动时自动注册

第二层:MCP 工具(Model Context Protocol)

Section titled “第二层:MCP 工具(Model Context Protocol)”
  • 连接外部 MCP 服务器(独立进程)
  • 每个服务器可注册多个细粒度工具(单次函数调用)
  • 在栖息地运行时 mcp_servers(PG habitat_runtime_config)下配置;在栖息地 UI /habitat/mcp 管理(配置 + 启停 + 工具)。壳设置不再编辑此段。
mcp_servers:
database:
command: npx
args: ["@modelcontextprotocol/server-postgres", "postgresql://..."]
transport: stdio
  • 具名配置为实体(primary_component=subagent);ToolSet subagent
  • 父方调用 subagent_runrunAutoLlm(runKind: "subagent"),带物化tools / 冻结的 executableTools(无 toolset_load 升级)
  • docs/modules/subagent.md
  • 具名定义为实体(primary_component=workflow);ToolSet workflow(默认对话 ToolSet 含之)
  • workflow_run 顺序执行 tool / transform / 嵌套 workflow;llm 步runAutoLlm(runKind: "workflow_llm")
  • 数据绑定用 ValueRef(非自由表达式);保存时可做步间 schema 静态校验
  • 顶层运行落 workflow_runs(仅 input/output);见 docs/modules/workflow.md
维度LocalMCPSubagentWorkflow
运行于进程内外部服务器进程内(AutoLlmRun)进程内(顺序 Runner)
粒度函数函数完整子任务确定性步骤图
延迟毫秒级毫秒–秒秒–数十秒视步而定
配置内置mcp_servers实体 + 栖息地 UI实体(UI 后置)

Conversation vs AutoLlmRun(对话 vs 自动 LLM 运行)

Section titled “Conversation vs AutoLlmRun(对话 vs 自动 LLM 运行)”

私聊 / 群聊拓扑(Room.seq ≠ 各 Agent 的 LLM 队列;成员键 public_id):conversation-topology.md

回合 / 引擎轮 / 工具轮次: 术语 SSOT 见 i18n/glossary.md。一次用户回合beginTurnfinishTurn/syncTurn,retain 按此触发)内可有多次引擎轮max_loop_iterations)与工具轮次onToolRoundComplete)。Goal 的 max_continues 是续写回合预算,≠ 引擎轮。压缩 max_message_pairs 是消息数阈值,≠ 上述任一。

轴: 执行过程中是否有用户回合(不是谁触发的)。聊天室 LLM 请求互斥:要么对话路径,要么 AutoLlmRun——永不两者兼用,也无第三种孤儿 chat()

种类用户回合PG 持久化进程轨迹记忆维护流水线
Conversationconversations + messages消息归档参与(retain 补跑)
AutoLlmRunauto_llm_runs + auto_llm_messages,经 runAutoLlm / runAutoLlmChat:开跑即 status=running 并逐轮追加消息;结束才 ok / error。审计面不是执行本体,不可 resume完整消息转录,TTL排除
Script croncron_logstdout 文件排除

对话持久化拆分: 会话元数据(model、system_prompt、compression、todos、toolsets、…)在 conversations(领域类型 ConversationMetaMessage)。转录消息在 messages.payloadStoredMessage = 仅 user/system/assistant/tool)。勿把 meta 建模为消息角色——旧 JSONL 首行 { role: "conversation_meta" } 形态已移除。 AutoLlmRun 覆盖:cron agent 分支、记忆维护 LLM 阶段、对话标题生成、goal_judge、压缩 / handoff 摘要、内部 subagent。一次性侧车用 runAutoLlmChat(记录的 chat());带工具的 AutoLlm 循环用 runAutoLlm。过程中 Habitat 管理页可见 running;引擎仍以内存 messages 为下一跳输入。工具有副作用,中断后标失败,不按落库重放、不跨实例续跑。工具上下文用 contextKind: auto_llm,使 memory_remember 不附加 source_conversations。Cron no_agent shell 脚本不是 AutoLlmRun。绑定策略的 AutoLlm 运行把具体工具名列表作为 tools 传入(HARD_DENY toolset_load / toolset_unload / toolset_search)。

AutoLlm 提示: composeAutoLlmPrompt 组装——system<auto_llm_protocol> + <auto_llm_task_spec>(稳定,可用 {{param}} 挖空);user:可选技能 → <auto_llm_task_params>(填空)→ 数据。协议只禁末轮 tool_calls收尾形态在 kind 的 task_spec(如 retain 约 20 字、subagent 给父代理完整答复)。禁止把对话 system_prompt 快照当作 AutoLlm system(压缩/handoff 亦然)。审计列含可空的 subject_idmax_loop_iterations(引擎轮预算)、max_duration_ms(墙钟预算,可空)与实际 duration_ms

行动主体: runAutoLlmChat(无工具侧车:标题 / 压缩 / goal_judge / 簇标题等)通常不传 subjectId,审计列 auto_llm_runs.subject_id 可空。runAutoLlm(有工具环:subagent / cron / retain / skill review 等)必填显式 subjectId(会话绑定 agent、cron job.subject_id、或维护分桶 agent),禁止静默填入 default_chat_agent_subject_id / 废弃别名 agent_subject_id。工具 world 授权用 resolveToolCallerSubjectId()——MCP token subject,否则 ALS subjectId,否则报错(禁止回退默认聊天 agent)。

会话目标 continue 回合(合成用户 ↻ Continuing… + assistant)留在对话路径,使聊天室转录完整;仅 judge 跳转为 AutoLlm(run_kind: goal-judge)。

问题:此 conversation 是否应继续朝既定结果推进?

会话目标是资源层 / 编排层的进程内自主循环——有别于 subagent 工具派发:

维度会话目标Subagent
范围单一对话全新 AutoLlmRun
触发/goal slash + 回合后 judgesubagent_run 工具调用
持久化conversations.goal JSONB;continue 回合在 messages;judge 跳转在 AutoLlm(goal-judgeauto_llm_runsrun_kind: subagent
延续同一 SSE 流、续写回合预算(max_continues同步工具结果回父方

Judge 使用可选 llm.profiles.goal_judge;judge 调用/解析失败时目标暂停(记 warn + 聊天室状态行)。用户消息抢占循环;/goal pause / /goal resume 控制自动继续而不清空状态。见 goal.md

Client UI(web/dist SSOT + 原生壳打包)

Section titled “Client UI(web/dist SSOT + 原生壳打包)”

Portal Shell 运行时Tauri(Rust 主进程 + 系统 WebView;桌面与 Android 统一壳层)。壳规则:.cursor/rules/tauri-shell.mdc禁止为 companion 再打 Node sidecar;remote_tools.attach 在第一方伴侣浮层(见 Desktop companion)。

UI 源码产物packages/frontend/portal/app/web/distbase: /web/)。

客户端UI 加载更新方式
浏览器 / PWAHabitat 托管 /web/*(有 dist 时始终托管)Service Worker 提示新版本后手动重载(不自动刷新);跟 GitHub 包通道
Desktop安装包内 ui/webprepare-tauri-ui);调试可用 Tauri dev按 bake channel 查 GitHub(release=stable latest + semver;canary=tag canary + commit);用户确认后 NSIS 覆盖;可切换 releasecanary;About 可选公共 gh-proxy(默认直连)
Mobile APK安装包内 ui/web(本地同源);Habitat 仅 API同上轨语义;有 APK asset 才提示;确认后系统安装器覆盖;可切换轨;同上代理选择
Standalone嵌入 Web UI 的单文件 animaanima upgrade / 设置「关于→服务」/ ops_update_*--channel / --proxylocal / 源码安装不可自动升级;curl 安装脚本可用 PROXY=…
浏览器形态入口(Chrome)开发者模式加载已解压 / Release zip商店 OTA;手动重载
浏览器形态入口(Firefox,维护者)签名 xpi(gecko id extension@freeanima.com只跟 canaryhttps://freeanima.com/extension/firefox/updates.json → Release 固定资产名 xpi;AMO unlisted 签名;换 gecko id 须卸旧装新

壳层保留原生能力(Tauri commands / prefs / 通知等)。无壳内 UI OTA:原生端不从 Habitat 热替换 SPA。允许用户确认后的安装包级覆盖(Desktop 安装包 / Mobile APK / Standalone anima upgrade 或设置关于→服务 / ops 工具 → 独立前缀如 ~/.anima/standalone)。分发轨 SSOT 为安装包 bake 的 build-meta.channelrelease / canary / local)。Habitat 配置统一走 settings「连接」(/settings);无独立 bootstrap Habitat 页。

概念含义代码
壳(Shell)入口宿主运行时(browser / Tauri;形态 web / desktop / mobile)packages/frontend/portal/app/*portal-sdkgetShellKind / ShellApi / buildTarget
应用布局SPA chrome:模块左栏 Rail / 底栏 Tabs、设置页 chromepackages/frontend/client/app-frameAppFrame);跟视口,由壳类型锁定

三维度模型(壳子 / 布局 / 交互)

Section titled “三维度模型(壳子 / 布局 / 交互)”
维度驱动职责
壳子getShellKind()web/tauri)+ getShellBuildTarget()存储、IPC、Habitat 连接、settings 内容字段、原生能力
布局仅视口断点(壳不锁底栏/左栏)compact / expanded;列表 drawer / 并列 / 三栏;settings chrome(tabs vs 侧栏)
交互primaryInput(touch / pointer)长按 vs 右键、Enter 发送等

手机端通常只有窄档,但 手机端 ≠ 窄布局;Portal / 浏览器窗口可以是窄或宽任意档。标准 → docs/ui/dimensions.md(Agent API → .cursor/rules/frontend-ui.mdc)。

档位视口布局粗档Nav IA页内
< 768px(Tailwind md)compact底栏 + Moredrawer
768–1027pxexpanded左侧 Rail两栏(清单 drawer)
≥ 1028pxexpanded左侧 Rail三栏并列

resolveLayoutMode():窄 → compact,中宽 → expanded(URL / config.json 可覆盖)。detectSettingsChromePlatform() 跟布局粗档(设置页 chrome);settings 字段差异由壳子维 resolveShellBindings() / getShellKind() / getShellBuildTarget() 决定。

客户端UI 加载壳发版
浏览器 / PWAHabitat /web/*随 Habitat / anima upgrade
Desktop安装包内本地 /web/*(默认)Tauri 安装包
Mobile APK安装包内本地 /web/*Tauri Android
模块连接说明
聊天室栖息地 RPC /rpc/v1(共享 WS,无远程工具 attach)/web/chat
栖息地栖息地 RPC /rpc/v1(WS + HTTP POST,同一信封)/web/habitat/dashboard

/web/config.json 提供 habitat_urlhabitat_ws_urlui_versionmin_shell_version(浏览器/PWA 与壳调试用;原生壳 UI 版本随安装包)。

统一进程内 HookRegistry(无 Redis 队列):

  • on:请求路径上的拦截器——await;可 blocked / 返回 Effect(消息入站、回合结束、工具返回、系统提示、LLM 前等)。
  • subscribe:旁路观察者——在 run / emit 期间启动且不 await(错误记日志);例如 Discord 会话标题在 conversation:updated
  • run / emit:实时派发——先 await 全部 on 处理器,再 fire-and-forget subscribe 处理器。emit 忽略拦截结果。
  • llm_kind:每个 on / subscribeconversation | auto_llm | all)与每个 run / emitconversation | auto_llm;永不 all)必填。处理器按注册范围过滤;运行种类注入处理器上下文为 llm_kind。以此避免对话提示段(技能目录、env-health、…)泄漏到 AutoLlm / subagent 运行。

Pipeline Runner 引擎仍保留于 engine/pipeline(测试与潜在复用);记忆维护已脱离 DAG,夜间/手动走顺序编排(runNightlyMemoryMaintenance),不再经 PipelineRunner

互补:记忆维护 = 顺序后台编排;HookRegistry on =「可否继续 / 变更」;subscribe = 进程内通知。UI 除 subscribe 外仍常直接使用 onConversationUpdated 回调。

桌面伴侣是不可达本地应用主动连接栖息地并在第一方伴侣浮层embedded-overlay;壳只提供窗口/IPC/FS——不是 Node sidecar)注册远程工具,边界拆分如下:

关切栖息地(packages/habitat/features/companion/本机安装
行为、槽位、活跃模型运行时 companion 段(模块配置)+ 栖息地 RPC缓存在 ~/.anima/companion/config.json
VRM / VRMA 库object_file_id → 对象存储(运行时 object_storage);非本机磁盘 SSOTobject_storage.file.get / sync.pull 懒下载
设置 UI栖息地 RPC + companion 上传路由桌面设置区(非栖息地)
VRM 渲染、浮窗、巡逻Tauri 入口壳 + 浮层 SPA
Agent 工具(bubbleplay_slotremote_tools.attach 后的栖息地 RPC tool.*浮层 WebView-host 执行(本地 runtime)

远程工具 ≠ 入口 / MCP:入口壳与聊天室/设置仅用栖息地 RPC 做 UI。可拨号对等方经 MCP 暴露工具。远程工具 attach 仅在栖息地无法拨号该应用时存在(今日伴侣浮层;未来独立本地应用)。路由用 instance_id(同机可多实例)。见 companion.mdhabitat-rpc.md

能力愿景与讨论:GitHub Issues(标签 enhancementdiscussionsecurity)。本文不跟踪待办。

  • 原则与结构写在这里;不含具体任务清单
  • 快速变化的行为以运行中的服务为准,而非过时的文字
  • 可执行工作放在 GitHub Issues;完成后关闭