@pairlobby/client 0.0.0-stage → 0.12.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 +93 -0
- package/README.md +4 -2
- package/dist/client.d.ts +171 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +458 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/local-store.d.ts +125 -0
- package/dist/local-store.d.ts.map +1 -0
- package/dist/local-store.js +212 -0
- package/dist/local-store.js.map +1 -0
- package/dist/open-requests.d.ts +16 -0
- package/dist/open-requests.d.ts.map +1 -0
- package/dist/open-requests.js +48 -0
- package/dist/open-requests.js.map +1 -0
- package/package.json +33 -4
package/dist/client.js
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
//! The HTTP client shared by the CLI and the MCP bridge. It turns protocol error
|
|
2
|
+
//! bodies back into `ProtocolError`, so callers handle one error type whether a
|
|
3
|
+
//! failure came from local validation or from the server.
|
|
4
|
+
import { PROTOCOL_VERSION, PROTOCOL_VERSION_HEADER, ProtocolError, ServerFrame, newCredential, newId } from '@pairlobby/protocol';
|
|
5
|
+
export class PairLobbyClient {
|
|
6
|
+
accountToken;
|
|
7
|
+
signal;
|
|
8
|
+
serverUrl;
|
|
9
|
+
socket = null;
|
|
10
|
+
watermark = 0;
|
|
11
|
+
earliestSeq = 0;
|
|
12
|
+
liveEvents = [];
|
|
13
|
+
liveBytes = 0;
|
|
14
|
+
liveRoom = null;
|
|
15
|
+
changed = new Set();
|
|
16
|
+
constructor(serverUrl, accountToken, signal) {
|
|
17
|
+
this.accountToken = accountToken;
|
|
18
|
+
this.signal = signal;
|
|
19
|
+
this.serverUrl = serverUrl.replace(/\/+$/, '');
|
|
20
|
+
}
|
|
21
|
+
async createRoom(name, identity, expiresAt, access) {
|
|
22
|
+
// Both credentials are generated here, so a lost response never strands a secret the caller does not hold.
|
|
23
|
+
const controllerCredential = newCredential('controller');
|
|
24
|
+
const participantCredential = newCredential('participant');
|
|
25
|
+
const body = await this.call('POST', '/v1/rooms', null, {
|
|
26
|
+
name,
|
|
27
|
+
controllerCredential,
|
|
28
|
+
participantCredential,
|
|
29
|
+
...identity,
|
|
30
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
31
|
+
...access
|
|
32
|
+
});
|
|
33
|
+
return { roomId: body.room.roomId, participantId: body.participantId, controllerCredential, participantCredential, invite: body.invite, room: body.room };
|
|
34
|
+
}
|
|
35
|
+
/** `attemptId` and the credential must be reused across retries, or a crashed join forks a second membership. */
|
|
36
|
+
async redeemInvite(code, identity, attempt, useInviteName = true) {
|
|
37
|
+
const attemptId = attempt?.attemptId ?? newId('attempt');
|
|
38
|
+
const participantCredential = attempt?.participantCredential ?? newCredential('participant');
|
|
39
|
+
const body = await this.call('POST', '/v1/invites/redeem', null, {
|
|
40
|
+
code,
|
|
41
|
+
useInviteName,
|
|
42
|
+
attemptId,
|
|
43
|
+
attemptSecret: newCredential('attempt'),
|
|
44
|
+
participantCredential,
|
|
45
|
+
...identity
|
|
46
|
+
});
|
|
47
|
+
return { roomId: body.roomId, participantId: body.participantId, participantCredential, role: body.role, room: body.room };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Asks whether this server issued an invite whose digest starts with `probe`
|
|
51
|
+
* (see `inviteProbe`), without sending the code. Never throws: a device looking
|
|
52
|
+
* for the right relay asks several, and most will not be it.
|
|
53
|
+
*/
|
|
54
|
+
async probeInvite(probe, timeoutMs = 1500) {
|
|
55
|
+
let response;
|
|
56
|
+
try {
|
|
57
|
+
response = await fetch(`${this.serverUrl}/v1/invites/probe?prefix=${encodeURIComponent(probe)}`, { headers: { [PROTOCOL_VERSION_HEADER]: String(PROTOCOL_VERSION) }, redirect: 'error', signal: AbortSignal.timeout(timeoutMs) });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return 'unreachable';
|
|
61
|
+
}
|
|
62
|
+
if (response.status === 404) {
|
|
63
|
+
return 'unsupported';
|
|
64
|
+
}
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
return 'unreachable';
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return (await response.json()).known === true ? 'known' : 'unknown';
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return 'unreachable';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Older servers and hosted relays do not answer this, which means they have nothing extra to share. */
|
|
76
|
+
async serverInfo() {
|
|
77
|
+
try {
|
|
78
|
+
const info = await this.call('GET', '/v1/server', null);
|
|
79
|
+
return { shareUrls: Array.isArray(info.shareUrls) ? info.shareUrls.filter((url) => typeof url === 'string') : [], reported: true, discoverable: info.discoverable === true };
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof ProtocolError && error.code === 'invalid_request') {
|
|
83
|
+
return { shareUrls: [], reported: false, discoverable: false };
|
|
84
|
+
}
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** Joins a room this client's account is allowed into; needs the account token and a server with account login. */
|
|
89
|
+
async joinWithAccount(roomId, identity, attempt) {
|
|
90
|
+
const attemptId = attempt?.attemptId ?? newId('attempt');
|
|
91
|
+
const participantCredential = attempt?.participantCredential ?? newCredential('participant');
|
|
92
|
+
const body = await this.call('POST', `/v1/rooms/${roomId}/account-join`, null, {
|
|
93
|
+
attemptId,
|
|
94
|
+
attemptSecret: newCredential('attempt'),
|
|
95
|
+
participantCredential,
|
|
96
|
+
...identity
|
|
97
|
+
});
|
|
98
|
+
return { roomId: body.roomId, participantId: body.participantId, participantCredential, role: body.role, room: body.room };
|
|
99
|
+
}
|
|
100
|
+
snapshot(roomId, credential) {
|
|
101
|
+
return this.call('GET', `/v1/rooms/${roomId}`, credential);
|
|
102
|
+
}
|
|
103
|
+
mintInvite(roomId, credential, role = 'member', reusable = true, expiresAt, defaultName) {
|
|
104
|
+
return this.call('POST', `/v1/rooms/${roomId}/invites`, credential, { role, reusable, ...(expiresAt !== undefined ? { expiresAt } : {}), ...(defaultName !== undefined ? { defaultName } : {}) });
|
|
105
|
+
}
|
|
106
|
+
setLocked(roomId, credential, locked) {
|
|
107
|
+
return this.call('POST', `/v1/rooms/${roomId}/lock`, credential, { locked });
|
|
108
|
+
}
|
|
109
|
+
setMuted(roomId, credential, participantId, muted) {
|
|
110
|
+
return this.call('POST', `/v1/rooms/${roomId}/participants/${participantId}/mute`, credential, { muted });
|
|
111
|
+
}
|
|
112
|
+
setRole(roomId, credential, participantId, role) {
|
|
113
|
+
return this.call('POST', `/v1/rooms/${roomId}/participants/${participantId}/role`, credential, { role });
|
|
114
|
+
}
|
|
115
|
+
accountRestrictions(roomId, credential) {
|
|
116
|
+
return this.call('GET', `/v1/rooms/${roomId}/allowed-accounts`, credential);
|
|
117
|
+
}
|
|
118
|
+
setAccountRestrictions(roomId, credential, privateRoom, emails) {
|
|
119
|
+
return this.call('PUT', `/v1/rooms/${roomId}/allowed-accounts`, credential, { private: privateRoom, ...(emails ? { accounts: emails } : {}) });
|
|
120
|
+
}
|
|
121
|
+
setAllowedAccounts(roomId, credential, accounts) {
|
|
122
|
+
return this.call('PUT', `/v1/rooms/${roomId}/allowed-accounts`, credential, { private: true, accounts });
|
|
123
|
+
}
|
|
124
|
+
readEvents(roomId, credential, after, limit = 200) {
|
|
125
|
+
if (this.liveRoom === roomId && this.socket?.readyState === WebSocket.OPEN) {
|
|
126
|
+
const events = this.liveEvents.filter((event) => event.seq > after).slice(0, limit);
|
|
127
|
+
if (events[0]?.seq === after + 1 || after === this.watermark) {
|
|
128
|
+
return Promise.resolve({ events, earliestSeq: this.earliestSeq, latestSeq: this.watermark, hasMore: (events.at(-1)?.seq ?? after) < this.watermark });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return this.call('GET', `/v1/rooms/${roomId}/events?after=${after}&limit=${limit}`, credential);
|
|
132
|
+
}
|
|
133
|
+
requests(roomId, credential, after = 0, limit = 100, recipientId) {
|
|
134
|
+
return this.call('GET', `/v1/rooms/${roomId}/requests?turns=1&after=${after}&limit=${limit}${recipientId ? `&to=${encodeURIComponent(recipientId)}` : ''}`, credential);
|
|
135
|
+
}
|
|
136
|
+
turnQueue(roomId, credential) {
|
|
137
|
+
return this.call('GET', `/v1/rooms/${roomId}/turns`, credential);
|
|
138
|
+
}
|
|
139
|
+
setTurnMode(roomId, credential, mode) {
|
|
140
|
+
return this.call('POST', `/v1/rooms/${roomId}/turns/mode`, credential, { mode });
|
|
141
|
+
}
|
|
142
|
+
controlTurn(roomId, credential, action) {
|
|
143
|
+
return this.call('POST', `/v1/rooms/${roomId}/turns`, credential, action);
|
|
144
|
+
}
|
|
145
|
+
claimTurn(roomId, credential, requestId, claimId) {
|
|
146
|
+
return this.call('POST', `/v1/rooms/${roomId}/requests/${requestId}/claim`, credential, { claimId });
|
|
147
|
+
}
|
|
148
|
+
renewTurn(roomId, credential, requestId, token) {
|
|
149
|
+
return this.call('POST', `/v1/rooms/${roomId}/requests/${requestId}/renew`, credential, { token });
|
|
150
|
+
}
|
|
151
|
+
async declareWorking(roomId, credential, requestId, token) {
|
|
152
|
+
await this.call('POST', `/v1/rooms/${roomId}/requests/${requestId}/working`, credential, { token });
|
|
153
|
+
}
|
|
154
|
+
async passTurn(roomId, credential, requestId, token) {
|
|
155
|
+
await this.call('POST', `/v1/rooms/${roomId}/requests/${requestId}/pass`, credential, { token });
|
|
156
|
+
}
|
|
157
|
+
async pendingRequests(roomId, credential, recipientId) {
|
|
158
|
+
const requests = [];
|
|
159
|
+
let after = 0;
|
|
160
|
+
for (let pageNumber = 0; pageNumber < 11; pageNumber++) {
|
|
161
|
+
const page = await this.requests(roomId, credential, after, 100, recipientId);
|
|
162
|
+
requests.push(...page.requests);
|
|
163
|
+
if (!page.hasMore) {
|
|
164
|
+
return requests;
|
|
165
|
+
}
|
|
166
|
+
const next = page.requests.at(-1)?.seq;
|
|
167
|
+
if (next === undefined || next <= after) {
|
|
168
|
+
throw new ProtocolError('server_unavailable', 'request pagination did not advance');
|
|
169
|
+
}
|
|
170
|
+
after = next;
|
|
171
|
+
}
|
|
172
|
+
throw new ProtocolError('server_unavailable', 'pending request limit exceeded; inbox cannot be verified');
|
|
173
|
+
}
|
|
174
|
+
request(roomId, credential, eventId) {
|
|
175
|
+
return this.call('GET', `/v1/rooms/${roomId}/requests/${eventId}`, credential);
|
|
176
|
+
}
|
|
177
|
+
async acknowledgeMessage(roomId, credential, eventId) {
|
|
178
|
+
await this.call('POST', `/v1/rooms/${roomId}/requests/${eventId}/ack`, credential, {});
|
|
179
|
+
}
|
|
180
|
+
async reportMessageStatus(roomId, credential, eventId, action, options = {}) {
|
|
181
|
+
if (!(await this.snapshot(roomId, credential)).messageStagesSupported) {
|
|
182
|
+
throw new ProtocolError('unsupported_capability', 'Update this relay before declaring Read or message action stages.');
|
|
183
|
+
}
|
|
184
|
+
await this.send(roomId, credential, { type: 'message.received', payload: { eventId, ...(action !== 'reply_pending' ? { stage: 'read' } : {}), ...(action !== 'read' ? { action } : {}), ...(options.reason ? { reason: options.reason } : {}), ...(options.responseEventId ? { responseEventId: options.responseEventId } : {}) }, idempotencyKey: action === 'done' && options.responseEventId ? `link-${eventId}-${options.responseEventId}` : newId('event'), ...(options.turnToken ? { turnToken: options.turnToken } : {}) });
|
|
185
|
+
}
|
|
186
|
+
async deliveryFailed(roomId, credential, eventId, reason, turnToken, stage) {
|
|
187
|
+
const request = await this.request(roomId, credential, eventId);
|
|
188
|
+
if (request.failureAt || request.responseEventId) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
await this.send(roomId, credential, { type: 'message.delivery_failed', payload: { eventId: request.eventId, reason, ...(stage ? { stage } : {}) }, idempotencyKey: `failure-${request.eventId}`, ...(turnToken ? { turnToken } : {}) });
|
|
192
|
+
}
|
|
193
|
+
async reply(roomId, credential, eventId, text, progress = false, turnToken) {
|
|
194
|
+
const target = await this.request(roomId, credential, eventId);
|
|
195
|
+
if (target.receivedAt === null) {
|
|
196
|
+
await this.acknowledgeMessage(roomId, credential, eventId);
|
|
197
|
+
}
|
|
198
|
+
return this.send(roomId, credential, {
|
|
199
|
+
type: 'message',
|
|
200
|
+
recipientId: target.from,
|
|
201
|
+
replyTo: target.eventId,
|
|
202
|
+
...(turnToken ? { turnToken } : {}),
|
|
203
|
+
payload: { text, priority: 'normal', responseStage: progress ? 'progress' : 'final' },
|
|
204
|
+
idempotencyKey: progress ? newId('event') : `reply-${target.eventId}`
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
send(roomId, credential, request) {
|
|
208
|
+
return this.call('POST', `/v1/rooms/${roomId}/events`, credential, request);
|
|
209
|
+
}
|
|
210
|
+
control(roomId, credential, targetParticipantId, paused) {
|
|
211
|
+
return this.call('POST', `/v1/rooms/${roomId}/control`, credential, { targetParticipantId, paused });
|
|
212
|
+
}
|
|
213
|
+
/** Stops one agent's running turn and holds its queued work until resume. Owner or admin only. */
|
|
214
|
+
interrupt(roomId, credential, targetParticipantId) {
|
|
215
|
+
return this.call('POST', `/v1/rooms/${roomId}/control`, credential, { targetParticipantId, paused: true, interrupt: true });
|
|
216
|
+
}
|
|
217
|
+
revoke(roomId, credential, participantId) {
|
|
218
|
+
return this.call('DELETE', `/v1/rooms/${roomId}/participants/${participantId}`, credential);
|
|
219
|
+
}
|
|
220
|
+
leave(roomId, credential) {
|
|
221
|
+
return this.call('POST', `/v1/rooms/${roomId}/leave`, credential, {});
|
|
222
|
+
}
|
|
223
|
+
rejoin(roomId, credential) {
|
|
224
|
+
return this.call('POST', `/v1/rooms/${roomId}/rejoin`, credential, {});
|
|
225
|
+
}
|
|
226
|
+
renameSelf(roomId, credential, name, source = 'room') {
|
|
227
|
+
return this.call('POST', `/v1/rooms/${roomId}/self/name`, credential, { name, source });
|
|
228
|
+
}
|
|
229
|
+
rename(roomId, credential, name) {
|
|
230
|
+
return this.call('POST', `/v1/rooms/${roomId}/name`, credential, { name });
|
|
231
|
+
}
|
|
232
|
+
setAutoClose(roomId, credential, autoClose) {
|
|
233
|
+
return this.call('POST', `/v1/rooms/${roomId}/auto-close`, credential, { autoClose });
|
|
234
|
+
}
|
|
235
|
+
setInviteRole(roomId, credential, inviteRole) {
|
|
236
|
+
return this.call('POST', `/v1/rooms/${roomId}/invite-role`, credential, { inviteRole });
|
|
237
|
+
}
|
|
238
|
+
setJoinPolicy(roomId, credential, joinPolicy) {
|
|
239
|
+
return this.call('POST', `/v1/rooms/${roomId}/access`, credential, { joinPolicy });
|
|
240
|
+
}
|
|
241
|
+
/** Enters an open room as a read-only guest. No invite code, no credential to present. */
|
|
242
|
+
async joinAsGuest(roomId, identity) {
|
|
243
|
+
const participantCredential = newCredential('participant');
|
|
244
|
+
const body = await this.call('POST', `/v1/rooms/${roomId}/guests`, null, {
|
|
245
|
+
participantCredential,
|
|
246
|
+
...identity
|
|
247
|
+
});
|
|
248
|
+
return { roomId: body.roomId, participantId: body.participantId, participantCredential, role: body.role, room: body.room };
|
|
249
|
+
}
|
|
250
|
+
/** Joins a room open to the relay's local network, as a member. The relay checks where the request comes from. */
|
|
251
|
+
async joinOnLocalNetwork(roomId, identity) {
|
|
252
|
+
const participantCredential = newCredential('participant');
|
|
253
|
+
const body = await this.call('POST', `/v1/rooms/${roomId}/local-join`, null, {
|
|
254
|
+
participantCredential,
|
|
255
|
+
...identity
|
|
256
|
+
});
|
|
257
|
+
return { roomId: body.roomId, participantId: body.participantId, participantCredential, role: body.role, room: body.room };
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Rooms on this relay that its local network may join by name. Null when the relay
|
|
261
|
+
* cannot be reached, predates local joins, or does not count this device as local.
|
|
262
|
+
* Never throws: a device looking for a room asks several relays.
|
|
263
|
+
*/
|
|
264
|
+
async localRooms(name, timeoutMs = 1500) {
|
|
265
|
+
try {
|
|
266
|
+
// Without a name the relay lists them all; one that predates listing answers 400, hence null.
|
|
267
|
+
const response = await fetch(`${this.serverUrl}/v1/rooms/local${name === undefined ? '' : `?name=${encodeURIComponent(name)}`}`, { headers: { [PROTOCOL_VERSION_HEADER]: String(PROTOCOL_VERSION) }, redirect: 'error', signal: AbortSignal.timeout(timeoutMs) });
|
|
268
|
+
if (!response.ok) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
const body = (await response.json());
|
|
272
|
+
return Array.isArray(body.rooms) ? body.rooms : null;
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Invites an account to a hosted room by its handle. The room credential must be
|
|
280
|
+
* the owner's or an admin's, and this client needs the inviter's account token:
|
|
281
|
+
* the person invited is told who asked.
|
|
282
|
+
*/
|
|
283
|
+
async inviteAccount(roomId, credential, handle, role = 'member') {
|
|
284
|
+
return (await this.call('POST', `/v1/rooms/${roomId}/invitations`, credential, { handle, role })).invitation;
|
|
285
|
+
}
|
|
286
|
+
/** A hosted room's unanswered and accepted invitations, newest first. */
|
|
287
|
+
async roomInvitations(roomId, credential) {
|
|
288
|
+
return (await this.call('GET', `/v1/rooms/${roomId}/invitations`, credential)).invitations;
|
|
289
|
+
}
|
|
290
|
+
/** Withdraws an invitation nobody has answered yet. */
|
|
291
|
+
async revokeInvitation(roomId, credential, invitationId) {
|
|
292
|
+
await this.call('DELETE', `/v1/rooms/${roomId}/invitations/${invitationId}`, credential);
|
|
293
|
+
}
|
|
294
|
+
setLocalJoin(roomId, credential, localJoin) {
|
|
295
|
+
return this.call('POST', `/v1/rooms/${roomId}/local-access`, credential, { localJoin });
|
|
296
|
+
}
|
|
297
|
+
setExpiry(roomId, credential, expiresAt) {
|
|
298
|
+
return this.call('POST', `/v1/rooms/${roomId}/expiry`, credential, { expiresAt });
|
|
299
|
+
}
|
|
300
|
+
close(roomId, credential) {
|
|
301
|
+
return this.call('POST', `/v1/rooms/${roomId}/close`, credential, {});
|
|
302
|
+
}
|
|
303
|
+
export(roomId, credential) {
|
|
304
|
+
return this.call('GET', `/v1/rooms/${roomId}/export`, credential);
|
|
305
|
+
}
|
|
306
|
+
async delete(roomId, credential) {
|
|
307
|
+
await this.call('DELETE', `/v1/rooms/${roomId}`, credential);
|
|
308
|
+
}
|
|
309
|
+
/** Hosted reads sleep on socket notifications; local relays retain polling. */
|
|
310
|
+
async waitForChange(roomId, credential, after, timeoutMs, localIntervalMs = 1000) {
|
|
311
|
+
if (!new URL(this.serverUrl).pathname.startsWith('/relay/')) {
|
|
312
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(timeoutMs, localIntervalMs)));
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (this.liveRoom !== roomId) {
|
|
316
|
+
this.closeLive();
|
|
317
|
+
}
|
|
318
|
+
if (!this.socket) {
|
|
319
|
+
const { ticket } = await this.call('POST', `/v1/rooms/${roomId}/connect-ticket`, credential, {});
|
|
320
|
+
const url = new URL(`${this.serverUrl}/v1/rooms/${roomId}/connect`);
|
|
321
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
322
|
+
url.searchParams.set('ticket', ticket);
|
|
323
|
+
const socket = new WebSocket(url);
|
|
324
|
+
this.socket = socket;
|
|
325
|
+
this.liveRoom = roomId;
|
|
326
|
+
this.watermark = after;
|
|
327
|
+
socket.addEventListener('message', (event) => {
|
|
328
|
+
let raw;
|
|
329
|
+
try {
|
|
330
|
+
raw = JSON.parse(String(event.data));
|
|
331
|
+
const frame = ServerFrame.parse(raw);
|
|
332
|
+
if (frame.type === 'hello') {
|
|
333
|
+
this.watermark = Math.max(this.watermark, frame.watermarkSeq);
|
|
334
|
+
this.earliestSeq = frame.snapshot.earliestSeq;
|
|
335
|
+
}
|
|
336
|
+
if (frame.type === 'event') {
|
|
337
|
+
this.watermark = Math.max(this.watermark, frame.event.seq);
|
|
338
|
+
this.liveEvents.push(frame.event);
|
|
339
|
+
this.liveBytes += new TextEncoder().encode(JSON.stringify(frame.event)).byteLength;
|
|
340
|
+
while (this.liveEvents.length > 500 || this.liveBytes > 1024 * 1024)
|
|
341
|
+
this.liveBytes -= new TextEncoder().encode(JSON.stringify(this.liveEvents.shift())).byteLength;
|
|
342
|
+
}
|
|
343
|
+
if (frame.type === 'error' && frame.fatal) {
|
|
344
|
+
socket.close();
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
for (const wake of this.changed)
|
|
348
|
+
wake();
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// An event kind from a newer relay is not a broken connection: skip it,
|
|
352
|
+
// and the gap it leaves makes the next read fetch it over HTTP instead.
|
|
353
|
+
if (isEventFrame(raw)) {
|
|
354
|
+
for (const wake of this.changed)
|
|
355
|
+
wake();
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
socket.close();
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
const closed = () => {
|
|
362
|
+
if (this.socket === socket) {
|
|
363
|
+
this.socket = null;
|
|
364
|
+
}
|
|
365
|
+
for (const wake of this.changed)
|
|
366
|
+
wake();
|
|
367
|
+
};
|
|
368
|
+
socket.addEventListener('close', closed);
|
|
369
|
+
socket.addEventListener('error', closed);
|
|
370
|
+
}
|
|
371
|
+
if (this.watermark > after) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
await new Promise((resolve, reject) => {
|
|
375
|
+
const finish = () => {
|
|
376
|
+
if (this.watermark <= after && this.socket) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
clearTimeout(timer);
|
|
380
|
+
this.changed.delete(finish);
|
|
381
|
+
if (!this.socket) {
|
|
382
|
+
reject(new ProtocolError('server_unavailable', 'Live connection closed; reconnect to resume'));
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
resolve();
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
const timer = setTimeout(() => {
|
|
389
|
+
this.changed.delete(finish);
|
|
390
|
+
resolve();
|
|
391
|
+
}, timeoutMs);
|
|
392
|
+
this.changed.add(finish);
|
|
393
|
+
finish();
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
closeLive() {
|
|
397
|
+
const socket = this.socket;
|
|
398
|
+
this.socket = null;
|
|
399
|
+
this.liveRoom = null;
|
|
400
|
+
this.watermark = 0;
|
|
401
|
+
this.liveEvents = [];
|
|
402
|
+
this.liveBytes = 0;
|
|
403
|
+
socket?.close();
|
|
404
|
+
for (const wake of this.changed)
|
|
405
|
+
wake();
|
|
406
|
+
}
|
|
407
|
+
async call(method, path, credential, body) {
|
|
408
|
+
const headers = new Headers({ [PROTOCOL_VERSION_HEADER]: String(PROTOCOL_VERSION) });
|
|
409
|
+
if (credential) {
|
|
410
|
+
headers.set('authorization', `Bearer ${credential}`);
|
|
411
|
+
}
|
|
412
|
+
if (this.accountToken && method === 'POST' && (path === '/v1/rooms' || path === '/v1/invites/redeem' || path.endsWith('/account-join') || path.endsWith('/invitations'))) {
|
|
413
|
+
headers.set('x-pairlobby-account-token', this.accountToken);
|
|
414
|
+
}
|
|
415
|
+
if (body !== undefined) {
|
|
416
|
+
headers.set('content-type', 'application/json');
|
|
417
|
+
}
|
|
418
|
+
let response;
|
|
419
|
+
try {
|
|
420
|
+
response = await fetch(`${this.serverUrl}${path}`, {
|
|
421
|
+
method,
|
|
422
|
+
headers,
|
|
423
|
+
redirect: 'error',
|
|
424
|
+
signal: this.signal ? AbortSignal.any([this.signal, AbortSignal.timeout(path.endsWith('/export') ? 60_000 : 15_000)]) : AbortSignal.timeout(path.endsWith('/export') ? 60_000 : 15_000),
|
|
425
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) })
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
throw new ProtocolError('server_unavailable', `could not reach ${this.serverUrl}`, { retryAfterMs: 1000 });
|
|
430
|
+
}
|
|
431
|
+
if (response.status === 204) {
|
|
432
|
+
return undefined;
|
|
433
|
+
}
|
|
434
|
+
const text = await response.text();
|
|
435
|
+
if (!response.ok) {
|
|
436
|
+
throw toProtocolError(response.status, text);
|
|
437
|
+
}
|
|
438
|
+
return JSON.parse(text);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function toProtocolError(status, text) {
|
|
442
|
+
try {
|
|
443
|
+
const parsed = JSON.parse(text);
|
|
444
|
+
if (parsed.error?.code) {
|
|
445
|
+
const { code, message, ...details } = parsed.error;
|
|
446
|
+
return new ProtocolError(code, message ?? 'the server refused this request', details);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
catch {
|
|
450
|
+
// Fall through to a generic error rather than surfacing a parse failure.
|
|
451
|
+
}
|
|
452
|
+
return new ProtocolError(status >= 500 ? 'server_unavailable' : 'invalid_request', `the server returned ${status}`);
|
|
453
|
+
}
|
|
454
|
+
function isEventFrame(value) {
|
|
455
|
+
const frame = value;
|
|
456
|
+
return typeof frame === 'object' && frame !== null && frame.type === 'event' && typeof frame.event?.seq === 'number';
|
|
457
|
+
}
|
|
458
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
type RoomResolution = {
|
|
2
|
+
room: RoomEntry;
|
|
3
|
+
} | {
|
|
4
|
+
ambiguous: RoomEntry[];
|
|
5
|
+
} | {
|
|
6
|
+
missing: true;
|
|
7
|
+
};
|
|
8
|
+
export interface SessionEntry {
|
|
9
|
+
participantId: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
displayName: string;
|
|
12
|
+
nameSource?: 'profile' | 'room';
|
|
13
|
+
kind: 'agent' | 'human';
|
|
14
|
+
/** The runtime that created this session, when it identified itself. A claim, never a verified fact. */
|
|
15
|
+
runtime?: string;
|
|
16
|
+
/** Human session which created this managed agent locally. */
|
|
17
|
+
spawnedBy?: string;
|
|
18
|
+
/** Configured values; not a claim about the model actually used by the provider. */
|
|
19
|
+
model?: string;
|
|
20
|
+
effort?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The runtime's own conversation id, so a human can leave the room and go
|
|
23
|
+
* instruct this agent directly. Read from the environment or passed in; the
|
|
24
|
+
* relay never sees it.
|
|
25
|
+
*/
|
|
26
|
+
conversationId?: string;
|
|
27
|
+
/** Terminal session the agent is running in, to help find its pane. */
|
|
28
|
+
terminal?: string;
|
|
29
|
+
/** Process that invoked the CLI. */
|
|
30
|
+
pid?: number;
|
|
31
|
+
role: 'guest' | 'member' | 'controller';
|
|
32
|
+
joinedAt: number;
|
|
33
|
+
lastReadSeq: number;
|
|
34
|
+
/** Where the session was working, to tell two agents in one checkout apart when listing. */
|
|
35
|
+
cwd: string;
|
|
36
|
+
}
|
|
37
|
+
export interface RoomEntry {
|
|
38
|
+
roomId: string;
|
|
39
|
+
name: string;
|
|
40
|
+
serverUrl: string;
|
|
41
|
+
createdAt: number;
|
|
42
|
+
/** Null for a room that does not expire. */
|
|
43
|
+
expiresAt: number | null;
|
|
44
|
+
/** True when this device holds the controller credential for the room. */
|
|
45
|
+
controls: boolean;
|
|
46
|
+
sessions: SessionEntry[];
|
|
47
|
+
/** Chosen by a human chat, never inferred from a matching display name. */
|
|
48
|
+
preferredHumanSessionId?: string;
|
|
49
|
+
}
|
|
50
|
+
/** Defaults for this device, so a human does not retype their identity on every join. */
|
|
51
|
+
export interface Profile {
|
|
52
|
+
displayName?: string;
|
|
53
|
+
kind?: 'agent' | 'human';
|
|
54
|
+
runtime?: string;
|
|
55
|
+
server?: string;
|
|
56
|
+
}
|
|
57
|
+
/** Behavioural preferences for this device. Distinct from the profile, which is identity. */
|
|
58
|
+
export interface Settings {
|
|
59
|
+
/** Ask before deleting a room. */
|
|
60
|
+
confirmDelete: boolean;
|
|
61
|
+
/** How often the live room asks for new events, in milliseconds. */
|
|
62
|
+
pollIntervalMs: number;
|
|
63
|
+
/** Print participant and room ids next to names in the live room. */
|
|
64
|
+
showIds: boolean;
|
|
65
|
+
/** How long a new room lives, in milliseconds, or null for no expiry. */
|
|
66
|
+
defaultRoomLifetimeMs: number | null;
|
|
67
|
+
/** How long a new invite code stays redeemable, or null for no expiry. */
|
|
68
|
+
defaultInviteLifetimeMs: number | null;
|
|
69
|
+
/** Check GitHub for a newer PairLobby release, at most once a day. */
|
|
70
|
+
updateCheck: boolean;
|
|
71
|
+
/** Install a newer release in the background instead of only offering it. */
|
|
72
|
+
autoUpdate: boolean;
|
|
73
|
+
/** Reply mode for rooms this device creates. */
|
|
74
|
+
defaultTurnMode: 'sequential' | 'parallel';
|
|
75
|
+
/** What a plain `/invite` admits in rooms this device creates. */
|
|
76
|
+
defaultInviteRole: 'member' | 'guest';
|
|
77
|
+
/** Whether local rooms this device creates let anyone with the room id read as a guest. */
|
|
78
|
+
defaultGuestAccess: 'invite_only' | 'open_to_guests';
|
|
79
|
+
/** Whether online rooms this device creates are restricted to allowed accounts. */
|
|
80
|
+
defaultPrivateOnline: boolean;
|
|
81
|
+
/** Auto-close for rooms this device creates: off, idle:<duration>, age:<duration> or agents-and-guests-left. */
|
|
82
|
+
defaultAutoClose: string;
|
|
83
|
+
/** Which other devices this device's relay (`pairlobby serve`) accepts: none, Tailscale peers, or the local network. */
|
|
84
|
+
relayNetwork: 'off' | 'tailscale' | 'lan';
|
|
85
|
+
/** Show rooms open to the local network or tailnet in the room list, which searches the network on each refresh. */
|
|
86
|
+
networkRooms: boolean;
|
|
87
|
+
}
|
|
88
|
+
export declare const DEFAULT_SETTINGS: Settings;
|
|
89
|
+
export declare function dataDirectory(): string;
|
|
90
|
+
export declare class LocalStore {
|
|
91
|
+
readonly directory: string;
|
|
92
|
+
constructor(directory?: string);
|
|
93
|
+
private get roomsFile();
|
|
94
|
+
private get credentialsFile();
|
|
95
|
+
private get profileFile();
|
|
96
|
+
profile(): Profile;
|
|
97
|
+
setProfile(profile: Profile): Profile;
|
|
98
|
+
clearProfile(): void;
|
|
99
|
+
private get settingsFile();
|
|
100
|
+
settings(): Settings;
|
|
101
|
+
setSettings(update: Partial<Settings>): Settings;
|
|
102
|
+
resetSettings(): Settings;
|
|
103
|
+
rooms(): RoomEntry[];
|
|
104
|
+
room(roomId: string): RoomEntry | undefined;
|
|
105
|
+
/** Resolves a room by id, exact name, or unique name prefix. Ambiguity is reported, never guessed. */
|
|
106
|
+
resolveRoom(reference: string): RoomResolution;
|
|
107
|
+
/** The only room when there is exactly one open room on this device. */
|
|
108
|
+
soleRoom(now?: number): RoomEntry | null;
|
|
109
|
+
upsertRoom(entry: RoomEntry): void;
|
|
110
|
+
rememberHumanSession(roomId: string, sessionId: string): void;
|
|
111
|
+
updateSessionName(roomId: string, sessionId: string, displayName: string, nameSource?: 'profile' | 'room'): void;
|
|
112
|
+
addSession(roomId: string, session: SessionEntry): void;
|
|
113
|
+
/** Attaches or corrects the runtime conversation id for a session already in the registry. */
|
|
114
|
+
setConversation(roomId: string, sessionId: string, conversationId: string): boolean;
|
|
115
|
+
updateCursor(roomId: string, sessionId: string, lastReadSeq: number): void;
|
|
116
|
+
forgetRoom(roomId: string): void;
|
|
117
|
+
putCredential(roomId: string, scope: string, credential: string): void;
|
|
118
|
+
/** Admission codes are private local data, not public registry metadata. */
|
|
119
|
+
putSessionInvite(roomId: string, sessionId: string, code: string): void;
|
|
120
|
+
sessionInvite(roomId: string, sessionId: string): string | undefined;
|
|
121
|
+
credential(roomId: string, scope: string): string | undefined;
|
|
122
|
+
private credentials;
|
|
123
|
+
}
|
|
124
|
+
export {};
|
|
125
|
+
//# sourceMappingURL=local-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-store.d.ts","sourceRoot":"","sources":["../src/local-store.ts"],"names":[],"mappings":"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"}
|