An IM-first world communication base for real people. It uses a shared vocabulary of 世界 / 城邦 / 聚落 / 居民 / 城主 / 互联 / 共建, with the gateway contract as the single source of truth, H5 as the current primary interaction entry, and TUI as a parallel mapped client. Different windows share the same world model, but they do not share the same rights.
入口口径统一为“先聊天,再展开共建入口”:H5 先承接主流程,TUI 作为消费同一套 gateway 合同的并行终端客户端,城主与居民共用同一套世界观,但在同窗里拥有不同权限,不把页面说成旧式工具页或工具墙。
- 启动页:
apps/lobster-web-shell/index.html - 居民投影:
apps/lobster-web-shell/creative.html - 城主投影:
apps/lobster-web-shell/admin.html - 城主后台新视觉基线:
apps/lobster-web-shell/admin-ds.html - 世界入口:
apps/lobster-web-shell/unified.html - 世界广场:
apps/lobster-web-shell/world-square.html - 默认网关示例:
http://127.0.0.1:8787 - 快速验收说明:
docs/WEB_SHELL_ACCEPTANCE.md - 线性后台功能目录:
docs/ADMIN_FUNCTION_CATALOG.md - 前端技术债治理计划:
docs/FRONTEND_DEBT_REDUCTION_PLAN.md
最小直接预览方式是将 apps/lobster-web-shell 作为静态目录挂起来。示例入口地址如下(前缀 http://127.0.0.1:8080 取决于你的静态服务器):
http://127.0.0.1:8080/—— 主城群聊入口。http://127.0.0.1:8080/creative.html—— 正式居民住宅 / 私聊 IM,接真实 gateway 时使用居民登录态过滤会话。http://127.0.0.1:8080/user.html—— 旧链接兼容入口,保留 query 参数后跳转到creative.html。http://127.0.0.1:8080/admin.html—— 城主治理兜底页,当前只保基础可用和移动端兜底。http://127.0.0.1:8080/admin-ds.html—— DeepSeek V4 Pro 后台视觉方案,已作为后续正式后台样式基线保留。http://127.0.0.1:8080/unified.html—— 世界入口,地铁候车站式导航页,不展示聊天框。http://127.0.0.1:8080/world-square.html—— 世界广场,只读公共入口,展示公告、公共讨论和跨城发现摘要。
运行方式:
cd apps/lobster-web-shell
python3 -m http.server 8080需要接真实消息时,先起一个本地 gateway(默认 http://127.0.0.1:8787),然后把 ?gateway=http://127.0.0.1:8787 拼到上面的任意页面 URL 上。
详细的快速验收请直接看 docs/WEB_SHELL_ACCEPTANCE.md。
脚本化 H5 smoke:
cd /Volumes/AJW-Data/Projects/lobster-chat
./scripts/smoke-web-shell.sh这条 smoke 当前覆盖:
index.html/creative.html/admin.html/admin-ds.html/unified.html/world-square.html的静态入口结构creative.html的 fake-DOM 启动与默认聊天主路径user.html的兼容跳转:保留 query 参数后重定向到creative.html- 切换会话后输入区 placeholder 跟随当前线程刷新
真实 gateway shell 双端 HTTP smoke:
cd /Volumes/AJW-Data/Projects/lobster-chat
./scripts/smoke-shell-dual-http.sh
./scripts/smoke-shell-direct-http.sh这些 smoke 会启动临时 gateway:公共房间用 qa-a 发送 shell 消息并验证 qa-b 的 /v1/shell/events 与 /v1/shell/state 都能看到同一条消息;私聊用 qa-a/qa-b 打开 dm:qa-a:qa-b,验证 send/edit/recall 都会进入 peer SSE 与 state projection,并确认 qa-c 不可见且不能写入。
额外的外部入口 smoke:
cd /Volumes/AJW-Data/Projects/lobster-chat
BASE_URL=https://<node>.<tailnet>.ts.net ./scripts/smoke-public-ingress.sh它会验证外部入口的:
/GET /healthHEAD /health/v1/provider
当前页面边界:
creative.html目前固定为住宅 / 私聊入口,默认直接进入房间列表与消息流creative.html?gateway=...会在访客态显示紧凑邮箱验证码登录片,登录成功后保存resident_id并重新拉取该居民可见会话- 真实 gateway 模式下,
creative.html会请求GET /v1/shell/state?resident_id=<当前身份>;未登录身份为访客,只能看到公共/访客可见入口,且不能向私聊或房间发送正式消息 - H5 实时读侧合同优先使用
GET /v1/shell/events?resident_id=<当前身份>的 SSEshell-state事件,ShellState带state_version供客户端判断快照变化;需要等待变化时可带after=<state_version>&wait_ms=<ms>,网关会等待到版本变化或超时,超时无变化时返回同版本快照和shell-heartbeat,客户端按最新state_version重连;写侧仍走POST /v1/shell/message,成功回执必须带delivery_status="delivered"、message_id、delivered_at_ms、sender和规范化text,可选reply_to_message_id用于微信式回复引用;后续状态投影里的同条消息也会带delivery_status="delivered";撤回走POST /v1/shell/message/recall,编辑走POST /v1/shell/message/edit,H5 和 CLI/TUI 读侧投影都保留审计记录并返回is_recalled/recalled_by/recalled_at_ms与is_edited/edited_by/edited_at_ms - H5 与 CLI 写入统一使用 gateway 文本合同:正文先 trim,trim 后必须为 1-2000 字符;空白消息和超长消息直接由 gateway 返回失败
user.html只保留为旧链接兼容入口,不再展示独立住宅 UI;它会保留 query 参数并跳转到creative.htmlauth / world / governance这些附加 workspace 现在只在非user页面暴露
- 打开用户端页面,阅读“如何开始”指引,优先进入会话列表。
- 住宅页当前默认直接进入聊天主路径;接入真实 gateway 后,访客态先用邮箱验证码登录,登录成功后刷新为该居民视角。
- 用户端默认是“两栏 IM”:左侧收件箱,右侧线程和输入框。会话摘要优先显示最后一条消息、时间、未读和草稿。
- 底部输入区明确按“聊天输入区”来设计:先提示当前线程和发送状态,再露出真正的输入框和发送按钮。
- 终端默认先把焦点放在会话导航;按
i进入输入,Enter发送,Shift+Enter插入换行,ArrowUp快速恢复上一条。 /open、/world等命令仍然可用,但只算补充入口。/governance仅在当前 surface 已挂出治理会话时才会切换;主流程仍然是聊天、提醒和共建留言。
- 城主投影优先用于处理待跟进聚落、公告、安全提醒和互联巡检结果。
- 城主投影是“会话优先的线性共建台”:左侧居民与聚落列表,中间当前线程,右侧是少量、明确、可解释的共建动作。
- 底部输入区仍然像聊天框,但默认语义是跟进、公告和处置,而不是工具操作。
- 右侧区域只在分析、调度或公告时展开,不要让它抢走线程本身的主位。
- 任何巡检动作都应生成可见卡片,带上当前责任人、影响范围和处理结果。
- 默认先在导航区,按 i 进入输入;进入输入后,Enter 发送,Shift+Enter 插入换行,ArrowUp 复用上一条。
- 透明助手口令:
/assistant,/owner,/dog,直接叫 OpenClaw 共建助手辅助留言、巡检、公告。 - 保持会话上下文可见:输入区下方会提示同步状态、共建记忆和访客提醒;网关慢时会先显示本地待同步消息。
| 模块 | 测试数 | Clippy | 状态 |
|---|---|---|---|
| Gateway (Rust) | 232 | ✅ | 97 路由, 设备管理, 场景权限, 审核持久化 |
| TUI (Rust/ratatui) | 218 | ✅ | 用户端/城主端/世界广场/私聊终端 |
| CLI (Rust) | 42 | ✅ | 14 子命令, 集成测试 |
| H5 Web Shell (JS) | 731 | — | 6 页面注册, 场景交互, admin-ds 10 模块 |
| crypto-mls | 20 | ✅ | AES-256-GCM + HKDF 前向安全 |
| ai-sidecar | 7 | ✅ | HTTP AI 助手 + 流式 |
| chat-core | 20 | ✅ | 合同定义, SceneImageLayer day/night |
| chat-storage | 17 | ✅ | 文件存储, 原子写 |
| 总计 | ~1,290 | 零警告 | 全模块通过 |
最近更新:
- 🔐 crypto-mls: 骨架→AES-256-GCM 真加密 + 公钥交换
- 🤖 ai-sidecar: trait→HTTP AI 助手实现
- 🖥️ admin-ds: 审计日志 loading/error 状态, 设备管理 UI
- 🎨 CSS: tokens 提取, admin 专属规则分离
- 🧪 CLI: 31→42 测试, Gateway 集成覆盖
- 🔧 工作区 clippy 零警告
完整审计: docs/TECH_AUDIT_REPORT_20260604.md 开发蓝图: docs/DEVELOPMENT_BLUEPRINT.md
lobster-chat is intentionally built around three mutually reinforcing experiences:
- 居民 IM – a chat-first surface with conversation lists, timelines, and handoff-friendly inputs that look and feel like a modern messaging client.
- 轻巡与互联守望 – passive monitoring agents that keep an eye on safety signals, surface action cards, and quietly report to the城主 when something needs attention.
- Personal OpenClaw 共建助手 – a trusted helper that can leave visitor notes, moderate 聚落, carry a lightweight memory, and alert the城主 or tools when needed.
These pillars sit on top of the existing expansion strategy:
- downward: keep the core runnable on embedded/low-resource hosts without dragging in bulky AI/GUI stacks.
- sideways: provide mobile H5 projections so residents can dip in via browsers before native apps ship.
- upward: ensure wearables and glance surfaces can consume the same core via compact interactions.
The build order remains:
- local-first core
- host adapter boundary
- lightweight transport and security layers
- wearable expansions after the base stabilizes
- gateway contract as the only source of truth for chat and scene state
- H5 主交互入口 for current IM and SFC-style scene work
- TUI parallel mapped client for terminal-first operation and parity checks
- Linux / macOS / Windows compatibility
- lightweight core that can run headless
- Waku transport for decentralized delivery
- MLS-based security layer
- local archive with active-window sync
- optional AI sidecar for translation, summarization, and semantic assistance
- host adapter layer for embedding inside Lobster
- embedded-friendly and wearable-friendly surface design
crates/chat-core: shared message, identity, room, archive, and device modelscrates/chat-storage: local persistence traits and in-memory timeline prototypecrates/host-adapter: embedding boundary for Lobster, desktop, mobile web, and wearable hostscrates/transport-waku: Waku transport boundary and future light-client implementationcrates/crypto-mls: MLS session and room security boundarycrates/ai-sidecar: optional AI assist boundaryapps/lobster-tui: standalone terminal client that consumes the shared gateway contractapps/lobster-web-shell: current primary H5 client for browsers and future PWA packagingapps/lobster-waku-gateway: localhost JSON gateway skeleton for sharing one Waku-facing transport service across entriesscripts/: preflight, packaging, smoke verification, and server install helpersdocs/: architecture and phased implementation notesdocs/CARETAKER_PLAYBOOK.md: product vision for the IM-first caretaker, patrol, and visitor flowsdocs/NOVEL_TTS_PLAYBOOK.md: audiobook/TTS repair workflow and delivery checklist for caretaker-style agent operations
The protocol uses a 世界 / 城邦 / 居民 / 城主 model:
世界: shared protocol, identity, and互联规则城邦: a hosted service domain that provides relay, storage, discovery, and public共建聚落: a conversational or community unit inside a城邦居民: a portable user identity that is not trapped inside any one城邦城主: a city-scoped authority with WeChat-group-owner-level stewardship for public spaces plus infrastructure responsibility, but without private-message plaintext access or global ownership over any resident
The public城邦目录 should be mirrored across multiple互联城邦.
lobster-chat is being designed so optional OpenClaw-powered bots can help
居民在聚落、城邦和世界相关流程中协作,而不会把
whole product into a single AI entry.
See:
docs/OPENCLAW_AGENT_INTERFACE.mdThe first 城邦 can act as a seed city early on, but the architecture should not depend on a permanent world server.
Key references:
- docs/PRODUCT_CHARTER.md
- docs/WORLD_CITY_MODEL.md
- docs/WORLD_CITY_API.md
- docs/WORLD_SQUARE_AND_SAFETY.md
- docs/WAKU_GATEWAY_PROTOCOL.md
- docs/MLS_SKELETON.md
- docs/AUTH_AND_REGISTRATION.md
- docs/RESOURCE_BUDGET.md
- docs/DEPLOYMENT_PITFALLS_AND_HARDENING.md
- docs/TUI_RENDERING_STRATEGY.md
- docs/THEME_AND_NOMENCLATURE.md
- docs/SPATIAL_SCENE_MODEL.md
Current state already includes:
- compile-ready Rust workspace
- local-first domain model
- file-backed timeline and archive policy prototype
- host capability split for embedded / desktop / mobile web / wearable
- postcard-based compact message framing for Waku payload transport
- gateway-backed Waku adapter boundary with an in-memory light-node gateway for topic subscribe / poll / history recovery
- localhost Waku gateway process skeleton with JSON request / response contract
- gateway-side file-backed state so room timelines survive localhost gateway restarts
- localhost gateway endpoints for world, city, membership, and public-room operations
- optional upstream gateway interlinking for multi-city transport experiments
- downstream world discovery can now merge upstream city catalogs
- direction agreed: the world directory should be mirrorable across multiple cities so discovery survives loss of any single seed city
- direction agreed: the world should include a mirrored World Square plus a world-level safety coordination layer for emergency quarantine of malicious cities
- severe confirmed abuse can revoke cross-city portability for the offending resident identity, and the gateway now has resident-sanction plus hashed registration blacklist feeds for email/mobile handles
- the gateway now has a low-cost auth skeleton for email OTP registration/login plus blacklist-aware handle preflight
- the H5 projection can now request and verify email OTP login against that auth skeleton
- H5 residents can now file public-abuse reports into the world safety queue
- MLS lifecycle skeleton for direct sessions, room sessions, epoch rotation, and transport envelopes
- direct 1v1 session bootstrap API with persisted MLS skeleton state
- standalone TUI bootstrap that simulates a local message flow
- static H5 projection that consumes Rust-exported bootstrap and room state
- H5 projection gateway mode with live poll/send support and locally remembered resident handle
- H5 projection world view with city discovery, join, found-city, and public-room actions
- H5 resident directory with direct-message bootstrap against the localhost gateway
- H5 resident-visible history export for private, group, and city-public conversations
- H5 projection now exposes unread state, active-room highlighting, send / sync / empty feedback, and narrow-screen chat switching
- H5 城主互联策略 modes for
Open / Selective / Isolated - provider status endpoint so clients can see whether they are on local memory transport or a remote provider bridge
- provider connect / disconnect flow so a city gateway can persistently bridge to another provider without CLI-only setup
- terminal render capability model for SFC-inspired high-color terminals with graceful FC-style fallback
- city-lord moderation API for join approval, steward assignment, and public-room freeze handling
- world-square notice model plus world-safety trust/advisory skeleton
- world-directory snapshot and mirror list endpoints so clients can render a mirrored entry catalog
- world snapshot bundle endpoint with checksum metadata for mirror nodes and cached clients
- H5 world layer that now surfaces directory entries, mirrored sources, notices, and safety advisories
- release-side helper scripts for preflight, packaging, and server installation
- unified local release gate now covers CLI, auth, resident, public/direct shell, web shell, and terminal smoke in one entrypoint
当前版本不按“把全部 Phase 一次做完”推进,而是先收一版可用主线。
当前只把下面这些算作 MVP 范围:
- gateway 正式合同作为唯一真源:
conversation_shell / scene_render H5主交互入口,承接当前 IM 与 SFC 场景主路径TUI并行映射客户端,用于终端操作、验收和后续多入口一致性- 单城邦范围内的私聊、群聊、房间聊天主路径
lobster-cli命令行聊天通道,供OpenClaw / Codex / Claude Code等本地智能体直接发消息、看收件箱、追消息流- 为后续真实 transport 和真实加密保留明确边界
当前明确后置:
World Square / World Safety的完整产品面- 多城邦互联产品化
- 眼镜端实现
- 装扮编辑器、素材系统与自由摆放
H5的离线/PWA 完整体验与二阶段产品化抛光
所以现在如果你看到文档里还有更大的世界层、互联层、穿戴层设想,那些都应理解成“后续预留”,不是当前版本必须同时落地的内容。当前版本先保证 H5 和 TUI 都消费同一套正式合同,而不是让任一前端继续长私有状态。
Run the local gateway:
cargo run -p lobster-waku-gateway -- --host 127.0.0.1 --port 8787Optional: choose a persistent state directory explicitly.
cargo run -p lobster-waku-gateway -- --host 127.0.0.1 --port 8787 --state-dir ./.lobster-chat-dev/gatewayThen point the TUI at it:
LOBSTER_WAKU_GATEWAY_URL=http://127.0.0.1:8787 cargo run -p lobster-tuilobster-cli 是挂在本地 gateway 旁边的一条命令行聊天通道。它不是新的独立聊天系统,也不是绕过 gateway 直写本地存储,而是给这些调用方补一条非图形入口:
OpenClawCodexClaude Code- 以后需要批处理或自动化发消息的脚本
第一版只做 lobster 内部送达,不接飞书、微信、短信等外部网络。
地址格式:
user:<id>:用户身份,例如user:zhangsanagent:<id>:智能体身份,例如agent:openclawroom:<scope>:<city>:<name>:房间身份,例如room:city:core-harbor:lobby
注意:
send --to这里传的是 CLI 地址,不是内部conversation_id- 不要把
dm:openclaw:zhangsan这类会话 ID 直接传给--to - 点对点消息要传
user:...或agent:...,再由 gateway 归一化成内部dm:...
输出约定:
- 默认输出人类可读文本,适合手工排查和临时操作
- 带
--json时输出结构化 JSON,适合OpenClaw / Codex / Claude Code这类本地智能体或脚本直接解析 tail人类可读输出会把已撤回消息标成[已撤回]且只显示消息已撤回,把已编辑消息标成[已编辑];脚本侧应优先读取 JSON 里的is_recalled/is_edited元数据send/edit正文由 gateway 统一 trim;trim 后为空或超过 2000 字符会失败,客户端不要本地伪造成功状态
可用命令:
# 发一条私聊
cargo run -p lobster-cli -- send \
--from agent:openclaw \
--to user:zhangsan \
--text "晚上一起吃饭吗"
# 看某个身份的收件箱摘要
cargo run -p lobster-cli -- inbox --for user:zhangsan
# 看某个身份当前可见的房间/私聊列表
cargo run -p lobster-cli -- rooms --for user:zhangsan
# 看某个身份最近一段消息流
cargo run -p lobster-cli -- tail --for user:zhangsan
# 编辑自己发过的消息
cargo run -p lobster-cli -- edit \
--actor user:zhangsan \
--conversation-id dm:openclaw:zhangsan \
--message-id msg-1 \
--text "改过后的内容"
# 撤回自己发过的消息
cargo run -p lobster-cli -- recall \
--actor user:zhangsan \
--conversation-id dm:openclaw:zhangsan \
--message-id msg-1如果要显式查看某条会话,可以带 --conversation-id:
cargo run -p lobster-cli -- tail \
--for user:zhangsan \
--conversation-id dm:openclaw:zhangsanOpenClaw 先走最稳的私聊路径:
cargo run -p lobster-cli -- send \
--from agent:openclaw \
--to user:zhangsan \
--text "晚上一起吃饭吗" \
--jsonCodex 拉自己的收件箱摘要:
cargo run -p lobster-cli -- inbox \
--for agent:codex \
--jsonClaude Code 跟一条已知会话的消息流:
cargo run -p lobster-cli -- tail \
--for user:zhangsan \
--conversation-id dm:openclaw:zhangsan \
--json接入建议只记三条:
- 发消息用
send - 拉摘要用
inbox - 持续盯流用
tail --follow
补充一条经验规则:
- 新接入时优先先把私聊跑通;房间发言还会受房间可见性和发言权限约束
这条通道的定位是:
TUI:给真人直接聊天H5:后续做投影lobster-cli:给智能体和脚本发消息、看收件箱、追消息流
本地 smoke 已验证过一轮,统一入口是:
bash ./scripts/smoke-release-gate.sh这个统一入口会串起当前默认的本地黑盒门禁:
./scripts/smoke-cli-channel.sh
./scripts/smoke-auth-registration.sh
./scripts/smoke-resident-mainline.sh
./scripts/smoke-provider-federation.sh
./scripts/smoke-web-shell.sh
python3 ./scripts/test_start_terminal.py如果只想跳过 provider federation,可以显式:
INCLUDE_PROVIDER_FEDERATION=0 bash ./scripts/smoke-release-gate.sh部署链另外还有一条独立 smoke,会验证安装脚本产物布局而不依赖真实 Linux 主机:
./scripts/smoke-install-layout.sh它会校验当前 artifact / 安装目录 / systemd unit / nginx 配置的生成结果,不替代真实 Linux 主机上的 systemctl、nginx 和公网入口验收,但能提前拦掉路径、打包和安装合同错误。
仓库现在也把同一组检查固化进了 GitHub Actions:
/.github/workflows/ci.ymlscripts/test_start_terminal.py已支持通过LOBSTER_CHAT_ROOT覆盖根目录,避免 CI 依赖本机绝对路径
这条脚本会自动:
- 构建
lobster-waku-gateway和lobster-cli - 起一个临时本地 gateway
- 跑
send / inbox / rooms / tail / tail --follow - 同时验证人类可读输出和
--json结构化输出 - 验证最小直聊链路和 live follow 是否真的通了
而 ./scripts/smoke-auth-registration.sh 会验证当前低成本注册骨架:
- 起一个临时本地 gateway,并打开
LOBSTER_DEV_EMAIL_OTP_INLINE=1 - 跑一遍
auth/preflight -> email-otp/request -> email-otp/verify - 检查
auth-state.json里确实持久化了注册 resident 和已消费的 challenge - 再走一遍 world-blacklist 反例,确认被拉黑的邮箱/手机/设备会在 preflight 被拦截,且不能继续请求 OTP
而 ./scripts/smoke-resident-mainline.sh 会验证当前居民主路径:
- 先确认未注册 resident 不能直接加入城邦
- 跑一遍
auth/preflight -> email-otp/request -> email-otp/verify - 让刚注册的 resident 加入
core-harbor - 先确认注册时自动生成的住宅私聊
dm:guide:<resident>已进入会话集合 - 启动
lobster-tui --mode user,用真实 resident 身份往room:city:core-harbor:lobby发第一条公共频道正文 - 在同一条 user 会话里执行
/dm builder,再发第一条额外私帖 - 再用
lobster-cli tail --for user:<resident>分别验证公共频道消息、住宅私聊和额外 canonical 私帖都已落盘
而 python3 ./scripts/test_start_terminal.py 会继续补上 TUI 侧验收:
- 起一个临时本地 gateway
- 先抓一帧默认
user/workbench视角的终端语义快照,确认首屏是CityPublic,且可见status/switcher/scene/profile/transcript/input - 通过
lobster-cli往room:city:core-harbor:lobby预置一条城邦大厅消息 - 用
lobster-cli tail验证默认user主路径真的能看到这条大厅消息 - 再用真实 PTY 按键走一遍默认
user视角的TUI发送链:i -> 输入正文 -> Enter - 由另一进程用
lobster-cli tail验证这条TUI发出的大厅消息确实进入room:city:core-harbor:lobby - 重启同一个 gateway 进程后,再抓一次默认
userdump,确认刚才那条大厅正文仍然可见 - 先抓一帧
world视角的终端快照,确认主界面标记正常 - 通过
lobster-cli往room:world:lobby预置一条新消息 - 再抓一帧
lobster-tui的单次 plain dump - 验证
worlddump 里真的出现这条广场消息 - 再用真实 PTY 按键走一遍
world视角的TUI发送链:i -> 输入正文 -> Enter - 由另一进程用
lobster-cli tail验证这条TUI发出的广场消息确实进入room:world:lobby - 保持同一个运行中的
worldTUI 会话,在 gateway 暂停时再发一条消息,确认正文先落进本地 store 而不是直接丢失 - 同一个 gateway 恢复后,再由另一进程用
lobster-cli tail验证这条离线期正文会被自动补发到room:world:lobby - 重启同一个 gateway 进程后,再抓一次
worlddump,确认刚才那条TUI广场消息仍然可见 - 再切到
direct视角,确认首屏是 resident 的住宅私聊dm:guide:<resident> - 用
guide -> resident预置一条住宅私帖,验证directdump 里真的出现这条住宅私聊 - 再额外验证显式
/dm builder仍会 canonical 到dm:builder:<resident> - 最后重启同一个 gateway 进程,再抓一次
directdump,确认私帖正文在重启后保持可见 - 继续用真实 PTY 按键走一遍
TUI发送链:i -> 输入正文 -> Enter - 再由另一进程用
lobster-cli tail验证这条TUI发出的住宅私帖确实进入dm:guide:<resident>
也就是说,现在最小主路径不再只是 CLI -> gateway,而是同时覆盖:
CLI -> gatewayuser/workbench -> city lobby -> gateway -> restart recoverygateway -> TUITUI world send -> gateway -> cross-process tailTUI world offline send -> local pending -> gateway recovery -> auto republishworld TUI send -> gateway restart -> TUI recoverydirect canonicalization -> TUITUI direct send -> gateway -> cross-process taildirect TUI history -> gateway restart -> TUI recovery
如果要保留临时状态和日志,便于排查:
KEEP_STATE=1 ./scripts/smoke-cli-channel.sh统一入口同样支持:
KEEP_STATE=1 bash ./scripts/smoke-release-gate.sh也可以手工逐条执行:
# 临时起本地 gateway
cargo run -p lobster-waku-gateway -- --host 127.0.0.1 --port 8792 --state-dir /tmp/lobster-cli-smoke-gateway
# 另一终端里发消息
cargo run -p lobster-cli -- send \
--from agent:openclaw \
--to user:zhangsan \
--text "晚上一起吃饭吗" \
--gateway http://127.0.0.1:8792
# 查看 inbox / rooms / tail
cargo run -p lobster-cli -- inbox --for user:zhangsan --gateway http://127.0.0.1:8792
cargo run -p lobster-cli -- rooms --for user:zhangsan --gateway http://127.0.0.1:8792
cargo run -p lobster-cli -- tail --for user:zhangsan --gateway http://127.0.0.1:8792预期最小信号:
send返回一条“已投递到 ...”的人类可读确认;如果是脚本接入,就给它加--jsoninbox能看到刚才那条会话摘要rooms能看到对应私聊或房间tail能拉到刚发送的正文;要持续盯流就改成tail --follow
Or use the one-command terminal launcher:
lobster-tui 现在是一个真正可交互的中文终端聊天入口,不再只是黑底调试界面。首屏已经按真实聊天器的层次整理成四块,并参考了 Lazygit / ratatui 常见的“标题行 / 元信息行 / 正文区”节奏;输入区是单行落字栏,输入焦点会跟着你当前选中的会话走:
- 左侧
聚落与私信:按频道 / 私信分组,像收件箱,会话标题尽量收成短名,不把类型文案重复塞进每一行。 - 左下
线程详情:只保留当前会话的对象、路由、世界、归档和缓存信息,不再塞提醒类文本。 - 右上
当前线程:显示聚落/私信对象、路由标签、场景片头和最近一条消息,更像 thread header。 - 右中
消息流:只保留聊天正文,不把状态提示和共建信息挤进消息区。 - 底部
输入区:改成更像草稿箱的结构,先看到输入提示,再看到发送目标、对象和快捷命令提示,按 Enter 就会发送到当前会话。
这样终端首屏更像聊天客户端:左侧像 inbox,右侧像 thread view,底部像落字栏。区块顶端也不再把标题塞进边框里,而是统一成更标准的标题行;顶部状态也改成了更像产品顶栏的短签列。遇到窄终端时,TUI 会自动切到单列布局,把会话、状态、正文和输入区从上到下排开,优先保住可读性和输入顺滑度。
推荐优先用脚本启动,这样会自动拉起或复用本地网关,并直接进入用户聊天视角:
./scripts/start-terminal.sh
./scripts/start-terminal.sh user
./scripts/start-terminal.sh admin
./scripts/start-terminal.sh world
./scripts/start-terminal.sh direct
./scripts/start-terminal.sh workbench终端聊天中可以输入 /world 快速打开世界广场;如果当前 surface 已挂出治理会话,/governance 也会切过去。默认启动时焦点先在导航区,按 i 进入输入。底部 prompt 会直接显示当前发送目标,更接近真实聊天器,而不是命令行工具界面。workbench 目前不是独立 surface,只是 user 的别名,方便保留旧入口口径。
可用模式:
# 默认聊天视角
cargo run -p lobster-tui
# 用户端视角
cargo run -p lobster-tui -- --mode user
# 城主视角
cargo run -p lobster-tui -- --mode admin
# 世界广场 / 聊天优先视角
cargo run -p lobster-tui -- --mode world
# 私聊终端视角
cargo run -p lobster-tui -- --mode direct
# 默认聊天页别名(等同于 user)
cargo run -p lobster-tui -- --mode workbench在终端里你会看到这些操作提示:
i进入输入区Enter发送当前输入/open 1到/open 5切换当前窗口/dm <resident_id>打开或复用一条 canonical 私帖/world切到世界广场/governance在当前 surface 已挂出治理会话时切过去/help在当前会话追加本地帮助提示,不发布到网络/status在当前会话追加本地身份、连接和会话状态提示/refresh在当前会话追加本地刷新反馈/quit退出终端
说明:
/help、/refresh、/status是本地终端反馈命令,不写入 gateway,不影响远端房间workbench与user走同一条主路径,验收和行为保持一致
终端入口这轮又做了两件关键收口:
- 线框不再一视同仁。左侧会话栏、线程主体和输入区现在用了不同的框体语气,输入区会比消息区更醒目,减少“全屏都是同一种盒子”的粗糙感。
- 标题和内容之间加了元信息分层。每个区块顶部会先给标题行,再给元信息行,然后才进入正文,信息密度更像真实聊天器。
左侧会话列表现在更接近收件箱:当前焦点有明显高亮,其他线程保留轻量预览,不会一上来就像监控表格。右侧线程头单独承担“聚落名、对象、路由、场景”这些信息,消息流只负责读消息。底部输入区固定提醒当前发送目标,让 /open 切窗口时心里有数,而输入区的快捷行会根据 user / admin / world / direct 模式自动提示最常用命令;切换会话后,输入焦点会继续跟到新会话,不会留在旧窗口。
会话信息区现在也显式显示“模式”与 mode_callout,让居民端/城主端提前知道手头的交互脚本;连接区同样把 mode_callout 拉进元信息条,Web 端同步更好的分层感。
状态条也保持在 6 项以内:频道、窗口号、连接摘要、人数/消息、管家状态加上 mode_callout 文字,让居民端、城主端或广场视角一眼辨别当前角色和期待的交互方式。
启动脚本会顺手告诉你当前模式、网关地址和日志位置,方便排障和确认是不是连到了本地网关。
当前终端入口已经支持:
- 中文聊天首页
- 居民端 / 城主端 / 世界广场 / 私聊终端 四种启动视角
- 左侧会话列表 +
/open 序号的窗口切换 - 终端能力自动降级(TrueColor / 256 色 / 16 色 / ASCII)
- 低资源终端下保持 FC 风格符号化,高配终端继续走 SFC 氛围感方向
- 黑底聊天页 + 状态区组合,输入区与命令提示清晰,像真正的聊天器一样可输入、可发送、可观察状态
Useful world-layer endpoints once the gateway is up:
curl http://127.0.0.1:8787/v1/world-directory
curl http://127.0.0.1:8787/v1/world-snapshot
curl http://127.0.0.1:8787/v1/world-mirrors
curl http://127.0.0.1:8787/v1/world-square
curl http://127.0.0.1:8787/v1/world-safetyQuick checks before deployment:
bash ./scripts/preflight.shPackage release artifacts:
./scripts/package-release.sh用两个 gateway 本地烟测 provider 互联:
SKIP_BUILD=1 \
GATEWAY_ARTIFACT=./dist/lobster-waku-gateway-$(rustc -vV | awk '/host:/ { print $2 }').tar.gz \
./scripts/smoke-provider-federation.sh完整 release/deploy 口径见 docs/DEPLOYMENT_SMOKE_TEST.md。
What the smoke covers and what still needs a real server check:
Install on a Linux server from source:
sudo ./scripts/install-server.shInstall on a Linux server from a prebuilt target-matched artifact:
sudo GATEWAY_ARTIFACT=./dist/lobster-waku-gateway-x86_64-unknown-linux-gnu.tar.gz \
./scripts/install-server.shInstall on a Linux server from gateway + H5 artifacts only:
sudo GATEWAY_ARTIFACT=./dist/lobster-waku-gateway-x86_64-unknown-linux-gnu.tar.gz \
WEB_ARTIFACT=./dist/lobster-web-shell.tar.gz \
./scripts/install-server.shThe installer now refuses to use a gateway artifact whose filename target triple does not match the current host.
If WEB_ARTIFACT is omitted, install-server.sh still copies the H5 shell from the checked-out workspace.
Gateway 通过环境变量控制安全敏感行为,无需改代码或配置文件:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
LOBSTER_CORS_ORIGIN |
* |
CORS Access-Control-Allow-Origin。生产部署应设置为前端域名(如 https://chat.example.com),留空或 * 为通配。 |
LOBSTER_DEV_AUTH_BYPASS |
(空) | 设为 1 后跳过所有 capability 校验。仅限本地开发,生产必须关闭。 |
LOBSTER_DEV_EMAIL_OTP_INLINE |
(空) | 设为 1 后 OTP 验证码直接返回在 API 响应里(dev_code 字段),跳过邮件发送。仅限本地开发。 |
LOBSTER_WAKU_PROVIDER_URL |
(空) | 上游 gateway / Waku provider URL。设置后 gateway 启动时自动连接上游。 |
LOBSTER_WAKU_UPSTREAM_URL |
(空) | LOBSTER_WAKU_PROVIDER_URL 的旧名,仍受支持。 |
生产部署检查清单:
-
LOBSTER_CORS_ORIGIN设为实际前端域名,非* -
LOBSTER_DEV_AUTH_BYPASS未设置(或显式设为0) -
LOBSTER_DEV_EMAIL_OTP_INLINE未设置(生产邮件发送必须走 mailer adapter) - OTP 限流已生效:每邮箱 1次/分钟请求,每 challenge 5次/分钟验证
- Session token 30 天过期,logout 立即撤销
- 审计日志写入
audit-log.json,高风险操作全部可追溯 - 若部署在反向代理后,代理须透传
Authorizationheader
make build # release 构建
make test # 全部测试 (gateway + frontend)
make test-gateway # gateway 测试 (227+)
make test-frontend # web-shell 前端测试 (659+)
make smoke # 双端 HTTP smoke
make release # 发布打包
make dev # 构建 + 重启 gatewayStill pending / deferred (external dependencies):
- live Waku relay adapter (multi-city federation — PRODUCT_CHARTER deferred)
- real cryptographic MLS implementation (PRODUCT_CHARTER deferred)
- chain anchoring path (not in MVP scope)
- SMS OTP for mobile device auth (needs SMS provider infrastructure)
- IndexedDB/PWA offline sync (post-MVP enhancement)
- wearable-specific transport bridge (not in scope)
This project is intentionally split so the core can be embedded into a Lobster host without forcing the full TUI, AI sidecar, or chain features into every build.