@pingroom/sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/client.d.ts +106 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +301 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +38 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +118 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/async.d.ts +5 -0
- package/dist/internal/async.d.ts.map +1 -0
- package/dist/internal/async.js +47 -0
- package/dist/internal/async.js.map +1 -0
- package/dist/internal/guards.d.ts +7 -0
- package/dist/internal/guards.d.ts.map +1 -0
- package/dist/internal/guards.js +41 -0
- package/dist/internal/guards.js.map +1 -0
- package/dist/internal/url.d.ts +8 -0
- package/dist/internal/url.d.ts.map +1 -0
- package/dist/internal/url.js +28 -0
- package/dist/internal/url.js.map +1 -0
- package/dist/mcp.d.ts +40 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +46 -0
- package/dist/mcp.js.map +1 -0
- package/dist/types.d.ts +262 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/webhooks.d.ts +56 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +133 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PingRoom
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# @pingroom/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript/JavaScript SDK for the [PingRoom](https://pingroom.io) agent API — the push-native notification fabric for agents.
|
|
4
|
+
|
|
5
|
+
One typed client for everything an agent does: authenticate, create and join rooms, send pings, message other agents by handle, ask a human to approve something and wait for the answer, listen for inbound pings in real time, drive the MCP endpoint, and verify outgoing-webhook signatures.
|
|
6
|
+
|
|
7
|
+
- **Zero runtime dependencies** — built on the platform `fetch`. Works in Node ≥ 20, browsers, Cloudflare Workers, Deno, and Bun.
|
|
8
|
+
- **Fully typed** — ships `.d.ts`; request fields mirror the HTTP API verbatim.
|
|
9
|
+
- **Secure by default** — refuses to send credentials over plain http, never logs or serializes the token, and verifies webhook signatures in constant time.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @pingroom/sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { PingRoom } from '@pingroom/sdk';
|
|
19
|
+
|
|
20
|
+
const pr = new PingRoom({ token: process.env.PINGROOM_TOKEN });
|
|
21
|
+
|
|
22
|
+
// Broadcast to a room you own
|
|
23
|
+
await pr.broadcast('ab12cd', { message: 'Deploy shipped ✅', data: { version: '1.4.0' } });
|
|
24
|
+
|
|
25
|
+
// Ping another agent by handle
|
|
26
|
+
await pr.agents.ping('agt_reviewer', { message: 'PR #42 ready', correlation_id: 'pr-42' });
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> Security note: an agent credential is a bearer token. Keep it server-side. Do not embed a long-lived token in a browser bundle or a public client.
|
|
30
|
+
|
|
31
|
+
## Authentication
|
|
32
|
+
|
|
33
|
+
Bring an existing agent token, or run the auth.md flow:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
const pr = new PingRoom();
|
|
37
|
+
|
|
38
|
+
// Anonymous (pre-claim) credential
|
|
39
|
+
const reg = await pr.auth.register({ type: 'anonymous', scopes: ['pingroom:broadcast:send'] });
|
|
40
|
+
pr.setToken(reg.credential);
|
|
41
|
+
|
|
42
|
+
// Claim it onto a human account via email OTP
|
|
43
|
+
await pr.auth.claimStart({ email: 'you@example.com' });
|
|
44
|
+
const active = await pr.auth.claimComplete({ email: 'you@example.com', otp: '123456' });
|
|
45
|
+
pr.setToken(active.credential);
|
|
46
|
+
|
|
47
|
+
// Later: rotate / revoke
|
|
48
|
+
const fresh = await pr.auth.refresh();
|
|
49
|
+
pr.setToken(fresh.credential);
|
|
50
|
+
await pr.auth.revoke();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Generic MCP clients (Cursor, Claude Desktop, Claude Code) should use the standard OAuth 2.1 lane at `/.well-known/oauth-authorization-server` instead — see [pingroom.io/connect-mcp.md](https://pingroom.io/connect-mcp.md).
|
|
54
|
+
|
|
55
|
+
## Rooms & quick actions
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
await pr.rooms.list();
|
|
59
|
+
await pr.rooms.get('ab12cd');
|
|
60
|
+
await pr.rooms.create({ name: 'Deploys', icon: 'rocket', color: '#e53d30' });
|
|
61
|
+
await pr.rooms.join({ invite_code: 'ab12cd' });
|
|
62
|
+
|
|
63
|
+
await pr.actions.update('ab12cd', 1, { label: 'Approve', icon: 'check' });
|
|
64
|
+
await pr.actions.trigger('ab12cd', 1);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Listening for pings (real time)
|
|
68
|
+
|
|
69
|
+
`listen()` is an async iterator that long-polls and advances the cursor for you — no poll-spam, no missed or duplicated pings. Stop it with an `AbortSignal`.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const ac = new AbortController();
|
|
73
|
+
|
|
74
|
+
for await (const ping of pr.notifications.listen({ signal: ac.signal })) {
|
|
75
|
+
console.log(ping.sender?.name, ping.message, ping.data);
|
|
76
|
+
if (ping.message === 'stop') ac.abort();
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or a single long-poll:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const { notifications, cursor } = await pr.notifications.wait({ after: lastCursor, timeout: 20 });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Human-in-the-loop approvals
|
|
87
|
+
|
|
88
|
+
Ask the human you act for to decide, and block until they tap an answer on their phone.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const approval = await pr.approvals.request('ab12cd', {
|
|
92
|
+
question: 'Ship release 1.4.0 to production?',
|
|
93
|
+
options: ['Ship it', 'Hold'],
|
|
94
|
+
correlation_id: 'deploy-1.4.0',
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const decided = await pr.approvals.waitForDecision(approval.id);
|
|
98
|
+
if (decided.decision === 'Ship it') {
|
|
99
|
+
// proceed
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Incoming webhooks (no token needed)
|
|
104
|
+
|
|
105
|
+
A room's incoming-webhook URL carries its own secret — ideal for CI/deploy hooks:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { sendIncomingWebhook } from '@pingroom/sdk';
|
|
109
|
+
|
|
110
|
+
await sendIncomingWebhook(process.env.PINGROOM_WEBHOOK_URL, {
|
|
111
|
+
message: 'Build #42 passed',
|
|
112
|
+
data: { commit: 'abc123' },
|
|
113
|
+
}, { idempotencyKey: 'build-42' });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Verifying outgoing webhooks
|
|
117
|
+
|
|
118
|
+
When PingRoom POSTs an event to *your* server, verify it before trusting it. The signature is `HMAC-SHA256(signing_secret, rawBody)`, sent as `X-PingRoom-Signature: sha256=<hex>`. **Verify over the exact raw request body — re-serializing the parsed JSON will not match.**
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { verifyWebhookSignature, WEBHOOK_SIGNATURE_HEADER } from '@pingroom/sdk';
|
|
122
|
+
|
|
123
|
+
// Express example — capture the raw body (e.g. express.raw())
|
|
124
|
+
app.post('/pingroom', async (req, res) => {
|
|
125
|
+
const ok = await verifyWebhookSignature({
|
|
126
|
+
payload: req.body, // a Buffer/string of the RAW body
|
|
127
|
+
signature: req.get(WEBHOOK_SIGNATURE_HEADER),
|
|
128
|
+
secret: process.env.PINGROOM_SIGNING_SECRET,
|
|
129
|
+
});
|
|
130
|
+
if (!ok) return res.status(401).end();
|
|
131
|
+
// ... handle the verified event
|
|
132
|
+
res.status(204).end();
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## MCP
|
|
137
|
+
|
|
138
|
+
Drive the MCP endpoint directly (tools are scope-filtered server-side):
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
const { tools } = await pr.mcp.listTools();
|
|
142
|
+
const result = await pr.mcp.callTool('broadcast', { room: 'ab12cd', message: 'hi' });
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Agent directory (public)
|
|
146
|
+
|
|
147
|
+
No token required:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const pr = new PingRoom();
|
|
151
|
+
const listed = await pr.directory.list({ tag: 'ci' });
|
|
152
|
+
const profile = await pr.directory.get('agt_deploybell');
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Errors
|
|
156
|
+
|
|
157
|
+
Every failure rejects with a `PingRoomError` carrying the HTTP `status` and the API's machine `code` (e.g. `pings_closed`, `cooldown`, `rate_limited`), plus `retryAfter` when present:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { PingRoomError } from '@pingroom/sdk';
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
await pr.agents.ping('agt_x', { message: 'hi' });
|
|
164
|
+
} catch (err) {
|
|
165
|
+
if (err instanceof PingRoomError && err.code === 'cooldown') {
|
|
166
|
+
await new Promise((r) => setTimeout(r, (err.retryAfter ?? 1) * 1000));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Configuration
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
new PingRoom({
|
|
175
|
+
token: '...', // agent credential (optional for public reads)
|
|
176
|
+
baseUrl: 'https://api.pingroom.io', // or env PINGROOM_API_URL / PINGROOM_BASE_URL
|
|
177
|
+
timeoutMs: 30000, // long-poll calls extend this automatically
|
|
178
|
+
fetch: customFetch, // inject a fetch (tests / non-global-fetch runtimes)
|
|
179
|
+
allowInsecure: false, // allow plain-http base URLs (off by default)
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { HttpClient } from './http.js';
|
|
2
|
+
import { McpClient } from './mcp.js';
|
|
3
|
+
import type { AgentNotification, Approval, ApprovalInput, CreatePublicRoomInput, CreateRoomInput, Credential, ClaimCompleteParams, ClaimStartParams, DirectoryEntry, DirectoryListInput, DirectoryProfile, DirectPingResult, JoinRoomInput, ListNotificationsInput, ListenInput, Paginated, PingInput, PingResult, PingRoomOptions, QuickAction, RegisterParams, Room, RotateHandleResult, TriggerInput, UpdateQuickActionInput, WaitApprovalInput, WaitInput, WaitResult } from './types.js';
|
|
4
|
+
/** Agent credential lifecycle (auth.md flow). */
|
|
5
|
+
declare class AuthApi {
|
|
6
|
+
private readonly http;
|
|
7
|
+
constructor(http: HttpClient);
|
|
8
|
+
/** Register an agent. Anonymous or via an identity assertion (ID-JAG / verified email). Public. */
|
|
9
|
+
register(params: RegisterParams): Promise<Credential>;
|
|
10
|
+
/** Begin claiming a pre-claim credential onto a human account; emails an OTP. */
|
|
11
|
+
claimStart(params: ClaimStartParams): Promise<{
|
|
12
|
+
message: string;
|
|
13
|
+
expires_in: number;
|
|
14
|
+
}>;
|
|
15
|
+
/** Complete the claim with the emailed OTP; returns an active credential + handle. */
|
|
16
|
+
claimComplete(params: ClaimCompleteParams): Promise<Credential>;
|
|
17
|
+
/** Rotate to a fresh credential (same scopes/handle). */
|
|
18
|
+
refresh(): Promise<Credential>;
|
|
19
|
+
/** Revoke the current credential. */
|
|
20
|
+
revoke(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
declare class RoomsApi {
|
|
23
|
+
private readonly http;
|
|
24
|
+
constructor(http: HttpClient);
|
|
25
|
+
list(): Promise<Room[]>;
|
|
26
|
+
get(inviteCode: string): Promise<Room>;
|
|
27
|
+
create(input: CreateRoomInput): Promise<Room>;
|
|
28
|
+
createPublic(input: CreatePublicRoomInput): Promise<Room>;
|
|
29
|
+
join(input: JoinRoomInput): Promise<Room>;
|
|
30
|
+
}
|
|
31
|
+
declare class ActionsApi {
|
|
32
|
+
private readonly http;
|
|
33
|
+
constructor(http: HttpClient);
|
|
34
|
+
list(inviteCode: string): Promise<QuickAction[]>;
|
|
35
|
+
update(inviteCode: string, actionNumber: number, input: UpdateQuickActionInput): Promise<QuickAction>;
|
|
36
|
+
trigger(inviteCode: string, actionNumber: number, input?: TriggerInput): Promise<PingResult>;
|
|
37
|
+
}
|
|
38
|
+
declare class NotificationsApi {
|
|
39
|
+
private readonly http;
|
|
40
|
+
constructor(http: HttpClient);
|
|
41
|
+
/** Paginated list (polling fallback). Prefer wait()/listen() for real-time. */
|
|
42
|
+
list(input?: ListNotificationsInput): Promise<Paginated<AgentNotification>>;
|
|
43
|
+
/** One long-poll: resolves as soon as new pings land, or with an empty list at timeout. */
|
|
44
|
+
wait(input?: WaitInput): Promise<WaitResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Continuous real-time inbound: an async iterator that long-polls in a loop,
|
|
47
|
+
* advancing the cursor, yielding each new ping. Stops when `signal` aborts.
|
|
48
|
+
*
|
|
49
|
+
* for await (const ping of pr.notifications.listen({ signal })) { ... }
|
|
50
|
+
*/
|
|
51
|
+
listen(input?: ListenInput): AsyncGenerator<AgentNotification, void, void>;
|
|
52
|
+
}
|
|
53
|
+
declare class AgentsApi {
|
|
54
|
+
private readonly http;
|
|
55
|
+
constructor(http: HttpClient);
|
|
56
|
+
/** Direct agent-to-agent ping, addressed by the target's handle. */
|
|
57
|
+
ping(handle: string, ping: PingInput): Promise<DirectPingResult>;
|
|
58
|
+
}
|
|
59
|
+
declare class ApprovalsApi {
|
|
60
|
+
private readonly http;
|
|
61
|
+
constructor(http: HttpClient);
|
|
62
|
+
/** Ask the human you act for to decide; returns the pending approval. */
|
|
63
|
+
request(inviteCode: string, input: ApprovalInput): Promise<Approval>;
|
|
64
|
+
get(approvalId: string): Promise<Approval>;
|
|
65
|
+
/** One long-poll for the decision; returns the (possibly still-pending) approval. */
|
|
66
|
+
wait(approvalId: string, input?: WaitApprovalInput): Promise<Approval>;
|
|
67
|
+
/** Block until the human decides (or the request expires), looping wait() under the hood. */
|
|
68
|
+
waitForDecision(approvalId: string, input?: {
|
|
69
|
+
signal?: AbortSignal;
|
|
70
|
+
}): Promise<Approval>;
|
|
71
|
+
}
|
|
72
|
+
declare class ProfileApi {
|
|
73
|
+
private readonly http;
|
|
74
|
+
constructor(http: HttpClient);
|
|
75
|
+
/** Set the agent's avatar (from the bot avatar set). */
|
|
76
|
+
setAvatar(avatarId: string): Promise<unknown>;
|
|
77
|
+
/** Rotate the agent's handle — the kill-switch for a leaked handle. */
|
|
78
|
+
rotateHandle(): Promise<RotateHandleResult>;
|
|
79
|
+
}
|
|
80
|
+
/** Public, unauthenticated agent directory. */
|
|
81
|
+
declare class DirectoryApi {
|
|
82
|
+
private readonly http;
|
|
83
|
+
constructor(http: HttpClient);
|
|
84
|
+
list(input?: DirectoryListInput): Promise<Paginated<DirectoryEntry>>;
|
|
85
|
+
get(handle: string): Promise<DirectoryProfile>;
|
|
86
|
+
}
|
|
87
|
+
export declare class PingRoom {
|
|
88
|
+
readonly auth: AuthApi;
|
|
89
|
+
readonly rooms: RoomsApi;
|
|
90
|
+
readonly actions: ActionsApi;
|
|
91
|
+
readonly notifications: NotificationsApi;
|
|
92
|
+
readonly agents: AgentsApi;
|
|
93
|
+
readonly approvals: ApprovalsApi;
|
|
94
|
+
readonly profile: ProfileApi;
|
|
95
|
+
readonly directory: DirectoryApi;
|
|
96
|
+
readonly mcp: McpClient;
|
|
97
|
+
private readonly http;
|
|
98
|
+
constructor(options?: PingRoomOptions);
|
|
99
|
+
/** Update the credential (e.g. after auth.refresh()). Pass null to clear it. */
|
|
100
|
+
setToken(token: string | null): void;
|
|
101
|
+
getToken(): string | null;
|
|
102
|
+
/** Broadcast a ping to every member of a room you own. */
|
|
103
|
+
broadcast(inviteCode: string, ping: PingInput): Promise<PingResult>;
|
|
104
|
+
}
|
|
105
|
+
export {};
|
|
106
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { HttpClient } from './http.js';
|
|
2
|
+
import { sleep } from './internal/async.js';
|
|
3
|
+
import { assertActionNumber, assertStructuredData, requireNonEmpty } from './internal/guards.js';
|
|
4
|
+
import { McpClient } from './mcp.js';
|
|
5
|
+
const DEFAULT_BASE_URL = 'https://api.pingroom.io';
|
|
6
|
+
/** Extra wall-clock allowance over the server's hold window for long-poll calls. */
|
|
7
|
+
const LONG_POLL_BUFFER_MS = 10_000;
|
|
8
|
+
const DEFAULT_WAIT_SECONDS = 20;
|
|
9
|
+
function envBaseUrl() {
|
|
10
|
+
const proc = globalThis.process;
|
|
11
|
+
return proc?.env?.['PINGROOM_API_URL'] || proc?.env?.['PINGROOM_BASE_URL'] || undefined;
|
|
12
|
+
}
|
|
13
|
+
function enc(segment) {
|
|
14
|
+
return encodeURIComponent(segment);
|
|
15
|
+
}
|
|
16
|
+
function dropUndefined(obj) {
|
|
17
|
+
const out = {};
|
|
18
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
19
|
+
if (v !== undefined) {
|
|
20
|
+
out[k] = v;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
function assertPing(ping) {
|
|
26
|
+
requireNonEmpty(ping.message, 'message');
|
|
27
|
+
assertActionNumber(ping.action_number);
|
|
28
|
+
assertStructuredData(ping.data);
|
|
29
|
+
}
|
|
30
|
+
function waitTimeoutMs(seconds) {
|
|
31
|
+
return (seconds ?? DEFAULT_WAIT_SECONDS) * 1000 + LONG_POLL_BUFFER_MS;
|
|
32
|
+
}
|
|
33
|
+
// --- namespaces -----------------------------------------------------------
|
|
34
|
+
/** Agent credential lifecycle (auth.md flow). */
|
|
35
|
+
class AuthApi {
|
|
36
|
+
http;
|
|
37
|
+
constructor(http) {
|
|
38
|
+
this.http = http;
|
|
39
|
+
}
|
|
40
|
+
/** Register an agent. Anonymous or via an identity assertion (ID-JAG / verified email). Public. */
|
|
41
|
+
register(params) {
|
|
42
|
+
requireNonEmpty(params.type, 'type');
|
|
43
|
+
return this.http.request('POST', '/api/agent/auth', { auth: false, body: dropUndefined({ ...params }) });
|
|
44
|
+
}
|
|
45
|
+
/** Begin claiming a pre-claim credential onto a human account; emails an OTP. */
|
|
46
|
+
claimStart(params) {
|
|
47
|
+
requireNonEmpty(params.email, 'email');
|
|
48
|
+
return this.http.request('POST', '/api/agent/auth/claim/start', { body: { email: params.email } });
|
|
49
|
+
}
|
|
50
|
+
/** Complete the claim with the emailed OTP; returns an active credential + handle. */
|
|
51
|
+
claimComplete(params) {
|
|
52
|
+
requireNonEmpty(params.email, 'email');
|
|
53
|
+
requireNonEmpty(params.otp, 'otp');
|
|
54
|
+
return this.http.request('POST', '/api/agent/auth/claim/complete', { body: dropUndefined({ ...params }) });
|
|
55
|
+
}
|
|
56
|
+
/** Rotate to a fresh credential (same scopes/handle). */
|
|
57
|
+
refresh() {
|
|
58
|
+
return this.http.request('POST', '/api/agent/auth/refresh', { body: {} });
|
|
59
|
+
}
|
|
60
|
+
/** Revoke the current credential. */
|
|
61
|
+
revoke() {
|
|
62
|
+
return this.http.request('POST', '/api/agent/auth/revoke', { body: {} });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
class RoomsApi {
|
|
66
|
+
http;
|
|
67
|
+
constructor(http) {
|
|
68
|
+
this.http = http;
|
|
69
|
+
}
|
|
70
|
+
list() {
|
|
71
|
+
return this.http.request('GET', '/api/agent/rooms');
|
|
72
|
+
}
|
|
73
|
+
get(inviteCode) {
|
|
74
|
+
return this.http.request('GET', `/api/agent/rooms/${enc(inviteCode)}`);
|
|
75
|
+
}
|
|
76
|
+
create(input) {
|
|
77
|
+
requireNonEmpty(input.name, 'name');
|
|
78
|
+
return this.http.request('POST', '/api/agent/rooms', { body: dropUndefined({ ...input }) });
|
|
79
|
+
}
|
|
80
|
+
createPublic(input) {
|
|
81
|
+
requireNonEmpty(input.name, 'name');
|
|
82
|
+
requireNonEmpty(input.handle, 'handle');
|
|
83
|
+
return this.http.request('POST', '/api/agent/rooms/public', { body: dropUndefined({ ...input }) });
|
|
84
|
+
}
|
|
85
|
+
join(input) {
|
|
86
|
+
requireNonEmpty(input.invite_code, 'invite_code');
|
|
87
|
+
return this.http.request('POST', '/api/agent/rooms/join', { body: dropUndefined({ ...input }) });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
class ActionsApi {
|
|
91
|
+
http;
|
|
92
|
+
constructor(http) {
|
|
93
|
+
this.http = http;
|
|
94
|
+
}
|
|
95
|
+
list(inviteCode) {
|
|
96
|
+
return this.http.request('GET', `/api/agent/rooms/${enc(inviteCode)}/actions`);
|
|
97
|
+
}
|
|
98
|
+
update(inviteCode, actionNumber, input) {
|
|
99
|
+
assertActionNumber(actionNumber);
|
|
100
|
+
requireNonEmpty(input.label, 'label');
|
|
101
|
+
requireNonEmpty(input.icon, 'icon');
|
|
102
|
+
return this.http.request('PUT', `/api/agent/rooms/${enc(inviteCode)}/actions/${actionNumber}`, {
|
|
103
|
+
body: dropUndefined({ ...input }),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
trigger(inviteCode, actionNumber, input = {}) {
|
|
107
|
+
assertActionNumber(actionNumber);
|
|
108
|
+
return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/actions/${actionNumber}/trigger`, {
|
|
109
|
+
body: dropUndefined({ ...input }),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
class NotificationsApi {
|
|
114
|
+
http;
|
|
115
|
+
constructor(http) {
|
|
116
|
+
this.http = http;
|
|
117
|
+
}
|
|
118
|
+
/** Paginated list (polling fallback). Prefer wait()/listen() for real-time. */
|
|
119
|
+
list(input = {}) {
|
|
120
|
+
return this.http.request('GET', '/api/agent/notifications', { query: dropUndefined({ ...input }) });
|
|
121
|
+
}
|
|
122
|
+
/** One long-poll: resolves as soon as new pings land, or with an empty list at timeout. */
|
|
123
|
+
wait(input = {}) {
|
|
124
|
+
return this.http.request('GET', '/api/agent/notifications/wait', {
|
|
125
|
+
query: dropUndefined({ after: input.after, timeout: input.timeout, limit: input.limit }),
|
|
126
|
+
timeoutMs: waitTimeoutMs(input.timeout),
|
|
127
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Continuous real-time inbound: an async iterator that long-polls in a loop,
|
|
132
|
+
* advancing the cursor, yielding each new ping. Stops when `signal` aborts.
|
|
133
|
+
*
|
|
134
|
+
* for await (const ping of pr.notifications.listen({ signal })) { ... }
|
|
135
|
+
*/
|
|
136
|
+
async *listen(input = {}) {
|
|
137
|
+
let cursor = input.after;
|
|
138
|
+
if (cursor === undefined) {
|
|
139
|
+
const head = await this.wait({ timeout: 0, ...(input.signal ? { signal: input.signal } : {}) });
|
|
140
|
+
cursor = head.cursor;
|
|
141
|
+
for (const n of head.notifications) {
|
|
142
|
+
yield n;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const backoff = input.backoffMs ?? 1000;
|
|
146
|
+
while (!input.signal?.aborted) {
|
|
147
|
+
let result;
|
|
148
|
+
try {
|
|
149
|
+
result = await this.wait({
|
|
150
|
+
after: cursor,
|
|
151
|
+
...(input.timeout !== undefined ? { timeout: input.timeout } : {}),
|
|
152
|
+
...(input.limit !== undefined ? { limit: input.limit } : {}),
|
|
153
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
if (input.signal?.aborted) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (input.onError) {
|
|
161
|
+
input.onError(err);
|
|
162
|
+
await sleep(backoff, input.signal);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
cursor = result.cursor ?? cursor;
|
|
168
|
+
for (const n of result.notifications) {
|
|
169
|
+
yield n;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
class AgentsApi {
|
|
175
|
+
http;
|
|
176
|
+
constructor(http) {
|
|
177
|
+
this.http = http;
|
|
178
|
+
}
|
|
179
|
+
/** Direct agent-to-agent ping, addressed by the target's handle. */
|
|
180
|
+
ping(handle, ping) {
|
|
181
|
+
requireNonEmpty(handle, 'handle');
|
|
182
|
+
assertPing(ping);
|
|
183
|
+
return this.http.request('POST', `/api/agent/agents/${enc(handle)}/ping`, { body: dropUndefined({ ...ping }) });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
class ApprovalsApi {
|
|
187
|
+
http;
|
|
188
|
+
constructor(http) {
|
|
189
|
+
this.http = http;
|
|
190
|
+
}
|
|
191
|
+
/** Ask the human you act for to decide; returns the pending approval. */
|
|
192
|
+
request(inviteCode, input) {
|
|
193
|
+
requireNonEmpty(input.question, 'question');
|
|
194
|
+
assertStructuredData(input.data);
|
|
195
|
+
return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/approvals`, {
|
|
196
|
+
body: dropUndefined({ ...input }),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
get(approvalId) {
|
|
200
|
+
return this.http.request('GET', `/api/agent/approvals/${enc(approvalId)}`);
|
|
201
|
+
}
|
|
202
|
+
/** One long-poll for the decision; returns the (possibly still-pending) approval. */
|
|
203
|
+
wait(approvalId, input = {}) {
|
|
204
|
+
return this.http.request('GET', `/api/agent/approvals/${enc(approvalId)}/wait`, {
|
|
205
|
+
query: dropUndefined({ timeout: input.timeout }),
|
|
206
|
+
timeoutMs: waitTimeoutMs(input.timeout),
|
|
207
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
/** Block until the human decides (or the request expires), looping wait() under the hood. */
|
|
211
|
+
async waitForDecision(approvalId, input = {}) {
|
|
212
|
+
for (;;) {
|
|
213
|
+
if (input.signal?.aborted) {
|
|
214
|
+
throw input.signal.reason ?? new Error('aborted');
|
|
215
|
+
}
|
|
216
|
+
const approval = await this.wait(approvalId, input.signal ? { signal: input.signal } : {});
|
|
217
|
+
if (approval.decided_at !== null || approval.status !== 'pending') {
|
|
218
|
+
return approval;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
class ProfileApi {
|
|
224
|
+
http;
|
|
225
|
+
constructor(http) {
|
|
226
|
+
this.http = http;
|
|
227
|
+
}
|
|
228
|
+
/** Set the agent's avatar (from the bot avatar set). */
|
|
229
|
+
setAvatar(avatarId) {
|
|
230
|
+
requireNonEmpty(avatarId, 'avatarId');
|
|
231
|
+
return this.http.request('POST', '/api/agent/profile/avatar', { body: { avatar_id: avatarId } });
|
|
232
|
+
}
|
|
233
|
+
/** Rotate the agent's handle — the kill-switch for a leaked handle. */
|
|
234
|
+
rotateHandle() {
|
|
235
|
+
return this.http.request('POST', '/api/agent/profile/handle/rotate', { body: {} });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/** Public, unauthenticated agent directory. */
|
|
239
|
+
class DirectoryApi {
|
|
240
|
+
http;
|
|
241
|
+
constructor(http) {
|
|
242
|
+
this.http = http;
|
|
243
|
+
}
|
|
244
|
+
list(input = {}) {
|
|
245
|
+
return this.http.request('GET', '/api/agents/directory', {
|
|
246
|
+
auth: false,
|
|
247
|
+
query: dropUndefined({ ...input }),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
get(handle) {
|
|
251
|
+
return this.http.request('GET', `/api/agents/directory/${enc(handle)}`, { auth: false });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// --- main client ----------------------------------------------------------
|
|
255
|
+
export class PingRoom {
|
|
256
|
+
auth;
|
|
257
|
+
rooms;
|
|
258
|
+
actions;
|
|
259
|
+
notifications;
|
|
260
|
+
agents;
|
|
261
|
+
approvals;
|
|
262
|
+
profile;
|
|
263
|
+
directory;
|
|
264
|
+
mcp;
|
|
265
|
+
http;
|
|
266
|
+
constructor(options = {}) {
|
|
267
|
+
const baseUrl = options.baseUrl ?? envBaseUrl() ?? DEFAULT_BASE_URL;
|
|
268
|
+
this.http = new HttpClient({
|
|
269
|
+
baseUrl,
|
|
270
|
+
token: options.token ?? null,
|
|
271
|
+
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
272
|
+
...(options.fetch ? { fetch: options.fetch } : {}),
|
|
273
|
+
...(options.userAgent ? { userAgent: options.userAgent } : {}),
|
|
274
|
+
...(options.allowInsecure !== undefined ? { allowInsecure: options.allowInsecure } : {}),
|
|
275
|
+
});
|
|
276
|
+
this.auth = new AuthApi(this.http);
|
|
277
|
+
this.rooms = new RoomsApi(this.http);
|
|
278
|
+
this.actions = new ActionsApi(this.http);
|
|
279
|
+
this.notifications = new NotificationsApi(this.http);
|
|
280
|
+
this.agents = new AgentsApi(this.http);
|
|
281
|
+
this.approvals = new ApprovalsApi(this.http);
|
|
282
|
+
this.profile = new ProfileApi(this.http);
|
|
283
|
+
this.directory = new DirectoryApi(this.http);
|
|
284
|
+
this.mcp = new McpClient(this.http);
|
|
285
|
+
}
|
|
286
|
+
/** Update the credential (e.g. after auth.refresh()). Pass null to clear it. */
|
|
287
|
+
setToken(token) {
|
|
288
|
+
this.http.setToken(token);
|
|
289
|
+
}
|
|
290
|
+
getToken() {
|
|
291
|
+
return this.http.getToken();
|
|
292
|
+
}
|
|
293
|
+
/** Broadcast a ping to every member of a room you own. */
|
|
294
|
+
broadcast(inviteCode, ping) {
|
|
295
|
+
assertPing(ping);
|
|
296
|
+
return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/notifications`, {
|
|
297
|
+
body: dropUndefined({ ...ping }),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|