@superblocksteam/gateway 2.0.155-next.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 (183) hide show
  1. package/LICENSE.txt +87 -0
  2. package/README.md +170 -0
  3. package/dist/agents/resolve-orchestrator-url.d.ts +22 -0
  4. package/dist/agents/resolve-orchestrator-url.js +38 -0
  5. package/dist/agents/resolve-orchestrator-url.js.map +1 -0
  6. package/dist/capabilities/import-prompt.d.ts +11 -0
  7. package/dist/capabilities/import-prompt.js +96 -0
  8. package/dist/capabilities/import-prompt.js.map +1 -0
  9. package/dist/capabilities/lifecycle.d.ts +73 -0
  10. package/dist/capabilities/lifecycle.js +2531 -0
  11. package/dist/capabilities/lifecycle.js.map +1 -0
  12. package/dist/capabilities/persisted-progress.d.ts +46 -0
  13. package/dist/capabilities/persisted-progress.js +246 -0
  14. package/dist/capabilities/persisted-progress.js.map +1 -0
  15. package/dist/capabilities/types.d.ts +446 -0
  16. package/dist/capabilities/types.js +47 -0
  17. package/dist/capabilities/types.js.map +1 -0
  18. package/dist/capture/browser-contract.d.ts +36 -0
  19. package/dist/capture/browser-contract.js +24 -0
  20. package/dist/capture/browser-contract.js.map +1 -0
  21. package/dist/capture/browser-instructions.d.ts +9 -0
  22. package/dist/capture/browser-instructions.js +17 -0
  23. package/dist/capture/browser-instructions.js.map +1 -0
  24. package/dist/capture/capture-library-probe.d.ts +55 -0
  25. package/dist/capture/capture-library-probe.js +177 -0
  26. package/dist/capture/capture-library-probe.js.map +1 -0
  27. package/dist/capture/capture-library.d.ts +52 -0
  28. package/dist/capture/capture-library.js +249 -0
  29. package/dist/capture/capture-library.js.map +1 -0
  30. package/dist/capture/classify-library-paint.d.ts +21 -0
  31. package/dist/capture/classify-library-paint.js +13 -0
  32. package/dist/capture/classify-library-paint.js.map +1 -0
  33. package/dist/capture/host-mcp-scan.d.ts +16 -0
  34. package/dist/capture/host-mcp-scan.js +64 -0
  35. package/dist/capture/host-mcp-scan.js.map +1 -0
  36. package/dist/capture/library-parent-script.d.ts +34 -0
  37. package/dist/capture/library-parent-script.js +82 -0
  38. package/dist/capture/library-parent-script.js.map +1 -0
  39. package/dist/capture/mode.d.ts +22 -0
  40. package/dist/capture/mode.js +45 -0
  41. package/dist/capture/mode.js.map +1 -0
  42. package/dist/config.d.ts +141 -0
  43. package/dist/config.js +109 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/debug.d.ts +2 -0
  46. package/dist/debug.js +9 -0
  47. package/dist/debug.js.map +1 -0
  48. package/dist/deps.d.ts +36 -0
  49. package/dist/deps.js +2 -0
  50. package/dist/deps.js.map +1 -0
  51. package/dist/events/cursor.d.ts +43 -0
  52. package/dist/events/cursor.js +78 -0
  53. package/dist/events/cursor.js.map +1 -0
  54. package/dist/events/memory-event-store.d.ts +34 -0
  55. package/dist/events/memory-event-store.js +110 -0
  56. package/dist/events/memory-event-store.js.map +1 -0
  57. package/dist/events/merge.d.ts +23 -0
  58. package/dist/events/merge.js +97 -0
  59. package/dist/events/merge.js.map +1 -0
  60. package/dist/events/normalized-collector.d.ts +62 -0
  61. package/dist/events/normalized-collector.js +156 -0
  62. package/dist/events/normalized-collector.js.map +1 -0
  63. package/dist/events/schema.d.ts +9 -0
  64. package/dist/events/schema.js +93 -0
  65. package/dist/events/schema.js.map +1 -0
  66. package/dist/events/snapshot.d.ts +32 -0
  67. package/dist/events/snapshot.js +57 -0
  68. package/dist/events/snapshot.js.map +1 -0
  69. package/dist/events/stream-key.d.ts +2 -0
  70. package/dist/events/stream-key.js +31 -0
  71. package/dist/events/stream-key.js.map +1 -0
  72. package/dist/events/types.d.ts +179 -0
  73. package/dist/events/types.js +66 -0
  74. package/dist/events/types.js.map +1 -0
  75. package/dist/health/readiness.d.ts +99 -0
  76. package/dist/health/readiness.js +202 -0
  77. package/dist/health/readiness.js.map +1 -0
  78. package/dist/index.d.ts +10 -0
  79. package/dist/index.js +10 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/integrations/filters.d.ts +8 -0
  82. package/dist/integrations/filters.js +40 -0
  83. package/dist/integrations/filters.js.map +1 -0
  84. package/dist/integrations/map.d.ts +26 -0
  85. package/dist/integrations/map.js +43 -0
  86. package/dist/integrations/map.js.map +1 -0
  87. package/dist/integrations/profile-key.d.ts +19 -0
  88. package/dist/integrations/profile-key.js +35 -0
  89. package/dist/integrations/profile-key.js.map +1 -0
  90. package/dist/main.d.ts +2 -0
  91. package/dist/main.js +5 -0
  92. package/dist/main.js.map +1 -0
  93. package/dist/orchestrator/client.d.ts +62 -0
  94. package/dist/orchestrator/client.js +160 -0
  95. package/dist/orchestrator/client.js.map +1 -0
  96. package/dist/playwright/ensure-chromium.d.ts +26 -0
  97. package/dist/playwright/ensure-chromium.js +60 -0
  98. package/dist/playwright/ensure-chromium.js.map +1 -0
  99. package/dist/preview/capture-screenshot.d.ts +52 -0
  100. package/dist/preview/capture-screenshot.js +158 -0
  101. package/dist/preview/capture-screenshot.js.map +1 -0
  102. package/dist/preview/viewer-url.d.ts +82 -0
  103. package/dist/preview/viewer-url.js +128 -0
  104. package/dist/preview/viewer-url.js.map +1 -0
  105. package/dist/process/fault-barrier.d.ts +55 -0
  106. package/dist/process/fault-barrier.js +113 -0
  107. package/dist/process/fault-barrier.js.map +1 -0
  108. package/dist/resume/memory-progress-store.d.ts +39 -0
  109. package/dist/resume/memory-progress-store.js +82 -0
  110. package/dist/resume/memory-progress-store.js.map +1 -0
  111. package/dist/resume/memory-recent-app-store.d.ts +14 -0
  112. package/dist/resume/memory-recent-app-store.js +27 -0
  113. package/dist/resume/memory-recent-app-store.js.map +1 -0
  114. package/dist/resume/memory-turn-store.d.ts +18 -0
  115. package/dist/resume/memory-turn-store.js +73 -0
  116. package/dist/resume/memory-turn-store.js.map +1 -0
  117. package/dist/resume/progress-key.d.ts +21 -0
  118. package/dist/resume/progress-key.js +58 -0
  119. package/dist/resume/progress-key.js.map +1 -0
  120. package/dist/resume/stores.d.ts +14 -0
  121. package/dist/resume/stores.js +18 -0
  122. package/dist/resume/stores.js.map +1 -0
  123. package/dist/resume/types.d.ts +124 -0
  124. package/dist/resume/types.js +13 -0
  125. package/dist/resume/types.js.map +1 -0
  126. package/dist/sabs/agent-facing-text.d.ts +33 -0
  127. package/dist/sabs/agent-facing-text.js +125 -0
  128. package/dist/sabs/agent-facing-text.js.map +1 -0
  129. package/dist/sabs/browser-context.d.ts +53 -0
  130. package/dist/sabs/browser-context.js +91 -0
  131. package/dist/sabs/browser-context.js.map +1 -0
  132. package/dist/sabs/editor-client-methods.d.ts +147 -0
  133. package/dist/sabs/editor-client-methods.js +715 -0
  134. package/dist/sabs/editor-client-methods.js.map +1 -0
  135. package/dist/sabs/recent-tool-runs.d.ts +14 -0
  136. package/dist/sabs/recent-tool-runs.js +61 -0
  137. package/dist/sabs/recent-tool-runs.js.map +1 -0
  138. package/dist/sabs/session-peer.d.ts +351 -0
  139. package/dist/sabs/session-peer.js +2 -0
  140. package/dist/sabs/session-peer.js.map +1 -0
  141. package/dist/sabs/turn-collector.d.ts +152 -0
  142. package/dist/sabs/turn-collector.js +573 -0
  143. package/dist/sabs/turn-collector.js.map +1 -0
  144. package/dist/sabs/websocket-session-peer.d.ts +514 -0
  145. package/dist/sabs/websocket-session-peer.js +2487 -0
  146. package/dist/sabs/websocket-session-peer.js.map +1 -0
  147. package/dist/security/constant-time.d.ts +9 -0
  148. package/dist/security/constant-time.js +13 -0
  149. package/dist/security/constant-time.js.map +1 -0
  150. package/dist/server/client.d.ts +371 -0
  151. package/dist/server/client.js +572 -0
  152. package/dist/server/client.js.map +1 -0
  153. package/dist/server/identity-reads.d.ts +76 -0
  154. package/dist/server/identity-reads.js +209 -0
  155. package/dist/server/identity-reads.js.map +1 -0
  156. package/dist/start.d.ts +14 -0
  157. package/dist/start.js +75 -0
  158. package/dist/start.js.map +1 -0
  159. package/dist/telemetry/metrics.d.ts +32 -0
  160. package/dist/telemetry/metrics.js +57 -0
  161. package/dist/telemetry/metrics.js.map +1 -0
  162. package/dist/transports/mcp/admin-tools.d.ts +47 -0
  163. package/dist/transports/mcp/admin-tools.js +164 -0
  164. package/dist/transports/mcp/admin-tools.js.map +1 -0
  165. package/dist/transports/mcp/app-status-html.d.ts +15 -0
  166. package/dist/transports/mcp/app-status-html.js +563 -0
  167. package/dist/transports/mcp/app-status-html.js.map +1 -0
  168. package/dist/transports/mcp/decision-elicitation.d.ts +74 -0
  169. package/dist/transports/mcp/decision-elicitation.js +233 -0
  170. package/dist/transports/mcp/decision-elicitation.js.map +1 -0
  171. package/dist/transports/mcp/dispatch-probe.d.ts +24 -0
  172. package/dist/transports/mcp/dispatch-probe.js +48 -0
  173. package/dist/transports/mcp/dispatch-probe.js.map +1 -0
  174. package/dist/transports/mcp/format-tool-content.d.ts +25 -0
  175. package/dist/transports/mcp/format-tool-content.js +48 -0
  176. package/dist/transports/mcp/format-tool-content.js.map +1 -0
  177. package/dist/transports/mcp/mount.d.ts +9 -0
  178. package/dist/transports/mcp/mount.js +469 -0
  179. package/dist/transports/mcp/mount.js.map +1 -0
  180. package/dist/transports/mcp/progress-notifier.d.ts +39 -0
  181. package/dist/transports/mcp/progress-notifier.js +52 -0
  182. package/dist/transports/mcp/progress-notifier.js.map +1 -0
  183. package/package.json +72 -0
