@pingroom/sdk 0.8.0 → 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 (179) hide show
  1. package/README.md +153 -41
  2. package/dist/client.d.ts +14 -348
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +15 -1300
  5. package/dist/client.js.map +1 -1
  6. package/dist/errors.d.ts +32 -3
  7. package/dist/errors.d.ts.map +1 -1
  8. package/dist/errors.js +47 -1
  9. package/dist/errors.js.map +1 -1
  10. package/dist/http.d.ts.map +1 -1
  11. package/dist/http.js +7 -1
  12. package/dist/http.js.map +1 -1
  13. package/dist/index.d.ts +3 -5
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/internal/guards.d.ts +7 -0
  18. package/dist/internal/guards.d.ts.map +1 -1
  19. package/dist/internal/guards.js +1 -1
  20. package/dist/internal/guards.js.map +1 -1
  21. package/dist/internal/request.d.ts +41 -0
  22. package/dist/internal/request.d.ts.map +1 -0
  23. package/dist/internal/request.js +78 -0
  24. package/dist/internal/request.js.map +1 -0
  25. package/dist/internal/retry.d.ts +9 -2
  26. package/dist/internal/retry.d.ts.map +1 -1
  27. package/dist/internal/retry.js +24 -6
  28. package/dist/internal/retry.js.map +1 -1
  29. package/dist/internal/validate.d.ts +13 -0
  30. package/dist/internal/validate.d.ts.map +1 -0
  31. package/dist/internal/validate.js +36 -0
  32. package/dist/internal/validate.js.map +1 -0
  33. package/dist/liveStatus.d.ts +106 -11
  34. package/dist/liveStatus.d.ts.map +1 -1
  35. package/dist/liveStatus.js +20 -3
  36. package/dist/liveStatus.js.map +1 -1
  37. package/dist/mcp.d.ts.map +1 -1
  38. package/dist/mcp.js +30 -8
  39. package/dist/mcp.js.map +1 -1
  40. package/dist/namespaces/actions.d.ts +50 -0
  41. package/dist/namespaces/actions.d.ts.map +1 -0
  42. package/dist/namespaces/actions.js +219 -0
  43. package/dist/namespaces/actions.js.map +1 -0
  44. package/dist/namespaces/approvals.d.ts +23 -0
  45. package/dist/namespaces/approvals.d.ts.map +1 -0
  46. package/dist/namespaces/approvals.js +78 -0
  47. package/dist/namespaces/approvals.js.map +1 -0
  48. package/dist/namespaces/attachments.d.ts +37 -0
  49. package/dist/namespaces/attachments.d.ts.map +1 -0
  50. package/dist/namespaces/attachments.js +91 -0
  51. package/dist/namespaces/attachments.js.map +1 -0
  52. package/dist/namespaces/auth.d.ts +58 -0
  53. package/dist/namespaces/auth.d.ts.map +1 -0
  54. package/dist/namespaces/auth.js +242 -0
  55. package/dist/namespaces/auth.js.map +1 -0
  56. package/dist/namespaces/directory.d.ts +10 -0
  57. package/dist/namespaces/directory.d.ts.map +1 -0
  58. package/dist/namespaces/directory.js +19 -0
  59. package/dist/namespaces/directory.js.map +1 -0
  60. package/dist/namespaces/handoffs.d.ts +47 -0
  61. package/dist/namespaces/handoffs.d.ts.map +1 -0
  62. package/dist/namespaces/handoffs.js +126 -0
  63. package/dist/namespaces/handoffs.js.map +1 -0
  64. package/dist/namespaces/inbox.d.ts +17 -0
  65. package/dist/namespaces/inbox.d.ts.map +1 -0
  66. package/dist/namespaces/inbox.js +192 -0
  67. package/dist/namespaces/inbox.js.map +1 -0
  68. package/dist/namespaces/live.d.ts +57 -0
  69. package/dist/namespaces/live.d.ts.map +1 -0
  70. package/dist/namespaces/live.js +116 -0
  71. package/dist/namespaces/live.js.map +1 -0
  72. package/dist/namespaces/notifications.d.ts +25 -0
  73. package/dist/namespaces/notifications.d.ts.map +1 -0
  74. package/dist/namespaces/notifications.js +128 -0
  75. package/dist/namespaces/notifications.js.map +1 -0
  76. package/dist/namespaces/profile.d.ts +19 -0
  77. package/dist/namespaces/profile.d.ts.map +1 -0
  78. package/dist/namespaces/profile.js +22 -0
  79. package/dist/namespaces/profile.js.map +1 -0
  80. package/dist/namespaces/questions.d.ts +41 -0
  81. package/dist/namespaces/questions.d.ts.map +1 -0
  82. package/dist/namespaces/questions.js +107 -0
  83. package/dist/namespaces/questions.js.map +1 -0
  84. package/dist/namespaces/rooms.d.ts +13 -0
  85. package/dist/namespaces/rooms.d.ts.map +1 -0
  86. package/dist/namespaces/rooms.js +41 -0
  87. package/dist/namespaces/rooms.js.map +1 -0
  88. package/dist/namespaces/webhooks.d.ts +11 -0
  89. package/dist/namespaces/webhooks.d.ts.map +1 -0
  90. package/dist/namespaces/webhooks.js +32 -0
  91. package/dist/namespaces/webhooks.js.map +1 -0
  92. package/dist/types/approvals.d.ts +62 -0
  93. package/dist/types/approvals.d.ts.map +1 -0
  94. package/dist/types/approvals.js +2 -0
  95. package/dist/types/approvals.js.map +1 -0
  96. package/dist/types/auth.d.ts +185 -0
  97. package/dist/types/auth.d.ts.map +1 -0
  98. package/dist/types/auth.js +2 -0
  99. package/dist/types/auth.js.map +1 -0
  100. package/dist/types/common.d.ts +43 -0
  101. package/dist/types/common.d.ts.map +1 -0
  102. package/dist/types/common.js +2 -0
  103. package/dist/types/common.js.map +1 -0
  104. package/dist/types/handoffs.d.ts +121 -0
  105. package/dist/types/handoffs.d.ts.map +1 -0
  106. package/dist/types/handoffs.js +2 -0
  107. package/dist/types/handoffs.js.map +1 -0
  108. package/dist/types/inbox.d.ts +51 -0
  109. package/dist/types/inbox.d.ts.map +1 -0
  110. package/dist/types/inbox.js +2 -0
  111. package/dist/types/inbox.js.map +1 -0
  112. package/dist/types/notifications.d.ts +376 -0
  113. package/dist/types/notifications.d.ts.map +1 -0
  114. package/dist/types/notifications.js +2 -0
  115. package/dist/types/notifications.js.map +1 -0
  116. package/dist/types/profile.d.ts +30 -0
  117. package/dist/types/profile.d.ts.map +1 -0
  118. package/dist/types/profile.js +3 -0
  119. package/dist/types/profile.js.map +1 -0
  120. package/dist/types/questions.d.ts +210 -0
  121. package/dist/types/questions.d.ts.map +1 -0
  122. package/dist/types/questions.js +2 -0
  123. package/dist/types/questions.js.map +1 -0
  124. package/dist/types/rooms.d.ts +163 -0
  125. package/dist/types/rooms.d.ts.map +1 -0
  126. package/dist/types/rooms.js +3 -0
  127. package/dist/types/rooms.js.map +1 -0
  128. package/dist/types.d.ts +9 -1199
  129. package/dist/types.d.ts.map +1 -1
  130. package/dist/version.d.ts +1 -1
  131. package/dist/version.js +1 -1
  132. package/dist/webhooks.d.ts +14 -4
  133. package/dist/webhooks.d.ts.map +1 -1
  134. package/dist/webhooks.js +30 -5
  135. package/dist/webhooks.js.map +1 -1
  136. package/package.json +4 -2
  137. package/src/client.ts +115 -0
  138. package/src/errors.ts +291 -0
  139. package/src/http.ts +225 -0
  140. package/src/index.ts +97 -0
  141. package/src/internal/async.ts +54 -0
  142. package/src/internal/guards.ts +129 -0
  143. package/src/internal/request.ts +97 -0
  144. package/src/internal/retry.ts +157 -0
  145. package/src/internal/url.ts +78 -0
  146. package/src/internal/validate.ts +42 -0
  147. package/src/linkPing.ts +56 -0
  148. package/src/liveStatus.ts +337 -0
  149. package/src/locationPing.ts +101 -0
  150. package/src/mcp.ts +161 -0
  151. package/src/namespaces/actions.ts +234 -0
  152. package/src/namespaces/approvals.ts +104 -0
  153. package/src/namespaces/attachments.ts +106 -0
  154. package/src/namespaces/auth.ts +284 -0
  155. package/src/namespaces/directory.ts +21 -0
  156. package/src/namespaces/handoffs.ts +160 -0
  157. package/src/namespaces/inbox.ts +253 -0
  158. package/src/namespaces/live.ts +134 -0
  159. package/src/namespaces/notifications.ts +152 -0
  160. package/src/namespaces/profile.ts +24 -0
  161. package/src/namespaces/questions.ts +133 -0
  162. package/src/namespaces/rooms.ts +53 -0
  163. package/src/namespaces/webhooks.ts +38 -0
  164. package/src/types/approvals.ts +67 -0
  165. package/src/types/auth.ts +202 -0
  166. package/src/types/common.ts +74 -0
  167. package/src/types/handoffs.ts +148 -0
  168. package/src/types/inbox.ts +64 -0
  169. package/src/types/notifications.ts +393 -0
  170. package/src/types/profile.ts +37 -0
  171. package/src/types/questions.ts +226 -0
  172. package/src/types/rooms.ts +169 -0
  173. package/src/types.ts +17 -0
  174. package/src/version.ts +2 -0
  175. package/src/webhooks.ts +373 -0
  176. package/dist/liveActivity.d.ts +0 -101
  177. package/dist/liveActivity.d.ts.map +0 -1
  178. package/dist/liveActivity.js +0 -83
  179. package/dist/liveActivity.js.map +0 -1
