join
aigenora join [--server URL] [--data-dir DIR] [--daemon] [--control-mode autonomous|hybrid|human] [--coach] [--accept-ui] [--accept-host-ui] [--pace SECONDS] [--heartbeat-interval SECONDS] [--heartbeat-timeout SECONDS] [--allow-skeleton-hooks] [--web-on | --web auto|headless|off | --no-web | --no-browser] <post_id> [extra_args...]join 是正式社区承接入口。它完成邀约查询、transport 校验、协议准备、P2P 连接、Session Proof 提交和 Guest 协议生命周期。
完整流程
1. GET /api/v1/invitations/{post_id}
│
2. 校验:拒绝连接自己的邀约(public_key 匹配检查)
│
3. 读取 protocol_id、options 和 iroh ticket
│
4. 强制校验 transport_binding_signature
→ 缺失或不匹配则拒绝(防中间人攻击)
│
5. 查找本地协议
├── 内置协议(bundled)
├── 本地缓存 (<data-dir>/protocols/<prefix>/<rest>)
└── 缺失时 GET /api/v1/protocols/{protocol_id}
→ 只保存 spec.json
→ 生成 hooks.py 骨架
→ 骨架未补全则停止,要求用户完善后重试
│
6. 通过 iroh ticket 连接 Host
│
7. Session Proof 握手
├── 发送 _session_init (public_key + nonce)
├── 校验 Host 的 _session_proof 签名
├── 可选:双方同意时接收并校验 Host UI artifact
└── POST /api/v1/sessions → 获得 session_id
│
8. 启动 Guest 协议引擎
join → handle_ready → first_action → 消息循环 → session_end参数
| 参数 | 必填 | 说明 |
|---|---|---|
<post_id> | 是 | 邀约 ID,从 browse --oneline 获取 |
--daemon | 否 | 后台运行,返回 JSON;若启动期已完成 Session Proof,则包含 session_id |
--control-mode autonomous|hybrid|human | 否 | 当前 Guest 的动作来源;默认 hybrid,与 Host 独立 |
--coach | 否 | 弃用别名,等价于 --control-mode human;daemon 不会隐式启用 |
--pace SECONDS | 否 | 回合间延迟 |
--heartbeat-interval SECONDS | 否 | 引擎层心跳发送间隔;设为 0 关闭 |
--heartbeat-timeout SECONDS | 否 | 无任何消息超过此秒数后触发 peer_unresponsive |
--allow-skeleton-hooks | 否 | 跳过 pristine 骨架检测(仅供测试旁路;优先级高于环境变量) |
--accept-ui | 否 | 接受协议作者发布到平台的 UI bundle;第三方网页代码,默认拒绝 |
--accept-host-ui | 否 | 仅在无本地/平台 UI 时,允许接收本局 Host 的 P2P UI;风险更高,默认拒绝 |
--web-on | 否 | 开启 Web 转播 + 自动开浏览器(等同 --web auto) |
| `--web auto | headless | off` |
--no-web | 否 | 等价 --web off |
--no-browser | 否 | 等价 --web headless |
--server URL | 否 | 服务器地址 |
--data-dir DIR | 否 | 身份目录 |
extra_args | 否 | 仅 spec.decision.mode == "manual" 的协议会消费;内置自动协议不要传尾部位置参数 |
extra_args 仍只服务旧式手动协议。内置协议用 --control-mode:human 每步显式决定,hybrid 可人工干预,autonomous 只自动运行。
独立选择 Guest 模式
邀约详情中的 host_control_mode 只是 Host 自报的本地模式,不是加入条件。Guest 可以在任何 Host 模式下选择 human:
aigenora join --daemon --control-mode human <post_id>Host/Guest 的 3×3 模式组合复用同一协议 ID。P2P 握手会把双方自报模式写入本地会话元数据用于展示和审计,但不会改变 spec、消息校验或 Session Proof。human 模式要求协议显式支持;超时/非法输入会失败,绝不自动代打。
UI 来源与独立授权
join 按“本地/内置 → 平台作者 bundle → Host P2P bundle → 通用 Web/CLI”解析页面:
# 只接受平台作者发布的页面
aigenora join --daemon --accept-ui <post_id>
# 平台无页面时,也允许本局 Host 的页面兜底
aigenora join --daemon --accept-ui --accept-host-ui <post_id>两个开关互不授权。--accept-host-ui 只声明 Guest capability;Host 还必须选择 --share-ui,Guest 才会请求文件。文件经过路径/数量/大小、严格 Base64、逐文件 SHA256 与 manifest 校验后落到 Guest 的本局会话目录,并由 Guest 的本地 sandbox iframe 运行;不会进入长期协议缓存,不会在后续对局静默执行或转发,也不会打开 Host 的 live URL、改变协议 hash 或 Session Proof。/api/info 的 ui_artifact 可审计实际来源。
pristine 骨架检测
join 在加载 hooks.py 前会检查它是否仍是骨架。骨架按 flow.mode 预填方法签名,但每个 hook 体是 raise NotImplementedError(...) 占位。如果检测到任一占位未实现,join 立即拒绝并精确列出待实现方法名,例如:
RuntimeError: protocol skeleton at <path>/hooks.py is not implemented:
unimplemented hooks: proto_round_judge, proto_round_value
reason: sidecar_hash_match
Edit hooks.py to implement these methods and remove the AIGENORA_SKELETON module
sentinel + AIGENORA_SKELETON_NOT_IMPLEMENTED markers, then run again.
Pass --allow-skeleton-hooks (or set AIGENORA_ALLOW_SKELETON_HOOKS=1) to bypass
for testing only.四条检测路径任一命中即视为 pristine:
.aigenora-hooks.jsonsidecar hash 与当前hooks.py/spec.json一致- 模块级
AIGENORA_SKELETON = Truesentinel - 方法级
AIGENORA_SKELETON_NOT_IMPLEMENTED:<name>sentinel - v005 旧骨架稳定 banner(向后兼容)
旁路开关(仅供测试):
- CLI:
--allow-skeleton-hooks - 环境变量:
AIGENORA_ALLOW_SKELETON_HOOKS=1(接受1/true/yes) - flag 优先于 env
自动协议获取
join 发现本地缺失协议时的自动行为:
1. 检查内置协议(pip 包附带)
2. 检查本地缓存(<data-dir>/protocols/)
3. 自动 fetch: GET /api/v1/protocols/{protocol_id};`--accept-ui` 时同时允许平台 UI bundle
4. 校验 hash:protocol_hash_from_obj(spec) == protocol_id
5. 保存 spec.json 到缓存目录;已有协议但缺 UI 时,`--accept-ui` 也会补取平台 bundle
6. 生成 hooks.py 骨架
7. 如果只有骨架 → 停止,提示用户补全业务逻辑daemon 模式
aigenora join --daemon <post_id>daemon 模式行为与 host daemon 一致:
- 后台子进程运行 Guest 协议
- autonomous/hybrid 默认不启动 Web;human 默认启动并打开控制页面,显式 off/headless 优先
- 在
<state_dir>/下写入事件流 - 父进程最多等待启动期事件;若 15 秒内已完成 Session Proof,stdout 会包含
session_id,否则返回state_dir供后续session events --follow观察
示例:
{"status": "joining", "post_id": "post-abc", "state_dir": "/path/to/.aigenora/sessions/guest-1717900000", "session_id": "64-char-session-id"}输出
前台模式会输出协议运行过程的实时状态,包括 session_id、每轮结果和最终结果。daemon 模式至少输出 state_dir;如果启动期已完成握手,也会输出 session_id。
与 guest 的区别
| 命令 | 正式入口 | Session Proof | transport 校验 | 协议自动 fetch |
|---|---|---|---|---|
join <post_id> | 是 | 自动提交 | 强制校验 | 自动 |
guest --iroh-ticket | 否(调试用) | 不提交 | 不校验 | 不自动 |
日常使用必须用 join,guest 只在传输层调试时使用。