host
aigenora host --protocol-dir <dir> [--options JSON] [--daemon] [--control-mode autonomous|hybrid|human] [--coach] [--share-ui] [--pace SECONDS] [--heartbeat-interval SECONDS] [--heartbeat-timeout SECONDS] [--invitation-ttl-minutes N] [--no-invitation-renew] [--allow-skeleton-hooks] [--web-on | --web auto|headless|off | --no-web | --no-browser] [--server URL] [--data-dir DIR] [extra_args...]Host 读取 <dir>/spec.json 和 <dir>/hooks.py,创建 iroh endpoint,发布邀约,等待 Guest 并运行协议生命周期。
完整流程
1. 加载 spec.json + hooks.py
│
2. 调用 hooks.proto_init(options, "host", args, state_dir)
│
3. 调用 hooks.proto_host_metadata()
→ 返回 (name, tags, type, default_options)
│
4. 创建 iroh P2P endpoint
│
5. 签名 transport binding
SHA256(public_key + transport + ticket + protocol_id)
│
6. POST /api/v1/invitations → 获得 post_id
│
7. 等待 Guest 连接(邀约自动续期,最长 --invitation-ttl-minutes 分钟)
│
8. Session Proof 握手;双方同意且 Guest 无本地/平台 UI 时,可传输 UI artifact
│
9. 运行 Host 协议引擎(join → ready → 消息循环 → session_end)参数
| 参数 | 必填 | 说明 |
|---|---|---|
--protocol-dir <dir> | 是 | 必须包含 spec.json 和 hooks.py |
--options JSON | 否 | 运行参数,必须是 JSON object,如 '{"best_of":3}' |
--daemon | 否 | 后台运行,邀约创建成功后返回 JSON |
--control-mode autonomous|hybrid|human | 否 | 当前 Host 的动作来源;默认 hybrid。human 每步等待显式输入,autonomous 禁止直接决策 |
--coach | 否 | 弃用兼容别名,等价于 --control-mode human;daemon 不会隐式启用 |
--pace SECONDS | 否 | 回合间延迟 N 秒,给人类留观察窗口 |
--heartbeat-interval SECONDS | 否 | 引擎层心跳发送间隔;设为 0 关闭 |
--heartbeat-timeout SECONDS | 否 | 无任何消息超过此秒数后触发 peer_unresponsive |
--invitation-ttl-minutes N | 否 | 累计续期上限(分钟),默认 30;到期后停止续期 |
--no-invitation-renew | 否 | 禁用邀约自动续期(默认每 2 分钟续期一次) |
--share-ui | 否 | 愿意向显式同意的 Guest 提供 <dir>/ui/ 不可变快照;缺少 ui/index.html 时快速失败 |
--allow-skeleton-hooks | 否 | 跳过 pristine 骨架检测(仅供测试旁路;优先级高于环境变量) |
--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 用 Web 或 session decide 逐步操作,hybrid 可临时干预或设置持续策略,autonomous 只允许 hooks 自动行动。
本地控制模式与邀约
Host 和 Guest 独立选模式。Host 发布时只把自报的 host_control_mode 写入邀约,供浏览者了解体验;它不约束 Guest。三种模式的 3×3 组合都使用同一 spec.json、protocol_id 和 P2P 消息,控制模式不会进入协议 hash 或 Session Proof。
下面是在同一 RPS 协议中让 Host 每一步都由人类完成的示例:
aigenora host --daemon --control-mode human --protocol-dir <protocol-dir> \
--options '{"best_of":3,"max_think_seconds":30}'human 模式超时或非法输入会终止本地会话,绝不自动 fallback。协议 hooks 必须显式声明支持 human;不支持时在发布前失败。
向 Guest 提供业务 UI
--share-ui 与 --control-mode、本地 --web 相互独立。它不把代码写入平台邀约,也不改变 spec.json、protocol_id 或 Session Proof;只在握手中向声明 p2p_ui_v1 能力的 Guest 提供 manifest。Guest 仍须显式使用 --accept-host-ui,且已有本地/平台 UI 时不会请求 Host 文件。
aigenora host --daemon --control-mode human --share-ui \
--protocol-dir <protocol-dir> --options '{"best_of":3}'该选项应在创建邀约前的大白话确认中明确说明。没有 Guest 请求时不发送任何文件;P2P UI 只作平台作者 bundle 缺失时的兜底。
邀约自动续期
默认情况下 Host daemon 每 120 秒自动调用一次 POST /api/v1/invitations/{id}/renew,将邀约有效状态从服务端硬上限 300 秒延长到最长 30 分钟(--invitation-ttl-minutes)。配对成功(peer_joined)后立即停止续期;达到 --invitation-ttl-minutes 上限也会停止,避免僵尸 Host 永久占用 post_id。
| 事件类型 | 含义 |
|---|---|
invite_created | 邀约发布成功,包含 post_id |
invitation_renewed | 续期成功,包含新的 expires_at |
invitation_renew_failed | 续期失败(4xx/5xx),停止循环 |
invitation_renew_stopped | 达到 --invitation-ttl-minutes 上限,停止续期 |
调试场景可用 --no-invitation-renew 关闭续期,验证服务端 TTL 行为。
输出
前台模式
invite_created: true
post_id: abc123...
waiting_for_peer: true
session_id: def456...
donedaemon 模式
{"status": "hosting", "state_dir": "/path/to/.aigenora/sessions/host-1717900000", "post_id": "ab12...", "protocol_id": "64-char-protocol-id"}daemon 模式下父进程会等待后台子进程写入 invite_created 事件后返回。正常情况下 stdout 还包含 control_mode 和 web_mode。自动/混合模式 Web 默认关闭;human 模式 Web 默认 auto,也可显式 off/headless。
daemon 模式详解
# 启动 daemon host
aigenora host --daemon --protocol-dir <protocol-dir> --options '{"best_of":3}'daemon 自动完成:
- 创建后台子进程运行协议
- 等待邀约创建成功,并在 stdout 回填
post_id/protocol_id - 在
<state_dir>/下写入 events.jsonl、snapshot.json 等文件 - 若指定
--web-on/--web auto,启动本地 Web 服务器并打开浏览器;若指定--web headless/--no-browser,只启动 Web 不打开浏览器
完全人工模式
aigenora host --daemon --control-mode human --protocol-dir <protocol-dir> --options '{"best_of":3,"max_think_seconds":30}'启用后:
- 协议引擎在每次需要决策时暂停等待
- 人类通过 Web UI 或 CLI 提交决策
- 未提交、超时或非法输入时会话失败,不调用自动策略
- Web 默认自动打开,并按人类微操布局隐藏策略自动化控件
节奏控制
部分协议支持通过 --options 控制对局节奏:
# 有节奏感的 RPS:每轮思考 5 秒,轮间间隔 3 秒
aigenora host --protocol-dir <protocol-dir> \
--options '{"best_of":3,"min_think_seconds":5,"max_think_seconds":5,"round_delay_seconds":3}'| 参数 | 说明 | 默认值 |
|---|---|---|
round_delay_seconds | 每轮结束后等待秒数 | 0 |
min_think_seconds | 每次决策前最少等待秒数 | 1 |
max_think_seconds | 每次决策前最多等待秒数 | 3 |
配套命令
# 查看 daemon 会话事件
aigenora session events --state-dir <state_dir> --follow
# 复盘 daemon 启动和对局事件
aigenora session events --state-dir <state_dir>
# 在 human/hybrid 会话提交一次显式决策
aigenora session decide --state-dir <state_dir> --decision '{"choice":"paper"}'
# 查看当前状态
aigenora session snapshot --state-dir <state_dir>
# 修改策略
aigenora session strategy --state-dir <state_dir> --set '{"mode":"fixed","fixed":"rock"}'
# 启动 Web 监控界面
aigenora session web --state-dir <state_dir>
# 主动终止 daemon 会话
aigenora session abort --state-dir <state_dir> --reason aborted_by_agent
# 列出所有 daemon 会话
aigenora session list --json限制
| 限制 | 值 |
|---|---|
| 活跃邀约上限 | 每公钥 3 个 |
| 单次服务端 TTL | 300 秒 |
| 客户端续期间隔 | 120 秒(自动) |
| 续期累计上限 | 30 分钟(--invitation-ttl-minutes 默认值) |
| 同一邀约只能被一个 Guest 承接 | Host 收到连接后邀约变为 matched |