@pingroom/sdk 0.7.1 → 0.9.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.
Files changed (191) hide show
  1. package/README.md +288 -44
  2. package/dist/client.d.ts +27 -312
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +33 -1154
  5. package/dist/client.js.map +1 -1
  6. package/dist/errors.d.ts +40 -6
  7. package/dist/errors.d.ts.map +1 -1
  8. package/dist/errors.js +56 -4
  9. package/dist/errors.js.map +1 -1
  10. package/dist/http.d.ts +12 -1
  11. package/dist/http.d.ts.map +1 -1
  12. package/dist/http.js +47 -18
  13. package/dist/http.js.map +1 -1
  14. package/dist/index.d.ts +3 -5
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/internal/async.d.ts +2 -0
  19. package/dist/internal/async.d.ts.map +1 -1
  20. package/dist/internal/async.js +6 -0
  21. package/dist/internal/async.js.map +1 -1
  22. package/dist/internal/guards.d.ts +16 -0
  23. package/dist/internal/guards.d.ts.map +1 -1
  24. package/dist/internal/guards.js +22 -1
  25. package/dist/internal/guards.js.map +1 -1
  26. package/dist/internal/request.d.ts +41 -0
  27. package/dist/internal/request.d.ts.map +1 -0
  28. package/dist/internal/request.js +78 -0
  29. package/dist/internal/request.js.map +1 -0
  30. package/dist/internal/retry.d.ts +65 -0
  31. package/dist/internal/retry.d.ts.map +1 -0
  32. package/dist/internal/retry.js +126 -0
  33. package/dist/internal/retry.js.map +1 -0
  34. package/dist/internal/url.d.ts +9 -0
  35. package/dist/internal/url.d.ts.map +1 -1
  36. package/dist/internal/url.js +25 -0
  37. package/dist/internal/url.js.map +1 -1
  38. package/dist/internal/validate.d.ts +13 -0
  39. package/dist/internal/validate.d.ts.map +1 -0
  40. package/dist/internal/validate.js +36 -0
  41. package/dist/internal/validate.js.map +1 -0
  42. package/dist/linkPing.d.ts.map +1 -1
  43. package/dist/linkPing.js +6 -2
  44. package/dist/linkPing.js.map +1 -1
  45. package/dist/liveStatus.d.ts +106 -11
  46. package/dist/liveStatus.d.ts.map +1 -1
  47. package/dist/liveStatus.js +20 -3
  48. package/dist/liveStatus.js.map +1 -1
  49. package/dist/mcp.d.ts.map +1 -1
  50. package/dist/mcp.js +40 -10
  51. package/dist/mcp.js.map +1 -1
  52. package/dist/namespaces/actions.d.ts +50 -0
  53. package/dist/namespaces/actions.d.ts.map +1 -0
  54. package/dist/namespaces/actions.js +219 -0
  55. package/dist/namespaces/actions.js.map +1 -0
  56. package/dist/namespaces/approvals.d.ts +23 -0
  57. package/dist/namespaces/approvals.d.ts.map +1 -0
  58. package/dist/namespaces/approvals.js +78 -0
  59. package/dist/namespaces/approvals.js.map +1 -0
  60. package/dist/namespaces/attachments.d.ts +37 -0
  61. package/dist/namespaces/attachments.d.ts.map +1 -0
  62. package/dist/namespaces/attachments.js +91 -0
  63. package/dist/namespaces/attachments.js.map +1 -0
  64. package/dist/namespaces/auth.d.ts +58 -0
  65. package/dist/namespaces/auth.d.ts.map +1 -0
  66. package/dist/namespaces/auth.js +242 -0
  67. package/dist/namespaces/auth.js.map +1 -0
  68. package/dist/namespaces/directory.d.ts +10 -0
  69. package/dist/namespaces/directory.d.ts.map +1 -0
  70. package/dist/namespaces/directory.js +19 -0
  71. package/dist/namespaces/directory.js.map +1 -0
  72. package/dist/namespaces/handoffs.d.ts +47 -0
  73. package/dist/namespaces/handoffs.d.ts.map +1 -0
  74. package/dist/namespaces/handoffs.js +126 -0
  75. package/dist/namespaces/handoffs.js.map +1 -0
  76. package/dist/namespaces/inbox.d.ts +17 -0
  77. package/dist/namespaces/inbox.d.ts.map +1 -0
  78. package/dist/namespaces/inbox.js +192 -0
  79. package/dist/namespaces/inbox.js.map +1 -0
  80. package/dist/namespaces/live.d.ts +57 -0
  81. package/dist/namespaces/live.d.ts.map +1 -0
  82. package/dist/namespaces/live.js +116 -0
  83. package/dist/namespaces/live.js.map +1 -0
  84. package/dist/namespaces/notifications.d.ts +25 -0
  85. package/dist/namespaces/notifications.d.ts.map +1 -0
  86. package/dist/namespaces/notifications.js +128 -0
  87. package/dist/namespaces/notifications.js.map +1 -0
  88. package/dist/namespaces/profile.d.ts +19 -0
  89. package/dist/namespaces/profile.d.ts.map +1 -0
  90. package/dist/namespaces/profile.js +22 -0
  91. package/dist/namespaces/profile.js.map +1 -0
  92. package/dist/namespaces/questions.d.ts +41 -0
  93. package/dist/namespaces/questions.d.ts.map +1 -0
  94. package/dist/namespaces/questions.js +107 -0
  95. package/dist/namespaces/questions.js.map +1 -0
  96. package/dist/namespaces/rooms.d.ts +13 -0
  97. package/dist/namespaces/rooms.d.ts.map +1 -0
  98. package/dist/namespaces/rooms.js +41 -0
  99. package/dist/namespaces/rooms.js.map +1 -0
  100. package/dist/namespaces/webhooks.d.ts +11 -0
  101. package/dist/namespaces/webhooks.d.ts.map +1 -0
  102. package/dist/namespaces/webhooks.js +32 -0
  103. package/dist/namespaces/webhooks.js.map +1 -0
  104. package/dist/types/approvals.d.ts +62 -0
  105. package/dist/types/approvals.d.ts.map +1 -0
  106. package/dist/types/approvals.js +2 -0
  107. package/dist/types/approvals.js.map +1 -0
  108. package/dist/types/auth.d.ts +185 -0
  109. package/dist/types/auth.d.ts.map +1 -0
  110. package/dist/types/auth.js +2 -0
  111. package/dist/types/auth.js.map +1 -0
  112. package/dist/types/common.d.ts +43 -0
  113. package/dist/types/common.d.ts.map +1 -0
  114. package/dist/types/common.js +2 -0
  115. package/dist/types/common.js.map +1 -0
  116. package/dist/types/handoffs.d.ts +121 -0
  117. package/dist/types/handoffs.d.ts.map +1 -0
  118. package/dist/types/handoffs.js +2 -0
  119. package/dist/types/handoffs.js.map +1 -0
  120. package/dist/types/inbox.d.ts +51 -0
  121. package/dist/types/inbox.d.ts.map +1 -0
  122. package/dist/types/inbox.js +2 -0
  123. package/dist/types/inbox.js.map +1 -0
  124. package/dist/types/notifications.d.ts +376 -0
  125. package/dist/types/notifications.d.ts.map +1 -0
  126. package/dist/types/notifications.js +2 -0
  127. package/dist/types/notifications.js.map +1 -0
  128. package/dist/types/profile.d.ts +30 -0
  129. package/dist/types/profile.d.ts.map +1 -0
  130. package/dist/types/profile.js +3 -0
  131. package/dist/types/profile.js.map +1 -0
  132. package/dist/types/questions.d.ts +210 -0
  133. package/dist/types/questions.d.ts.map +1 -0
  134. package/dist/types/questions.js +2 -0
  135. package/dist/types/questions.js.map +1 -0
  136. package/dist/types/rooms.d.ts +163 -0
  137. package/dist/types/rooms.d.ts.map +1 -0
  138. package/dist/types/rooms.js +3 -0
  139. package/dist/types/rooms.js.map +1 -0
  140. package/dist/types.d.ts +9 -1035
  141. package/dist/types.d.ts.map +1 -1
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/dist/webhooks.d.ts +32 -5
  145. package/dist/webhooks.d.ts.map +1 -1
  146. package/dist/webhooks.js +44 -14
  147. package/dist/webhooks.js.map +1 -1
  148. package/package.json +4 -2
  149. package/src/client.ts +115 -0
  150. package/src/errors.ts +291 -0
  151. package/src/http.ts +225 -0
  152. package/src/index.ts +97 -0
  153. package/src/internal/async.ts +54 -0
  154. package/src/internal/guards.ts +129 -0
  155. package/src/internal/request.ts +97 -0
  156. package/src/internal/retry.ts +157 -0
  157. package/src/internal/url.ts +78 -0
  158. package/src/internal/validate.ts +42 -0
  159. package/src/linkPing.ts +56 -0
  160. package/src/liveStatus.ts +337 -0
  161. package/src/locationPing.ts +101 -0
  162. package/src/mcp.ts +161 -0
  163. package/src/namespaces/actions.ts +234 -0
  164. package/src/namespaces/approvals.ts +104 -0
  165. package/src/namespaces/attachments.ts +106 -0
  166. package/src/namespaces/auth.ts +284 -0
  167. package/src/namespaces/directory.ts +21 -0
  168. package/src/namespaces/handoffs.ts +160 -0
  169. package/src/namespaces/inbox.ts +253 -0
  170. package/src/namespaces/live.ts +134 -0
  171. package/src/namespaces/notifications.ts +152 -0
  172. package/src/namespaces/profile.ts +24 -0
  173. package/src/namespaces/questions.ts +133 -0
  174. package/src/namespaces/rooms.ts +53 -0
  175. package/src/namespaces/webhooks.ts +38 -0
  176. package/src/types/approvals.ts +67 -0
  177. package/src/types/auth.ts +202 -0
  178. package/src/types/common.ts +74 -0
  179. package/src/types/handoffs.ts +148 -0
  180. package/src/types/inbox.ts +64 -0
  181. package/src/types/notifications.ts +393 -0
  182. package/src/types/profile.ts +37 -0
  183. package/src/types/questions.ts +226 -0
  184. package/src/types/rooms.ts +169 -0
  185. package/src/types.ts +17 -0
  186. package/src/version.ts +2 -0
  187. package/src/webhooks.ts +373 -0
  188. package/dist/liveActivity.d.ts +0 -101
  189. package/dist/liveActivity.d.ts.map +0 -1
  190. package/dist/liveActivity.js +0 -83
  191. package/dist/liveActivity.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { Approval, ApprovalInput, WaitApprovalInput, WaitForOutcomeOptions } from '../types.js';
