Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/reference/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ enable_sentry: false # this machine
details: true # this machine
btw: claude/claude-opus-5:high # this machine
every_epic: true # this machine
notifications: # this machine; Settings › Notifications in the web interface
kinds: {done: true, failed: true, stopped: true, asked: true, listening: true}
system: true
spelling: 2 # how envs are spelled; written with every change
fallbacks: # this machine; the Fallback page
- spec: claude@work/claude-opus-5
Expand Down Expand Up @@ -76,6 +79,7 @@ backup: # this machine
| `details` | `bool` (only `true` is on) | `false` | `/settings` › General › **Details** | the TUI | immediately: turns show every tool call and all thinking instead of responses only |
| `btw` | `str`: `cli[@account]/model:effort` | `""`: the running flow's first agent | `/settings` › General › **/btw agent** | the TUI | the next time `/btw` is entered |
| `every_epic` | `bool` (only `true` is on) | `false`: this directory's | `ctrl+t` on [`/epics`](/reference/tui#the-runs-that-have-already-happened) | the TUI | the next time `/epics` is opened |
| `notifications` | `{kinds: {done, failed, stopped, asked, listening}: bool, system: bool}` | every kind told, and shown by the system too; only `false` turns one off | the web interface's Settings › Notifications, [`POST /api/notifications/settings`](/reference/web#api-notifications) | `hmz web` | immediately: the next notice of a kind is told or not |
| <span id="spelling"></span>`spelling` | `int` | absent: written before `-e` wrote `@` only before a provider | every write of the file, as `2` | every process, as it reads the file | absent, `envs` are read as their old spelling meant and rewritten once; `2`, as written |

What error reports contain and exclude is listed on `/settings` › General › **What is sent**.
Expand Down
21 changes: 21 additions & 0 deletions docs/reference/web.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,27 @@ Every `error` but the last is the runtime's own sentence, e.g.

An account is listed by the names of the variables it sets (`sets`), never by a value.

### Notifications {#api-notifications}

What every daemon's notices come to, served by the interface a page is open on alone: its own
machine's as they are heard, and each SSH daemon's while it is reached, off the
`/api/notices/stream` that daemon's own interface serves -- from what it says once first
reached, and from where it was last heard after that. A notification is the notice, with its own
`id` (counted from `1` each time `hmz web` starts), `daemon` (`local` or the daemon's name) and
`read`. The last **200** are kept, in memory.

| Method and path | Takes | Answers |
| --- | --- | --- |
| `GET /api/notifications` | | `items` (newest first), `unread` (how many are not read) |
| `GET /api/notifications/stream` | `Last-Event-ID` header, or `?last=` | `text/event-stream`: a `notification` event, `id` its `id`, for each kept after the one named -- every one kept where it names one later than any here -- then each as it comes; with none, from now. `: quiet` after **15 s** of nothing |
| `POST /api/notifications/read` | `ids` (a list), or `all: true` | As `GET` |
| `POST /api/notifications/clear` | | As `GET`, with nothing kept |
| `GET /api/notifications/settings` | | `kinds` (`{done, failed, stopped, asked, listening}`: whether each is told) and `system` (whether the page asks the system to show them too), as [`notifications`](/reference/settings#machine-settings) holds them |
| `POST /api/notifications/settings` | any of `kinds` (any of those five, each a bool), `system` (bool) | As `GET`; `400`, and nothing written, for anything else |

A notice of a kind turned off is never kept nor sent. Which kinds are told is read afresh for
every notice, so a change takes effect at once.

## The stream {#stream}

`GET /api/held/stream` answers `text/event-stream`, starting with `retry: 2000`. Each event is
Expand Down
4 changes: 4 additions & 0 deletions src/hmz/web/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def listening(*, port: int = 0, apart: bool = True) -> Generator[Site]:

from hmz.coganchor import releases

from .notifications import Notifications
from .places import Places
from .runs import Runs
from .site import Site
Expand All @@ -73,6 +74,9 @@ def listening(*, port: int = 0, apart: bool = True) -> Generator[Site]:
# And which release of humanize is the newest, where what is kept has got old.
releases.refresh()
held_open.callback(site.server_close)
# Every daemon's notices, as this machine's interface tells them.
site.notifications = Notifications(site)
held_open.callback(site.notifications.close)
# Set first as the block ends, which is what ends every stream being sent.
held_open.callback(site.going.set)
yield site
Expand Down
Loading
Loading