@@ -0,0 +1,192 @@
1
+ // `pr.inbox`: setting up and activating the human's Agent Inbox.
2
+ import { PingRoomActivationIncompleteError, PingRoomError } from '../errors.js';
3
+ import { combineSignals, sleep, throwIfAborted } from '../internal/async.js';
4
+ import { isTransientError, transientDelayMs } from '../internal/retry.js';
5
+ import { MIN_HANDOFF_POLL_INTERVAL_MS, enc, dropUndefined, waitTimeoutMs, } from '../internal/request.js';
6
+ import { isRecord, isNonEmptyString, isNullableString } from '../internal/validate.js';
7
+ const DEFAULT_INBOX_ACTIVATION_TIMEOUT_MS = 120_000;
8
+ function invalidInboxResponse(message, body = {}) {
9
+ throw new PingRoomError(message, { code: 'inbox_invalid_response', body });
10
+ }
11
+ function validateInboxEnsure(value) {
12
+ if (!isRecord(value) || value['onboarded'] !== true || typeof value['replayed'] !== 'boolean') {
13
+ return invalidInboxResponse('PingRoom returned an invalid Agent Inbox ensure response.');
14
+ }
15
+ const room = value['room'];
16
+ const question = value['question'];
17
+ if (!isRecord(room)
18
+ || !isNonEmptyString(room['id'])
19
+ || typeof room['name'] !== 'string'
20
+ || !isNonEmptyString(room['invite_code'])
21
+ || typeof room['is_agent_inbox'] !== 'boolean'
22
+ || !isRecord(question)
23
+ || !isNonEmptyString(question['id'])
24
+ || question['kind'] !== 'question'
25
+ || !isNonEmptyString(question['prompt'])
26
+ || !Array.isArray(question['options'])
27
+ || question['options'].some((option) => (!isRecord(option)
28
+ || !isNonEmptyString(option['value'])
29
+ || !isNonEmptyString(option['label'])))
30
+ || (question['state'] !== 'pending'
31
+ && question['state'] !== 'answered'
32
+ && question['state'] !== 'expired'
33
+ && question['state'] !== 'cancelled')
34
+ || !isNullableString(question['expires_at'])
35
+ || !isNullableString(question['created_at'])) {
36
+ return invalidInboxResponse('PingRoom returned an incomplete Agent Inbox ensure response.');
37
+ }
38
+ return value;
39
+ }
40
+ function validateInboxWait(value, expectedId) {
41
+ if (!isRecord(value)) {
42
+ return invalidInboxResponse('PingRoom returned an invalid Agent Inbox wait response.');
43
+ }
44
+ const state = value['state'];
45
+ if (!isNonEmptyString(value['id'])
46
+ || value['id'] !== expectedId
47
+ || value['kind'] !== 'question'
48
+ || (state !== 'pending' && state !== 'answered' && state !== 'expired' && state !== 'cancelled')
49
+ || (value['activation_completed'] !== undefined && typeof value['activation_completed'] !== 'boolean')
50
+ || (state !== 'answered' && value['activation_completed'] === true)) {
51
+ return invalidInboxResponse('PingRoom returned a mismatched Agent Inbox wait response.', {
52
+ expected_id: expectedId,
53
+ received_id: typeof value['id'] === 'string' ? value['id'] : null,
54
+ kind: typeof value['kind'] === 'string' ? value['kind'] : null,
55
+ state: typeof state === 'string' ? state : null,
56
+ });
57
+ }
58
+ if (state === 'answered') {
59
+ const answer = value['answer'];
60
+ if (!isRecord(answer)
61
+ || !isNullableString(answer['value'])
62
+ || !isNullableString(answer['label'])
63
+ || !isNullableString(answer['text'])
64
+ || (!isNonEmptyString(answer['value']) && !isNonEmptyString(answer['text']))
65
+ || !isNullableString(answer['answered_at'])
66
+ || (answer['responder'] !== null && !isRecord(answer['responder']))) {
67
+ return invalidInboxResponse('PingRoom returned an answered activation without a valid answer.', {
68
+ id: expectedId,
69
+ state,
70
+ });
71
+ }
72
+ const responder = answer['responder'];
73
+ if (isRecord(responder)
74
+ && (!isNullableString(responder['id']) || !isNullableString(responder['display_name']))) {
75
+ return invalidInboxResponse('PingRoom returned an invalid activation responder.', {
76
+ id: expectedId,
77
+ state,
78
+ });
79
+ }
80
+ }
81
+ else if (value['answer'] !== undefined && value['answer'] !== null) {
82
+ return invalidInboxResponse('PingRoom returned an answer for an unresolved activation.', {
83
+ id: expectedId,
84
+ state,
85
+ });
86
+ }
87
+ return value;
88
+ }
89
+ /** Setup and activation of the bound human's Agent Inbox delivery room. */
90
+ export class InboxApi {
91
+ http;
92
+ constructor(http) {
93
+ this.http = http;
94
+ }
95
+ /** Replay the viable activation attempt or create its next numbered retry. */
96
+ ensure(input = {}) {
97
+ return this.http.request('POST', '/api/agent/inbox/ensure', {
98
+ body: {},
99
+ ...(input.signal ? { signal: input.signal } : {}),
100
+ });
101
+ }
102
+ /**
103
+ * Ensure the bound human's Agent Inbox, then block on its onboarding
104
+ * Question until the server confirms activation, it expires/cancels, or the
105
+ * overall deadline elapses. Pairing remains a separate operation so adopting
106
+ * a credential never silently waits for a phone response.
107
+ */
108
+ async activate(input = {}) {
109
+ const overallTimeoutMs = input.overallTimeoutMs ?? DEFAULT_INBOX_ACTIVATION_TIMEOUT_MS;
110
+ if (!Number.isFinite(overallTimeoutMs) || overallTimeoutMs < 0) {
111
+ throw new PingRoomError('`overallTimeoutMs` must be a non-negative finite number.', {
112
+ code: 'invalid_request',
113
+ });
114
+ }
115
+ const deadlineError = () => (new PingRoomActivationIncompleteError('deadline_exceeded', 'Agent Inbox activation did not complete before the overall deadline.', { overall_timeout_ms: overallTimeoutMs }));
116
+ const deadlineController = new AbortController();
117
+ const deadlineTimer = overallTimeoutMs === 0
118
+ ? null
119
+ : setTimeout(() => deadlineController.abort(deadlineError()), overallTimeoutMs);
120
+ if (overallTimeoutMs === 0)
121
+ deadlineController.abort(deadlineError());
122
+ const signal = input.signal
123
+ ? combineSignals(input.signal, deadlineController.signal)
124
+ : deadlineController.signal;
125
+ try {
126
+ throwIfAborted(signal);
127
+ const ensured = validateInboxEnsure(await this.ensure({ signal }));
128
+ const questionId = ensured.question.id;
129
+ let failures = 0;
130
+ for (;;) {
131
+ throwIfAborted(signal);
132
+ const pollStartedAt = Date.now();
133
+ let question;
134
+ try {
135
+ question = validateInboxWait(await this.http.request('GET', `/api/agent/handoffs/${enc(questionId)}/wait`, {
136
+ query: dropUndefined({ timeout: input.timeout }),
137
+ timeoutMs: waitTimeoutMs(input.timeout),
138
+ signal,
139
+ }), questionId);
140
+ }
141
+ catch (error) {
142
+ // A dropped connection, a request deadline, a 429 (each wait route
143
+ // has its own 30/min bucket per human) or a 5xx is not an outcome:
144
+ // retry it like every other wait, inside the overall deadline.
145
+ // Anything else is permanent and surfaces.
146
+ throwIfAborted(signal);
147
+ if (!isTransientError(error)) {
148
+ throw error;
149
+ }
150
+ failures += 1;
151
+ await sleep(Math.max(transientDelayMs(error, failures), MIN_HANDOFF_POLL_INTERVAL_MS - (Date.now() - pollStartedAt)), signal);
152
+ continue;
153
+ }
154
+ failures = 0;
155
+ throwIfAborted(signal);
156
+ if (question.state === 'pending') {
157
+ await sleep(Math.max(0, MIN_HANDOFF_POLL_INTERVAL_MS - (Date.now() - pollStartedAt)), signal);
158
+ continue;
159
+ }
160
+ if (question.state === 'answered' && question.activation_completed === true) {
161
+ return {
162
+ ...ensured,
163
+ activation_completed: true,
164
+ question: question,
165
+ };
166
+ }
167
+ if (question.state === 'answered') {
168
+ throw new PingRoomActivationIncompleteError('answered_without_completion', 'The onboarding Question was answered without verified native phone receipt before the answer.', { question_id: questionId, activation_completed: question.activation_completed ?? null });
169
+ }
170
+ if (question.state === 'expired' || question.state === 'cancelled') {
171
+ throw new PingRoomActivationIncompleteError(question.state, `The onboarding Question ${question.state} before Agent Inbox activation completed.`, { question_id: questionId, activation_completed: question.activation_completed ?? null });
172
+ }
173
+ return invalidInboxResponse('PingRoom returned an invalid terminal activation state.', {
174
+ id: questionId,
175
+ state: question.state,
176
+ });
177
+ }
178
+ }
179
+ catch (error) {
180
+ // A custom fetch implementation may reject with a generic AbortError
181
+ // instead of the signal's richer reason. Preserve caller cancellation
182
+ // and the activation-specific deadline error at this public boundary.
183
+ throwIfAborted(signal);
184
+ throw error;
185
+ }
186
+ finally {
187
+ if (deadlineTimer !== null)
188
+ clearTimeout(deadlineTimer);
189
+ }
190
+ }
191
+ }
192
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/namespaces/inbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { LiveClaimAction, LiveClaimResult, LiveStatusPing, LiveStatusResult, LiveStatusSnapshot } from '../liveStatus.js';
3
+ /**
4
+ * Live-status streams — a self-updating card on the room members' lock screen.
5
+ *
6
+ * Requires the `pingroom:live:write` scope. Free accounts get a small daily
7
+ * budget of NEW streams; updates and the terminal ping of an open stream are
8
+ * never charged, so a card can never be quota-blocked into hanging open. A
9
+ * first ping that is already `done`/`failed` is a new stream and is charged.
10
+ */
11
+ export declare class LiveApi {
12
+ private readonly http;
13
+ constructor(http: HttpClient);
14
+ /**
15
+ * Send one stream ping — start, update, or end, chosen by `live_status.state`
16
+ * and whether the correlation already exists.
17
+ */
18
+ push(inviteCode: string, ping: LiveStatusPing): Promise<LiveStatusResult>;
19
+ /**
20
+ * Read back a stream this credential started, so a restarted producer can
21
+ * reconcile instead of opening a duplicate.
22
+ *
23
+ * Resolves null ONLY for a 404 `stream_not_found` — no stream with that
24
+ * correlation id in the last 24 hours. Every other failure throws: a 404 for
25
+ * an unknown or deleted room code, and a 403 `room_not_granted`
26
+ * ({@link RoomScopedErrorCode}) when the room is outside the grant the human
27
+ * gave this agent, both propagate rather than being reported as "no stream".
28
+ */
29
+ get(inviteCode: string, correlationId: string): Promise<LiveStatusSnapshot | null>;
30
+ /**
31
+ * Act on a "Who's on it?" request as the human this credential acts for:
32
+ * `claim` takes an open request (anyone but its asker), `release` lets go of
33
+ * one you hold, `done` finishes it (its claimer, or its asker at any time) and
34
+ * `cancel` withdraws it (its asker, or a room owner or admin).
35
+ *
36
+ * `release` returns the request to `open` only while it can still be taken.
37
+ * Past its deadline (or four hours after it was made, when it has none) it
38
+ * ends the request as `expired` instead: a 200 whose `claim.status` is
39
+ * `expired` and whose `state` is `failed`, with `claim.by` and `claim.at`
40
+ * `null`. It is not an error, and the asker hears "No one took it". No other
41
+ * action resolves that way.
42
+ *
43
+ * `notificationId` is the request's `notification_id`, from the `push()`
44
+ * result or `notifications.list()`. It needs only room membership, not room
45
+ * ownership, and the `pingroom:live:write` scope.
46
+ *
47
+ * Repeating your own last action resolves with `idempotent: true`. A refusal
48
+ * throws `PingRoomError`: `claim_conflict` (409), `claim_own_request` (422),
49
+ * `claim_private_rooms_only` (422), `claim_not_found` (404) or `forbidden`
50
+ * (403). On 409 and 422 `error.body` is a `LiveClaimRefusal` carrying the
51
+ * request as it stands, so you can say who got it first.
52
+ * A malformed or mismatched success throws `invalid_response`; the SDK
53
+ * never repeats the transition POST automatically.
54
+ */
55
+ claim(inviteCode: string, notificationId: string, action: LiveClaimAction): Promise<LiveClaimResult>;
56
+ }
57
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/namespaces/live.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAGf,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAqC1B;;;;;;;GAOG;AACH,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAOzE;;;;;;;;;OASG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAcxF;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;CAYrG"}
@@ -0,0 +1,116 @@
1
+ // `pr.live`: live-status streams.
2
+ import { PingRoomError } from '../errors.js';
3
+ import { assertStructuredData, requireNonEmpty } from '../internal/guards.js';
4
+ import { enc } from '../internal/request.js';
5
+ import { isNonEmptyString, isRecord, sameId } from '../internal/validate.js';
6
+ /**
7
+ * What each action's 200 receipt may say, as `[claim.status, stream state]`
8
+ * pairs. `release` has two: letting go reopens a request that can still be
9
+ * taken, but a request past its deadline (or four hours old with none) ends as
10
+ * `expired` with stream state `failed`, exactly as time ends an open one. That
11
+ * is still a 200, and a retry replays it. Only `release` can end that way.
12
+ */
13
+ const CLAIM_OUTCOMES = {
14
+ claim: [['claimed', 'running']],
15
+ release: [['open', 'running'], ['expired', 'failed']],
16
+ done: [['done', 'done']],
17
+ cancel: [['cancelled', 'failed']],
18
+ };
19
+ function validateClaimResult(value, notificationId, action) {
20
+ const expected = CLAIM_OUTCOMES[action];
21
+ const claim = isRecord(value) ? value['claim'] : undefined;
22
+ const party = isRecord(claim) ? claim['by'] : undefined;
23
+ if (!isRecord(value) || !sameId(value['notification_id'], notificationId)
24
+ || !isNonEmptyString(value['correlation_id']) || typeof value['idempotent'] !== 'boolean'
25
+ || !isRecord(claim) || !expected
26
+ || !expected.some(([status, state]) => claim['status'] === status && value['state'] === state)
27
+ || typeof claim['late'] !== 'boolean'
28
+ || !(party === null || isRecord(party) && isNonEmptyString(party['id']) && typeof party['name'] === 'string')
29
+ || !(claim['at'] === null || typeof claim['at'] === 'number' && Number.isFinite(claim['at']))) {
30
+ throw new PingRoomError('PingRoom returned an invalid claim transition receipt.', {
31
+ code: 'invalid_response',
32
+ body: { expected_notification_id: notificationId, action },
33
+ });
34
+ }
35
+ return value;
36
+ }
37
+ /**
38
+ * Live-status streams — a self-updating card on the room members' lock screen.
39
+ *
40
+ * Requires the `pingroom:live:write` scope. Free accounts get a small daily
41
+ * budget of NEW streams; updates and the terminal ping of an open stream are
42
+ * never charged, so a card can never be quota-blocked into hanging open. A
43
+ * first ping that is already `done`/`failed` is a new stream and is charged.
44
+ */
45
+ export class LiveApi {
46
+ http;
47
+ constructor(http) {
48
+ this.http = http;
49
+ }
50
+ /**
51
+ * Send one stream ping — start, update, or end, chosen by `live_status.state`
52
+ * and whether the correlation already exists.
53
+ */
54
+ push(inviteCode, ping) {
55
+ requireNonEmpty(inviteCode, 'inviteCode');
56
+ requireNonEmpty(ping.correlation_id, 'correlation_id');
57
+ assertStructuredData(ping.data);
58
+ return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/live`, { body: ping });
59
+ }
60
+ /**
61
+ * Read back a stream this credential started, so a restarted producer can
62
+ * reconcile instead of opening a duplicate.
63
+ *
64
+ * Resolves null ONLY for a 404 `stream_not_found` — no stream with that
65
+ * correlation id in the last 24 hours. Every other failure throws: a 404 for
66
+ * an unknown or deleted room code, and a 403 `room_not_granted`
67
+ * ({@link RoomScopedErrorCode}) when the room is outside the grant the human
68
+ * gave this agent, both propagate rather than being reported as "no stream".
69
+ */
70
+ async get(inviteCode, correlationId) {
71
+ requireNonEmpty(inviteCode, 'inviteCode');
72
+ requireNonEmpty(correlationId, 'correlationId');
73
+ try {
74
+ return await this.http.request('GET', `/api/agent/rooms/${enc(inviteCode)}/live/${enc(correlationId)}`);
75
+ }
76
+ catch (error) {
77
+ if (error instanceof PingRoomError && error.status === 404 && error.code === 'stream_not_found')
78
+ return null;
79
+ throw error;
80
+ }
81
+ }
82
+ /**
83
+ * Act on a "Who's on it?" request as the human this credential acts for:
84
+ * `claim` takes an open request (anyone but its asker), `release` lets go of
85
+ * one you hold, `done` finishes it (its claimer, or its asker at any time) and
86
+ * `cancel` withdraws it (its asker, or a room owner or admin).
87
+ *
88
+ * `release` returns the request to `open` only while it can still be taken.
89
+ * Past its deadline (or four hours after it was made, when it has none) it
90
+ * ends the request as `expired` instead: a 200 whose `claim.status` is
91
+ * `expired` and whose `state` is `failed`, with `claim.by` and `claim.at`
92
+ * `null`. It is not an error, and the asker hears "No one took it". No other
93
+ * action resolves that way.
94
+ *
95
+ * `notificationId` is the request's `notification_id`, from the `push()`
96
+ * result or `notifications.list()`. It needs only room membership, not room
97
+ * ownership, and the `pingroom:live:write` scope.
98
+ *
99
+ * Repeating your own last action resolves with `idempotent: true`. A refusal
100
+ * throws `PingRoomError`: `claim_conflict` (409), `claim_own_request` (422),
101
+ * `claim_private_rooms_only` (422), `claim_not_found` (404) or `forbidden`
102
+ * (403). On 409 and 422 `error.body` is a `LiveClaimRefusal` carrying the
103
+ * request as it stands, so you can say who got it first.
104
+ * A malformed or mismatched success throws `invalid_response`; the SDK
105
+ * never repeats the transition POST automatically.
106
+ */
107
+ claim(inviteCode, notificationId, action) {
108
+ requireNonEmpty(inviteCode, 'inviteCode');
109
+ requireNonEmpty(notificationId, 'notificationId');
110
+ if (typeof action !== 'string' || !Object.hasOwn(CLAIM_OUTCOMES, action)) {
111
+ throw new PingRoomError('`action` must be claim, release, done or cancel.', { code: 'invalid_request' });
112
+ }
113
+ return this.http.request('POST', `/api/agent/rooms/${enc(inviteCode)}/live/${enc(notificationId)}/claim`, { body: { action } }).then((value) => validateClaimResult(value, notificationId, action));
114
+ }
115
+ }
116
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/namespaces/live.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { AcknowledgementWaitResult, AgentNotification, ListNotificationsInput, ListenInput, NotificationDetail, NotificationHistoryEntry, Paginated, WaitForAcknowledgementInput, WaitInput, WaitResult } from '../types.js';
3
+ export declare class NotificationsApi {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ /** Paginated list (polling fallback). Prefer wait()/listen() for real-time. */
7
+ list(input?: ListNotificationsInput): Promise<Paginated<NotificationHistoryEntry>>;
8
+ /** Fetch one visible notification, including its current acknowledgement state. */
9
+ getNotification(notificationId: string): Promise<NotificationDetail>;
10
+ /**
11
+ * One bounded long-poll for an ack-required ping. The returned state may
12
+ * still be `open` when the hold timeout elapses; call again to keep waiting.
13
+ */
14
+ waitForAcknowledgement(notificationId: string, input?: WaitForAcknowledgementInput): Promise<AcknowledgementWaitResult>;
15
+ /** One long-poll: resolves as soon as new pings land, or with an empty list at timeout. */
16
+ wait(input?: WaitInput): Promise<WaitResult>;
17
+ /**
18
+ * Continuous real-time inbound: an async iterator that long-polls in a loop,
19
+ * advancing the cursor, yielding each new ping. Stops when `signal` aborts.
20
+ *
21
+ * for await (const ping of pr.notifications.listen({ signal })) { ... }
22
+ */
23
+ listen(input?: ListenInput): AsyncGenerator<AgentNotification, void, void>;
24
+ }
25
+ //# sourceMappingURL=notifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/namespaces/notifications.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAK7C,OAAO,KAAK,EACV,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,EACtB,WAAW,EACX,kBAAkB,EAClB,wBAAwB,EACxB,SAAS,EACT,2BAA2B,EAC3B,SAAS,EACT,UAAU,EACX,MAAM,aAAa,CAAC;AAsBrB,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,+EAA+E;IACzE,IAAI,CAAC,KAAK,GAAE,sBAA2B,GAAG,OAAO,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAc5F,mFAAmF;IACnF,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAKpE;;;OAGG;IACH,sBAAsB,CACpB,cAAc,EAAE,MAAM,EACtB,KAAK,GAAE,2BAAgC,GACtC,OAAO,CAAC,yBAAyB,CAAC;IASrC,2FAA2F;IAC3F,IAAI,CAAC,KAAK,GAAE,SAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAQhD;;;;;OAKG;IACI,MAAM,CAAC,KAAK,GAAE,WAAgB,GAAG,cAAc,CAAC,iBAAiB,EAAE,IAAI,EAAE,IAAI,CAAC;CAuDtF"}
@@ -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":"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"}
@@ -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"}