Skip to content

0.5.0 — channels

Choose a tag to compare

@Sy-D Sy-D released this 02 Sep 15:39
· 12 commits to main since this release

Channels. 0.4.0 made an approval small enough to fit in a chat message: one screenshot, one sentence, two answers. 0.5.0 gives that message somewhere to go, and lets the answer come back from there.

import { raiseHand } from "handraise"
import { telegram } from "handraise-telegram"

await raiseHand(page, {
  mode: "approval",
  reason: "The agent may not move money without a human",
  action: "Submit EUR 12,430 vendor payment to Acme GmbH",
  channels: [telegram({ botToken, chatId })],
})

Added: channels?: HandoffChannel[] on raiseHand; ChannelHandoff, the view an adapter gets (a union on mode; approvals carry the screenshot bytes and answer("approve" | "deny"), which settles the handoff in-process and returns false if the phone was faster); settled, a promise that resolves with the outcome however the handoff ended, so an adapter knows when to stop; HandoffEvent.answeredVia. Everything is additive; no existing call, type or outcome changes.

Verified against the real Solari API: an approval answered by a channel end to end, plus 204 offline tests including first-answer-wins against the real relay process, a late answer after timeout and after a dead session, a channel that throws, one that never settles, and a compile-negative fixture. Two independent reviews (Opus, GPT-5.6 Sol), four fix rounds. ADR: docs/adr/0007-channels.md.

The first adapter, handraise-telegram, is written against this release and lands as its own package once its live test against the Bot API has run.