@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,128 @@
1
+ // `pr.notifications`: history, one-shot waits and the listen() iterator.
2
+ import { PingRoomError } from '../errors.js';
3
+ import { sleep } from '../internal/async.js';
4
+ import { requireNonEmpty } from '../internal/guards.js';
5
+ import { isTransientError, transientDelayMs } from '../internal/retry.js';
6
+ import { isRecord } from '../internal/validate.js';
7
+ import { enc, dropUndefined, MIN_LISTEN_POLL_INTERVAL_MS, waitTimeoutMs } from '../internal/request.js';
8
+ /**
9
+ * A 2xx that is not a wait answer (a captive portal's HTML, a proxy's error
10
+ * page served as 200) must not end `listen()` with a bare TypeError, nor
11
+ * advance its cursor.
12
+ */
13
+ function validateListenResult(value, requireCursor) {
14
+ if (!isRecord(value)
15
+ || !Array.isArray(value['notifications'])
16
+ || value['notifications'].some((notification) => !isRecord(notification))
17
+ || (value['cursor'] === undefined ? requireCursor : typeof value['cursor'] !== 'string')) {
18
+ throw new PingRoomError('PingRoom returned an invalid notifications wait response.', {
19
+ code: 'invalid_response',
20
+ });
21
+ }
22
+ return value;
23
+ }
24
+ export class NotificationsApi {
25
+ http;
26
+ constructor(http) {
27
+ this.http = http;
28
+ }
29
+ /** Paginated list (polling fallback). Prefer wait()/listen() for real-time. */
30
+ async list(input = {}) {
31
+ const { notifications_per_page, ...query } = input;
32
+ const page = await this.http.request('GET', '/api/agent/notifications', {
33
+ query: dropUndefined({ ...query, limit: input.limit ?? notifications_per_page }),
34
+ });
35
+ return {
36
+ ...page,
37
+ data: page.data.map(({ room, ...notification }) => ({
38
+ ...notification,
39
+ ...(room ? { room: { ...room, code: room.invite_code } } : {}),
40
+ })),
41
+ };
42
+ }
43
+ /** Fetch one visible notification, including its current acknowledgement state. */
44
+ getNotification(notificationId) {
45
+ requireNonEmpty(notificationId, 'notificationId');
46
+ return this.http.request('GET', `/api/agent/notifications/${enc(notificationId)}`);
47
+ }
48
+ /**
49
+ * One bounded long-poll for an ack-required ping. The returned state may
50
+ * still be `open` when the hold timeout elapses; call again to keep waiting.
51
+ */
52
+ waitForAcknowledgement(notificationId, input = {}) {
53
+ requireNonEmpty(notificationId, 'notificationId');
54
+ return this.http.request('GET', `/api/agent/notifications/${enc(notificationId)}/ack/wait`, {
55
+ query: dropUndefined({ timeout: input.timeout }),
56
+ timeoutMs: waitTimeoutMs(input.timeout),
57
+ ...(input.signal ? { signal: input.signal } : {}),
58
+ });
59
+ }
60
+ /** One long-poll: resolves as soon as new pings land, or with an empty list at timeout. */
61
+ wait(input = {}) {
62
+ return this.http.request('GET', '/api/agent/notifications/wait', {
63
+ query: dropUndefined({ after: input.after, timeout: input.timeout, limit: input.limit }),
64
+ timeoutMs: waitTimeoutMs(input.timeout),
65
+ ...(input.signal ? { signal: input.signal } : {}),
66
+ });
67
+ }
68
+ /**
69
+ * Continuous real-time inbound: an async iterator that long-polls in a loop,
70
+ * advancing the cursor, yielding each new ping. Stops when `signal` aborts.
71
+ *
72
+ * for await (const ping of pr.notifications.listen({ signal })) { ... }
73
+ */
74
+ async *listen(input = {}) {
75
+ let cursor = input.after;
76
+ let headRead = cursor !== undefined;
77
+ const backoffMs = input.backoffMs ?? 1000;
78
+ let failures = 0;
79
+ while (!input.signal?.aborted) {
80
+ let result;
81
+ // The head read is an immediate answer by design; only polls ahead of
82
+ // the cursor are spaced.
83
+ const polledForward = headRead;
84
+ const pollStartedAt = Date.now();
85
+ try {
86
+ // The head read exists to obtain a cursor, so it must carry one.
87
+ result = validateListenResult(headRead
88
+ ? await this.wait({
89
+ after: cursor,
90
+ ...(input.timeout !== undefined ? { timeout: input.timeout } : {}),
91
+ ...(input.limit !== undefined ? { limit: input.limit } : {}),
92
+ ...(input.signal ? { signal: input.signal } : {}),
93
+ })
94
+ // No cursor yet: read the current head (an immediate, empty answer)
95
+ // so only pings that land after this call are delivered.
96
+ : await this.wait({ timeout: 0, ...(input.signal ? { signal: input.signal } : {}) }), !headRead);
97
+ }
98
+ catch (err) {
99
+ if (input.signal?.aborted) {
100
+ return;
101
+ }
102
+ // A revoked credential or a bad request never heals; only network
103
+ // failures, deadlines, 429 and 5xx are retried.
104
+ if (!isTransientError(err)) {
105
+ throw err;
106
+ }
107
+ failures += 1;
108
+ input.onError?.(err);
109
+ await sleep(Math.max(transientDelayMs(err, failures, backoffMs), MIN_LISTEN_POLL_INTERVAL_MS - (Date.now() - pollStartedAt)), input.signal);
110
+ continue;
111
+ }
112
+ failures = 0;
113
+ headRead = true;
114
+ cursor = result.cursor ?? cursor;
115
+ for (const n of result.notifications) {
116
+ yield n;
117
+ }
118
+ // Yield between polls so timer-driven cancellation can run (see
119
+ // ApprovalsApi). After an empty answer also keep polls a floor apart, so
120
+ // `timeout: 0` or an early-answering proxy cannot spin the loop.
121
+ const spacingMs = polledForward && result.notifications.length === 0
122
+ ? Math.max(0, MIN_LISTEN_POLL_INTERVAL_MS - (Date.now() - pollStartedAt))
123
+ : 0;
124
+ await sleep(spacingMs, input.signal);
125
+ }
126
+ }
127
+ }
128
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../src/namespaces/notifications.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAanD,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAExG;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,KAAc,EAAE,aAAsB;IAClE,IACE,CAAC,QAAQ,CAAC,KAAK,CAAC;WACb,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;WACtC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;WACtE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,EACxF,CAAC;QACD,MAAM,IAAI,aAAa,CAAC,2DAA2D,EAAE;YACnF,IAAI,EAAE,kBAAkB;SACzB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAA8B,CAAC;AACxC,CAAC;AAED,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,+EAA+E;IAC/E,KAAK,CAAC,IAAI,CAAC,QAAgC,EAAE;QAC3C,MAAM,EAAE,sBAAsB,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;QACnD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAgC,KAAK,EAAE,0BAA0B,EAAE;YACrG,KAAK,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,sBAAsB,EAAE,CAAC;SACjF,CAAC,CAAC;QACH,OAAO;YACL,GAAG,IAAI;YACP,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;gBAClD,GAAG,YAAY;gBACf,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/D,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED,mFAAmF;IACnF,eAAe,CAAC,cAAsB;QACpC,eAAe,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,4BAA4B,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IAED;;;OAGG;IACH,sBAAsB,CACpB,cAAsB,EACtB,QAAqC,EAAE;QAEvC,eAAe,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,4BAA4B,GAAG,CAAC,cAAc,CAAC,WAAW,EAAE;YAC1F,KAAK,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;YAChD,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,CAAC,CAAC;IACL,CAAC;IAED,2FAA2F;IAC3F,IAAI,CAAC,QAAmB,EAAE;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,+BAA+B,EAAE;YAC/D,KAAK,EAAE,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YACxF,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,CAAC,MAAM,CAAC,QAAqB,EAAE;QACnC,IAAI,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QACzB,IAAI,QAAQ,GAAG,MAAM,KAAK,SAAS,CAAC;QACpC,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC;QAC1C,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC9B,IAAI,MAAkB,CAAC;YACvB,sEAAsE;YACtE,yBAAyB;YACzB,MAAM,aAAa,GAAG,QAAQ,CAAC;YAC/B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,iEAAiE;gBACjE,MAAM,GAAG,oBAAoB,CAAC,QAAQ;oBACpC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC;wBAChB,KAAK,EAAE,MAAM;wBACb,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAClE,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC5D,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAClD,CAAC;oBACF,oEAAoE;oBACpE,yDAAyD;oBACzD,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;YACrG,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;oBAC1B,OAAO;gBACT,CAAC;gBACD,kEAAkE;gBAClE,gDAAgD;gBAChD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3B,MAAM,GAAG,CAAC;gBACZ,CAAC;gBACD,QAAQ,IAAI,CAAC,CAAC;gBACd,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;gBACrB,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAClB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,EAC1C,2BAA2B,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,CAC3D,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBACjB,SAAS;YACX,CAAC;YACD,QAAQ,GAAG,CAAC,CAAC;YACb,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC;YACjC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACrC,MAAM,CAAC,CAAC;YACV,CAAC;YACD,gEAAgE;YAChE,yEAAyE;YACzE,iEAAiE;YACjE,MAAM,SAAS,GAAG,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC;gBAClE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,2BAA2B,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,CAAC;gBACzE,CAAC,CAAC,CAAC,CAAC;YACN,MAAM,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { RotateHandleResult } from '../types.js';
3
+ export declare class ProfileApi {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ /**
7
+ * Set this agent's own avatar (from the bot avatar set) — the robot face
8
+ * its pings and Questions wear. Never touches the bound human's profile
9
+ * picture. Returns `{ ok, avatar_id, avatar_url }`.
10
+ */
11
+ setAvatar(avatarId: string): Promise<{
12
+ ok: boolean;
13
+ avatar_id: string;
14
+ avatar_url: string;
15
+ }>;
16
+ /** Rotate the agent's handle — the kill-switch for a leaked handle. */
17
+ rotateHandle(): Promise<RotateHandleResult>;
18
+ }
19
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/namespaces/profile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAK5F,uEAAuE;IACvE,YAAY,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAG5C"}
@@ -0,0 +1,22 @@
1
+ // `pr.profile`: this agent's own avatar and handle.
2
+ import { requireNonEmpty } from '../internal/guards.js';
3
+ export class ProfileApi {
4
+ http;
5
+ constructor(http) {
6
+ this.http = http;
7
+ }
8
+ /**
9
+ * Set this agent's own avatar (from the bot avatar set) — the robot face
10
+ * its pings and Questions wear. Never touches the bound human's profile
11
+ * picture. Returns `{ ok, avatar_id, avatar_url }`.
12
+ */
13
+ setAvatar(avatarId) {
14
+ requireNonEmpty(avatarId, 'avatarId');
15
+ return this.http.request('POST', '/api/agent/profile/avatar', { body: { avatar_id: avatarId } });
16
+ }
17
+ /** Rotate the agent's handle — the kill-switch for a leaked handle. */
18
+ rotateHandle() {
19
+ return this.http.request('POST', '/api/agent/profile/handle/rotate', { body: {} });
20
+ }
21
+ }
22
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/namespaces/profile.ts"],"names":[],"mappings":"AAAA,oDAAoD;AAGpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,OAAO,UAAU;IACQ;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD;;;;OAIG;IACH,SAAS,CAAC,QAAgB;QACxB,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,2BAA2B,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IACnG,CAAC;IAED,uEAAuE;IACvE,YAAY;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,kCAAkC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;CACF"}
@@ -0,0 +1,41 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { ListQuestionsInput, Question, QuestionInput, WaitForOutcomeOptions, WaitQuestionInput } from '../types.js';
3
+ /**
4
+ * The general human-in-the-loop primitive: ask a human a question with 2–4
5
+ * options (or a short typed answer) and block until they tap an answer. An
6
+ * {@link ApprovalsApi | approval} is the two-option case; reach for questions
7
+ * when you need more choices, a typed reply, or room-scope answering.
8
+ */
9
+ export declare class QuestionsApi {
10
+ private readonly http;
11
+ constructor(http: HttpClient);
12
+ /**
13
+ * Ask a Question in a room; returns the pending Question (id + computed
14
+ * expiry). Pass `resolution_policy: 'all'` to poll the room: everyone asked
15
+ * votes once, and `results` carries the tally on every read.
16
+ */
17
+ ask(inviteCode: string, input: QuestionInput): Promise<Question>;
18
+ /** Fetch a Question's current state. */
19
+ get(questionId: string): Promise<Question>;
20
+ /** One long-poll for the answer; returns the (possibly still-pending) Question. */
21
+ wait(questionId: string, input?: WaitQuestionInput): Promise<Question>;
22
+ /**
23
+ * Block until the human answers (or the question expires/cancels), looping
24
+ * wait() under the hood. Returns the resolved Question — inspect `state` and
25
+ * `answer.value` to branch. A poll returns once it closes; its `answer` is the
26
+ * leading option, or `null` on a tie, and `results` holds the tally.
27
+ *
28
+ * Polls start at least 2.1 s apart. A response that is not this Question in a
29
+ * known state rejects with `invalid_response`. Network failures, 429 and 5xx
30
+ * are retried with backoff (honouring `retryAfter`), and reported to
31
+ * `onRetry`, until `signal` aborts or the outage outlasts the Question's
32
+ * `expires_at` by 5 minutes (15 minutes of failures while no `expires_at` has
33
+ * been read); that rejects with `unavailable`. See {@link WaitForOutcomeOptions}.
34
+ */
35
+ waitForAnswer(questionId: string, input?: WaitForOutcomeOptions): Promise<Question>;
36
+ /** List the asker's Questions, optionally filtered by state. */
37
+ list(input?: ListQuestionsInput): Promise<Question[]>;
38
+ /** Withdraw a still-pending Question (409 if it already resolved). */
39
+ cancel(questionId: string): Promise<Question>;
40
+ }
41
+ //# sourceMappingURL=questions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"questions.d.ts","sourceRoot":"","sources":["../../src/namespaces/questions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,OAAO,KAAK,EACV,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAqBrB;;;;;GAKG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;OAIG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWhE,wCAAwC;IACxC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI1C,mFAAmF;IACnF,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,iBAAsB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQ1E;;;;;;;;;;;;OAYG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,qBAA0B,GAAG,OAAO,CAAC,QAAQ,CAAC;IAe7F,gEAAgE;IAC1D,IAAI,CAAC,KAAK,GAAE,kBAAuB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAO/D,sEAAsE;IACtE,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAG9C"}
@@ -0,0 +1,107 @@
1
+ // `pr.questions`: Questions and polls in a room.
2
+ import { PingRoomError } from '../errors.js';
3
+ import { assertStructuredData, requireNonEmpty } from '../internal/guards.js';
4
+ import { pollUntilSettled } from '../internal/retry.js';
5
+ import { MIN_WAIT_POLL_INTERVAL_MS, enc, splitIdempotencyKey, assertOnRetry, dropUndefined, waitTimeoutMs, } from '../internal/request.js';
6
+ import { isRecord, sameId, invalidWaitResponse } from '../internal/validate.js';
7
+ const QUESTION_STATES = new Set(['pending', 'answered', 'expired', 'cancelled']);
8
+ function validateQuestionWait(value, questionId) {
9
+ const state = isRecord(value) ? value['state'] : undefined;
10
+ if (!isRecord(value) || !sameId(value['id'], questionId) || typeof state !== 'string' || !QUESTION_STATES.has(state)) {
11
+ return invalidWaitResponse('question', questionId, value, 'state');
12
+ }
13
+ return value;
14
+ }
15
+ /**
16
+ * The general human-in-the-loop primitive: ask a human a question with 2–4
17
+ * options (or a short typed answer) and block until they tap an answer. An
18
+ * {@link ApprovalsApi | approval} is the two-option case; reach for questions
19
+ * when you need more choices, a typed reply, or room-scope answering.
20
+ */
21
+ export class QuestionsApi {
22
+ http;
23
+ constructor(http) {
24
+ this.http = http;
25
+ }
26
+ /**
27
+ * Ask a Question in a room; returns the pending Question (id + computed
28
+ * expiry). Pass `resolution_policy: 'all'` to poll the room: everyone asked
29
+ * votes once, and `results` carries the tally on every read.
30
+ */
31
+ ask(inviteCode, input) {
32
+ requireNonEmpty(input.prompt, 'prompt');
33
+ assertStructuredData(input.data);
34
+ assertPollShape(input);
35
+ const { body, headers } = splitIdempotencyKey(input);
36
+ return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/questions`, {
37
+ body: dropUndefined(body),
38
+ ...(headers ? { headers } : {}),
39
+ });
40
+ }
41
+ /** Fetch a Question's current state. */
42
+ get(questionId) {
43
+ return this.http.request('GET', `/api/agent/questions/${enc(questionId)}`);
44
+ }
45
+ /** One long-poll for the answer; returns the (possibly still-pending) Question. */
46
+ wait(questionId, input = {}) {
47
+ return this.http.request('GET', `/api/agent/questions/${enc(questionId)}/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 answers (or the question expires/cancels), looping
55
+ * wait() under the hood. Returns the resolved Question — inspect `state` and
56
+ * `answer.value` to branch. A poll returns once it closes; its `answer` is the
57
+ * leading option, or `null` on a tie, and `results` holds the tally.
58
+ *
59
+ * Polls start at least 2.1 s apart. A response that is not this Question in a
60
+ * known state rejects with `invalid_response`. Network failures, 429 and 5xx
61
+ * are retried with backoff (honouring `retryAfter`), and reported to
62
+ * `onRetry`, until `signal` aborts or the outage outlasts the Question's
63
+ * `expires_at` by 5 minutes (15 minutes of failures while no `expires_at` has
64
+ * been read); that rejects with `unavailable`. See {@link WaitForOutcomeOptions}.
65
+ */
66
+ async waitForAnswer(questionId, input = {}) {
67
+ requireNonEmpty(questionId, 'questionId');
68
+ assertOnRetry(input.onRetry);
69
+ return pollUntilSettled({
70
+ poll: () => this.wait(questionId, input.signal ? { signal: input.signal } : {}),
71
+ validate: (value) => validateQuestionWait(value, questionId),
72
+ settled: (question) => question.state !== 'pending',
73
+ expiresAt: (question) => question.expires_at,
74
+ what: `question ${questionId}`,
75
+ minIntervalMs: MIN_WAIT_POLL_INTERVAL_MS,
76
+ ...(input.signal ? { signal: input.signal } : {}),
77
+ ...(input.onRetry ? { onRetry: input.onRetry } : {}),
78
+ });
79
+ }
80
+ /** List the asker's Questions, optionally filtered by state. */
81
+ async list(input = {}) {
82
+ const res = await this.http.request('GET', '/api/agent/questions', {
83
+ query: dropUndefined({ state: input.state }),
84
+ });
85
+ return res.questions ?? [];
86
+ }
87
+ /** Withdraw a still-pending Question (409 if it already resolved). */
88
+ cancel(questionId) {
89
+ return this.http.request('POST', `/api/agent/questions/${enc(questionId)}/cancel`, { body: {} });
90
+ }
91
+ }
92
+ /**
93
+ * A poll asks the whole room and counts option votes, so the server refuses it
94
+ * (422 on `resolution_policy`) alongside a direct scope, a named target, or a
95
+ * typed answer. Fail before the request instead.
96
+ */
97
+ function assertPollShape(input) {
98
+ if (input.resolution_policy !== 'all')
99
+ return;
100
+ const target = input.target_user_id;
101
+ if (input.responder_scope === 'direct'
102
+ || (target !== undefined && target !== null && target !== '')
103
+ || (input.text_input !== undefined && input.text_input !== null)) {
104
+ throw new PingRoomError("A poll (`resolution_policy: 'all'`) asks the whole room with options only; it cannot use `responder_scope: 'direct'`, `target_user_id`, or `text_input`.", { code: 'invalid_request' });
105
+ }
106
+ }
107
+ //# sourceMappingURL=questions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"questions.js","sourceRoot":"","sources":["../../src/namespaces/questions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { CreatePublicRoomInput, CreateRoomInput, JoinRoomInput, Room, RoomIconCatalog } from '../types.js';
3
+ export declare class RoomsApi {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ icons(): Promise<RoomIconCatalog>;
7
+ list(): Promise<Room[]>;
8
+ get(inviteCode: string): Promise<Room>;
9
+ create(input: CreateRoomInput): Promise<Room>;
10
+ createPublic(input: CreatePublicRoomInput): Promise<Room>;
11
+ join(input: JoinRoomInput): Promise<Room>;
12
+ }
13
+ //# sourceMappingURL=rooms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rooms.d.ts","sourceRoot":"","sources":["../../src/namespaces/rooms.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EACV,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,IAAI,EACJ,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IAIjC,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAIvB,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItC,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7C,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAczD,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAI1C"}
@@ -0,0 +1,41 @@
1
+ // `pr.rooms`: list, read, create and join rooms.
2
+ import { PingRoomError } from '../errors.js';
3
+ import { requireNonEmpty } from '../internal/guards.js';
4
+ import { enc, dropUndefined } from '../internal/request.js';
5
+ export class RoomsApi {
6
+ http;
7
+ constructor(http) {
8
+ this.http = http;
9
+ }
10
+ icons() {
11
+ return this.http.request('GET', '/api/agent/room-icons');
12
+ }
13
+ list() {
14
+ return this.http.request('GET', '/api/agent/rooms');
15
+ }
16
+ get(inviteCode) {
17
+ return this.http.request('GET', `/api/agent/rooms/${enc(inviteCode)}`);
18
+ }
19
+ create(input) {
20
+ requireNonEmpty(input.name, 'name');
21
+ return this.http.request('POST', '/api/agent/rooms', { body: dropUndefined({ ...input }) });
22
+ }
23
+ createPublic(input) {
24
+ requireNonEmpty(input.name, 'name');
25
+ requireNonEmpty(input.handle, 'handle');
26
+ // The server takes the location trio all-or-nothing; a partial set is a
27
+ // 422 on a field the caller may not have meant to send at all.
28
+ const present = [input.location_name, input.location_latitude, input.location_longitude].filter((v) => v !== undefined).length;
29
+ if (present !== 0 && present !== 3) {
30
+ throw new PingRoomError('Send `location_name`, `location_latitude` and `location_longitude` together, or none of them.', {
31
+ code: 'invalid_request',
32
+ });
33
+ }
34
+ return this.http.request('POST', '/api/agent/rooms/public', { body: dropUndefined({ ...input }) });
35
+ }
36
+ join(input) {
37
+ requireNonEmpty(input.invite_code, 'invite_code');
38
+ return this.http.request('POST', '/api/agent/rooms/join', { body: dropUndefined({ ...input }) });
39
+ }
40
+ }
41
+ //# sourceMappingURL=rooms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rooms.js","sourceRoot":"","sources":["../../src/namespaces/rooms.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQxD,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,OAAO,QAAQ;IACU;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,KAAK;QACH,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IACtD,CAAC;IAED,GAAG,CAAC,UAAkB;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,CAAC,KAAsB;QAC3B,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,YAAY,CAAC,KAA4B;QACvC,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxC,wEAAwE;QACxE,+DAA+D;QAC/D,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAC/H,IAAI,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,aAAa,CAAC,+FAA+F,EAAE;gBACvH,IAAI,EAAE,iBAAiB;aACxB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,yBAAyB,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,IAAI,CAAC,KAAoB;QACvB,eAAe,CAAC,KAAK,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,uBAAuB,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACnG,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { CreateWebhookInput, UpdateWebhookInput, Webhook } from '../types.js';
3
+ export declare class WebhooksApi {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ list(inviteCode: string): Promise<Webhook[]>;
7
+ create(inviteCode: string, input: CreateWebhookInput): Promise<Webhook>;
8
+ update(inviteCode: string, webhookId: string, input: UpdateWebhookInput): Promise<Webhook>;
9
+ delete(inviteCode: string, webhookId: string): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/namespaces/webhooks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGnF,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEvC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAOlD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQvE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQpF,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAInE"}
@@ -0,0 +1,32 @@
1
+ // `pr.webhooks`: a room's incoming webhooks.
2
+ import { assertActionNumber, requireNonEmpty } from '../internal/guards.js';
3
+ import { enc, dropUndefined } from '../internal/request.js';
4
+ export class WebhooksApi {
5
+ http;
6
+ constructor(http) {
7
+ this.http = http;
8
+ }
9
+ async list(inviteCode) {
10
+ const result = await this.http.request('GET', `/api/agent/rooms/${enc(inviteCode)}/webhooks`);
11
+ return result.webhooks;
12
+ }
13
+ create(inviteCode, input) {
14
+ requireNonEmpty(input.name, 'name');
15
+ assertActionNumber(input.action_number);
16
+ return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/webhooks`, {
17
+ body: dropUndefined({ ...input }),
18
+ });
19
+ }
20
+ update(inviteCode, webhookId, input) {
21
+ requireNonEmpty(webhookId, 'webhookId');
22
+ assertActionNumber(input.action_number);
23
+ return this.http.request('PUT', `/api/agent/rooms/${enc(inviteCode)}/webhooks/${enc(webhookId)}`, {
24
+ body: dropUndefined({ ...input }),
25
+ });
26
+ }
27
+ async delete(inviteCode, webhookId) {
28
+ requireNonEmpty(webhookId, 'webhookId');
29
+ await this.http.request('DELETE', `/api/agent/rooms/${enc(inviteCode)}/webhooks/${enc(webhookId)}`);
30
+ }
31
+ }
32
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/namespaces/webhooks.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAG7C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE5E,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,OAAO,WAAW;IACO;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,KAAK,CAAC,IAAI,CAAC,UAAkB;QAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CACpC,KAAK,EAAE,oBAAoB,GAAG,CAAC,UAAU,CAAC,WAAW,CACtD,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,KAAyB;QAClD,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,kBAAkB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,oBAAoB,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE;YAC/E,IAAI,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,SAAiB,EAAE,KAAyB;QACrE,eAAe,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACxC,kBAAkB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,CAAC,UAAU,CAAC,aAAa,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE;YAChG,IAAI,EAAE,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAAkB,EAAE,SAAiB;QAChD,eAAe,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACxC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,oBAAoB,GAAG,CAAC,UAAU,CAAC,aAAa,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACtG,CAAC;CACF"}
@@ -0,0 +1,62 @@
1
+ import type { PingRoomError } from '../errors.js';
2
+ import type { JsonObject } from './common.js';
3
+ export interface ApprovalInput {
4
+ question: string;
5
+ title?: string;
6
+ options?: string[];
7
+ correlation_id?: string;
8
+ data?: JsonObject;
9
+ ttl?: number;
10
+ /**
11
+ * Sent as the `Idempotency-Key` header (1–255 printable ASCII characters,
12
+ * spaces allowed), never in the body.
13
+ * Reuse the same key when retrying after a timeout or network error: the
14
+ * server replays the first result instead of asking the human a second time.
15
+ */
16
+ idempotencyKey?: string;
17
+ }
18
+ export interface Approval {
19
+ id: string;
20
+ /**
21
+ * A human answer has status `decided`; inspect `decision` for the chosen
22
+ * option. `approved`/`denied` are never sent.
23
+ */
24
+ status: 'pending' | 'decided' | 'expired' | 'cancelled' | (string & {});
25
+ question: string;
26
+ title: string | null;
27
+ options: string[];
28
+ decision: string | null;
29
+ decided_at: string | null;
30
+ expires_at: string | null;
31
+ correlation_id: string | null;
32
+ data: JsonObject | null;
33
+ /** Null when the approval's room no longer exists. */
34
+ room_code: string | null;
35
+ [key: string]: unknown;
36
+ }
37
+ export interface WaitApprovalInput {
38
+ /** Seconds the server holds the connection (0–30, default 20). */
39
+ timeout?: number;
40
+ signal?: AbortSignal;
41
+ }
42
+ /**
43
+ * Options for the blocking waits: `approvals.waitForDecision()`,
44
+ * `questions.waitForAnswer()` and `handoffs.waitForResult()`.
45
+ *
46
+ * Network errors, request timeouts, 429 and 5xx are retried with backoff. The
47
+ * retries stop with `PingRoomError` code `unavailable` (the last failure as
48
+ * its `cause`) once only failures have come back since the last valid
49
+ * response and the last-seen `expires_at` is more than 5 minutes past, or,
50
+ * before any `expires_at` was seen, after 15 minutes of unbroken failures.
51
+ */
52
+ export interface WaitForOutcomeOptions {
53
+ /** Abort to stop waiting; the wait rejects with the signal's reason. */
54
+ signal?: AbortSignal;
55
+ /**
56
+ * Called before each retry of a transient failure, with that failure and
57
+ * the number of consecutive failures so far (1 on the first). Throwing from
58
+ * it ends the wait with the thrown error.
59
+ */
60
+ onRetry?: (error: PingRoomError, attempt: number) => void;
61
+ }
62
+ //# sourceMappingURL=approvals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/types/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC,wEAAwE;IACxE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=approvals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/types/approvals.ts"],"names":[],"mappings":""}