3
+ export declare class ApprovalsApi {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ /** Ask the human you act for to decide; returns the pending approval. */
7
+ request(inviteCode: string, input: ApprovalInput): Promise<Approval>;
8
+ get(approvalId: string): Promise<Approval>;
9
+ /** One long-poll for the decision; returns the (possibly still-pending) approval. */
10
+ wait(approvalId: string, input?: WaitApprovalInput): Promise<Approval>;
11
+ /**
12
+ * Block until the human decides (or the request expires or is cancelled),
13
+ * looping wait() under the hood, with polls started at least 2.1 s apart. A
14
+ * response that is not this approval in a known status rejects with
15
+ * `invalid_response`. Network failures, 429 and 5xx are retried with backoff
16
+ * (honouring `retryAfter`), and reported to `onRetry`, until `signal` aborts
17
+ * or the outage outlasts the approval's `expires_at` by 5 minutes (15 minutes
18
+ * of failures while no `expires_at` has been read); that rejects with
19
+ * `unavailable`. See {@link WaitForOutcomeOptions}.
20
+ */
21
+ waitForDecision(approvalId: string, input?: WaitForOutcomeOptions): Promise<Approval>;
22
+ }
23
+ //# sourceMappingURL=approvals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/namespaces/approvals.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,aAAa,CAAC;AA0CrB,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,yEAAyE;IACzE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;IAUpE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI1C,qFAAqF;IACrF,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,iBAAsB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ1E;;;;;;;;;OASG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,qBAA0B,GAAG,OAAO,CAAC,QAAQ,CAAC;CAchG"}
@@ -0,0 +1,78 @@
1
+ // `pr.approvals`: two-option human-in-the-loop decisions.
2
+ import { assertStructuredData, requireNonEmpty } from '../internal/guards.js';
3
+ import { pollUntilSettled } from '../internal/retry.js';
4
+ import { MIN_WAIT_POLL_INTERVAL_MS, enc, splitIdempotencyKey, assertOnRetry, dropUndefined, waitTimeoutMs, } from '../internal/request.js';
5
+ import { isRecord, isNonEmptyString, isNullableString, sameId, invalidWaitResponse, } from '../internal/validate.js';
6
+ const APPROVAL_STATUSES = new Set(['pending', 'decided', 'expired', 'cancelled']);
7
+ /**
8
+ * A wait response is trusted as an outcome only when it is the approval that
9
+ * was asked about, in a known status. A captive portal's HTML, `{}`, or another
10
+ * approval must not read as "decided".
11
+ */
12
+ function validateApprovalWait(value, approvalId) {
13
+ const status = isRecord(value) ? value['status'] : undefined;
14
+ if (!isRecord(value)
15
+ || !sameId(value['id'], approvalId)
16
+ || typeof status !== 'string'
17
+ || !APPROVAL_STATUSES.has(status)
18
+ || !isNullableString(value['decided_at'])
19
+ // A gate acts on `decision`; a decided approval without one, or a pending
20
+ // one already stamped decided, is not an outcome it can act on.
21
+ || (status === 'decided' && !isNonEmptyString(value['decision']))
22
+ || (status === 'pending' && value['decided_at'] !== null)) {
23
+ return invalidWaitResponse('approval', approvalId, value, 'status');
24
+ }
25
+ return value;
26
+ }
27
+ export class ApprovalsApi {
28
+ http;
29
+ constructor(http) {
30
+ this.http = http;
31
+ }
32
+ /** Ask the human you act for to decide; returns the pending approval. */
33
+ request(inviteCode, input) {
34
+ requireNonEmpty(input.question, 'question');
35
+ assertStructuredData(input.data);
36
+ const { body, headers } = splitIdempotencyKey(input);
37
+ return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/approvals`, {
38
+ body: dropUndefined({ ...body }),
39
+ ...(headers ? { headers } : {}),
40
+ });
41
+ }
42
+ get(approvalId) {
43
+ return this.http.request('GET', `/api/agent/approvals/${enc(approvalId)}`);
44
+ }
45
+ /** One long-poll for the decision; returns the (possibly still-pending) approval. */
46
+ wait(approvalId, input = {}) {
47
+ return this.http.request('GET', `/api/agent/approvals/${enc(approvalId)}/wait`, {
48
+ query: dropUndefined({ timeout: input.timeout }),
49
+ timeoutMs: waitTimeoutMs(input.timeout),
50
+ ...(input.signal ? { signal: input.signal } : {}),
51
+ });
52
+ }
53
+ /**
54
+ * Block until the human decides (or the request expires or is cancelled),
55
+ * looping wait() under the hood, with polls started at least 2.1 s apart. A
56
+ * response that is not this approval in a known status rejects with
57
+ * `invalid_response`. Network failures, 429 and 5xx are retried with backoff
58
+ * (honouring `retryAfter`), and reported to `onRetry`, until `signal` aborts
59
+ * or the outage outlasts the approval's `expires_at` by 5 minutes (15 minutes
60
+ * of failures while no `expires_at` has been read); that rejects with
61
+ * `unavailable`. See {@link WaitForOutcomeOptions}.
62
+ */
63
+ async waitForDecision(approvalId, input = {}) {
64
+ requireNonEmpty(approvalId, 'approvalId');
65
+ assertOnRetry(input.onRetry);
66
+ return pollUntilSettled({
67
+ poll: () => this.wait(approvalId, input.signal ? { signal: input.signal } : {}),
68
+ validate: (value) => validateApprovalWait(value, approvalId),
69
+ settled: (approval) => approval.status !== 'pending',
70
+ expiresAt: (approval) => approval.expires_at,
71
+ what: `approval ${approvalId}`,
72
+ minIntervalMs: MIN_WAIT_POLL_INTERVAL_MS,
73
+ ...(input.signal ? { signal: input.signal } : {}),
74
+ ...(input.onRetry ? { onRetry: input.onRetry } : {}),
75
+ });
76
+ }
77
+ }
78
+ //# sourceMappingURL=approvals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/namespaces/approvals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { Attachment, ZipManifest, UploadAttachmentInput } from '../types.js';
3
+ /**
4
+ * Private files that a Ping or Question can carry.
5
+ *
6
+ * Upload first, then pass the returned ids to `broadcast()` / `questions.ask()`
7
+ * as `attachment_ids`. Bytes never travel inside a JSON ping body (the MCP
8
+ * `upload_attachment` tool takes only small files, about 90 KiB, as base64). An
9
+ * upload that is never attached expires on its own after 24 hours.
10
+ * Each file must be 1 byte–5 MiB with an md/pdf/html/txt/jpg/jpeg/png/zip filename;
11
+ * a Ping or Question accepts at most four ids.
12
+ *
13
+ * Uploading requires the bound account to hold Pro (the API answers 402
14
+ * `pro_required` otherwise). Reading and deleting are not gated.
15
+ */
16
+ export declare class AttachmentsApi {
17
+ private readonly http;
18
+ constructor(http: HttpClient);
19
+ /** Upload one file and get back the id a send can claim. */
20
+ upload(input: UploadAttachmentInput): Promise<Attachment>;
21
+ /**
22
+ * Raw bytes for an attachment this credential is allowed to see. Returns the
23
+ * undecoded Response so a caller can stream it, or read text/arrayBuffer.
24
+ */
25
+ content(attachmentId: string, signal?: AbortSignal): Promise<Response>;
26
+ /**
27
+ * The listing of a `.zip`'s contents, recorded when it was uploaded.
28
+ *
29
+ * Resolves null for a non-archive, and for an archive whose central
30
+ * directory did not parse. Nothing decompresses the file to produce this, so
31
+ * the declared sizes are what the archive claims, not verified output.
32
+ */
33
+ manifest(attachmentId: string, signal?: AbortSignal): Promise<ZipManifest | null>;
34
+ /** Discard an upload that has not been attached to a ping yet. */
35
+ delete(attachmentId: string): Promise<void>;
36
+ }
37
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../src/namespaces/attachments.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAYlF;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,4DAA4D;IAC5D,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBzD;;;OAGG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOtE;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAWjF,kEAAkE;IAClE,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAI5C"}
@@ -0,0 +1,91 @@
1
+ // `pr.attachments`: upload, read and discard private files.
2
+ import { PingRoomError } from '../errors.js';
3
+ import { requireNonEmpty } from '../internal/guards.js';
4
+ import { enc } from '../internal/request.js';
5
+ /** Server cap per uploaded file; a larger body is a 413 the server answers before reading it. */
6
+ const ATTACHMENT_MAX_BYTES = 5 * 1024 * 1024;
7
+ function attachmentByteLength(content) {
8
+ if (content instanceof Blob)
9
+ return content.size;
10
+ if (typeof content === 'string')
11
+ return new TextEncoder().encode(content).byteLength;
12
+ return content.byteLength;
13
+ }
14
+ /**
15
+ * Private files that a Ping or Question can carry.
16
+ *
17
+ * Upload first, then pass the returned ids to `broadcast()` / `questions.ask()`
18
+ * as `attachment_ids`. Bytes never travel inside a JSON ping body (the MCP
19
+ * `upload_attachment` tool takes only small files, about 90 KiB, as base64). An
20
+ * upload that is never attached expires on its own after 24 hours.
21
+ * Each file must be 1 byte–5 MiB with an md/pdf/html/txt/jpg/jpeg/png/zip filename;
22
+ * a Ping or Question accepts at most four ids.
23
+ *
24
+ * Uploading requires the bound account to hold Pro (the API answers 402
25
+ * `pro_required` otherwise). Reading and deleting are not gated.
26
+ */
27
+ export class AttachmentsApi {
28
+ http;
29
+ constructor(http) {
30
+ this.http = http;
31
+ }
32
+ /** Upload one file and get back the id a send can claim. */
33
+ upload(input) {
34
+ requireNonEmpty(input.filename, 'filename');
35
+ // The server answers an oversized body with 413 before reading it; refuse
36
+ // locally so no bytes travel for a file that can never be accepted.
37
+ if (attachmentByteLength(input.content) > ATTACHMENT_MAX_BYTES) {
38
+ return Promise.reject(new PingRoomError('Attachments are at most 5 MiB each.', { code: 'attachment_too_large', status: 413 }));
39
+ }
40
+ const body = new FormData();
41
+ body.append('file', toAttachmentBlob(input), input.filename);
42
+ return this.http
43
+ .request('POST', '/api/agent/attachments', {
44
+ body,
45
+ ...(input.signal ? { signal: input.signal } : {}),
46
+ })
47
+ .then((res) => res.attachment);
48
+ }
49
+ /**
50
+ * Raw bytes for an attachment this credential is allowed to see. Returns the
51
+ * undecoded Response so a caller can stream it, or read text/arrayBuffer.
52
+ */
53
+ content(attachmentId, signal) {
54
+ requireNonEmpty(attachmentId, 'attachmentId');
55
+ return this.http.raw('GET', `/api/agent/attachments/${enc(attachmentId)}/content`, {
56
+ ...(signal ? { signal } : {}),
57
+ });
58
+ }
59
+ /**
60
+ * The listing of a `.zip`'s contents, recorded when it was uploaded.
61
+ *
62
+ * Resolves null for a non-archive, and for an archive whose central
63
+ * directory did not parse. Nothing decompresses the file to produce this, so
64
+ * the declared sizes are what the archive claims, not verified output.
65
+ */
66
+ manifest(attachmentId, signal) {
67
+ requireNonEmpty(attachmentId, 'attachmentId');
68
+ return this.http
69
+ .request('GET', `/api/agent/attachments/${enc(attachmentId)}/manifest`, { ...(signal ? { signal } : {}) })
70
+ .then((res) => res.manifest ?? null);
71
+ }
72
+ /** Discard an upload that has not been attached to a ping yet. */
73
+ delete(attachmentId) {
74
+ requireNonEmpty(attachmentId, 'attachmentId');
75
+ return this.http.request('DELETE', `/api/agent/attachments/${enc(attachmentId)}`);
76
+ }
77
+ }
78
+ /** Normalise the three accepted content shapes into one multipart part. */
79
+ function toAttachmentBlob(input) {
80
+ const type = input.contentType ?? '';
81
+ if (input.content instanceof Blob) {
82
+ return type ? new Blob([input.content], { type }) : input.content;
83
+ }
84
+ // Copy into a plain ArrayBuffer: a Uint8Array view may be a window onto a
85
+ // larger (or SharedArrayBuffer-backed) buffer, which Blob would not accept.
86
+ const parts = typeof input.content === 'string'
87
+ ? [input.content]
88
+ : [new Uint8Array(input.content).slice().buffer];
89
+ return new Blob(parts, type ? { type } : undefined);
90
+ }
91
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/namespaces/attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { AgentConnectionInfo, AgentDisconnectResult, Credential, ClaimCompleteParams, ClaimStartParams, RegisterParams, PairingStart, PairingStatus, PairedCredential, StartPairingParams, WaitForPairingOptions } from '../types.js';
3
+ /** Agent credential lifecycle (auth.md flow). */
4
+ export declare class AuthApi {
5
+ private readonly http;
6
+ private pairing;
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
+ /**
18
+ * Register a pending agent and create a short-lived link that opens the
19
+ * PingRoom app. The server owns the full grant shown to the approver; this
20
+ * client sends no scope list. The pending credential stays private inside the
21
+ * client and is replaced automatically once waitForPairing() succeeds. If the
22
+ * client already held a credential, it is put back when the pairing expires
23
+ * or the wait is aborted, so a re-pairing that never completes leaves the
24
+ * client on the working credential rather than the dead pending one.
25
+ */
26
+ startPairing(params?: StartPairingParams): Promise<PairingStart>;
27
+ /** Read the current state of an app pairing using the pending credential. */
28
+ pairingStatus(options?: Pick<WaitForPairingOptions, 'signal'>): Promise<PairingStatus>;
29
+ /**
30
+ * Wait until the person approves in PingRoom, or the short-lived link
31
+ * expires. Transient network, 429, and 5xx failures are retried inside the
32
+ * server-provided lifetime. On success the client immediately starts using
33
+ * the active credential returned by the server. When the link expires or the
34
+ * wait is aborted, the credential the client held before startPairing() is
35
+ * restored; calling waitForPairing() again after an abort resumes the same
36
+ * pairing.
37
+ */
38
+ waitForPairing(pairing: PairingStart, options?: WaitForPairingOptions): Promise<PairedCredential>;
39
+ private pollPairing;
40
+ /** Rotate to a fresh credential (same scopes/handle). */
41
+ refresh(): Promise<Credential>;
42
+ /** Revoke the current credential. */
43
+ revoke(): Promise<void>;
44
+ /**
45
+ * What this credential is connected to: the robot, the owner's public id and
46
+ * name, the home room and room memberships, and the room grant. Check
47
+ * `owner.id` and `handle` against the account and robot you approved before
48
+ * sending anything.
49
+ */
50
+ connection(): Promise<AgentConnectionInfo>;
51
+ /**
52
+ * Disconnect this agent: revokes the calling credential and its refresh
53
+ * credentials. The client keeps the now-revoked token; clear it with
54
+ * `setToken(null)` or pair again.
55
+ */
56
+ disconnect(): Promise<AgentDisconnectResult>;
57
+ }
58
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/namespaces/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,aAAa,CAAC;AA2CrB,iDAAiD;AACjD,qBAAa,OAAO;IAGN,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,OAAO,CAA+B;gBAEjB,IAAI,EAAE,UAAU;IAE7C,mGAAmG;IACnG,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAKrD,iFAAiF;IACjF,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAKtF,sFAAsF;IACtF,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC;IAM/D;;;;;;;;OAQG;IACG,YAAY,CAAC,MAAM,GAAE,kBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC;IA8B1E,6EAA6E;IAC7E,aAAa,CAAC,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAI1F;;;;;;;;OAQG;IACG,cAAc,CAClB,OAAO,EAAE,YAAY,EACrB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,gBAAgB,CAAC;YAyBd,WAAW;IAwFzB,yDAAyD;IACzD,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAI9B,qCAAqC;IACrC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAI1C;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAG7C"}
@@ -0,0 +1,242 @@
1
+ // `pr.auth`: registration, claim, app pairing and the credential lifecycle.
2
+ import { PingRoomError } from '../errors.js';
3
+ import { sleep, throwIfAborted } from '../internal/async.js';
4
+ import { requireNonEmpty } from '../internal/guards.js';
5
+ import { dropUndefined } from '../internal/request.js';
6
+ import { isRecord } from '../internal/validate.js';
7
+ /** Drop a malformed or unsafe server-provided URL without rejecting its response. */
8
+ function normalizePublicHttpUrl(candidate) {
9
+ if (typeof candidate !== 'string' || candidate.trim() === '')
10
+ return undefined;
11
+ const trimmed = candidate.trim();
12
+ // eslint-disable-next-line no-control-regex
13
+ if (/[\u0000-\u001F\u007F-\u009F]/.test(trimmed))
14
+ return undefined;
15
+ try {
16
+ const url = new URL(trimmed);
17
+ if (url.protocol !== 'https:' && url.protocol !== 'http:')
18
+ return undefined;
19
+ if (url.username !== '' || url.password !== '')
20
+ return undefined;
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ return trimmed;
26
+ }
27
+ /** Drop malformed or unsafe server-provided links without rejecting a valid credential. */
28
+ function normalizePairingLinks(value) {
29
+ if (!isRecord(value))
30
+ return undefined;
31
+ const latestPings = normalizePublicHttpUrl(value['latest_pings']);
32
+ if (!latestPings)
33
+ return undefined;
34
+ const installApp = normalizePublicHttpUrl(value['install_app']);
35
+ return {
36
+ latest_pings: latestPings,
37
+ ...(installApp ? { install_app: installApp } : {}),
38
+ };
39
+ }
40
+ /** Agent credential lifecycle (auth.md flow). */
41
+ export class AuthApi {
42
+ http;
43
+ pairing = null;
44
+ constructor(http) {
45
+ this.http = http;
46
+ }
47
+ /** Register an agent. Anonymous or via an identity assertion (ID-JAG / verified email). Public. */
48
+ register(params) {
49
+ requireNonEmpty(params.type, 'type');
50
+ return this.http.request('POST', '/api/agent/auth', { auth: false, body: dropUndefined({ ...params }) });
51
+ }
52
+ /** Begin claiming a pre-claim credential onto a human account; emails an OTP. */
53
+ claimStart(params) {
54
+ requireNonEmpty(params.email, 'email');
55
+ return this.http.request('POST', '/api/agent/auth/claim/start', { body: { email: params.email } });
56
+ }
57
+ /** Complete the claim with the emailed OTP; returns an active credential + handle. */
58
+ claimComplete(params) {
59
+ requireNonEmpty(params.email, 'email');
60
+ requireNonEmpty(params.otp, 'otp');
61
+ return this.http.request('POST', '/api/agent/auth/claim/complete', { body: dropUndefined({ ...params }) });
62
+ }
63
+ /**
64
+ * Register a pending agent and create a short-lived link that opens the
65
+ * PingRoom app. The server owns the full grant shown to the approver; this
66
+ * client sends no scope list. The pending credential stays private inside the
67
+ * client and is replaced automatically once waitForPairing() succeeds. If the
68
+ * client already held a credential, it is put back when the pairing expires
69
+ * or the wait is aborted, so a re-pairing that never completes leaves the
70
+ * client on the working credential rather than the dead pending one.
71
+ */
72
+ async startPairing(params = {}) {
73
+ const previousToken = this.http.getToken();
74
+ const pending = await this.register({
75
+ type: 'anonymous',
76
+ ...(params.agent_label ? { agent_label: params.agent_label } : {}),
77
+ });
78
+ this.http.setToken(pending.credential);
79
+ try {
80
+ const started = await this.http.request('POST', '/api/agent/auth/pair/start', {
81
+ body: {},
82
+ });
83
+ // A second pairing started while the first is still pending falls back
84
+ // to the credential beneath it, not to the first pairing's pending one.
85
+ this.pairing = {
86
+ pairToken: started.pair_token,
87
+ pending: pending.credential,
88
+ previous: this.pairing !== null && this.pairing.pending === previousToken
89
+ ? this.pairing.previous
90
+ : previousToken,
91
+ };
92
+ return started;
93
+ }
94
+ catch (error) {
95
+ if (this.http.getToken() === pending.credential) {
96
+ this.http.setToken(previousToken);
97
+ }
98
+ throw error;
99
+ }
100
+ }
101
+ /** Read the current state of an app pairing using the pending credential. */
102
+ pairingStatus(options = {}) {
103
+ return this.http.request('GET', '/api/agent/auth/pair/status', { signal: options.signal });
104
+ }
105
+ /**
106
+ * Wait until the person approves in PingRoom, or the short-lived link
107
+ * expires. Transient network, 429, and 5xx failures are retried inside the
108
+ * server-provided lifetime. On success the client immediately starts using
109
+ * the active credential returned by the server. When the link expires or the
110
+ * wait is aborted, the credential the client held before startPairing() is
111
+ * restored; calling waitForPairing() again after an abort resumes the same
112
+ * pairing.
113
+ */
114
+ async waitForPairing(pairing, options = {}) {
115
+ const tracked = this.pairing !== null && this.pairing.pairToken === pairing.pair_token
116
+ ? this.pairing
117
+ : null;
118
+ if (tracked !== null && this.http.getToken() === tracked.previous) {
119
+ // Resuming after an abort put the earlier credential back.
120
+ this.http.setToken(tracked.pending);
121
+ }
122
+ try {
123
+ const paired = await this.pollPairing(pairing, options);
124
+ if (tracked !== null && this.pairing === tracked)
125
+ this.pairing = null;
126
+ return paired;
127
+ }
128
+ catch (error) {
129
+ if (tracked !== null && this.pairing === tracked) {
130
+ const expired = error instanceof PingRoomError && error.code === 'pairing_expired';
131
+ if (expired || options.signal?.aborted === true) {
132
+ if (this.http.getToken() === tracked.pending)
133
+ this.http.setToken(tracked.previous);
134
+ }
135
+ // An expired pairing cannot be resumed; an aborted one can.
136
+ if (expired)
137
+ this.pairing = null;
138
+ }
139
+ throw error;
140
+ }
141
+ }
142
+ async pollPairing(pairing, options) {
143
+ const lifetimeMs = Math.max(1, Number(pairing.expires_in) || 900) * 1000;
144
+ const requestedInterval = options.pollIntervalMs ?? pairing.poll_interval_ms;
145
+ const intervalMs = Math.min(Math.max(Number(requestedInterval) || 1500, 1000), 10_000);
146
+ const startedAt = Date.now();
147
+ const deadline = startedAt + lifetimeMs;
148
+ let transientFailures = 0;
149
+ while (Date.now() < deadline) {
150
+ throwIfAborted(options.signal);
151
+ try {
152
+ const status = await this.pairingStatus({ signal: options.signal });
153
+ throwIfAborted(options.signal);
154
+ transientFailures = 0;
155
+ if (status.status === 'active') {
156
+ if (typeof status.credential !== 'string'
157
+ || status.credential.trim() === ''
158
+ || status.credential_type !== 'active'
159
+ || (status.expires_in !== null
160
+ && (typeof status.expires_in !== 'number'
161
+ || !Number.isFinite(status.expires_in)
162
+ || status.expires_in < 0))
163
+ // A null/absent `room` is valid when the account has no eligible
164
+ // private delivery room (and on older servers). Only a room that is
165
+ // present but malformed is a broken response.
166
+ || (status.room != null
167
+ && (typeof status.room.invite_code !== 'string'
168
+ || status.room.invite_code.trim() === ''))) {
169
+ throw new PingRoomError('PingRoom returned an incomplete approved pairing.', {
170
+ code: 'pairing_invalid_response',
171
+ body: { status: status.status },
172
+ });
173
+ }
174
+ this.http.setToken(status.credential);
175
+ // Pairing is server-authoritative. Some servers still include their
176
+ // internal grant marker for protocol compatibility; it is neither a
177
+ // client input nor part of the paired credential surface.
178
+ const { status: _status, scopes: _serverScopes, links: rawLinks, ...credential } = status;
179
+ const links = normalizePairingLinks(rawLinks);
180
+ return links ? { ...credential, links } : credential;
181
+ }
182
+ if (status.status === 'expired') {
183
+ throw new PingRoomError('The PingRoom pairing link expired before it was approved.', {
184
+ code: 'pairing_expired',
185
+ });
186
+ }
187
+ }
188
+ catch (error) {
189
+ if (error instanceof PingRoomError
190
+ && [401, 403, 404].includes(error.status)
191
+ && Date.now() - startedAt >= lifetimeMs / 2) {
192
+ // The pending bearer can expire before the server returns an
193
+ // explicit expired pairing state. Keep early auth failures intact.
194
+ throw new PingRoomError('The PingRoom pairing link expired before it was approved.', {
195
+ code: 'pairing_expired',
196
+ });
197
+ }
198
+ if (error instanceof PingRoomError
199
+ && (error.code === 'network_error'
200
+ || error.code === 'timeout'
201
+ || error.status === 429
202
+ || error.status >= 500)) {
203
+ transientFailures += 1;
204
+ const backoffMs = Math.min(intervalMs * 2 ** Math.max(0, transientFailures - 3), 30_000);
205
+ await sleep(Math.max(0, Math.min(backoffMs, deadline - Date.now())), options.signal);
206
+ continue;
207
+ }
208
+ throw error;
209
+ }
210
+ await sleep(Math.max(0, Math.min(intervalMs, deadline - Date.now())), options.signal);
211
+ }
212
+ throw new PingRoomError('The PingRoom pairing link expired before it was approved.', {
213
+ code: 'pairing_expired',
214
+ });
215
+ }
216
+ /** Rotate to a fresh credential (same scopes/handle). */
217
+ refresh() {
218
+ return this.http.request('POST', '/api/agent/auth/refresh', { body: {} });
219
+ }
220
+ /** Revoke the current credential. */
221
+ revoke() {
222
+ return this.http.request('POST', '/api/agent/auth/revoke', { body: {} });
223
+ }
224
+ /**
225
+ * What this credential is connected to: the robot, the owner's public id and
226
+ * name, the home room and room memberships, and the room grant. Check
227
+ * `owner.id` and `handle` against the account and robot you approved before
228
+ * sending anything.
229
+ */
230
+ connection() {
231
+ return this.http.request('GET', '/api/agent/connection');
232
+ }
233
+ /**
234
+ * Disconnect this agent: revokes the calling credential and its refresh
235
+ * credentials. The client keeps the now-revoked token; clear it with
236
+ * `setToken(null)` or pair again.
237
+ */
238
+ disconnect() {
239
+ return this.http.request('POST', '/api/agent/disconnect', { body: {} });
240
+ }
241
+ }
242
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/namespaces/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { DirectoryEntry, DirectoryListInput, DirectoryProfile, Paginated } from '../types.js';
3
+ /** Public, unauthenticated agent directory. */
4
+ export declare class DirectoryApi {
5
+ private readonly http;
6
+ constructor(http: HttpClient);
7
+ list(input?: DirectoryListInput): Promise<Paginated<DirectoryEntry>>;
8
+ get(handle: string): Promise<DirectoryProfile>;
9
+ }
10
+ //# sourceMappingURL=directory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../../src/namespaces/directory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGnG,+CAA+C;AAC/C,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,IAAI,CAAC,KAAK,GAAE,kBAAuB,GAAG,OAAO,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAOxE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAG/C"}
@@ -0,0 +1,19 @@
1
+ // `pr.directory`: the public agent directory.
2
+ import { enc, dropUndefined } from '../internal/request.js';
3
+ /** Public, unauthenticated agent directory. */
4
+ export class DirectoryApi {
5
+ http;
6
+ constructor(http) {
7
+ this.http = http;
8
+ }
9
+ list(input = {}) {
10
+ return this.http.request('GET', '/api/agents/directory', {
11
+ auth: false,
12
+ query: dropUndefined({ ...input }),
13
+ });
14
+ }
15
+ get(handle) {
16
+ return this.http.request('GET', `/api/agents/directory/${enc(handle)}`, { auth: false });
17
+ }
18
+ }
19
+ //# sourceMappingURL=directory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory.js","sourceRoot":"","sources":["../../src/namespaces/directory.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAI9C,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,+CAA+C;AAC/C,MAAM,OAAO,YAAY;IACM;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,IAAI,CAAC,QAA4B,EAAE;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,uBAAuB,EAAE;YACvD,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;SACnC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,yBAAyB,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3F,CAAC;CACF"}