Skip to content

OriginRouter CLI v0.5.1

Latest

Choose a tag to compare

@chengaoyan chengaoyan released this 15 Oct 10:36

OriginRouter CLI 0.5.1

Release date: 2026-10-15. Supersedes 0.5.0. Twelve commits.

Summary

This release corrects a bind-address defect that prevented device pairing over
the local network, introduces a user-configurable timeout for permission
requests, and resolves several relay-routing and session-state defects
affecting remote agent control.


Action required before upgrading

The Local API bind address default changes to 0.0.0.0

0.5.0 0.5.1
bindAddress 127.0.0.1 0.0.0.0
allowLan off on

Three Local API endpoints are unauthenticated by bearer token and exist for
devices that cannot read the 0600 credential file on the host:
/local/e2ee/session, /local/e2ee/messages, /local/pair/redeem. Under the
0.5.0 default these endpoints were bound to loopback and therefore unreachable
from any client other than the host itself.

The authentication posture is unchanged. The bearer token remains the
authorisation boundary for all other routes on the socket, which return 401;
the three endpoints listed above authenticate by device identity.

Installations that have configured neither setting adopt the new default
automatically and require no action. To retain loopback binding:

originrouter local config set --bind 127.0.0.1 --allow-lan off

An address set this way is recorded as an operator choice rather than as a
record of the last resolved default, and is therefore not overwritten by a
subsequent upgrade. --bind and ORIGINROUTER_LOCAL_BIND passed to a single
daemon invocation apply to that invocation only and are not persisted.


Changes

Pairing

  • The address advertised by local api pair now derives from the configured
    bind address.
    In 0.5.0 the daemon bound loopback while the address
    suggestion scanned local interfaces and returned a LAN address, because a
    bind it could not read was treated as unknown. The pairing payload, the QR
    code and the Address line all advertised that LAN address, so clients
    following it reached no listener; pairing succeeded only from the host. The
    CLI additionally printed guidance to correct the address in the App, which
    misattributed the failure.

    The address suggestion now follows the bind: a concrete bind is preserved, a
    loopback bind yields loopback, and interface scanning applies only to the
    wildcard bind, which is the one bind whose LAN address is resolvable.

  • local api pair issues a single credential. The 8-character code and the
    signed pairing line conveyed the same ticket. The code path performed no
    signing and therefore returned a routing hint rather than a credential, while
    the client maintained two input fields, two error vocabularies and a mode
    switch for the associated privilege. The code, --line and --json have
    been removed. The signed line is printed as a terminal QR code and as text,
    wrapped as originrouter://pair?v=2&l=<payload>, which is the form the
    shared scanner accepts.

    This change is paired with a client update. The pairing import is the
    only remaining input on both sides; the code field has been removed from the
    App. Client and CLI must be updated together.

  • Output has been reduced to statements of fact. Field labels now match the
    output of local api status (bindAddress, tokenSet) because they are the
    keys used in the files they reference. Explanatory text covering credential
    storage, single-use semantics and address selection has been removed.

  • local api status no longer reports baseUrl as
    http://0.0.0.0:<port>.
    The value was formatted directly from the bind
    address, which is not a resolvable URL under a wildcard bind.

Agents and permissions

  • Permission requests are identified consistently across repeated
    deliveries.
    Claude Code 2.1.283 does not include tool_use_id on
    PermissionRequest. The hook server read that field, found it absent, and
    generated a new identifier per delivery, so each repeated delivery was
    registered as an independent permission — producing multiple approval cards,
    multiple expiries and multiple denials for a single tool call. Requests are
    now keyed by (session_id, prompt_id, tool_name, canonical(tool_input)), and
    a repeated delivery joins the open request and receives the same decision. A
    payload missing any component falls back to the previous behaviour.

  • Remote permission requests are no longer terminated after five seconds. The
    hook forwarder's HTTP client specified no agent and therefore inherited
    Node's global agent, which applies a five-second socket timeout. This
    overrode permissionRequestTimeoutMs: 0 — the value denoting an indefinite
    wait — with a deadline that was neither configurable nor intentional. The
    forwarder now uses a dedicated agent without a socket timeout.

  • agent.interactionTimeoutMs makes the permission-request timeout
    configurable.
    The previous bound was whichever of five hard-coded deadlines
    expired first, the outermost being 315 seconds. A device that was
    unreachable or inactive for that period produced an automatic denial, and the
    agent was informed that the request had been declined by the user.

    The setting accepts a millisecond count or a duration (5m, 2h, 1d),
    defaults to 0 (wait indefinitely), and is read per request, so a change
    takes effect on the next approval without restarting the daemon. All five
    layers that previously imposed a deadline now derive from this value, each
    outer layer receiving a fixed 15-second margin. Claude Code requires a finite
    hook deadline; that layer retains an 86400-second ceiling.

