Gateway: changed files, search across hosts, a richer complication summary, and question options in pushes
Gateway / check (push) Successful in 10s
Gateway / image (push) Successful in 23s

This commit is contained in:
gib committed 2026-11-02 13:39:49 -05:00
1 parent 45251b1a43
commit b08fd9bdb1
13 files changed
+500 -19

No files matched your search

+35 -6
View File
@@ -78,6 +78,7 @@ FeedItem {
"updatedAt": "2026-11-01T09:41:00.000Z",
"lastMessage": "Parser and tests are written. I want to run the suite.",
"activity": { "kind": "command", "text": "bun test", "startedAt": "..." } | null,
"changes": { "files": 3, "additions": 42, "deletions": 8 } | null,
"request": PendingRequest | null,
"via": { "hostId": "...", "threadId": "...", "title": "Check Panama PATH" } | null
}
@@ -99,6 +100,9 @@ directory), the search, the subagent's title or the tool's name, trimmed to abou
Monitors are left out, since they run for hours. It is null when no step is in progress. The gateway
rereads a running thread at most every 5 seconds, so it can lag that much.
`changes` totals the files the thread's latest run changed. It is null when the run changed no
files, and, like `lastMessage`, until the gateway has read the thread.
```
PendingRequest {
"id": "...",
@@ -120,13 +124,15 @@ thread". For questions (`kind: "user_input"`), `options` is empty and `questions
GET /v1/threads/:hostId/:threadId
200 { "item": FeedItem, "messages": [Message], "canStop": true, "askFirst": false,
"earlierCursor": "w12" | null, "subagents": [ThreadRow] }
"earlierCursor": "w12" | null, "subagents": [ThreadRow], "changedFiles": [ChangedFile] }
ChangedFile { "path": "gateway/Containerfile", "name": "Containerfile", "additions": 31, "deletions": 0 }
ThreadRow { "hostId": "...", "threadId": "...", "title": "Check PATH", "phase": "running" | null,
"settled": false, "updatedAt": "..." }
Message { "id": "...", "role": "assistant", "text": "...", "createdAt": "..." }
```
`messages` holds the last 20, oldest first, each trimmed to 2000 characters. `subagents` lists the
`messages` holds the last 20, oldest first, each trimmed to 2000 characters. `changedFiles` lists
the files the latest run changed, most lines changed first. `subagents` lists the
threads this one started, its own subagents and `delegate_task` children on any host, newest first.
A ThreadRow's `phase` is null for a thread that never ran or was stopped.
@@ -203,16 +209,36 @@ Thread detail fills `request` and `via` the same way as the feed when a subagent
## Summary
The counts behind the watch face complication. It reads no thread pages, so it is cheap to call.
What the watch face complication and Smart Stack widget show. It reads at most two threads, so it
is cheap to call.
```
GET /v1/summary
200 { "needsYou": 1, "working": 3, "hostsOffline": 0,
"next": { "hostId": "...", "threadId": "...", "title": "Receipt OCR", "hostLabel": "Mac mini" } }
"next": { "hostId": "...", "threadId": "...", "title": "Receipt OCR", "hostLabel": "Mac mini",
"request": "bun test --filter ocr" | null },
"current": { "hostId": "...", "threadId": "...", "title": "Phase 3 screens", "activity": Activity | null } }
```
`next` is the thread that has waited longest for you, or null.
`next` is the thread that has waited longest for you, or null. Its `request` is the command it wants
to run or its first question, trimmed to about 80 characters. `current` is the working thread that
changed most recently, or null when nothing is working.
## Search
```
GET /v1/search?q=containerfile
200 { "hits": [SearchHit], "unsearched": ["Laptop"] }
SearchHit { "thread": ThreadRow, "projectTitle": "wristcode", "hostLabel": "Mac mini",
"snippet": "…rebuild from the Containerfile and…" | null }
```
Searches thread titles and messages on every online host at once, up to 20 hits per host, newest
match first. `snippet` is the text around a match in a message, or null when only the title
matched. `unsearched` names the hosts that were offline, failed, or took over 5 seconds. A query
needs at least two characters.
## Browse
@@ -258,7 +284,10 @@ the host's, with its options, such as reasoning effort. A picked model the host
The gateway pushes when a thread starts waiting for you, finishes, or fails. Each push has an
`aps.category` and the custom keys `hostId`, `threadId` (absent on `host` pushes), and, for
approvals and questions, `requestId`. A `test` push carries no custom keys. A subagent's push is titled with the thread that started it,
approvals and questions, `requestId`. An `input` push that asks one single-choice question also
carries `question: { id, options: [{ label, value }], allowCustomAnswer }`, with at most 4 options,
so the notification can offer them as buttons. Answer with `{ "<id>": "<value>" }` on the respond
route. A `test` push carries no custom keys. A subagent's push is titled with the thread that started it,
its body starts with "Subagent <title>:", and its `hostId` and `threadId` are the subagent's.
| Category | When | Actions the watch registers |