agent-pager 0.1.0 → 0.1.1
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/README.md +35 -129
- package/dist/src/cli.js +6 -4
- package/dist/src/local-config.js +1 -1
- package/dist/src/mcp.js +1 -1
- package/package.json +13 -9
- package/web/app.js +11 -2
- package/web/index.html +4 -4
- package/dist/src/hosted-http.js +0 -849
- package/dist/src/hosted-service.js +0 -1038
- package/dist/src/hosted-vercel.js +0 -51
- package/dist/src/supabase.js +0 -32
- package/dist/src/supabase.types.js +0 -13
package/README.md
CHANGED
|
@@ -2,19 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
**Because people ignore their messages, but not their agents.**
|
|
4
4
|
|
|
5
|
-
Agent Pager
|
|
5
|
+
Agent Pager lets trusted friends page your local Codex or Claude agent session. Public links can request access, but only approved friends can send pages. Messages are text-only, device-signed, friend-gated, and rate-limited.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Web app: https://agent-pager.vercel.app
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
https://agent-pager.vercel.app
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Current launch status: GitHub, Supabase, Vercel production, and the npm CLI package are live.
|
|
14
|
-
|
|
15
|
-
## Quickstart
|
|
16
|
-
|
|
17
|
-
Install the CLI:
|
|
9
|
+
## Install
|
|
18
10
|
|
|
19
11
|
```bash
|
|
20
12
|
npm install -g agent-pager
|
|
@@ -22,148 +14,62 @@ agent-pager login
|
|
|
22
14
|
agent-pager start
|
|
23
15
|
```
|
|
24
16
|
|
|
25
|
-
|
|
17
|
+
`agent-pager login` opens a device-pairing flow. Approve the device in the web app, then keep `agent-pager start` running to receive pages.
|
|
26
18
|
|
|
27
|
-
|
|
19
|
+
## First Run
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
1. Create an account at https://agent-pager.vercel.app.
|
|
22
|
+
2. Run `agent-pager login` on the machine where your coding agent runs.
|
|
23
|
+
3. Approve the pairing code in the web app.
|
|
24
|
+
4. Run `agent-pager start`.
|
|
25
|
+
5. Optional: run `agent-pager setup codex` or `agent-pager setup claude`.
|
|
34
26
|
|
|
35
|
-
|
|
27
|
+
## Share
|
|
36
28
|
|
|
37
29
|
```bash
|
|
38
|
-
|
|
39
|
-
node dist/src/cli.js start
|
|
30
|
+
agent-pager share
|
|
40
31
|
```
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
Your share link lets people request access. It does not let strangers page you. You approve or deny friend requests before any pages can be delivered.
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
AGENT_PAGER_HOME=/tmp/agent-pager-sarah node dist/src/cli.js login --username sarah --local-dev
|
|
46
|
-
node dist/src/cli.js friends invite
|
|
47
|
-
AGENT_PAGER_HOME=/tmp/agent-pager-sarah node dist/src/cli.js friends add <bryson-invite-url>
|
|
48
|
-
AGENT_PAGER_HOME=/tmp/agent-pager-sarah node dist/src/cli.js page bryson "Can you check the PR?"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Open the web app:
|
|
52
|
-
|
|
53
|
-
```text
|
|
54
|
-
http://127.0.0.1:8787
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Hosted V1 foundation:
|
|
35
|
+
## Agent Tools
|
|
58
36
|
|
|
59
37
|
```bash
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
npm run test:doctor
|
|
64
|
-
npm run test:config
|
|
65
|
-
npm run build
|
|
66
|
-
npm run test:web
|
|
67
|
-
npm run test:mcp
|
|
68
|
-
npm run test:smoke
|
|
69
|
-
npm run test:package
|
|
70
|
-
npm run test:hosted
|
|
38
|
+
agent-pager setup codex
|
|
39
|
+
agent-pager setup claude
|
|
40
|
+
agent-pager mcp
|
|
71
41
|
```
|
|
72
42
|
|
|
73
|
-
The
|
|
74
|
-
|
|
75
|
-
`agent-pager doctor` is a local-only readiness check for the hosted V1. It verifies the npm package manifest, Vercel Git deployment guard, required environment variables, server signing keypair, local pairing state, Git remote/status, Docker runtime, and cloud-smoke gate without linking Supabase, pushing Git, publishing npm, or deploying Vercel.
|
|
76
|
-
|
|
77
|
-
`agent-pager launch-check` is the live hosted preflight. It reads GitHub, Supabase, and Vercel state to confirm repo, schema, project, and env readiness before a manual preview deployment.
|
|
78
|
-
|
|
79
|
-
`agent-pager login` now uses secure hosted device pairing by default. The old local prototype login is still available with `--username` / `--local-dev`.
|
|
80
|
-
|
|
81
|
-
`agent-pager start` uses Supabase Realtime as the fast path and a signed HTTP polling fallback while it is running. `agent-pager check-pages` remains available for manual recovery or debugging.
|
|
82
|
-
|
|
83
|
-
The npm package ships the built CLI plus bundled retro web assets. `npm run test:package` dry-runs `npm pack` and verifies the package contents.
|
|
43
|
+
The setup commands install local instructions and MCP wiring so agents know how to list friends, send pages, reply, review friend requests, mute/block users, and avoid abusing the pager.
|
|
84
44
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
## Commands
|
|
45
|
+
## Useful Commands
|
|
88
46
|
|
|
89
47
|
```bash
|
|
90
|
-
agent-pager server
|
|
91
|
-
agent-pager login
|
|
92
|
-
agent-pager login --username bryson --local-dev
|
|
93
|
-
agent-pager start
|
|
94
48
|
agent-pager status
|
|
95
|
-
agent-pager share
|
|
96
|
-
agent-pager doctor
|
|
97
|
-
agent-pager launch-check
|
|
98
|
-
agent-pager settings quiet-hours on --start 22:00 --end 08:00 --timezone America/Denver
|
|
99
|
-
agent-pager settings quiet-hours off
|
|
100
|
-
agent-pager settings rate-limit 8
|
|
101
|
-
agent-pager devices list
|
|
102
|
-
agent-pager devices revoke <device-id>
|
|
103
|
-
agent-pager logout
|
|
104
|
-
agent-pager page sarah "Can you review this?"
|
|
105
|
-
agent-pager mute sarah --for 1h
|
|
106
|
-
agent-pager unmute sarah
|
|
107
|
-
agent-pager mutes list
|
|
108
|
-
agent-pager block sarah
|
|
109
|
-
agent-pager unblock sarah
|
|
110
|
-
agent-pager blocks list
|
|
111
|
-
agent-pager report sarah --reason spam
|
|
112
|
-
agent-pager report --page-id <page-id> --reason spam
|
|
113
|
-
agent-pager reports list
|
|
114
|
-
agent-pager friends invite
|
|
115
|
-
agent-pager friends invites
|
|
116
|
-
agent-pager friends revoke-invite <invite-url-or-code>
|
|
117
|
-
agent-pager friends add <invite-url-or-code>
|
|
118
|
-
agent-pager friends request sarah "Page my agent?"
|
|
119
49
|
agent-pager friends requests
|
|
120
50
|
agent-pager friends approve <request-id>
|
|
121
51
|
agent-pager friends deny <request-id>
|
|
122
|
-
agent-pager friends cancel <request-id>
|
|
123
52
|
agent-pager friends list
|
|
124
|
-
agent-pager
|
|
125
|
-
agent-pager
|
|
126
|
-
agent-pager
|
|
127
|
-
agent-pager
|
|
128
|
-
agent-pager
|
|
53
|
+
agent-pager page <friend> "Can you check the PR?"
|
|
54
|
+
agent-pager mute <friend> --for 1h
|
|
55
|
+
agent-pager devices list
|
|
56
|
+
agent-pager devices revoke <device-id>
|
|
57
|
+
agent-pager logout
|
|
129
58
|
```
|
|
130
59
|
|
|
131
|
-
## Security
|
|
60
|
+
## Security
|
|
132
61
|
|
|
133
62
|
- Devices generate local Ed25519 keypairs.
|
|
134
|
-
- The service stores public keys only.
|
|
63
|
+
- The hosted service stores public keys only.
|
|
135
64
|
- Device requests are signed with timestamped canonical request signatures.
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
- Per-friend mutes block delivery before a page reaches a local session and can be listed or removed.
|
|
144
|
-
- Blocks prevent friend requests, invite acceptance, approvals, and pages in either direction.
|
|
145
|
-
- Abuse reports can target a username or a page the reporter participated in.
|
|
146
|
-
- Quiet hours block delivery before page rows are created.
|
|
147
|
-
- Invite links expire and can be revoked before use.
|
|
148
|
-
- Rate limits and message length limits protect against spam.
|
|
149
|
-
- Hosted V1 uses Supabase RLS policies and realtime delivery rows instead of exposing raw session lists.
|
|
150
|
-
|
|
151
|
-
## Agent Integration
|
|
152
|
-
|
|
153
|
-
`agent-pager setup codex` installs:
|
|
154
|
-
|
|
155
|
-
- a Codex skill at `~/.codex/skills/agent-pager/SKILL.md`
|
|
156
|
-
- an MCP config block for `agent-pager mcp`
|
|
157
|
-
|
|
158
|
-
`agent-pager setup claude` installs:
|
|
159
|
-
|
|
160
|
-
- a Claude skill at `~/.claude/skills/agent-pager/SKILL.md`
|
|
161
|
-
- setup instructions for `claude mcp add agent-pager -- agent-pager mcp`
|
|
162
|
-
|
|
163
|
-
The MCP server exposes paging, replies, presence, Page my agent sharing, friend-request review, muting, blocking, removal, and abuse-report tools with explicit human-intent wording for access-changing actions.
|
|
164
|
-
|
|
165
|
-
Claude Code channels are the best future path for true push into an already-running Claude session. The current local listener already receives signed pages, persists them, and sends desktop notifications.
|
|
65
|
+
- Delivery envelopes are signed by the server and verified locally.
|
|
66
|
+
- Pages only deliver between approved friends.
|
|
67
|
+
- Public profile links create friend requests, not unrestricted messages.
|
|
68
|
+
- Incoming pages are text-only. Agent Pager does not allow remote command execution.
|
|
69
|
+
- Mutes, blocks, quiet hours, message limits, and per-friend rate limits are enforced before delivery.
|
|
70
|
+
- Devices can be revoked from the web app or CLI.
|
|
71
|
+
- Friends see limited presence only; raw local agent sessions are not exposed.
|
|
166
72
|
|
|
167
|
-
##
|
|
73
|
+
## Notes
|
|
168
74
|
|
|
169
|
-
|
|
75
|
+
Agent Pager is experimental. Treat it like an early access tool: only approve people you trust, keep the CLI updated, and revoke devices you no longer use.
|
package/dist/src/cli.js
CHANGED
|
@@ -13,6 +13,8 @@ import { statusBox } from "./render.js";
|
|
|
13
13
|
import { runServer } from "./server.js";
|
|
14
14
|
import { setupClaude, setupCodex } from "./setup.js";
|
|
15
15
|
const DEFAULT_HOSTED_POLL_INTERVAL_MS = 30_000;
|
|
16
|
+
const DEFAULT_HOSTED_SERVER_URL = "https://agent-pager.vercel.app";
|
|
17
|
+
const DEFAULT_LOCAL_SERVER_URL = "http://127.0.0.1:8787";
|
|
16
18
|
const EXPECTED_GITHUB_REPO = "brysonkbarney/agent-pager";
|
|
17
19
|
const EXPECTED_SUPABASE_REF = "ghwzvpuggpqntowmbpih";
|
|
18
20
|
const EXPECTED_VERCEL_PROJECT = "agent-pager";
|
|
@@ -112,7 +114,7 @@ async function login(args) {
|
|
|
112
114
|
await localDevLogin(args);
|
|
113
115
|
return;
|
|
114
116
|
}
|
|
115
|
-
const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL ||
|
|
117
|
+
const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL || DEFAULT_HOSTED_SERVER_URL).replace(/\/+$/, "");
|
|
116
118
|
const deviceName = readFlag(args, "--device") || `${process.env.USER || "local"}@${process.env.HOSTNAME || "mac"}`;
|
|
117
119
|
const timeoutSeconds = Number(readFlag(args, "--timeout") || 600);
|
|
118
120
|
const keys = createDeviceKeyPair();
|
|
@@ -120,7 +122,7 @@ async function login(args) {
|
|
|
120
122
|
name: deviceName,
|
|
121
123
|
publicKeyPem: keys.publicKeyPem,
|
|
122
124
|
platform: process.platform,
|
|
123
|
-
appVersion: "0.1.
|
|
125
|
+
appVersion: "0.1.1"
|
|
124
126
|
});
|
|
125
127
|
console.log(statusBox({
|
|
126
128
|
Pairing: pairing.code,
|
|
@@ -153,7 +155,7 @@ async function login(args) {
|
|
|
153
155
|
}));
|
|
154
156
|
}
|
|
155
157
|
async function localDevLogin(args) {
|
|
156
|
-
const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL ||
|
|
158
|
+
const serverUrl = (readFlag(args, "--server") || process.env.AGENT_PAGER_SERVER_URL || DEFAULT_LOCAL_SERVER_URL).replace(/\/+$/, "");
|
|
157
159
|
let username = readFlag(args, "--username");
|
|
158
160
|
let displayName = readFlag(args, "--name");
|
|
159
161
|
if (!username) {
|
|
@@ -1067,7 +1069,7 @@ Because people ignore their messages, but not their agents.
|
|
|
1067
1069
|
|
|
1068
1070
|
Usage:
|
|
1069
1071
|
agent-pager server [--host 127.0.0.1] [--port 8787]
|
|
1070
|
-
agent-pager login [--server https://
|
|
1072
|
+
agent-pager login [--server https://agent-pager.vercel.app]
|
|
1071
1073
|
agent-pager login --username bryson [--local-dev]
|
|
1072
1074
|
agent-pager start
|
|
1073
1075
|
agent-pager status
|
package/dist/src/local-config.js
CHANGED
|
@@ -13,7 +13,7 @@ export function inboxPath() {
|
|
|
13
13
|
export function loadLocalConfig() {
|
|
14
14
|
const path = configPath();
|
|
15
15
|
if (!existsSync(path)) {
|
|
16
|
-
throw new Error("not logged in. Run `agent-pager login
|
|
16
|
+
throw new Error("not logged in. Run `agent-pager login` first.");
|
|
17
17
|
}
|
|
18
18
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
19
19
|
}
|
package/dist/src/mcp.js
CHANGED
|
@@ -197,7 +197,7 @@ async function handle(method, params) {
|
|
|
197
197
|
return {
|
|
198
198
|
protocolVersion: params.protocolVersion || "2024-11-05",
|
|
199
199
|
capabilities: { tools: {} },
|
|
200
|
-
serverInfo: { name: "agent-pager", version: "0.1.
|
|
200
|
+
serverInfo: { name: "agent-pager", version: "0.1.1" }
|
|
201
201
|
};
|
|
202
202
|
}
|
|
203
203
|
if (method === "tools/list") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-pager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Authorized Human Contact Service for paging trusted coding agents.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -14,13 +14,6 @@
|
|
|
14
14
|
"vercel"
|
|
15
15
|
],
|
|
16
16
|
"homepage": "https://agent-pager.vercel.app",
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/brysonkbarney/agent-pager.git"
|
|
20
|
-
},
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/brysonkbarney/agent-pager/issues"
|
|
23
|
-
},
|
|
24
17
|
"main": "./dist/src/cli.js",
|
|
25
18
|
"bin": {
|
|
26
19
|
"agent-pager": "dist/src/cli.js"
|
|
@@ -30,7 +23,18 @@
|
|
|
30
23
|
"registry": "https://registry.npmjs.org/"
|
|
31
24
|
},
|
|
32
25
|
"files": [
|
|
33
|
-
"dist/src",
|
|
26
|
+
"dist/src/cli.js",
|
|
27
|
+
"dist/src/crypto.js",
|
|
28
|
+
"dist/src/delivery.js",
|
|
29
|
+
"dist/src/http-client.js",
|
|
30
|
+
"dist/src/local-config.js",
|
|
31
|
+
"dist/src/mcp.js",
|
|
32
|
+
"dist/src/render.js",
|
|
33
|
+
"dist/src/server.js",
|
|
34
|
+
"dist/src/session-adapters.js",
|
|
35
|
+
"dist/src/setup.js",
|
|
36
|
+
"dist/src/store.js",
|
|
37
|
+
"dist/src/types.js",
|
|
34
38
|
"web",
|
|
35
39
|
"README.md"
|
|
36
40
|
],
|
package/web/app.js
CHANGED
|
@@ -201,8 +201,9 @@ function render() {
|
|
|
201
201
|
const username = profile?.username || state.session?.user?.email || "not signed in";
|
|
202
202
|
|
|
203
203
|
els["auth-panel"].classList.toggle("is-signed-in", signedIn);
|
|
204
|
-
|
|
205
|
-
els["
|
|
204
|
+
renderAuthActions(signedIn);
|
|
205
|
+
els["profile-line"].textContent = signedIn ? `Signed in as ${username}` : "Create an account or sign in to start.";
|
|
206
|
+
els["status-human"].textContent = signedIn ? username : "Create account or sign in";
|
|
206
207
|
els["status-cloud"].textContent = state.config?.publicUrl || "hosted API";
|
|
207
208
|
els["status-friends"].textContent = `${friends.length} approved`;
|
|
208
209
|
els["status-pending"].textContent = `${pending.length} pending`;
|
|
@@ -348,6 +349,13 @@ function render() {
|
|
|
348
349
|
`).join("") || empty("No abuse reports filed.", "Reports you file appear here.");
|
|
349
350
|
}
|
|
350
351
|
|
|
352
|
+
function renderAuthActions(signedIn) {
|
|
353
|
+
for (const element of document.querySelectorAll("#auth-panel [data-auth-when]")) {
|
|
354
|
+
const shouldShow = element.dataset.authWhen === (signedIn ? "signed-in" : "signed-out");
|
|
355
|
+
element.classList.toggle("is-hidden", !shouldShow);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
351
359
|
function renderSettings() {
|
|
352
360
|
const settings = state.settings || {};
|
|
353
361
|
const quietHours = quietHoursDefaults(settings.quietHours);
|
|
@@ -362,6 +370,7 @@ function renderPrototype() {
|
|
|
362
370
|
const users = state.prototype?.users || [];
|
|
363
371
|
const pages = state.prototype?.pages || [];
|
|
364
372
|
els["auth-panel"].classList.remove("is-signed-in");
|
|
373
|
+
renderAuthActions(false);
|
|
365
374
|
els["profile-line"].textContent = "Prototype mode";
|
|
366
375
|
els["status-human"].textContent = `${users.length} registered`;
|
|
367
376
|
els["status-cloud"].textContent = state.prototype?.publicUrl || "local service";
|
package/web/index.html
CHANGED
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
<label>Name<input id="auth-name" autocomplete="name" /></label>
|
|
72
72
|
</div>
|
|
73
73
|
<div class="button-row">
|
|
74
|
-
<button data-action="sign-in">Sign in</button>
|
|
75
|
-
<button data-action="sign-up">Create</button>
|
|
76
|
-
<button data-action="save-profile">Save profile</button>
|
|
77
|
-
<button data-action="sign-out">Sign out</button>
|
|
74
|
+
<button data-action="sign-in" data-auth-when="signed-out">Sign in</button>
|
|
75
|
+
<button data-action="sign-up" data-auth-when="signed-out">Create</button>
|
|
76
|
+
<button data-action="save-profile" data-auth-when="signed-in">Save profile</button>
|
|
77
|
+
<button data-action="sign-out" data-auth-when="signed-in">Sign out</button>
|
|
78
78
|
</div>
|
|
79
79
|
</article>
|
|
80
80
|
<article class="operator-card">
|