Sessions and relay

  • Relay types have a single dispatch owner. agent.workspace.browse had two
    responders. The one ordered ahead in the dispatch chain opened with a check
    comparing the relay payload's target device against the local device
    identifier — a field the App does not populate. An absent field yields an
    empty string, which never matches, so every such frame was claimed and
    discarded before any log entry, on both ends. This presented as an
    unresponsive device after a 30-second timeout and was not distinguishable
    from a slow device. collaboration.remote.error carried the same check
    inverted, causing App-originated error frames to bypass error handling.

  • A trailing thinking block no longer reopens a completed turn. Turns
    commonly arrive as agent.task.started → task_result_ready → agent.thinking → agent.text. Reading the final event as a turn start returned a completed
    turn to the running state, presenting a stop control for an idle agent.
    agent.thinking may now raise an active turn but cannot open one.

  • Device trust is evaluated at signing time. Trust was evaluated against
    the present state, so revoking a device or rotating its key invalidated
    signatures that device had already produced, including the admission policy
    other devices vouch for. Relay operation on the CLI side would stop while the
    App continued. Signatures are now accepted when the signer was trusted at the
    time of signing.

  • Trust events announce themselves to the sender. The sender retains the
    session on which an e2ee.sessions.reset was received; its next envelope was
    interpreted as an initial message and rejected, leaving the session blocked
    until the corresponding state expired. The sender is now instructed to discard
    its own session state.


Upgrade procedure

npm install -g @originrouter/cli@0.5.1
originrouter service restart
originrouter local api status

Verification points after upgrade:

  • bindAddress reports 0.0.0.0 and allowLan reports on, unless both were
    set explicitly.
  • local api pair prints a QR code and a text payload. --line and --json
    are no longer accepted and no 8-character code is issued.
  • The Address line reports an address reachable from the pairing device.


OriginRouter CLI 0.5.1

发布日期:2026-10-15。取代 0.5.0,共 12 个提交。

概述

本次发布修正了导致局域网设备配对无法完成的绑定地址缺陷,新增了权限请求超时的
用户配置项,并解决了若干影响远程智能体控制的中继路由与会话状态缺陷。


升级前须知

Local API 绑定地址默认值变更为 0.0.0.0

0.5.0 0.5.1
bindAddress 127.0.0.1 0.0.0.0
allowLan off on

Local API 中有三个端点不使用 bearer token 鉴权,其存在前提是客户端无法读取本机
0600 权限的凭据文件:/local/e2ee/session、/local/e2ee/messages、
/local/pair/redeem。在 0.5.0 的默认值下,这三个端点绑定于 loopback,除本机
之外的任何客户端均无法访问。

鉴权边界未发生变更。bearer token 仍是该 socket 上其余全部路由的鉴权边界,未授权
请求返回 401;上述三个端点通过设备身份完成认证。

未显式配置这两项的安装将自动采用新默认值,无需任何操作。如需保留 loopback 绑定:

originrouter local config set --bind 127.0.0.1 --allow-lan off

以此方式设置的地址会被记录为运维人员的选择,而非上一次默认值的解析结果记录,
因此后续升级不会将其覆盖。传入单次 daemon 调用的 --bind 与
ORIGINROUTER_LOCAL_BIND 仅对本次调用生效,不会持久化。


变更内容

