Metadata-Version: 2.5
Name: hitl-client
Version: 1.3.0
Summary: Zero-dependency Python SDK for HITL Broker: create/wait/consume human-in-the-loop checkpoints (approvals, OTP/short text, phone/app completion, image/QR display, live browser handoff).
Project-URL: Homepage, https://github.com/aqiu9/HITL-Broker
Project-URL: Repository, https://github.com/aqiu9/HITL-Broker
License: MIT
Keywords: approval,client,hitl,human-in-the-loop,otp,sdk
Requires-Python: >=3.9
Provides-Extra: browser
Requires-Dist: hitl-cdp-browser-provider==1.3.0; extra == 'browser'
Description-Content-Type: text/markdown

# hitl-client

Zero-dependency Python SDK for [HITL Broker](https://github.com/aqiu9/HITL-Broker) —
create, wait for, and consume human-in-the-loop checkpoints from an agent or
automation script: approvals (`decision`), OTP/short text (`text`),
phone/app confirmations (`completion`), image or QR display (`image`/`qr`),
and live browser handoff (`browser`).

This package is the single source of the SDK (the Broker repo, the
`human-checkpoint` skill and deployments all install it rather than copying
files around). Talks to the Broker over plain `urllib` (stdlib only, no
runtime dependencies).

## Install

```bash
pip install hitl-client
```

## Use

```python
import os
from pathlib import Path
from hitl_client import HitlClient

base_url = os.environ["HITL_INTERNAL_URL"]        # e.g. http://192.168.1.10:8081
api_key = Path(os.environ["HITL_API_KEY_FILE"]).read_text(encoding="utf-8").strip()
client = HitlClient(base_url, api_key)

result = client.wait_for_decision(
    "Approve this deploy?",
    description="Applies a schema migration if approved.",
    external_id="run-42:approve-deploy",
)
if result.response["decision"] == "approve":
    apply_deploy()
else:
    abort_deploy()
client.consume(result.task_id)
```

`create_*`/`wait_for_*` cover all six task kinds; see the class docstrings
in `hitl_client/client.py` for the full non-blocking + blocking API, and
the main [HITL-Broker README](https://github.com/aqiu9/HITL-Broker) for
task-kind semantics, the state machine, and realistic `expires_in` values
(especially the OTP two-step timing pattern — trigger the SMS only after a
human has confirmed they're ready, not before).

## Do you also need browser support?

Only if you're using the `browser` task kind (a human takes over a live
browser session). Everything else — `decision`/`text`/`completion`/
`image`/`qr` — works with just `pip install hitl-client`, nothing else.

For `browser` tasks you need a small bridge process running on **whichever
machine is actually hosting the browser session being handed off** — not
necessarily the same machine that installed `hitl-client`. Pick one based on
what that machine has, they're functionally identical:

```bash
# That machine runs Python:
pip install hitl-cdp-browser-provider
# — or, to also install it here as an extra when you already know you'll need it:
pip install hitl-client[browser]

# That machine runs Node instead:
npm install -g hitl-cdp-browser-provider
```

You only need one of the two, not both. See
[`hitl-cdp-browser-provider`](https://github.com/aqiu9/HITL-Broker/tree/main/packages)
for setup and the `--token` security flag.

## Browser handoff

`pip install "hitl-client[browser]"` also installs the matching
`hitl-cdp-browser-provider` and enables `hitl_client.browser.BrowserHandoff`:
attach to the page a bridge streams, prepare it, hand one step to a human on
their phone with a chosen stream profile, and get the result back:

```python
from hitl_client.browser import BrowserHandoff

h = BrowserHandoff(client, bridge_url="http://<bridge-host>:18234", bridge_token=token)
h.goto(login_url)
ok = h.ask_human("拖一下滑块", until_url_not_contains="/login", profile="smooth")
cookies = h.cookies("example.com") if ok else None
```