@@ -0,0 +1,572 @@
1
+ import { uploadAttachmentToServerApi } from "@superblocksteam/shared";
2
+ import { recordIdentityReadOutcome } from "../telemetry/metrics.js";
3
+ import { withGuardedIdentityReads, } from "./identity-reads.js";
4
+ const MAX_DETAIL_LENGTH = 300;
5
+ /**
6
+ * Pulls the server's own explanation out of an error body.
7
+ *
8
+ * Bounded because the body is attacker-influenced in principle and ends up in
9
+ * logs and in tool output the caller sees.
10
+ */
11
+ function detailSuffix(body) {
12
+ if (!body.trim()) {
13
+ return "";
14
+ }
15
+ let detail = body;
16
+ try {
17
+ const parsed = JSON.parse(body);
18
+ if (parsed && typeof parsed === "object") {
19
+ const record = parsed;
20
+ const message = record.responseMeta?.message ?? record.message ?? record.error;
21
+ if (typeof message === "string" && message.trim()) {
22
+ detail = message;
23
+ }
24
+ }
25
+ }
26
+ catch {
27
+ // Not JSON — fall back to the raw body.
28
+ }
29
+ const trimmed = detail.trim().slice(0, MAX_DETAIL_LENGTH);
30
+ return ` — ${trimmed}`;
31
+ }
32
+ export class ServerHttpError extends Error {
33
+ status;
34
+ constructor(message, status) {
35
+ super(message);
36
+ this.status = status;
37
+ this.name = "ServerHttpError";
38
+ }
39
+ }
40
+ /**
41
+ * Generous enough for a sandbox start.
42
+ *
43
+ * It is not short enough to keep a tool call from hanging, which is what this
44
+ * used to claim: a tool call waits on the identity read, and that one is bounded
45
+ * by {@link DEFAULT_IDENTITY_TIMEOUT_MS} instead.
46
+ */
47
+ const DEFAULT_TIMEOUT_MS = 120_000;
48
+ /**
49
+ * The identity read gets its own, much tighter bound.
50
+ *
51
+ * {@link DEFAULT_TIMEOUT_MS} is sized for starting a sandbox. Nothing waits on
52
+ * that; every tool call waits on `/users/me`. Giving the two the same budget is
53
+ * what let a single wedged route hold each call for two minutes.
54
+ *
55
+ * Still well above the ~10s a caller waits (see
56
+ * {@link withGuardedIdentityReads}) so that an endpoint which answers slowly
57
+ * rather than never can still finish and fill the cache.
58
+ */
59
+ const DEFAULT_IDENTITY_TIMEOUT_MS = 30_000;
60
+ /**
61
+ * Whether a failed identity read means the endpoint is unhealthy rather than
62
+ * that this one credential is bad.
63
+ *
64
+ * A 4xx is a definite answer about a single caller, so it must not trip the
65
+ * breaker and start failing everyone else fast. A 5xx, a timeout or a
66
+ * transport error says nothing about the credential and everything about the
67
+ * route.
68
+ *
69
+ * 429 is the exception on the 4xx side: a shared rate limit is a statement
70
+ * about the route's capacity, not about this credential, and it is exactly the
71
+ * case where hammering on is worst. Treating it as the caller's fault left it
72
+ * neither retried (only >= 500 is) nor able to open the breaker, so every call
73
+ * kept going straight at an endpoint already asking for less load.
74
+ */
75
+ function identityEndpointUnhealthy(error) {
76
+ return !(error instanceof ServerHttpError &&
77
+ error.status < 500 &&
78
+ error.status !== 429);
79
+ }
80
+ /**
81
+ * Extra attempts for reads that failed with a server-side error.
82
+ *
83
+ * Only GETs are retried: they carry no side effects, so a repeat is free. A
84
+ * failed POST may well have taken effect, and re-sending one can deploy or
85
+ * commit twice.
86
+ */
87
+ const READ_RETRY_ATTEMPTS = 2;
88
+ const READ_RETRY_BASE_DELAY_MS = 100;
89
+ function delay(ms) {
90
+ return new Promise((resolve) => setTimeout(resolve, ms));
91
+ }
92
+ const DEPLOY_STATUSES = [
93
+ "awaiting_ack",
94
+ "deployed",
95
+ "failed",
96
+ "queued",
97
+ ];
98
+ function isDeployStatus(value) {
99
+ return DEPLOY_STATUSES.includes(value);
100
+ }
101
+ /**
102
+ * SABS's build status as this client's own vocabulary.
103
+ *
104
+ * It answers with `BUILD_STATUS_*` strings through the server, and with the
105
+ * matching protobuf ordinals when the response is not re-serialized on the way
106
+ * — the editor's own client normalizes both, and so does this.
107
+ */
108
+ const BUILD_PROGRESS_BY_ORDINAL = {
109
+ 0: "none",
110
+ 1: "running",
111
+ 2: "success",
112
+ 3: "failed",
113
+ 4: "timed_out",
114
+ };
115
+ const BUILD_PROGRESS_BY_NAME = {
116
+ FAILED: "failed",
117
+ RUNNING: "running",
118
+ SUCCESS: "success",
119
+ TIMED_OUT: "timed_out",
120
+ UNSPECIFIED: "none",
121
+ };
122
+ function buildProgress(status) {
123
+ if (typeof status === "number") {
124
+ return BUILD_PROGRESS_BY_ORDINAL[status] ?? "none";
125
+ }
126
+ if (typeof status !== "string") {
127
+ return "none";
128
+ }
129
+ const name = status
130
+ .trim()
131
+ .toUpperCase()
132
+ .replace(/^BUILD_STATUS_/, "");
133
+ return BUILD_PROGRESS_BY_NAME[name] ?? "none";
134
+ }
135
+ export class HttpSuperblocksServerClient {
136
+ identityTimeoutMs;
137
+ readIdentity;
138
+ serverUrl;
139
+ timeoutMs;
140
+ constructor(serverUrl, options = {}) {
141
+ this.serverUrl = serverUrl;
142
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
143
+ this.identityTimeoutMs =
144
+ options.identityTimeoutMs ?? DEFAULT_IDENTITY_TIMEOUT_MS;
145
+ this.readIdentity = withGuardedIdentityReads((apiKey) => this.readIdentityFromServer(apiKey), {
146
+ onOutcome: recordIdentityReadOutcome,
147
+ opensBreaker: identityEndpointUnhealthy,
148
+ ...options.identityReads,
149
+ });
150
+ }
151
+ baseUrl() {
152
+ return this.serverUrl.replace(/\/$/, "");
153
+ }
154
+ /**
155
+ * Unwraps the Superblocks `ResponseDto` envelope.
156
+ *
157
+ * Every v1/v2/v3 route the gateway calls replies with
158
+ * `{ responseMeta, data }`. Reading the body directly yields `undefined` for
159
+ * every field, which is indistinguishable from a legitimately empty response
160
+ * — so this is deliberately strict rather than falling back to the raw body.
161
+ */
162
+ async requestData(path, init) {
163
+ const body = await this.request(path, init);
164
+ if (body?.data === undefined) {
165
+ throw new Error(`Server ${path} returned no data field; expected a { responseMeta, data } envelope`);
166
+ }
167
+ return body.data;
168
+ }
169
+ /**
170
+ * Issues the request, retrying a transient status when the verb makes that
171
+ * safe.
172
+ *
173
+ * A transient failure on the identity lookup used to fail the whole tool call
174
+ * and leave the caller guessing whether their account was broken.
175
+ *
176
+ * 429 counts as transient alongside 5xx: it is the route reporting its own
177
+ * capacity, and backing off is the whole point of it.
178
+ */
179
+ async request(path, init) {
180
+ const retryable = (init.method ?? "GET").toUpperCase() === "GET";
181
+ let lastError;
182
+ for (let attempt = 0; attempt <= (retryable ? READ_RETRY_ATTEMPTS : 0);) {
183
+ try {
184
+ return await this.send(path, init);
185
+ }
186
+ catch (error) {
187
+ lastError = error;
188
+ const transient = error instanceof ServerHttpError &&
189
+ (error.status >= 500 || error.status === 429);
190
+ attempt += 1;
191
+ if (!retryable || !transient || attempt > READ_RETRY_ATTEMPTS) {
192
+ throw error;
193
+ }
194
+ await delay(READ_RETRY_BASE_DELAY_MS * attempt);
195
+ }
196
+ }
197
+ throw lastError;
198
+ }
199
+ async send(path, init) {
200
+ const { apiKey, headers: callerHeaders, timeoutMs, ...rest } = init;
201
+ const bound = timeoutMs ?? this.timeoutMs;
202
+ const mergedHeaders = new Headers(callerHeaders);
203
+ // Auth and content-type are owned by this client — never override from callers.
204
+ mergedHeaders.set("Authorization", `Bearer ${apiKey}`);
205
+ if (!mergedHeaders.has("Content-Type")) {
206
+ mergedHeaders.set("Content-Type", "application/json");
207
+ }
208
+ let response;
209
+ try {
210
+ response = await fetch(`${this.baseUrl()}${path}`, {
211
+ ...rest,
212
+ headers: mergedHeaders,
213
+ signal: AbortSignal.timeout(bound),
214
+ });
215
+ }
216
+ catch (error) {
217
+ if (error instanceof Error && error.name === "TimeoutError") {
218
+ throw new Error(`Server ${path} timed out after ${bound}ms`);
219
+ }
220
+ throw error;
221
+ }
222
+ if (!response.ok) {
223
+ throw new ServerHttpError(`Server ${path} failed: ${response.status}${detailSuffix(await response.text().catch(() => ""))}`, response.status);
224
+ }
225
+ return (await response.json());
226
+ }
227
+ /**
228
+ * The Superblocks user behind a downstream credential.
229
+ *
230
+ * Cached, collapsed, deadlined and circuit-broken: this is the first thing
231
+ * every MCP tool call does, so reading it straight through coupled the whole
232
+ * tool surface to the health of one route.
233
+ */
234
+ async validateApiKey(apiKey) {
235
+ return this.readIdentity(apiKey);
236
+ }
237
+ /** The unguarded read behind {@link validateApiKey}. */
238
+ async readIdentityFromServer(apiKey) {
239
+ try {
240
+ const data = await this.requestData("/api/v1/users/me", {
241
+ apiKey,
242
+ method: "GET",
243
+ timeoutMs: this.identityTimeoutMs,
244
+ });
245
+ const user = data.user;
246
+ const organizationId = user?.currentOrganizationId ?? data.organizations?.[0]?.id;
247
+ if (!user || !organizationId) {
248
+ return undefined;
249
+ }
250
+ return {
251
+ email: user.email,
252
+ organizationId,
253
+ userId: user.id,
254
+ };
255
+ }
256
+ catch (error) {
257
+ // Auth failures → undefined (caller elicits login). Transport errors rethrow.
258
+ if (error instanceof ServerHttpError && error.status === 401) {
259
+ return undefined;
260
+ }
261
+ throw error;
262
+ }
263
+ }
264
+ async getAgentInventory(input) {
265
+ const data = await this.requestData("/api/v1/users/me", {
266
+ apiKey: input.apiKey,
267
+ method: "GET",
268
+ // Same route, so the same bound. This one runs on the build path rather
269
+ // than per tool call, and left at the sandbox timeout a wedged
270
+ // /users/me held a start_app open for two minutes here instead.
271
+ timeoutMs: this.identityTimeoutMs,
272
+ });
273
+ const organization = data.organizations?.find((org) => org.id === input.organizationId) ??
274
+ data.organizations?.find((org) => org.id === data.user?.currentOrganizationId) ??
275
+ data.organizations?.[0];
276
+ if (organization?.agentType === undefined) {
277
+ throw new Error(`Server /api/v1/users/me returned no agentType for organization ${input.organizationId}`);
278
+ }
279
+ const agents = [];
280
+ for (const raw of data.agents ?? []) {
281
+ if (typeof raw.url !== "string" ||
282
+ !raw.url ||
283
+ typeof raw.type !== "number" ||
284
+ typeof raw.status !== "string") {
285
+ continue;
286
+ }
287
+ agents.push({
288
+ status: raw.status,
289
+ tags: raw.tags ?? {},
290
+ type: raw.type,
291
+ url: raw.url,
292
+ });
293
+ }
294
+ return {
295
+ agentType: organization.agentType,
296
+ agents,
297
+ };
298
+ }
299
+ async createApplication(input) {
300
+ return this.requestData("/api/v2/applications/", {
301
+ apiKey: input.apiKey,
302
+ // Live edit only attaches to code-mode apps; without this the server
303
+ // builds a legacy DSL app and `connect` rejects it.
304
+ body: JSON.stringify({
305
+ createUsingReact: true,
306
+ name: input.name,
307
+ organizationId: input.organizationId,
308
+ ...(input.templateName ? { templateName: input.templateName } : {}),
309
+ }),
310
+ method: "POST",
311
+ });
312
+ }
313
+ async uploadAttachment(input) {
314
+ const mimeType = input.mimeType ?? "application/zip";
315
+ // Multipart must not go through {@link send}: that helper forces
316
+ // application/json and would break the boundary.
317
+ const response = await uploadAttachmentToServerApi({
318
+ applicationId: input.applicationId,
319
+ authorization: `Bearer ${input.apiKey}`,
320
+ baseUrl: this.baseUrl(),
321
+ descriptor: {
322
+ blob: new Blob([Buffer.from(input.bytes)], { type: mimeType }),
323
+ fileName: input.fileName,
324
+ mimeType,
325
+ },
326
+ prefix: "message-attachment",
327
+ purpose: "attachment",
328
+ scopeType: "app",
329
+ });
330
+ return {
331
+ applicationId: response.applicationId,
332
+ attachmentId: response.attachmentId,
333
+ contentUrl: response.contentUrl,
334
+ fileName: response.fileName,
335
+ mimeType: response.mimeType,
336
+ signedUrl: response.signedUrl,
337
+ signedUrlExpiresAt: response.signedUrlExpiresAt,
338
+ storageKey: response.storageKey,
339
+ };
340
+ }
341
+ async connectLiveEdit(input) {
342
+ const branchSegment = input.branch
343
+ ? `/branches/${encodeURIComponent(input.branch)}`
344
+ : "";
345
+ const data = await this.requestData(`/api/v3/applications/${input.applicationId}${branchSegment}/connect`, {
346
+ apiKey: input.apiKey,
347
+ method: "GET",
348
+ });
349
+ if (!data.sandboxStartData) {
350
+ // Absent for a LOCAL lock — there is no remote sandbox to drive.
351
+ throw new Error("Server returned no live edit session for this application");
352
+ }
353
+ return {
354
+ liveEditId: data.sandboxStartData.sandboxId,
355
+ liveEditUrl: data.sandboxStartData.pitcherURL,
356
+ pitcherToken: data.sandboxStartData.pitcherToken,
357
+ pitcherURL: data.sandboxStartData.pitcherURL,
358
+ };
359
+ }
360
+ /**
361
+ * Mints the credential the live-edit session accepts. Connect's
362
+ * `pitcherToken` is a placeholder in the local sandbox path, so the editor
363
+ * mints this separately and so must anything else driving a session.
364
+ */
365
+ async issueScopedToken(input) {
366
+ // Alone among the routes here, this one answers with a bare OAuth-shaped
367
+ // body rather than the `{ responseMeta, data }` envelope.
368
+ const scope = input.scope ?? "apps:update";
369
+ const body = {
370
+ applicationId: input.applicationId,
371
+ scope,
372
+ };
373
+ if (scope === "apps:preview") {
374
+ if (!input.commitId?.trim()) {
375
+ throw new Error("apps:preview scoped tokens require a commitId so the viewer can load that commit");
376
+ }
377
+ body.commitId = input.commitId;
378
+ }
379
+ const data = await this.request("/api/v1/token/scoped", {
380
+ apiKey: input.apiKey,
381
+ body: JSON.stringify(body),
382
+ method: "POST",
383
+ });
384
+ if (!data?.access_token) {
385
+ throw new Error("Server /api/v1/token/scoped returned no access_token; the live-edit session has nothing to verify");
386
+ }
387
+ return data.access_token;
388
+ }
389
+ async getSupersetIntegrations(input) {
390
+ const params = new URLSearchParams({
391
+ // The endpoint rejects a request without `kind` (400 "Kind must be
392
+ // provided."); PLUGIN is what the editor asks for when it builds the
393
+ // integration list Clark sees.
394
+ kind: "PLUGIN",
395
+ organizationId: input.organizationId,
396
+ });
397
+ if (input.applicationId) {
398
+ params.set("applicationId", input.applicationId);
399
+ }
400
+ const data = await this.requestData(`/api/v1/integrations/superset?${params.toString()}`, { apiKey: input.apiKey, method: "GET" });
401
+ return Array.isArray(data) ? data : [];
402
+ }
403
+ async getIntegration(input) {
404
+ try {
405
+ return await this.requestData(`/api/v1/integrations/${encodeURIComponent(input.integrationId)}`, { apiKey: input.apiKey, method: "GET" });
406
+ }
407
+ catch (error) {
408
+ if (error instanceof ServerHttpError && error.status === 404) {
409
+ return undefined;
410
+ }
411
+ throw error;
412
+ }
413
+ }
414
+ async getOrganizationProfiles(input) {
415
+ const data = await this.requestData(`/api/v1/organizations/${encodeURIComponent(input.organizationId)}/profiles`, { apiKey: input.apiKey, method: "GET" });
416
+ if (!Array.isArray(data)) {
417
+ return [];
418
+ }
419
+ return data
420
+ .filter((row) => typeof row?.key === "string" && row.key.length > 0)
421
+ .map((row) => ({
422
+ ...(row.allowedInEditor !== undefined
423
+ ? { allowedInEditor: row.allowedInEditor }
424
+ : {}),
425
+ ...(row.displayName ? { displayName: row.displayName } : {}),
426
+ ...(row.id ? { id: row.id } : {}),
427
+ key: row.key,
428
+ }));
429
+ }
430
+ /**
431
+ * Snapshots the application's current live-edit state as a commit.
432
+ *
433
+ * Deploys address a commit, never a branch head, so anything publishing work
434
+ * that has not been committed yet has to make one first — the same thing the
435
+ * editor's publish flow does.
436
+ */
437
+ async createCommit(input) {
438
+ const branchSegment = input.branch
439
+ ? `/branches/${encodeURIComponent(input.branch)}`
440
+ : "";
441
+ const data = await this.requestData(`/api/v2/applications/${input.applicationId}${branchSegment}/commit`, {
442
+ apiKey: input.apiKey,
443
+ body: JSON.stringify({
444
+ commitMessage: input.message,
445
+ // The server compares this against the last live-edit write to catch
446
+ // a commit racing an editor that has moved on since.
447
+ lastSuccessfulWrite: Date.now(),
448
+ }),
449
+ method: "POST",
450
+ });
451
+ return {
452
+ commitId: data.commitId,
453
+ ...(data.directoryContentsHash
454
+ ? { directoryHash: data.directoryContentsHash }
455
+ : {}),
456
+ };
457
+ }
458
+ /**
459
+ * Starts a SABS build of a commit's content, the same call the editor makes
460
+ * behind Preview and behind a publish.
461
+ *
462
+ * The response carries a build id this caller has no use for: progress is
463
+ * observed by content hash, which is also how a preview and a publish of the
464
+ * same content end up watching one build instead of racing two.
465
+ */
466
+ async createBuild(input) {
467
+ await this.request(`/api/v3/applications/${input.applicationId}/${encodeURIComponent(input.directoryHash)}/builds`, {
468
+ apiKey: input.apiKey,
469
+ body: JSON.stringify({ commitId: input.commitId }),
470
+ method: "POST",
471
+ });
472
+ }
473
+ async getBuildProgress(input) {
474
+ const path = `/api/v3/applications/${input.applicationId}/build-bulk-status`;
475
+ // POST because the hashes go in the body, but it is a read: the server
476
+ // asks SABS for status and changes nothing.
477
+ const data = await this.requestData(path, {
478
+ apiKey: input.apiKey,
479
+ body: JSON.stringify({ directoryHashes: [input.directoryHash] }),
480
+ method: "POST",
481
+ });
482
+ // Absent for content SABS has never built. Same meaning as UNSPECIFIED:
483
+ // there is no build to wait for.
484
+ return buildProgress(data.directoryHashToStatus?.[input.directoryHash]?.status);
485
+ }
486
+ async deployApplication(input) {
487
+ const path = `/api/v2/applications/${input.applicationId}/deployments`;
488
+ const body = await this.request(path, {
489
+ apiKey: input.apiKey,
490
+ // PostApplicationDeployRequestBody rejects unknown properties, so this
491
+ // body carries the commit and nothing else — the branch is already
492
+ // fixed by the commit being deployed.
493
+ body: JSON.stringify({ commitId: input.commitId }),
494
+ method: "POST",
495
+ });
496
+ if (body?.data?.deploymentId) {
497
+ return { deploymentId: body.data.deploymentId, status: "deployed" };
498
+ }
499
+ if (isDeployStatus(body?.status)) {
500
+ return { message: body?.message, status: body.status };
501
+ }
502
+ // Neither shape. Guessing "it worked" here would report a publish that
503
+ // never happened as a success.
504
+ throw new Error(`Server ${path} returned neither a deployment nor a deploy status`);
505
+ }
506
+ /**
507
+ * Polls the deploy queue for a commit the UI watches after a queued publish.
508
+ */
509
+ async getDeployStatus(input) {
510
+ const path = `/api/v2/applications/${input.applicationId}/deploy-status/${encodeURIComponent(input.commitId)}`;
511
+ const body = await this.request(path, {
512
+ apiKey: input.apiKey,
513
+ method: "GET",
514
+ });
515
+ const status = body?.status;
516
+ if (status === "none" ||
517
+ status === "QUEUED" ||
518
+ status === "DEPLOYING" ||
519
+ status === "DEPLOYED" ||
520
+ status === "FAILED" ||
521
+ status === "AWAITING_ACK") {
522
+ return {
523
+ error: typeof body?.error === "string" ? body.error : undefined,
524
+ isLive: typeof body?.isLive === "boolean" ? body.isLive : undefined,
525
+ status,
526
+ };
527
+ }
528
+ throw new Error(`Server ${path} returned an unknown deploy status`);
529
+ }
530
+ /**
531
+ * Asks Clark for an app name, the same way the editor header does after a
532
+ * prompt-created app loads.
533
+ */
534
+ async generateAppName(input) {
535
+ // Another bare body rather than the `{ responseMeta, data }` envelope.
536
+ const data = await this.request("/api/v1/ai/generate-app-name", {
537
+ apiKey: input.apiKey,
538
+ body: JSON.stringify({
539
+ applicationId: input.applicationId,
540
+ prompt: input.prompt,
541
+ }),
542
+ method: "POST",
543
+ });
544
+ if (!data?.name?.trim()) {
545
+ throw new Error("Server /api/v1/ai/generate-app-name returned no name");
546
+ }
547
+ return data.name.trim();
548
+ }
549
+ /**
550
+ * Looks a name up in the org-wide application listing.
551
+ *
552
+ * The API exposes no single-application GET that carries a name — only this
553
+ * listing and the metadata PUT — so one label costs a list read. That is
554
+ * affordable where it is used (alongside a build and a screenshot) and is
555
+ * why nothing on a hot path should call it.
556
+ */
557
+ async getApplicationName(input) {
558
+ const body = await this.request("/api/v2/applications", { apiKey: input.apiKey, method: "GET" });
559
+ const found = body?.data?.applications?.find((application) => application?.id === input.applicationId);
560
+ return found?.name?.trim() || undefined;
561
+ }
562
+ async renameApplication(input) {
563
+ await this.request(`/api/v2/applications/${input.applicationId}/metadata`, {
564
+ apiKey: input.apiKey,
565
+ // PutApplicationMetadataUpdateRequestBody accepts exactly one of name,
566
+ // folderId, or isPublic — sending more than one fails validation.
567
+ body: JSON.stringify({ name: input.name }),
568
+ method: "PUT",
569
+ });
570
+ }
571
+ }
572
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/server/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAItE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAGL,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAwF7B,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;;GAKG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,MAId,CAAC;YACF,MAAM,OAAO,GACX,MAAM,CAAC,YAAY,EAAE,OAAO,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC;YACjE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBAClD,MAAM,GAAG,OAAO,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC1D,OAAO,MAAM,OAAO,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAG7B;IAFX,YACE,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAwID;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAkB3C;;;;;;;;;;;;;;GAcG;AACH,SAAS,yBAAyB,CAAC,KAAc;IAC/C,OAAO,CAAC,CACN,KAAK,YAAY,eAAe;QAChC,KAAK,CAAC,MAAM,GAAG,GAAG;QAClB,KAAK,CAAC,MAAM,KAAK,GAAG,CACrB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,eAAe,GAAG;IACtB,cAAc;IACd,UAAU;IACV,QAAQ;IACR,QAAQ;CACA,CAAC;AAEX,SAAS,cAAc,CACrB,KAAc;IAEd,OAAO,eAAe,CAAC,QAAQ,CAAC,KAA4C,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,yBAAyB,GAAkC;IAC/D,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,QAAQ;IACX,CAAC,EAAE,WAAW;CACf,CAAC;AAEF,MAAM,sBAAsB,GAAkC;IAC5D,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,WAAW,EAAE,MAAM;CACpB,CAAC;AAEF,SAAS,aAAa,CAAC,MAAmC;IACxD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,yBAAyB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;IACrD,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,GAAG,MAAM;SAChB,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IACjC,OAAO,sBAAsB,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,2BAA2B;IACrB,iBAAiB,CAAS;IAC1B,YAAY,CAAuC;IACnD,SAAS,CAAS;IAClB,SAAS,CAAS;IAEnC,YAAY,SAAiB,EAAE,UAA0C,EAAE;QACzE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACzD,IAAI,CAAC,iBAAiB;YACpB,OAAO,CAAC,iBAAiB,IAAI,2BAA2B,CAAC;QAC3D,IAAI,CAAC,YAAY,GAAG,wBAAwB,CAC1C,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,EAC/C;YACE,SAAS,EAAE,yBAAyB;YACpC,YAAY,EAAE,yBAAyB;YACvC,GAAG,OAAO,CAAC,aAAa;SACzB,CACF,CAAC;IACJ,CAAC;IAEO,OAAO;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,WAAW,CACvB,IAAY,EACZ,IAAuB;QAEvB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAe,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1D,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,qEAAqE,CACpF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,IAAuB;QAC5D,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;QACjE,IAAI,SAAkB,CAAC;QACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAI,CAAC;YACzE,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,IAAI,CAAI,IAAI,EAAE,IAAI,CAAC,CAAC;YACxC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAK,CAAC;gBAClB,MAAM,SAAS,GACb,KAAK,YAAY,eAAe;oBAChC,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;gBAChD,OAAO,IAAI,CAAC,CAAC;gBACb,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,IAAI,OAAO,GAAG,mBAAmB,EAAE,CAAC;oBAC9D,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,MAAM,KAAK,CAAC,wBAAwB,GAAG,OAAO,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QACD,MAAM,SAAS,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,IAAI,CAAI,IAAY,EAAE,IAAuB;QACzD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACpE,MAAM,KAAK,GAAG,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC;QAC1C,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;QACjD,gFAAgF;QAChF,aAAa,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YACvC,aAAa,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE;gBACjD,GAAG,IAAI;gBACP,OAAO,EAAE,aAAa;gBACtB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAC5D,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,oBAAoB,KAAK,IAAI,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,eAAe,CACvB,UAAU,IAAI,YAAY,QAAQ,CAAC,MAAM,GAAG,YAAY,CACtD,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CACtC,EAAE,EACH,QAAQ,CAAC,MAAM,CAChB,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;IACtC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,cAAc,CAClB,MAAc;QAEd,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,wDAAwD;IAChD,KAAK,CAAC,sBAAsB,CAClC,MAAc;QAEd,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAOhC,kBAAkB,EAAE;gBACrB,MAAM;gBACN,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,IAAI,CAAC,iBAAiB;aAClC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACvB,MAAM,cAAc,GAClB,IAAI,EAAE,qBAAqB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC7D,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC7B,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,cAAc;gBACd,MAAM,EAAE,IAAI,CAAC,EAAE;aAChB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,8EAA8E;YAC9E,IAAI,KAAK,YAAY,eAAe,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC7D,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAGvB;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAShC,kBAAkB,EAAE;YACrB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK;YACb,wEAAwE;YACxE,+DAA+D;YAC/D,gEAAgE;YAChE,SAAS,EAAE,IAAI,CAAC,iBAAiB;SAClC,CAAC,CAAC;QAEH,MAAM,YAAY,GAChB,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,CAAC,cAAc,CAAC;YAClE,IAAI,CAAC,aAAa,EAAE,IAAI,CACtB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,qBAAqB,CACrD;YACD,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,YAAY,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,kEAAkE,KAAK,CAAC,cAAc,EAAE,CACzF,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAiC,EAAE,CAAC;QAChD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACpC,IACE,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;gBAC3B,CAAC,GAAG,CAAC,GAAG;gBACR,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAC5B,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAC9B,CAAC;gBACD,SAAS;YACX,CAAC;YACD,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,GAAG,EAAE,GAAG,CAAC,GAAG;aACb,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,SAAS,EAAE,YAAY,CAAC,SAAS;YACjC,MAAM;SACP,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAKvB;QACC,OAAO,IAAI,CAAC,WAAW,CACrB,uBAAuB,EACvB;YACE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,qEAAqE;YACrE,oDAAoD;YACpD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,gBAAgB,EAAE,IAAI;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;YACF,MAAM,EAAE,MAAM;SACf,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAMtB;QACC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,iBAAiB,CAAC;QACrD,iEAAiE;QACjE,iDAAiD;QACjD,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC;YACjD,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,aAAa,EAAE,UAAU,KAAK,CAAC,MAAM,EAAE;YACvC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;YACvB,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAC9D,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ;aACT;YACD,MAAM,EAAE,oBAAoB;YAC5B,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,OAAO;YACL,aAAa,EAAE,QAAQ,CAAC,aAAa;YACrC,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;YAC/C,UAAU,EAAE,QAAQ,CAAC,UAAU;SAChC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAIrB;QACC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM;YAChC,CAAC,CAAC,aAAa,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;YACjD,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAMhC,wBAAwB,KAAK,CAAC,aAAa,GAAG,aAAa,UAAU,EAAE;YACxE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,iEAAiE;YACjE,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;QACJ,CAAC;QACD,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,SAAS;YAC3C,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,UAAU;YAC7C,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC,YAAY;YAChD,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,UAAU;SAC7C,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CAAC,KAOtB;QACC,yEAAyE;QACzE,0DAA0D;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,aAAa,CAAC;QAC3C,MAAM,IAAI,GAA2B;YACnC,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,KAAK;SACN,CAAC;QACF,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QACjC,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAC7B,sBAAsB,EACtB;YACE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,MAAM;SACf,CACF,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,mGAAmG,CACpG,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,KAI7B;QACC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,mEAAmE;YACnE,qEAAqE;YACrE,+BAA+B;YAC/B,IAAI,EAAE,QAAQ;YACd,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;QACH,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CACjC,iCAAiC,MAAM,CAAC,QAAQ,EAAE,EAAE,EACpD,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CACxC,CAAC;QACF,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAGpB;QACC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,WAAW,CAC3B,wBAAwB,kBAAkB,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,EACjE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CACxC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,eAAe,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC7D,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,KAG7B;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CACjC,yBAAyB,kBAAkB,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAC5E,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CACxC,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,IAAI;aACR,MAAM,CACL,CAAC,GAAG,EAAyD,EAAE,CAC7D,OAAO,GAAG,EAAE,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CACrD;aACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACb,GAAG,CAAC,GAAG,CAAC,eAAe,KAAK,SAAS;gBACnC,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE;gBAC1C,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,GAAG,EAAE,GAAG,CAAC,GAAG;SACb,CAAC,CAAC,CAAC;IACR,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAC,KAKlB;QACC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM;YAChC,CAAC,CAAC,aAAa,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;YACjD,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAGhC,wBAAwB,KAAK,CAAC,aAAa,GAAG,aAAa,SAAS,EAAE;YACvE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,aAAa,EAAE,KAAK,CAAC,OAAO;gBAC5B,qEAAqE;gBACrE,qDAAqD;gBACrD,mBAAmB,EAAE,IAAI,CAAC,GAAG,EAAE;aAChC,CAAC;YACF,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,CAAC,IAAI,CAAC,qBAAqB;gBAC5B,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,qBAAqB,EAAE;gBAC/C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,WAAW,CAAC,KAKjB;QACC,MAAM,IAAI,CAAC,OAAO,CAChB,wBAAwB,KAAK,CAAC,aAAa,IAAI,kBAAkB,CAC/D,KAAK,CAAC,aAAa,CACpB,SAAS,EACV;YACE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;YAClD,MAAM,EAAE,MAAM;SACf,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAItB;QACC,MAAM,IAAI,GAAG,wBAAwB,KAAK,CAAC,aAAa,oBAAoB,CAAC;QAC7E,uEAAuE;QACvE,4CAA4C;QAC5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAEhC,IAAI,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YAChE,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,wEAAwE;QACxE,iCAAiC;QACjC,OAAO,aAAa,CAClB,IAAI,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,CAC1D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAIvB;QACC,MAAM,IAAI,GAAG,wBAAwB,KAAK,CAAC,aAAa,cAAc,CAAC;QACvE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAI5B,IAAI,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,uEAAuE;YACvE,mEAAmE;YACnE,sCAAsC;YACtC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;YAClD,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,IAAI,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;YAC7B,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACtE,CAAC;QACD,IAAI,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;YACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QACzD,CAAC;QACD,uEAAuE;QACvE,+BAA+B;QAC/B,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,oDAAoD,CACnE,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,KAIrB;QACC,MAAM,IAAI,GAAG,wBAAwB,KAAK,CAAC,aAAa,kBAAkB,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/G,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAI5B,IAAI,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;QAC5B,IACE,MAAM,KAAK,MAAM;YACjB,MAAM,KAAK,QAAQ;YACnB,MAAM,KAAK,WAAW;YACtB,MAAM,KAAK,UAAU;YACrB,MAAM,KAAK,QAAQ;YACnB,MAAM,KAAK,cAAc,EACzB,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,OAAO,IAAI,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;gBAC/D,MAAM,EAAE,OAAO,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACnE,MAAM;aACP,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,oCAAoC,CAAC,CAAC;IACtE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,KAIrB;QACC,uEAAuE;QACvE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAC7B,8BAA8B,EAC9B;YACE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC;YACF,MAAM,EAAE,MAAM;SACf,CACF,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,kBAAkB,CAAC,KAGxB;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAE5B,sBAAsB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAC1C,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,KAAK,KAAK,CAAC,aAAa,CACzD,CAAC;QACF,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAIvB;QACC,MAAM,IAAI,CAAC,OAAO,CAChB,wBAAwB,KAAK,CAAC,aAAa,WAAW,EACtD;YACE,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,uEAAuE;YACvE,kEAAkE;YAClE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAC1C,MAAM,EAAE,KAAK;SACd,CACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Why an identity lookup produced no answer.
3
+ *
4
+ * `caller_timeout` and `read_failed` need telling apart: the first means the
5
+ * endpoint is slow and the cache is about to fill, the second means it is down.
6
+ */
7
+ export type IdentityUnavailableReason = "breaker_open" | "caller_timeout" | "read_failed";
8
+ /**
9
+ * The identity lookup did not produce an answer this caller can act on.
10
+ *
11
+ * Distinct from "the credential was refused": nothing is known about the
12
+ * caller's account, so the right response is to try again rather than to
13
+ * re-link. Capabilities map this to `downstream_unavailable`.
14
+ */
15
+ export declare class IdentityUnavailableError extends Error {
16
+ readonly reason: IdentityUnavailableReason;
17
+ constructor(message: string, options?: {
18
+ cause?: unknown;
19
+ reason?: IdentityUnavailableReason;
20
+ });
21
+ }
22
+ /**
23
+ * What one guarded call cost. A closed set because it becomes a metric label.
24
+ */
25
+ export type IdentityReadOutcome = "breaker_open" | "cached" | "caller_timeout"
26
+ /**
27
+ * The read failed in a way that says something about this one credential
28
+ * rather than about the endpoint — the errors `opensBreaker` rejects.
29
+ * Separate from `outage` so a client looping on a revoked key cannot make a
30
+ * healthy endpoint look like it is failing.
31
+ */
32
+ | "credential_error" | "outage" | "refused" | "resolved";
33
+ /** Resolves the identity behind a downstream credential, or refuses it. */
34
+ export type IdentityRead<T> = (apiKey: string) => Promise<T | undefined>;
35
+ export type GuardedIdentityReadOptions = {
36
+ /** How long a resolved identity is trusted before the API is asked again. */
37
+ cacheTtlMs?: number;
38
+ /** How long one caller waits for a read before it gives up on this call. */
39
+ callerWaitMs?: number;
40
+ /** How long reads fail fast after the API failed to answer one. */
41
+ cooldownMs?: number;
42
+ now?: () => number;
43
+ /** Reports what one call cost. Wired to a counter in the HTTP client. */
44
+ onOutcome?: (outcome: IdentityReadOutcome) => void;
45
+ /**
46
+ * Whether a failed read means the endpoint is unhealthy, rather than that
47
+ * this one credential was refused. Only the former opens the breaker: a
48
+ * single bad credential must not fail every other caller fast.
49
+ */
50
+ opensBreaker?: (error: unknown) => boolean;
51
+ };
52
+ /**
53
+ * Makes the identity lookup that every tool call gates on cheap and bounded.
54
+ *
55
+ * `GET /api/v1/users/me` is the first thing every capability does and the
56
+ * slowest endpoint the Superblocks API exposes. Read straight through, one
57
+ * wedged upstream took down the whole tool surface: each call waited out the
58
+ * full client timeout, a burst of callers multiplied the load on the endpoint
59
+ * that was already stuck, and nothing remembered that the last twenty calls
60
+ * had just failed the same way.
61
+ *
62
+ * Four things fix that, and they have to work together:
63
+ *
64
+ * - **Cache.** Identity does not change between polls, so a poll loop spends
65
+ * one read per TTL instead of one per call.
66
+ * - **Collapse.** Concurrent callers on a cold cache join one read rather than
67
+ * each starting their own.
68
+ * - **Caller deadline.** A tool call stops waiting at the window its own
69
+ * contract advertises. The read keeps running, so an endpoint that answers
70
+ * slowly still fills the cache and the next call is served from it — the
71
+ * reason this is a deadline on the wait and not a shorter timeout on the
72
+ * read.
73
+ * - **Breaker.** Once a read fails, later calls fail fast for a cooldown
74
+ * instead of each discovering the same outage the slow way.
75
+ */
76
+ export declare function withGuardedIdentityReads<T>(read: IdentityRead<T>, options?: GuardedIdentityReadOptions): IdentityRead<T>;