agent-lookout 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/PRIVACY.md +151 -26
- package/README.md +190 -160
- package/SECURITY.md +24 -9
- package/dist/assets/{HistoryPanel-Cwmn7YtJ.js → HistoryPanel-CQ7zovsM.js} +1 -1
- package/dist/assets/{SessionPanel-BJ5t_CPi.js → SessionPanel-DS29Z04P.js} +1 -1
- package/dist/assets/index-BWFkRW4g.js +3 -0
- package/dist/assets/motion-DlYOyClL.js +9 -0
- package/dist/cli/agent-lookout.js +2 -2
- package/dist/cli/{mcpServer-HJSH3WIS.js → mcpServer-BMSF2TXC.js} +2 -2
- package/dist/cli/{startCommand-PR5JPWCT.js → startCommand-ANC7NVAO.js} +2496 -474
- package/dist/index.html +2 -2
- package/docs/API.md +102 -46
- package/docs/GUIDE.md +250 -147
- package/docs/INSTALL.md +177 -0
- package/package.json +6 -1
- package/dist/assets/index-QSfCI-L_.js +0 -3
- package/dist/assets/motion-BAhdRuCw.js +0 -9
package/dist/index.html
CHANGED
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
document.documentElement.setAttribute("data-theme", theme);
|
|
29
29
|
})();
|
|
30
30
|
</script>
|
|
31
|
-
<script type="module" crossorigin src="/assets/index-
|
|
31
|
+
<script type="module" crossorigin src="/assets/index-BWFkRW4g.js"></script>
|
|
32
32
|
<link rel="modulepreload" crossorigin href="/assets/react-C2DiJaR6.js">
|
|
33
|
-
<link rel="modulepreload" crossorigin href="/assets/motion-
|
|
33
|
+
<link rel="modulepreload" crossorigin href="/assets/motion-DlYOyClL.js">
|
|
34
34
|
<link rel="modulepreload" crossorigin href="/assets/radix-BH0JH8UU.js">
|
|
35
35
|
<link rel="stylesheet" crossorigin href="/assets/index-B_1Its0R.css">
|
|
36
36
|
</head>
|
package/docs/API.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# API
|
|
2
2
|
|
|
3
|
-
Agent Lookout's server answers a small HTTP API under `/api/`. The dashboard reads it, and so do `agent-lookout status` and `agent-lookout mcp`. It is meant for this computer only: it listens on a loopback address, and it answers only requests made to a loopback name. Every route returns JSON, and every route but
|
|
3
|
+
Agent Lookout's server answers a small HTTP API under `/api/`. The dashboard reads it, and so do `agent-lookout status` and `agent-lookout mcp`. It is meant for this computer only: it listens on a loopback address, and it answers only requests made to a loopback name. Every route returns JSON, and every route but eight only reads.
|
|
4
4
|
|
|
5
5
|
The answers hold your session names and folder paths. Check one before you share it.
|
|
6
6
|
|
|
@@ -36,7 +36,7 @@ Every answer has `Content-Type: application/json; charset=utf-8`, `Cache-Control
|
|
|
36
36
|
| 400 | The address, `since` or `windowMs` could not be read |
|
|
37
37
|
| 403 | The `Host`, the `Origin` or `Sec-Fetch-Site` above |
|
|
38
38
|
| 404 | There is no route at that path |
|
|
39
|
-
| 405 | Any method but `GET`, with `Allow: GET`. The
|
|
39
|
+
| 405 | Any method but `GET`, with `Allow: GET`. The eight routes that act take only `POST`, with `Allow: POST` |
|
|
40
40
|
| 500 | Something went wrong that the server did not expect |
|
|
41
41
|
|
|
42
42
|
## Routes
|
|
@@ -49,16 +49,19 @@ Every answer has `Content-Type: application/json; charset=utf-8`, `Cache-Control
|
|
|
49
49
|
| `GET /api/history?windowMs=<ms>` | `{ points, startedAt, since, kept, restarts }`, one point for each poll, oldest first |
|
|
50
50
|
| `GET /api/email` | `{ on, to, events, afterMs, asking, problem, last, limitedUntil }` |
|
|
51
51
|
| `GET /api/webhook` | `{ on, host, events, afterMs, asking, problem, last, limitedUntil }` |
|
|
52
|
+
| `GET /api/ntfy` | `{ on, host, tokenSet, events, afterMs, asking, problem, last, limitedUntil }` |
|
|
53
|
+
| `GET /api/pushover` | `{ on, events, afterMs, asking, problem, last, limitedUntil }` |
|
|
52
54
|
| `GET /api/pull-requests` | `{ on, problem, gh, last }`: whether each branch's pull request is shown |
|
|
53
55
|
| `GET /api/waits` | `{ at, today, sevenDays, since, where }`: how long sessions waited on you |
|
|
54
56
|
| `GET /api/settings` | `{ timeRules, file, problem, permissionRules, permissionRulesProblem, ruleAnswers, ruleAnswersSince }`: the time rules, the permission rules, the file they are kept in, and what the rules answered |
|
|
55
|
-
| `POST /api/jump` | `{ ok: true, kind, place }`, with `app` for a terminal tab. One of
|
|
57
|
+
| `POST /api/jump` | `{ ok: true, kind, place }`, with `app` for a terminal tab. One of eight routes that act |
|
|
56
58
|
| `POST /api/history/clear` | `{ ok: true, clearedAt }`. A route that acts |
|
|
57
59
|
| `POST /api/sessions/stop` | `{ ok: true }` once the session's process has ended. A route that acts |
|
|
58
60
|
| `POST /api/sessions/clean-up` | `{ results }`, what became of each session left running. A route that acts |
|
|
59
61
|
| `POST /api/permission/answer` | `{ ok: true, decision }` once a permission prompt was answered. A route that acts |
|
|
60
62
|
| `POST /api/settings/time-rules` | `{ ok: true, timeRules }` once the time rules are saved. A route that acts |
|
|
61
63
|
| `POST /api/settings/permission-rules` | `{ ok: true, permissionRules }` once one change to the permission rules is saved. A route that acts |
|
|
64
|
+
| `POST /api/phone/test` | `{ ok: true, channel, sentAt }` once a test push went through ntfy or Pushover. A route that acts |
|
|
62
65
|
|
|
63
66
|
Times are milliseconds since 1970, and lengths of time are milliseconds.
|
|
64
67
|
|
|
@@ -122,46 +125,46 @@ The snapshot the collector made at its last poll, two seconds apart at most:
|
|
|
122
125
|
|
|
123
126
|
Sessions come in this order: those that need you first, longest wait first, then working, idle, finished, failed and unknown, each with the most recent change first.
|
|
124
127
|
|
|
125
|
-
| Session field | Holds
|
|
126
|
-
| ----------------- |
|
|
127
|
-
| `id` | Stable across polls: the source, a colon, and the agent's own id for the session. A session on another machine has that machine's own id for it after its source: `remote:devbox:claude-code:…`
|
|
128
|
-
| `source` | `claude-code`, `codex` or `status-files`, or for a session on another machine `remote:` and the machine's name, such as `remote:devbox`
|
|
129
|
-
| `agent` | The agent's own name, for a session from a status file, and for a session on another machine, such as `Claude Code`. Left out for the others, whose agent is the source's `label`
|
|
130
|
-
| `machine` | The other machine it runs on, as `AGENT_LOOKOUT_REMOTES` names it: letters, digits and dashes, such as `devbox`. Left out for a session on this computer. Such a session has no `pid`, `links.open`, `jump`, `stop`, `ask` or `git.pullRequest`, since those act on this computer or are read from its folders
|
|
131
|
-
| `surface` | `terminal`, `vscode`, `desktop`, `cloud`, `browser` or `unknown`
|
|
132
|
-
| `name` | What the dashboard calls it
|
|
133
|
-
| `cwd` | The folder it works in, or `null`
|
|
134
|
-
| `project` | The last part of `cwd`, or `null`
|
|
135
|
-
| `git` | `{ branch }`, or `{ commit }` with seven characters when no branch is checked out, each with `repository`. Left out when the folder is in no repository that could be read
|
|
136
|
-
| `git.repository` | `{ id, name }`: the repository the folder belongs to, the same for its main folder and every worktree of it. `name` is the main folder's name. `id` is 16 hexadecimal characters, a hash of the path of the repository's own git folder, which its worktrees share, for telling repositories apart. Left out for a repository with no name, at the root, or a worktree whose `commondir` cannot be read
|
|
137
|
-
| `git.pullRequest` | With `AGENT_LOOKOUT_PULL_REQUESTS=on` only, for a branch whose pull request on github.com your own `gh` found: `{ number, title, state, checks, url }`. Described below. Left out with the setting off, for a commit, for the default branch, for a branch named with digits alone, such as `51`, for a repository with no remote on github.com, for a branch with no pull request, and for a session on another machine
|
|
138
|
-
| `status` | `needs-you`, `working`, `idle`, `finished`, `failed` or `unknown`
|
|
139
|
-
| `waitingReason` | For `needs-you` only: `permission`, `question` or `other`
|
|
140
|
-
| `waitingDetail` | The agent's own words for the wait, when it gives any
|
|
141
|
-
| `waitingText` | For `needs-you` Claude Code sessions only, and sessions on another machine whose Agent Lookout sent it: what the session is asking, in a line or two, read from the last message of its transcript, such as `Run: npm test`, `Edit: src/app.ts` or the question it put. Plain text of at most 200 characters. Left out when the transcript does not say, or with `AGENT_LOOKOUT_WAITING_TEXT=off`. No event in `/api/events`, and no history point, holds it. An email
|
|
142
|
-
| `startedAt` | When it started, or `null`
|
|
143
|
-
| `statusSince` | When its status last changed, or `null`. It does not move while a wait goes on
|
|
144
|
-
| `lastWriteAt` | When its agent last wrote the file it is read from, for Codex and status files
|
|
145
|
-
| `pid`, `alive` | Its process and whether that still runs, when known
|
|
146
|
-
| `links.open` | A `vscode://` address that opens it, for a session in VS Code
|
|
147
|
-
| `jump` | `{ kind: "tmux", place }` or `{ kind: "terminal", app, place }` when `POST /api/jump` can take you to it
|
|
148
|
-
| `stop` | `{ how: "signal" }` or `{ how: "background" }` when `POST /api/sessions/stop` can stop it: a Claude Code session in a terminal or VS Code, or a background job. It holds nothing else
|
|
149
|
-
| `ask` | For `needs-you` Claude Code sessions with the Agent Lookout plugin only, while Agent Lookout holds the session's permission request: `{ requestId, tool, command, description, inputs, allow, denyOnly, subagent, until }`. `command` is the whole command for `Bash`, every line, and `inputs` is `[{ name, value }]`, each input as text, for any other tool or the rest of a command's. `allow` says whether `POST /api/permission/answer` takes `allow`, which it does only when the whole of what is allowed is here: never for `Edit`, `Write`, `MultiEdit` or `NotebookEdit`, and not for `ExitPlanMode` or `AskUserQuestion`, past 4,000 characters or 40 lines, with a character that cannot be shown as it is, with more than two blank lines in a row, or for a command holding right-to-left letters, with `denyOnly` saying why: `edit`, `too-long`, `hidden-characters`, `not-yes-or-no`, `right-to-left` or `blank-lines`. `until` is when the request is let go. Kept in memory only while it is held: no event, history point, email, webhook post or answer of `agent-lookout mcp` holds it |
|
|
150
|
-
| `answered` | `true` for a `needs-you` Claude Code session whose permission request Agent Lookout has answered, from Allow, Deny or a [permission rule](GUIDE.md#permission-rules), or is answering by a rule, while its registry file still says it waits in that wait, as it can for a second or two after the answer, and for 10 seconds after the answer at most. A session on another machine has it when Agent Lookout there sent it, for an answer given there. The wait is over: the dashboard's notifications and Agent Lookout's own, email
|
|
151
|
-
| `stale` | `true` once it has been idle for 24 hours, or for as long as the idle rule in `timeRules` says while it is on. For a session on another machine too, by this computer's rule, whatever that machine said
|
|
152
|
-
|
|
153
|
-
| Source field | Holds
|
|
154
|
-
| -------------- |
|
|
155
|
-
| `id`, `label` | `claude-code` and `Claude Code`, `codex` and `Codex`, or `status-files` and `Status files`, or for another machine `remote:devbox` and `devbox`
|
|
156
|
-
| `state` | `ok`, `searching`, `unavailable`, `not-set-up` or `error`
|
|
157
|
-
| `detail` | One plain sentence: how it is being read, or what went wrong
|
|
158
|
-
| `advice` | One plain sentence saying what you can do about a problem, when the collector knows
|
|
159
|
-
| `watching` | `[{ label, value }]`: what it reads and runs, and how often
|
|
160
|
-
| `basis` | Which way the sessions were read, for a source that has more than one
|
|
161
|
-
| `capabilities` | What its agent can report, and whether its sessions can be stopped and answered: for each of nine things, `{ level: "yes" }`, or `{ level: "no" }` or `"partly"` with a `reason`
|
|
162
|
-
| `checkedAt` | When it was last read
|
|
163
|
-
| `machine` | For another machine: its name, which its sessions carry as their `machine`
|
|
164
|
-
| `agents` | For another machine: `[{ label, capabilities }]`, what each agent found there can report, as last read from it, with `jump`, `stop` and `answer` always `no`
|
|
128
|
+
| Session field | Holds |
|
|
129
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
130
|
+
| `id` | Stable across polls: the source, a colon, and the agent's own id for the session. A session on another machine has that machine's own id for it after its source: `remote:devbox:claude-code:…` |
|
|
131
|
+
| `source` | `claude-code`, `codex`, `antigravity-cli` or `status-files`, or for a session on another machine `remote:` and the machine's name, such as `remote:devbox` |
|
|
132
|
+
| `agent` | The agent's own name, for a session from a status file, and for a session on another machine, such as `Claude Code`. Left out for the others, whose agent is the source's `label` |
|
|
133
|
+
| `machine` | The other machine it runs on, as `AGENT_LOOKOUT_REMOTES` names it: letters, digits and dashes, such as `devbox`. Left out for a session on this computer. Such a session has no `pid`, `links.open`, `jump`, `stop`, `ask` or `git.pullRequest`, since those act on this computer or are read from its folders |
|
|
134
|
+
| `surface` | `terminal`, `vscode`, `desktop`, `cloud`, `browser` or `unknown` |
|
|
135
|
+
| `name` | What the dashboard calls it |
|
|
136
|
+
| `cwd` | The folder it works in, or `null` |
|
|
137
|
+
| `project` | The last part of `cwd`, or `null` |
|
|
138
|
+
| `git` | `{ branch }`, or `{ commit }` with seven characters when no branch is checked out, each with `repository`. Left out when the folder is in no repository that could be read |
|
|
139
|
+
| `git.repository` | `{ id, name }`: the repository the folder belongs to, the same for its main folder and every worktree of it. `name` is the main folder's name. `id` is 16 hexadecimal characters, a hash of the path of the repository's own git folder, which its worktrees share, for telling repositories apart. Left out for a repository with no name, at the root, or a worktree whose `commondir` cannot be read |
|
|
140
|
+
| `git.pullRequest` | With `AGENT_LOOKOUT_PULL_REQUESTS=on` only, for a branch whose pull request on github.com your own `gh` found: `{ number, title, state, checks, url }`. Described below. Left out with the setting off, for a commit, for the default branch, for a branch named with digits alone, such as `51`, for a repository with no remote on github.com, for a branch with no pull request, and for a session on another machine |
|
|
141
|
+
| `status` | `needs-you`, `working`, `idle`, `finished`, `failed` or `unknown` |
|
|
142
|
+
| `waitingReason` | For `needs-you` only: `permission`, `question` or `other` |
|
|
143
|
+
| `waitingDetail` | The agent's own words for the wait, when it gives any |
|
|
144
|
+
| `waitingText` | For `needs-you` Claude Code sessions only, and sessions on another machine whose Agent Lookout sent it: what the session is asking, in a line or two, read from the last message of its transcript, such as `Run: npm test`, `Edit: src/app.ts` or the question it put. Plain text of at most 200 characters. Left out when the transcript does not say, or with `AGENT_LOOKOUT_WAITING_TEXT=off`. No event in `/api/events`, and no history point, holds it. An email, a webhook post or a push holds it only with `AGENT_LOOKOUT_EMAIL_ASKING=on`, `AGENT_LOOKOUT_WEBHOOK_ASKING=on`, `AGENT_LOOKOUT_NTFY_ASKING=on` or `AGENT_LOOKOUT_PUSHOVER_ASKING=on` |
|
|
145
|
+
| `startedAt` | When it started, or `null` |
|
|
146
|
+
| `statusSince` | When its status last changed, or `null`. It does not move while a wait goes on |
|
|
147
|
+
| `lastWriteAt` | When its agent last wrote the file it is read from, for Codex, the Antigravity CLI and status files |
|
|
148
|
+
| `pid`, `alive` | Its process and whether that still runs, when known |
|
|
149
|
+
| `links.open` | A `vscode://` address that opens it, for a session in VS Code |
|
|
150
|
+
| `jump` | `{ kind: "tmux", place }` or `{ kind: "terminal", app, place }` when `POST /api/jump` can take you to it |
|
|
151
|
+
| `stop` | `{ how: "signal" }` or `{ how: "background" }` when `POST /api/sessions/stop` can stop it: a Claude Code session in a terminal or VS Code, or a background job. It holds nothing else |
|
|
152
|
+
| `ask` | For `needs-you` Claude Code sessions with the Agent Lookout plugin only, while Agent Lookout holds the session's permission request: `{ requestId, tool, command, description, inputs, allow, denyOnly, subagent, until }`. `command` is the whole command for `Bash`, every line, and `inputs` is `[{ name, value }]`, each input as text, for any other tool or the rest of a command's. `allow` says whether `POST /api/permission/answer` takes `allow`, which it does only when the whole of what is allowed is here: never for `Edit`, `Write`, `MultiEdit` or `NotebookEdit`, and not for `ExitPlanMode` or `AskUserQuestion`, past 4,000 characters or 40 lines, with a character that cannot be shown as it is, with more than two blank lines in a row, or for a command holding right-to-left letters, with `denyOnly` saying why: `edit`, `too-long`, `hidden-characters`, `not-yes-or-no`, `right-to-left` or `blank-lines`. `until` is when the request is let go. Kept in memory only while it is held: no event, history point, email, webhook post, push or answer of `agent-lookout mcp` holds it |
|
|
153
|
+
| `answered` | `true` for a `needs-you` Claude Code session whose permission request Agent Lookout has answered, from Allow, Deny or a [permission rule](GUIDE.md#permission-rules), or is answering by a rule, while its registry file still says it waits in that wait, as it can for a second or two after the answer, and for 10 seconds after the answer at most. A session on another machine has it when Agent Lookout there sent it, for an answer given there. The wait is over: the dashboard's notifications and Agent Lookout's own, email, the webhook, ntfy and Pushover send nothing more for it, no reminder comes, `/api/waits` does not count it as waiting, `/api/history` counts it as working, not as needing you, and the dashboard, the Mac app's Dock badge and menu bar, `agent-lookout status` and the MCP tools count it as working too. Left out otherwise |
|
|
154
|
+
| `stale` | `true` once it has been idle for 24 hours, or for as long as the idle rule in `timeRules` says while it is on. For a session on another machine too, by this computer's rule, whatever that machine said |
|
|
155
|
+
|
|
156
|
+
| Source field | Holds |
|
|
157
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
158
|
+
| `id`, `label` | `claude-code` and `Claude Code`, `codex` and `Codex`, `antigravity-cli` and `Antigravity CLI`, or `status-files` and `Status files`, or for another machine `remote:devbox` and `devbox` |
|
|
159
|
+
| `state` | `ok`, `searching`, `unavailable`, `not-set-up` or `error` |
|
|
160
|
+
| `detail` | One plain sentence: how it is being read, or what went wrong |
|
|
161
|
+
| `advice` | One plain sentence saying what you can do about a problem, when the collector knows |
|
|
162
|
+
| `watching` | `[{ label, value }]`: what it reads and runs, and how often |
|
|
163
|
+
| `basis` | Which way the sessions were read, for a source that has more than one |
|
|
164
|
+
| `capabilities` | What its agent can report, and whether its sessions can be stopped and answered: for each of nine things, `{ level: "yes" }`, or `{ level: "no" }` or `"partly"` with a `reason` |
|
|
165
|
+
| `checkedAt` | When it was last read |
|
|
166
|
+
| `machine` | For another machine: its name, which its sessions carry as their `machine` |
|
|
167
|
+
| `agents` | For another machine: `[{ label, capabilities }]`, what each agent found there can report, as last read from it, with `jump`, `stop` and `answer` always `no` |
|
|
165
168
|
|
|
166
169
|
The [guide](GUIDE.md#what-each-agent-can-report) has the table `capabilities` holds.
|
|
167
170
|
|
|
@@ -311,6 +314,35 @@ Whether [email](GUIDE.md#email) or a [webhook](GUIDE.md#webhook) is set up, and
|
|
|
311
314
|
|
|
312
315
|
Neither ever holds the mail server's address, its user name or its password, the webhook's path, or anything a session was asking.
|
|
313
316
|
|
|
317
|
+
### `GET /api/ntfy` and `GET /api/pushover`
|
|
318
|
+
|
|
319
|
+
Whether pushes to a phone go through [ntfy](GUIDE.md#ntfy) or [Pushover](GUIDE.md#pushover), and how the last one went. They only read: both are set up in the environment Agent Lookout starts with.
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{
|
|
323
|
+
"on": true,
|
|
324
|
+
"host": "ntfy.sh",
|
|
325
|
+
"tokenSet": false,
|
|
326
|
+
"events": ["needs-you"],
|
|
327
|
+
"afterMs": 60000,
|
|
328
|
+
"asking": false,
|
|
329
|
+
"problem": null,
|
|
330
|
+
"last": { "at": 1791205920000, "sent": true },
|
|
331
|
+
"limitedUntil": null
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Each has the fields of `GET /api/webhook`, ntfy's with one more, `tokenSet`, and Pushover's without `host`. These differ:
|
|
336
|
+
|
|
337
|
+
| Field | Holds |
|
|
338
|
+
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
339
|
+
| `host` | ntfy only: the host of the server the topic is on, such as `ntfy.sh`, and never the topic |
|
|
340
|
+
| `tokenSet` | ntfy only: whether `AGENT_LOOKOUT_NTFY_TOKEN` is set, `true` or `false`, and `null` while ntfy is off. Never the token |
|
|
341
|
+
| `asking` | `true` with `AGENT_LOOKOUT_NTFY_ASKING=on` or `AGENT_LOOKOUT_PUSHOVER_ASKING=on`, `false` when that setting is `off` or left out |
|
|
342
|
+
| `last` | The last push of a notice that was tried. A test push from `POST /api/phone/test` is not counted here, though it counts toward the 20 an hour |
|
|
343
|
+
|
|
344
|
+
Neither ever holds the ntfy topic or its token, Pushover's application token or the user key, or anything a session was asking.
|
|
345
|
+
|
|
314
346
|
### `GET /api/pull-requests`
|
|
315
347
|
|
|
316
348
|
Whether Agent Lookout shows each session's [pull request](GUIDE.md#pull-requests), with `AGENT_LOOKOUT_PULL_REQUESTS=on`, and whether the GitHub CLI, `gh`, can be asked for them. It only reads.
|
|
@@ -335,7 +367,7 @@ The settings Agent Lookout keeps itself, in a file on this computer, so they hol
|
|
|
335
367
|
```json
|
|
336
368
|
{
|
|
337
369
|
"timeRules": {
|
|
338
|
-
"longWait": { "on": true, "minutes": 10 },
|
|
370
|
+
"longWait": { "on": true, "minutes": 10, "repeat": { "on": true, "minutes": 30 } },
|
|
339
371
|
"idle": { "on": true, "hours": 48 },
|
|
340
372
|
"quietHours": {
|
|
341
373
|
"on": true,
|
|
@@ -370,6 +402,7 @@ The settings Agent Lookout keeps itself, in a file on this computer, so they hol
|
|
|
370
402
|
| Field | Holds |
|
|
371
403
|
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
372
404
|
| `timeRules.longWait` | The long wait reminder: `on`, and `minutes`, a whole number from 1 to 1,440, how long a wait lasts before it is reminded of. 10 unless set |
|
|
405
|
+
| `longWait.repeat` | Whether the reminder goes again while the wait goes on: `on`, and `minutes`, a whole number from 5 to 1,440, how long from one reminder to the next. Left out until it is first set, which is the same as off, so a file from before it reads as it did. The Time rules card sets 30 when it is first turned on |
|
|
373
406
|
| `timeRules.idle` | The idle rule: `on`, and `hours`, a whole number from 1 to 720, how long a session is idle before it is stale. 48 unless set. While it is off a session is stale after 24 hours |
|
|
374
407
|
| `timeRules.quietHours` | Quiet hours: `on`, `from` and `to` on the 24-hour clock as `HH:MM`, two different times, which run past midnight when `to` is the earlier, and `days`, the days they begin on, any of `mon` to `sun`. 22:00 to 08:00 every day unless set |
|
|
375
408
|
| `quietHours.leaveOutAnswered` | Whether the summary sent when quiet hours end leaves out the waits that were answered while they held |
|
|
@@ -391,7 +424,7 @@ A route that acts. It puts the time rules in force and saves them in the setting
|
|
|
391
424
|
- is marked `same-origin` in `Sec-Fetch-Site`, when that header is sent, or gets 403.
|
|
392
425
|
- carries `X-Agent-Lookout-Action: time-rules`, or gets 403.
|
|
393
426
|
- has `Content-Type: application/json`, or gets 415.
|
|
394
|
-
- has a body of 2,048 bytes or less, or gets 413, that is exactly the three rules, `longWait`, `idle` and `quietHours`, each whole, with exactly the fields `GET /api/settings` gives and every value in range, or gets 400.
|
|
427
|
+
- has a body of 2,048 bytes or less, or gets 413, that is exactly the three rules, `longWait`, `idle` and `quietHours`, each whole, with exactly the fields `GET /api/settings` gives and every value in range, or gets 400. `longWait.repeat` may be left out, which is no repeat, and when it is there it is `{ "on", "minutes" }` whole.
|
|
395
428
|
|
|
396
429
|
The rules are in force once they are saved, and not before: the file is written whole, with mode 600, in a folder made with mode 700, and never through a link. Nothing in the request names a file.
|
|
397
430
|
|
|
@@ -424,9 +457,32 @@ A new rule goes to the end of the list, with an ID the server makes. A move at e
|
|
|
424
457
|
|
|
425
458
|
A held permission request is put to the rules as its session's registry file confirms its wait, and a deny or an allow rule answers it through the same path as `POST /api/permission/answer`, below, with every check it makes. [Permission rules](GUIDE.md#permission-rules) says what each rule matches.
|
|
426
459
|
|
|
460
|
+
### `POST /api/phone/test`
|
|
461
|
+
|
|
462
|
+
A route that acts. It sends one test push through ntfy or Pushover, as Send a test on the card in Settings does. The push is titled "Agent Lookout test", says "Pushes from Agent Lookout reach this device.", and holds nothing of any session. It goes during quiet hours too, since the person asked, and counts toward the channel's 20 an hour. It makes the same checks as `POST /api/jump`, with its own action, in `src/collector/outbound/testSendRoute.ts`, and answers only a request that:
|
|
463
|
+
|
|
464
|
+
- is a `POST`. Any other method gets 405, with `Allow: POST`.
|
|
465
|
+
- has an `Origin` that names this computer, or gets 403.
|
|
466
|
+
- is marked `same-origin` in `Sec-Fetch-Site`, when that header is sent, or gets 403.
|
|
467
|
+
- carries `X-Agent-Lookout-Action: phone-test`, or gets 403.
|
|
468
|
+
- has `Content-Type: application/json`, or gets 415.
|
|
469
|
+
- has a body of 64 bytes or less, or gets 413, that is exactly `{ "channel": "ntfy" }` or `{ "channel": "pushover" }`, or gets 400.
|
|
470
|
+
|
|
471
|
+
Nothing in the request reaches the push or says where it goes: that is the channel's own setting. It sends one test a second, and one at a time.
|
|
472
|
+
|
|
473
|
+
| Status | Body |
|
|
474
|
+
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
475
|
+
| 200 | `{ "ok": true, "channel": "ntfy", "sentAt": 1791205920000 }`: the service took it |
|
|
476
|
+
| 409 | `reason: "off"`: the channel is not set up |
|
|
477
|
+
| 429 | `reason: "too-soon"`, with `Retry-After: 1` |
|
|
478
|
+
| 429 | `reason: "limited"`, with `limitedUntil` and `Retry-After` in seconds: 20 pushes were tried through that channel in the last hour |
|
|
479
|
+
| 502 | `reason: "not-sent"`: it was tried, and the service did not take it. The `error` says why, such as `Pushover had a problem (status 503).` |
|
|
480
|
+
|
|
481
|
+
Each of these has an `error` sentence beside its `reason`, and none holds the topic, a token or a key.
|
|
482
|
+
|
|
427
483
|
### `POST /api/jump`
|
|
428
484
|
|
|
429
|
-
One of the
|
|
485
|
+
One of the eight routes that act. It selects the tmux pane a session runs in, or brings its tab of Terminal or iTerm2 to the front, as the Jump button does. Its checks, on top of the ones every request passes, are `jumpRefusalFor` in `src/collector/jumpRoute.ts`, which makes those `actionRefusalFor` in `src/collector/handler.ts` makes for every route that acts. It answers only a request that:
|
|
430
486
|
|
|
431
487
|
- is a `POST`. Any other method gets 405, with `Allow: POST`.
|
|
432
488
|
- has an `Origin` that names this computer. A request with no `Origin` gets 403 here, though a read may go without one.
|