配对

  • local api pair 公布的地址现取自实际配置的绑定地址。 0.5.0 中 daemon
    绑定于 loopback,而地址建议逻辑会扫描本机网卡并返回局域网地址——因为读不到的
    绑定被视为未知。配对载荷、二维码与 Address 行公布的均为该局域网地址,依此
    连接的客户端不会命中监听套接字;配对仅在本机可用。CLI 另会输出提示要求在
    App 中修正地址,导致故障归因错误。

    地址建议现遵循绑定地址:具体绑定地址予以保留,loopback 绑定返回 loopback,
    网卡扫描仅适用于通配绑定——这是唯一可解析出局域网地址的绑定形式。

  • local api pair 只签发一种凭据。 此前的 8 位字符码与签名配对行表示同一张
    票据。字符码路径不执行签名,因此签发的是路由提示而非凭据,而客户端需为此
    维护两个输入框、两套错误文案与一个权限模式开关。字符码、--line 与 --json
    已移除。签名行以终端二维码与文本两种形式打印,包装为
    originrouter://pair?v=2&l=<payload>,该形式为共享扫描器所接受。

    该项变更需与客户端同步发布。 配对导入是两端唯一保留的输入方式,App 侧的
    字符码输入框已移除,客户端与 CLI 需同步升级。

  • 输出内容精简为事实陈述。 字段标签现与 local api status 的输出一致
    (bindAddress、tokenSet),因其即为其所引用文件中的键名。有关凭据存储、
    单次使用语义与地址选择的说明性文字均已移除。

  • local api status 不再将 baseUrl 报告为 http://0.0.0.0:<port>。
    该值此前直接由绑定地址格式化而来,在通配绑定下并非可解析的 URL。

智能体与权限

  • 权限请求在重复投递间保持一致标识。 Claude Code 2.1.283 的
    PermissionRequest 不包含 tool_use_id。hook server 读取该字段未获结果,
    于每次投递时生成新标识,导致同一工具调用的每次重复投递都被登记为一项独立权限,
    产生多个审批卡片、多个过期时间与多份拒绝结果。现改为按
    (session_id, prompt_id, tool_name, canonical(tool_input)) 标识请求,重复
    投递将并入未决请求并获得同一处理结果。任一分量缺失时回退至原有行为。

  • 远程权限请求不再于五秒后被终止。 hook forwarder 的 HTTP 客户端未指定
    agent,因而继承 Node 全局 agent 的五秒套接字超时。该超时覆盖了
    permissionRequestTimeoutMs: 0(表示无限等待),且该截止时间既不可配置,也
    非有意设定。现 forwarder 使用不带套接字超时的专用 agent。

  • agent.interactionTimeoutMs 使权限请求超时可配置。 此前的上限为五个
    硬编码截止时间中最先到期者,最外层为 315 秒。设备在此期间不可达或未响应时
    会产生自动拒绝,并向智能体报告该请求已被用户拒绝。

    该配置项接受毫秒数或时长(5m、2h、1d),默认值为 0(无限等待),
    且按请求读取,因此变更在下一次审批即刻生效,无需重启 daemon。原先施加截止
    时间的五个层级现均由该配置项推导,每个外层保留固定 15 秒余量。Claude Code
    要求 hook 截止时间必须有限,该层级保留 86400 秒上限。

会话与中继

  • 中继类型具有唯一的分发归属方。 agent.workspace.browse 存在两个响应方。
    排在分发链首位的响应方以「relay 载荷中的目标设备与本机设备标识比对」作为入口
    判断,而 App 并不填充该字段。字段缺失得到空字符串,永远无法匹配,因此此类帧
    在任何日志输出之前即被认领并丢弃,且两端均不可见。该现象表现为设备在 30 秒
    超时后无响应,与设备响应缓慢的情形无法区分。collaboration.remote.error 上
    存在方向相反的同类判断,导致 App 发起的错误帧绕过错误处理。

  • 尾部 thinking 事件不再重新开启已结束的回合。 回合通常以
    agent.task.started → task_result_ready → agent.thinking → agent.text 的
    顺序到达。将末位事件读作回合开始会将已完成的回合重新置为运行状态,导致空闲
    智能体仍显示停止控件。现 agent.thinking 可提升进行中的回合,但不可开启新
    回合。

  • 设备信任在签名时刻进行判定。 信任此前依据当前状态评估,因此吊销设备或
    轮换其密钥会连带作废该设备已产生的签名,其中包含其他设备共同背书的准入策略,
    结果为 CLI 侧停止中继而 App 继续运行。现签名在签名方当时受信任的前提下予以
    接受。

  • 信任事件向发送方发出通知。 发送方仍持有接收到 e2ee.sessions.reset 的
    会话,其后续信封此前会被判定为初始消息并遭拒绝,导致会话阻塞,直至对应状态
    过期。现发送方会收到丢弃自身会话状态的明确指示。


升级步骤

npm install -g @originrouter/cli@0.5.1
originrouter service restart
originrouter local api status

升级后的核对项:

  • bindAddress 显示 0.0.0.0、allowLan 显示 on;除非已显式配置为其他值。
  • local api pair 输出二维码与文本载荷;--line 与 --json 不再被接受,也不再
    签发 8 位字符码。
  • Address 行给出的地址可由发起配对的设备访问。