@amigo-ai/platform-sdk 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.md +6 -3
- package/dist/core/errors.js +155 -9
- package/dist/core/errors.js.map +1 -1
- package/dist/core/reconnecting-websocket.js +371 -0
- package/dist/core/reconnecting-websocket.js.map +1 -0
- package/dist/index.cjs +711 -13
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +711 -13
- package/dist/index.mjs.map +4 -4
- package/dist/resources/events.js +139 -3
- package/dist/resources/events.js.map +1 -1
- package/dist/resources/integrations.js +25 -0
- package/dist/resources/integrations.js.map +1 -1
- package/dist/resources/observers.js +238 -0
- package/dist/resources/observers.js.map +1 -0
- package/dist/types/core/errors.d.ts +93 -1
- package/dist/types/core/errors.d.ts.map +1 -1
- package/dist/types/core/reconnecting-websocket.d.ts +156 -0
- package/dist/types/core/reconnecting-websocket.d.ts.map +1 -0
- package/dist/types/generated/api.d.ts +686 -113
- package/dist/types/generated/api.d.ts.map +1 -1
- package/dist/types/index.d.cts +42 -2
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +42 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/resources/events.d.ts +33 -0
- package/dist/types/resources/events.d.ts.map +1 -1
- package/dist/types/resources/functions.d.ts.map +1 -1
- package/dist/types/resources/integrations.d.ts +33 -0
- package/dist/types/resources/integrations.d.ts.map +1 -1
- package/dist/types/resources/metrics.d.ts.map +1 -1
- package/dist/types/resources/observers.d.ts +148 -0
- package/dist/types/resources/observers.d.ts.map +1 -0
- package/dist/types/resources/operators.d.ts.map +1 -1
- package/dist/types/resources/settings.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/core/errors.ts
|
|
2
|
+
var RAW_BODY_LIMIT = 8 * 1024;
|
|
2
3
|
var SENSITIVE_FIELDS = /* @__PURE__ */ new Set([
|
|
3
4
|
"id_token",
|
|
4
5
|
"access_token",
|
|
@@ -34,6 +35,20 @@ var AmigoError = class extends Error {
|
|
|
34
35
|
requestId;
|
|
35
36
|
detail;
|
|
36
37
|
context;
|
|
38
|
+
/**
|
|
39
|
+
* Typed body of the error response, when one was returned and successfully
|
|
40
|
+
* parsed. Use the `isHttpException` / `isHttpValidationError` /
|
|
41
|
+
* `isUnparseableErrorBody` type guards to narrow the discriminated union.
|
|
42
|
+
*
|
|
43
|
+
* Named `errorBody` (not `body`) to avoid colliding with the legacy
|
|
44
|
+
* `ParseError.body: string` field.
|
|
45
|
+
*/
|
|
46
|
+
errorBody;
|
|
47
|
+
/**
|
|
48
|
+
* Raw response body (truncated to 8 KB). Populated even when parsing fails,
|
|
49
|
+
* so callers always have something to log when debugging server errors.
|
|
50
|
+
*/
|
|
51
|
+
rawBody;
|
|
37
52
|
constructor(message, ctx = {}) {
|
|
38
53
|
super(message);
|
|
39
54
|
this.name = this.constructor.name;
|
|
@@ -42,6 +57,8 @@ var AmigoError = class extends Error {
|
|
|
42
57
|
this.requestId = ctx.requestId;
|
|
43
58
|
this.detail = ctx.detail;
|
|
44
59
|
this.context = ctx.context ? sanitizeErrorContext(ctx.context) : void 0;
|
|
60
|
+
this.errorBody = ctx.errorBody;
|
|
61
|
+
this.rawBody = ctx.rawBody;
|
|
45
62
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
46
63
|
if (typeof Error.captureStackTrace === "function") {
|
|
47
64
|
Error.captureStackTrace(this, this.constructor);
|
|
@@ -134,21 +151,69 @@ var ConfigurationError = class extends AmigoError {
|
|
|
134
151
|
super(message);
|
|
135
152
|
}
|
|
136
153
|
};
|
|
137
|
-
async function
|
|
138
|
-
let
|
|
154
|
+
async function readErrorBody(response) {
|
|
155
|
+
let rawBody = "";
|
|
139
156
|
try {
|
|
140
|
-
|
|
141
|
-
body = JSON.parse(rawBody);
|
|
157
|
+
rawBody = await response.text();
|
|
142
158
|
} catch {
|
|
159
|
+
return {
|
|
160
|
+
body: { detail: response.statusText || `HTTP ${response.status}`, raw_body: "" },
|
|
161
|
+
rawBody: ""
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
const truncatedRaw = rawBody.length > RAW_BODY_LIMIT ? rawBody.slice(0, RAW_BODY_LIMIT) : rawBody;
|
|
165
|
+
if (rawBody.length === 0) {
|
|
166
|
+
return {
|
|
167
|
+
body: { detail: response.statusText || `HTTP ${response.status}`, raw_body: "" },
|
|
168
|
+
rawBody: ""
|
|
169
|
+
};
|
|
143
170
|
}
|
|
171
|
+
try {
|
|
172
|
+
const parsed = JSON.parse(rawBody);
|
|
173
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
174
|
+
return { body: parsed, rawBody: truncatedRaw };
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
body: {
|
|
178
|
+
detail: response.statusText || `HTTP ${response.status}`,
|
|
179
|
+
raw_body: truncatedRaw
|
|
180
|
+
},
|
|
181
|
+
rawBody: truncatedRaw
|
|
182
|
+
};
|
|
183
|
+
} catch {
|
|
184
|
+
return {
|
|
185
|
+
body: {
|
|
186
|
+
detail: response.statusText || `HTTP ${response.status}`,
|
|
187
|
+
raw_body: truncatedRaw
|
|
188
|
+
},
|
|
189
|
+
rawBody: truncatedRaw
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function safeStringify(value) {
|
|
194
|
+
try {
|
|
195
|
+
return JSON.stringify(value);
|
|
196
|
+
} catch {
|
|
197
|
+
return String(value);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function createApiError(response) {
|
|
201
|
+
const { body, rawBody } = await readErrorBody(response);
|
|
202
|
+
const flat = body;
|
|
203
|
+
const detailString = typeof flat.detail === "string" ? flat.detail : flat.detail !== void 0 ? safeStringify(flat.detail) : void 0;
|
|
204
|
+
const errorCode = typeof flat.error_code === "string" ? flat.error_code : void 0;
|
|
205
|
+
const requestIdFromBody = typeof flat.request_id === "string" ? flat.request_id : void 0;
|
|
206
|
+
const messageFromBody = typeof flat.message === "string" ? flat.message : void 0;
|
|
144
207
|
const ctx = {
|
|
145
208
|
statusCode: response.status,
|
|
146
|
-
errorCode
|
|
147
|
-
requestId:
|
|
148
|
-
detail:
|
|
149
|
-
context: { url: response.url, response: body }
|
|
209
|
+
errorCode,
|
|
210
|
+
requestId: requestIdFromBody ?? response.headers.get("x-request-id") ?? void 0,
|
|
211
|
+
detail: detailString,
|
|
212
|
+
context: { url: response.url, response: body },
|
|
213
|
+
errorBody: body,
|
|
214
|
+
rawBody
|
|
150
215
|
};
|
|
151
|
-
const message =
|
|
216
|
+
const message = messageFromBody ?? detailString ?? response.statusText ?? `HTTP ${response.status}`;
|
|
152
217
|
switch (response.status) {
|
|
153
218
|
case 400:
|
|
154
219
|
return new BadRequestError(message, ctx);
|
|
@@ -198,6 +263,40 @@ function isAuthenticationError(err) {
|
|
|
198
263
|
function isRequestTimeoutError(err) {
|
|
199
264
|
return err instanceof RequestTimeoutError;
|
|
200
265
|
}
|
|
266
|
+
function isPermissionError(err) {
|
|
267
|
+
return err instanceof PermissionError;
|
|
268
|
+
}
|
|
269
|
+
function isConflictError(err) {
|
|
270
|
+
return err instanceof ConflictError;
|
|
271
|
+
}
|
|
272
|
+
function isValidationError(err) {
|
|
273
|
+
return err instanceof ValidationError;
|
|
274
|
+
}
|
|
275
|
+
function isServerError(err) {
|
|
276
|
+
return err instanceof ServerError;
|
|
277
|
+
}
|
|
278
|
+
function isNetworkError(err) {
|
|
279
|
+
return err instanceof NetworkError;
|
|
280
|
+
}
|
|
281
|
+
function isHttpValidationError(err) {
|
|
282
|
+
if (!(err instanceof AmigoError)) return false;
|
|
283
|
+
const body = err.errorBody;
|
|
284
|
+
return Array.isArray(body?.detail);
|
|
285
|
+
}
|
|
286
|
+
function isHttpException(err) {
|
|
287
|
+
if (!(err instanceof AmigoError)) return false;
|
|
288
|
+
const body = err.errorBody;
|
|
289
|
+
if (!body) return false;
|
|
290
|
+
if (Array.isArray(body.detail)) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
return "detail" in body && !("raw_body" in body);
|
|
294
|
+
}
|
|
295
|
+
function isUnparseableErrorBody(err) {
|
|
296
|
+
if (!(err instanceof AmigoError)) return false;
|
|
297
|
+
const body = err.errorBody;
|
|
298
|
+
return typeof body?.raw_body === "string";
|
|
299
|
+
}
|
|
201
300
|
|
|
202
301
|
// src/core/openapi-client.ts
|
|
203
302
|
import createClientImport from "openapi-fetch";
|
|
@@ -2361,6 +2460,36 @@ var IntegrationsResource = class extends WorkspaceScopedResource {
|
|
|
2361
2460
|
)
|
|
2362
2461
|
);
|
|
2363
2462
|
}
|
|
2463
|
+
/**
|
|
2464
|
+
* Probe an integration's connection + auth without invoking any specific
|
|
2465
|
+
* endpoint. Exercises auth resolution end-to-end (SSM lookups, OAuth2 token
|
|
2466
|
+
* mints, JWT signing) and sends a HEAD request to ``base_url`` (REST/FHIR)
|
|
2467
|
+
* or ``mcp_url`` (MCP). Safe on production integrations — HEAD carries no
|
|
2468
|
+
* side effects.
|
|
2469
|
+
*
|
|
2470
|
+
* The most recent probe outcome is persisted on the integration so
|
|
2471
|
+
* subsequent ``get`` / ``list`` responses surface ``last_tested_at`` +
|
|
2472
|
+
* ``last_test_status`` without re-probing.
|
|
2473
|
+
*
|
|
2474
|
+
* @returns ``status`` is one of ``healthy`` / ``auth_failed`` /
|
|
2475
|
+
* ``unreachable`` / ``timeout`` / ``ssl_error`` / ``misconfigured``,
|
|
2476
|
+
* each mapping to a distinct, actionable user message.
|
|
2477
|
+
*/
|
|
2478
|
+
async testConnection(integrationId2) {
|
|
2479
|
+
return extractData(
|
|
2480
|
+
await this.client.POST(
|
|
2481
|
+
"/v1/{workspace_id}/integrations/{integration_id}/test-connection",
|
|
2482
|
+
{
|
|
2483
|
+
params: {
|
|
2484
|
+
path: {
|
|
2485
|
+
workspace_id: this.workspaceId,
|
|
2486
|
+
integration_id: integrationId2
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
)
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2364
2493
|
/** Check health of all integrations in the workspace */
|
|
2365
2494
|
async getHealthCheck() {
|
|
2366
2495
|
return extractData(
|
|
@@ -3251,6 +3380,22 @@ var ComplianceResource = class extends WorkspaceScopedResource {
|
|
|
3251
3380
|
};
|
|
3252
3381
|
|
|
3253
3382
|
// src/resources/events.ts
|
|
3383
|
+
var WorkspaceEventStreamError = class extends Error {
|
|
3384
|
+
code;
|
|
3385
|
+
retryable;
|
|
3386
|
+
/** Raw decoded ``error`` frame body (or ``undefined`` for transport errors). */
|
|
3387
|
+
frame;
|
|
3388
|
+
constructor(message, code, retryable, frame) {
|
|
3389
|
+
super(message);
|
|
3390
|
+
this.name = "WorkspaceEventStreamError";
|
|
3391
|
+
this.code = code;
|
|
3392
|
+
this.retryable = retryable;
|
|
3393
|
+
this.frame = frame;
|
|
3394
|
+
}
|
|
3395
|
+
};
|
|
3396
|
+
function isWorkspaceEventStreamError(value) {
|
|
3397
|
+
return value instanceof WorkspaceEventStreamError;
|
|
3398
|
+
}
|
|
3254
3399
|
var DEFAULT_INITIAL_DELAY_MS = 3e3;
|
|
3255
3400
|
var DEFAULT_MAX_DELAY_MS = 3e4;
|
|
3256
3401
|
var DEFAULT_MAX_RECONNECTS = 10;
|
|
@@ -3302,6 +3447,13 @@ var EventsResource = class extends WorkspaceScopedResource {
|
|
|
3302
3447
|
};
|
|
3303
3448
|
}
|
|
3304
3449
|
};
|
|
3450
|
+
var TERMINAL_SERVER_ERROR_CODES = {
|
|
3451
|
+
too_many_streams: "too_many_streams"
|
|
3452
|
+
};
|
|
3453
|
+
var RECOVERABLE_SERVER_ERROR_CODES = {
|
|
3454
|
+
stream_unavailable: "stream_unavailable",
|
|
3455
|
+
stream_error: "stream_error"
|
|
3456
|
+
};
|
|
3305
3457
|
async function runSubscription(client, workspaceId2, options, signal) {
|
|
3306
3458
|
let lastEventId = options.lastEventId;
|
|
3307
3459
|
let attempt = 0;
|
|
@@ -3350,10 +3502,23 @@ async function runSubscription(client, workspaceId2, options, signal) {
|
|
|
3350
3502
|
reportError(outcome.error);
|
|
3351
3503
|
return;
|
|
3352
3504
|
}
|
|
3505
|
+
if (outcome.kind === "terminal-server-error") {
|
|
3506
|
+
reportError(
|
|
3507
|
+
new WorkspaceEventStreamError(
|
|
3508
|
+
outcome.message,
|
|
3509
|
+
outcome.code,
|
|
3510
|
+
outcome.retryable,
|
|
3511
|
+
outcome.frame
|
|
3512
|
+
)
|
|
3513
|
+
);
|
|
3514
|
+
return;
|
|
3515
|
+
}
|
|
3353
3516
|
if (attempt >= maxReconnects) {
|
|
3354
3517
|
reportError(
|
|
3355
|
-
new
|
|
3356
|
-
`SSE subscription exhausted reconnect budget (${maxReconnects}): ${outcome.reason}
|
|
3518
|
+
new WorkspaceEventStreamError(
|
|
3519
|
+
`SSE subscription exhausted reconnect budget (${maxReconnects}): ${outcome.reason}`,
|
|
3520
|
+
"transport_exhausted",
|
|
3521
|
+
true
|
|
3357
3522
|
)
|
|
3358
3523
|
);
|
|
3359
3524
|
return;
|
|
@@ -3388,7 +3553,7 @@ async function runOneConnection(args) {
|
|
|
3388
3553
|
return { kind: "transport-error", reason: error.message };
|
|
3389
3554
|
}
|
|
3390
3555
|
if (result.error !== void 0) {
|
|
3391
|
-
return { kind: "transport-error", reason: `API error: ${
|
|
3556
|
+
return { kind: "transport-error", reason: `API error: ${safeStringify2(result.error)}` };
|
|
3392
3557
|
}
|
|
3393
3558
|
const body = result.data;
|
|
3394
3559
|
if (!(body instanceof ReadableStream)) {
|
|
@@ -3403,6 +3568,19 @@ async function runOneConnection(args) {
|
|
|
3403
3568
|
if (frame.id !== void 0) {
|
|
3404
3569
|
args.onIdAdvance(frame.id);
|
|
3405
3570
|
}
|
|
3571
|
+
if (frame.event === "error" && frame.data !== void 0) {
|
|
3572
|
+
const errOutcome = interpretServerErrorFrame(frame.data);
|
|
3573
|
+
if (errOutcome.terminal) {
|
|
3574
|
+
return {
|
|
3575
|
+
kind: "terminal-server-error",
|
|
3576
|
+
code: errOutcome.code,
|
|
3577
|
+
message: errOutcome.message,
|
|
3578
|
+
retryable: errOutcome.retryable,
|
|
3579
|
+
frame: errOutcome.frame
|
|
3580
|
+
};
|
|
3581
|
+
}
|
|
3582
|
+
return { kind: "transport-error", reason: errOutcome.message };
|
|
3583
|
+
}
|
|
3406
3584
|
if (frame.event && frame.data !== void 0) {
|
|
3407
3585
|
const event = parseWorkspaceFrame(frame.event, frame.data);
|
|
3408
3586
|
if (event) {
|
|
@@ -3526,12 +3704,63 @@ function parseWorkspaceFrame(eventName, dataJson) {
|
|
|
3526
3704
|
event_type: eventName
|
|
3527
3705
|
};
|
|
3528
3706
|
}
|
|
3707
|
+
function interpretServerErrorFrame(dataJson) {
|
|
3708
|
+
let payload;
|
|
3709
|
+
try {
|
|
3710
|
+
payload = JSON.parse(dataJson);
|
|
3711
|
+
} catch {
|
|
3712
|
+
return {
|
|
3713
|
+
terminal: false,
|
|
3714
|
+
code: "stream_error",
|
|
3715
|
+
message: "Server sent malformed error frame",
|
|
3716
|
+
retryable: true,
|
|
3717
|
+
frame: {}
|
|
3718
|
+
};
|
|
3719
|
+
}
|
|
3720
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) {
|
|
3721
|
+
return {
|
|
3722
|
+
terminal: false,
|
|
3723
|
+
code: "stream_error",
|
|
3724
|
+
message: "Server sent non-object error frame",
|
|
3725
|
+
retryable: true,
|
|
3726
|
+
frame: {}
|
|
3727
|
+
};
|
|
3728
|
+
}
|
|
3729
|
+
const obj = payload;
|
|
3730
|
+
const rawCode = typeof obj["code"] === "string" ? obj["code"] : "";
|
|
3731
|
+
const message = typeof obj["message"] === "string" ? obj["message"] : "Stream error";
|
|
3732
|
+
if (rawCode in TERMINAL_SERVER_ERROR_CODES) {
|
|
3733
|
+
return {
|
|
3734
|
+
terminal: true,
|
|
3735
|
+
code: TERMINAL_SERVER_ERROR_CODES[rawCode],
|
|
3736
|
+
message,
|
|
3737
|
+
retryable: false,
|
|
3738
|
+
frame: obj
|
|
3739
|
+
};
|
|
3740
|
+
}
|
|
3741
|
+
if (rawCode in RECOVERABLE_SERVER_ERROR_CODES) {
|
|
3742
|
+
return {
|
|
3743
|
+
terminal: false,
|
|
3744
|
+
code: RECOVERABLE_SERVER_ERROR_CODES[rawCode],
|
|
3745
|
+
message,
|
|
3746
|
+
retryable: true,
|
|
3747
|
+
frame: obj
|
|
3748
|
+
};
|
|
3749
|
+
}
|
|
3750
|
+
return {
|
|
3751
|
+
terminal: false,
|
|
3752
|
+
code: "unknown",
|
|
3753
|
+
message: rawCode ? `${message} (code=${rawCode})` : message,
|
|
3754
|
+
retryable: true,
|
|
3755
|
+
frame: obj
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3529
3758
|
function readStatus(error) {
|
|
3530
3759
|
if (typeof error !== "object" || error === null) return void 0;
|
|
3531
3760
|
const status = error.statusCode;
|
|
3532
3761
|
return typeof status === "number" ? status : void 0;
|
|
3533
3762
|
}
|
|
3534
|
-
function
|
|
3763
|
+
function safeStringify2(value) {
|
|
3535
3764
|
try {
|
|
3536
3765
|
return JSON.stringify(value);
|
|
3537
3766
|
} catch {
|
|
@@ -3616,6 +3845,450 @@ var FunctionsResource = class extends WorkspaceScopedResource {
|
|
|
3616
3845
|
}
|
|
3617
3846
|
};
|
|
3618
3847
|
|
|
3848
|
+
// src/core/reconnecting-websocket.ts
|
|
3849
|
+
var ReconnectingWebSocketError = class extends Error {
|
|
3850
|
+
reason;
|
|
3851
|
+
closeCode;
|
|
3852
|
+
closeReason;
|
|
3853
|
+
attempts;
|
|
3854
|
+
constructor(message, reason, closeCode, closeReason, attempts) {
|
|
3855
|
+
super(message);
|
|
3856
|
+
this.name = "ReconnectingWebSocketError";
|
|
3857
|
+
this.reason = reason;
|
|
3858
|
+
this.closeCode = closeCode;
|
|
3859
|
+
this.closeReason = closeReason;
|
|
3860
|
+
this.attempts = attempts;
|
|
3861
|
+
}
|
|
3862
|
+
};
|
|
3863
|
+
var TERMINAL_CLOSE_CODES = /* @__PURE__ */ new Set([1008, 4001, 4003, 4100, 4403]);
|
|
3864
|
+
var RATE_LIMITED_CLOSE_CODES = /* @__PURE__ */ new Set([1013, 4029]);
|
|
3865
|
+
var RATE_LIMITED_FLOOR_MS = 5e3;
|
|
3866
|
+
var DEFAULT_INITIAL_DELAY_MS2 = 1e3;
|
|
3867
|
+
var DEFAULT_MAX_DELAY_MS2 = 3e4;
|
|
3868
|
+
var DEFAULT_MAX_RECONNECTS2 = 10;
|
|
3869
|
+
var DEFAULT_IDLE_TIMEOUT_MS = 45e3;
|
|
3870
|
+
function createReconnectingWebSocket(options) {
|
|
3871
|
+
const factory = resolveWebSocketFactory(options.webSocketFactory);
|
|
3872
|
+
const initialDelayMs = options.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS2;
|
|
3873
|
+
const maxDelayMs = options.maxDelayMs ?? DEFAULT_MAX_DELAY_MS2;
|
|
3874
|
+
const maxReconnects = options.maxReconnects ?? DEFAULT_MAX_RECONNECTS2;
|
|
3875
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
3876
|
+
const localController = new AbortController();
|
|
3877
|
+
if (options.signal) {
|
|
3878
|
+
if (options.signal.aborted) {
|
|
3879
|
+
localController.abort(options.signal.reason);
|
|
3880
|
+
} else {
|
|
3881
|
+
const onAbort = () => localController.abort(options.signal?.reason);
|
|
3882
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
let currentSocket = null;
|
|
3886
|
+
let state = "connecting";
|
|
3887
|
+
let errorReported = false;
|
|
3888
|
+
function setState(next) {
|
|
3889
|
+
if (state === next) return;
|
|
3890
|
+
state = next;
|
|
3891
|
+
try {
|
|
3892
|
+
options.onStateChange?.(next);
|
|
3893
|
+
} catch {
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
function reportError(err) {
|
|
3897
|
+
if (errorReported) return;
|
|
3898
|
+
errorReported = true;
|
|
3899
|
+
setState("terminal");
|
|
3900
|
+
try {
|
|
3901
|
+
options.onError?.(err);
|
|
3902
|
+
} catch {
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
const handle = {
|
|
3906
|
+
get state() {
|
|
3907
|
+
return state;
|
|
3908
|
+
},
|
|
3909
|
+
get done() {
|
|
3910
|
+
return done;
|
|
3911
|
+
},
|
|
3912
|
+
send(data) {
|
|
3913
|
+
if (!currentSocket || currentSocket.readyState !== 1) {
|
|
3914
|
+
throw new Error(`Cannot send on socket in state ${state}`);
|
|
3915
|
+
}
|
|
3916
|
+
currentSocket.send(data);
|
|
3917
|
+
},
|
|
3918
|
+
close(code, reason) {
|
|
3919
|
+
localController.abort(new Error(reason ?? "closed"));
|
|
3920
|
+
try {
|
|
3921
|
+
currentSocket?.close(code, reason);
|
|
3922
|
+
} catch {
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
const done = runLoop({
|
|
3927
|
+
factory,
|
|
3928
|
+
options,
|
|
3929
|
+
initialDelayMs,
|
|
3930
|
+
maxDelayMs,
|
|
3931
|
+
maxReconnects,
|
|
3932
|
+
idleTimeoutMs,
|
|
3933
|
+
signal: localController.signal,
|
|
3934
|
+
setState,
|
|
3935
|
+
reportError,
|
|
3936
|
+
setSocket: (s) => {
|
|
3937
|
+
currentSocket = s;
|
|
3938
|
+
}
|
|
3939
|
+
});
|
|
3940
|
+
return handle;
|
|
3941
|
+
}
|
|
3942
|
+
async function runLoop(args) {
|
|
3943
|
+
const { options, signal, setState, reportError, setSocket } = args;
|
|
3944
|
+
let attempt = 0;
|
|
3945
|
+
let delayMs = args.initialDelayMs;
|
|
3946
|
+
while (!signal.aborted) {
|
|
3947
|
+
if (attempt > 0) {
|
|
3948
|
+
setState("reconnecting");
|
|
3949
|
+
const sleepMs = jitter2(delayMs);
|
|
3950
|
+
try {
|
|
3951
|
+
options.onReconnect?.({ attempt, delayMs: sleepMs, closeCode: void 0 });
|
|
3952
|
+
} catch {
|
|
3953
|
+
}
|
|
3954
|
+
const slept = await abortableSleep2(sleepMs, signal);
|
|
3955
|
+
if (!slept) break;
|
|
3956
|
+
delayMs = Math.min(delayMs * 2, args.maxDelayMs);
|
|
3957
|
+
}
|
|
3958
|
+
setState(attempt === 0 ? "connecting" : "connecting");
|
|
3959
|
+
let outcome;
|
|
3960
|
+
try {
|
|
3961
|
+
outcome = await runOneConnection2(args);
|
|
3962
|
+
} catch (err) {
|
|
3963
|
+
reportError(
|
|
3964
|
+
new ReconnectingWebSocketError(
|
|
3965
|
+
err instanceof Error ? err.message : "Failed to open WebSocket",
|
|
3966
|
+
"open_failed",
|
|
3967
|
+
void 0,
|
|
3968
|
+
void 0,
|
|
3969
|
+
attempt
|
|
3970
|
+
)
|
|
3971
|
+
);
|
|
3972
|
+
return;
|
|
3973
|
+
} finally {
|
|
3974
|
+
setSocket(null);
|
|
3975
|
+
}
|
|
3976
|
+
if (outcome.closeCode !== void 0 && TERMINAL_CLOSE_CODES.has(outcome.closeCode)) {
|
|
3977
|
+
reportError(
|
|
3978
|
+
new ReconnectingWebSocketError(
|
|
3979
|
+
`Server closed with terminal code ${outcome.closeCode}: ${outcome.closeReason ?? ""}`,
|
|
3980
|
+
outcome.closeCode === 4403 ? "auth" : "client_error",
|
|
3981
|
+
outcome.closeCode,
|
|
3982
|
+
outcome.closeReason,
|
|
3983
|
+
attempt
|
|
3984
|
+
)
|
|
3985
|
+
);
|
|
3986
|
+
return;
|
|
3987
|
+
}
|
|
3988
|
+
if (outcome.aborted || signal.aborted) {
|
|
3989
|
+
setState("closed");
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3992
|
+
if (attempt >= args.maxReconnects) {
|
|
3993
|
+
reportError(
|
|
3994
|
+
new ReconnectingWebSocketError(
|
|
3995
|
+
`Reconnect budget exhausted (${args.maxReconnects} attempts)`,
|
|
3996
|
+
"reconnect_budget_exhausted",
|
|
3997
|
+
outcome.closeCode,
|
|
3998
|
+
outcome.closeReason,
|
|
3999
|
+
attempt
|
|
4000
|
+
)
|
|
4001
|
+
);
|
|
4002
|
+
return;
|
|
4003
|
+
}
|
|
4004
|
+
if (outcome.closeCode !== void 0 && RATE_LIMITED_CLOSE_CODES.has(outcome.closeCode)) {
|
|
4005
|
+
delayMs = Math.max(delayMs, RATE_LIMITED_FLOOR_MS);
|
|
4006
|
+
}
|
|
4007
|
+
attempt += 1;
|
|
4008
|
+
}
|
|
4009
|
+
setState("closed");
|
|
4010
|
+
}
|
|
4011
|
+
async function runOneConnection2(args) {
|
|
4012
|
+
const { options, factory, signal, setState, setSocket, idleTimeoutMs } = args;
|
|
4013
|
+
let socket;
|
|
4014
|
+
try {
|
|
4015
|
+
socket = factory(options.url, options.protocols);
|
|
4016
|
+
} catch (err) {
|
|
4017
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
4018
|
+
}
|
|
4019
|
+
setSocket(socket);
|
|
4020
|
+
return new Promise((resolve) => {
|
|
4021
|
+
let watchdogTimer = null;
|
|
4022
|
+
let resolved = false;
|
|
4023
|
+
function clearWatchdog() {
|
|
4024
|
+
if (watchdogTimer !== null) {
|
|
4025
|
+
clearTimeout(watchdogTimer);
|
|
4026
|
+
watchdogTimer = null;
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
function armWatchdog() {
|
|
4030
|
+
if (idleTimeoutMs <= 0) return;
|
|
4031
|
+
clearWatchdog();
|
|
4032
|
+
watchdogTimer = setTimeout(() => {
|
|
4033
|
+
if (resolved) return;
|
|
4034
|
+
try {
|
|
4035
|
+
socket.close(4001, "idle timeout");
|
|
4036
|
+
} catch {
|
|
4037
|
+
}
|
|
4038
|
+
finalize({
|
|
4039
|
+
closeCode: 4001,
|
|
4040
|
+
closeReason: "idle timeout",
|
|
4041
|
+
watchdogTriggered: true,
|
|
4042
|
+
aborted: false
|
|
4043
|
+
});
|
|
4044
|
+
}, idleTimeoutMs);
|
|
4045
|
+
}
|
|
4046
|
+
function finalize(outcome) {
|
|
4047
|
+
if (resolved) return;
|
|
4048
|
+
resolved = true;
|
|
4049
|
+
clearWatchdog();
|
|
4050
|
+
signal.removeEventListener("abort", onAbort);
|
|
4051
|
+
try {
|
|
4052
|
+
socket.removeEventListener("open", onOpen);
|
|
4053
|
+
socket.removeEventListener("message", onMessage);
|
|
4054
|
+
socket.removeEventListener("close", onClose);
|
|
4055
|
+
socket.removeEventListener("error", onSocketError);
|
|
4056
|
+
} catch {
|
|
4057
|
+
}
|
|
4058
|
+
resolve(outcome);
|
|
4059
|
+
}
|
|
4060
|
+
function onOpen() {
|
|
4061
|
+
setState("open");
|
|
4062
|
+
armWatchdog();
|
|
4063
|
+
}
|
|
4064
|
+
function onMessage(ev) {
|
|
4065
|
+
armWatchdog();
|
|
4066
|
+
try {
|
|
4067
|
+
options.onMessage(ev);
|
|
4068
|
+
} catch {
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
function onClose(ev) {
|
|
4072
|
+
setState("closed");
|
|
4073
|
+
finalize({
|
|
4074
|
+
closeCode: ev.code,
|
|
4075
|
+
closeReason: ev.reason,
|
|
4076
|
+
watchdogTriggered: false,
|
|
4077
|
+
aborted: false
|
|
4078
|
+
});
|
|
4079
|
+
}
|
|
4080
|
+
function onSocketError() {
|
|
4081
|
+
}
|
|
4082
|
+
function onAbort() {
|
|
4083
|
+
try {
|
|
4084
|
+
socket.close(1e3, "client aborted");
|
|
4085
|
+
} catch {
|
|
4086
|
+
}
|
|
4087
|
+
finalize({
|
|
4088
|
+
closeCode: void 0,
|
|
4089
|
+
closeReason: void 0,
|
|
4090
|
+
watchdogTriggered: false,
|
|
4091
|
+
aborted: true
|
|
4092
|
+
});
|
|
4093
|
+
}
|
|
4094
|
+
if (signal.aborted) {
|
|
4095
|
+
onAbort();
|
|
4096
|
+
return;
|
|
4097
|
+
}
|
|
4098
|
+
socket.addEventListener("open", onOpen);
|
|
4099
|
+
socket.addEventListener("message", onMessage);
|
|
4100
|
+
socket.addEventListener(
|
|
4101
|
+
"close",
|
|
4102
|
+
onClose
|
|
4103
|
+
);
|
|
4104
|
+
socket.addEventListener("error", onSocketError);
|
|
4105
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4106
|
+
});
|
|
4107
|
+
}
|
|
4108
|
+
function resolveWebSocketFactory(factory) {
|
|
4109
|
+
if (factory) return factory;
|
|
4110
|
+
const globalWs = globalThis.WebSocket;
|
|
4111
|
+
if (!globalWs) {
|
|
4112
|
+
return () => {
|
|
4113
|
+
throw new Error(
|
|
4114
|
+
"No global WebSocket available; pass webSocketFactory to createReconnectingWebSocket"
|
|
4115
|
+
);
|
|
4116
|
+
};
|
|
4117
|
+
}
|
|
4118
|
+
return (url, protocols) => new globalWs(url, protocols);
|
|
4119
|
+
}
|
|
4120
|
+
function jitter2(ms) {
|
|
4121
|
+
return Math.floor(Math.random() * Math.max(1, ms));
|
|
4122
|
+
}
|
|
4123
|
+
async function abortableSleep2(ms, signal) {
|
|
4124
|
+
if (signal.aborted) return false;
|
|
4125
|
+
return new Promise((resolve) => {
|
|
4126
|
+
const timer = setTimeout(() => {
|
|
4127
|
+
signal.removeEventListener("abort", onAbort);
|
|
4128
|
+
resolve(true);
|
|
4129
|
+
}, ms);
|
|
4130
|
+
const onAbort = () => {
|
|
4131
|
+
clearTimeout(timer);
|
|
4132
|
+
signal.removeEventListener("abort", onAbort);
|
|
4133
|
+
resolve(false);
|
|
4134
|
+
};
|
|
4135
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4136
|
+
});
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4139
|
+
// src/resources/observers.ts
|
|
4140
|
+
var WEB_SOCKET_PROTOCOL_TOKEN_RE2 = /^[!#$%&'*+\-.^_`|~A-Za-z0-9]+$/;
|
|
4141
|
+
var MAX_AUTH_TOKEN_CHARS2 = 4096;
|
|
4142
|
+
function observerAuthProtocols(token) {
|
|
4143
|
+
if (!token) {
|
|
4144
|
+
throw new ConfigurationError("observerAuthProtocols requires a non-empty token");
|
|
4145
|
+
}
|
|
4146
|
+
if (token.length > MAX_AUTH_TOKEN_CHARS2) {
|
|
4147
|
+
throw new ConfigurationError(
|
|
4148
|
+
`observer token exceeds the ${MAX_AUTH_TOKEN_CHARS2}-character WebSocket subprotocol limit`
|
|
4149
|
+
);
|
|
4150
|
+
}
|
|
4151
|
+
if (!WEB_SOCKET_PROTOCOL_TOKEN_RE2.test(token)) {
|
|
4152
|
+
throw new ConfigurationError(
|
|
4153
|
+
"observer token contains characters browsers reject in WebSocket subprotocols"
|
|
4154
|
+
);
|
|
4155
|
+
}
|
|
4156
|
+
return ["auth", token];
|
|
4157
|
+
}
|
|
4158
|
+
var ObserversResource = class extends WorkspaceScopedResource {
|
|
4159
|
+
agentBaseUrl;
|
|
4160
|
+
constructor(client, workspaceId2, agentBaseUrl) {
|
|
4161
|
+
super(client, workspaceId2);
|
|
4162
|
+
this.agentBaseUrl = agentBaseUrl;
|
|
4163
|
+
}
|
|
4164
|
+
/**
|
|
4165
|
+
* Subscribe to the live observer stream for a call.
|
|
4166
|
+
*
|
|
4167
|
+
* Returns a {@link ReconnectingWebSocketHandle} that resolves
|
|
4168
|
+
* ``handle.done`` when the stream terminates (consumer-aborted, terminal
|
|
4169
|
+
* close code, or reconnect budget exhausted). Errors are surfaced through
|
|
4170
|
+
* ``onError``; the promise never rejects.
|
|
4171
|
+
*/
|
|
4172
|
+
subscribe(options) {
|
|
4173
|
+
const url = buildObserverUrl({
|
|
4174
|
+
baseUrl: this.agentBaseUrl ?? this.platformBaseUrl,
|
|
4175
|
+
workspaceId: this.workspaceId,
|
|
4176
|
+
callSid: options.callSid,
|
|
4177
|
+
observerUrl: options.observerUrl
|
|
4178
|
+
});
|
|
4179
|
+
const protocols = observerAuthProtocols(options.token);
|
|
4180
|
+
return createReconnectingWebSocket({
|
|
4181
|
+
url,
|
|
4182
|
+
protocols: [...protocols],
|
|
4183
|
+
onMessage: (ev) => {
|
|
4184
|
+
const parsed = parseObserverFrame(ev.data);
|
|
4185
|
+
if (parsed) {
|
|
4186
|
+
try {
|
|
4187
|
+
options.onEvent(parsed);
|
|
4188
|
+
} catch {
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
},
|
|
4192
|
+
onStateChange: options.onStateChange,
|
|
4193
|
+
onReconnect: options.onReconnect,
|
|
4194
|
+
onError: options.onError,
|
|
4195
|
+
signal: options.signal,
|
|
4196
|
+
idleTimeoutMs: options.idleTimeoutMs ?? 6e4,
|
|
4197
|
+
initialDelayMs: options.initialDelayMs ?? 1e3,
|
|
4198
|
+
maxDelayMs: options.maxDelayMs ?? 3e4,
|
|
4199
|
+
maxReconnects: options.maxReconnects ?? 10,
|
|
4200
|
+
webSocketFactory: options.webSocketFactory
|
|
4201
|
+
});
|
|
4202
|
+
}
|
|
4203
|
+
};
|
|
4204
|
+
var CALL_SID_RE = /^CA[a-zA-Z0-9]{32}$/;
|
|
4205
|
+
function buildObserverUrl(args) {
|
|
4206
|
+
if (!args.workspaceId) {
|
|
4207
|
+
throw new ConfigurationError("workspaceId is required to build the observer URL");
|
|
4208
|
+
}
|
|
4209
|
+
if (!args.callSid) {
|
|
4210
|
+
throw new ConfigurationError("callSid is required to subscribe to the observer stream");
|
|
4211
|
+
}
|
|
4212
|
+
if (args.observerUrl) {
|
|
4213
|
+
return parseOverride(args.observerUrl).toString();
|
|
4214
|
+
}
|
|
4215
|
+
if (!CALL_SID_RE.test(args.callSid)) {
|
|
4216
|
+
throw new ConfigurationError(
|
|
4217
|
+
`callSid does not match Twilio CA SID format (CA + 32 hex chars): ${args.callSid}`
|
|
4218
|
+
);
|
|
4219
|
+
}
|
|
4220
|
+
return deriveFromBase(args.baseUrl, args.workspaceId, args.callSid).toString();
|
|
4221
|
+
}
|
|
4222
|
+
function parseOverride(observerUrl) {
|
|
4223
|
+
let url;
|
|
4224
|
+
try {
|
|
4225
|
+
url = new URL(observerUrl);
|
|
4226
|
+
} catch (cause) {
|
|
4227
|
+
throw new ConfigurationError(
|
|
4228
|
+
`observerUrl must be an absolute URL: ${String(cause)}`
|
|
4229
|
+
);
|
|
4230
|
+
}
|
|
4231
|
+
if (url.protocol !== "ws:" && url.protocol !== "wss:") {
|
|
4232
|
+
throw new ConfigurationError("observerUrl overrides must use ws: or wss: URLs");
|
|
4233
|
+
}
|
|
4234
|
+
if (url.search || url.hash) {
|
|
4235
|
+
throw new ConfigurationError(
|
|
4236
|
+
"observerUrl overrides must not include query parameters or fragments"
|
|
4237
|
+
);
|
|
4238
|
+
}
|
|
4239
|
+
return url;
|
|
4240
|
+
}
|
|
4241
|
+
function deriveFromBase(baseUrl, workspaceId2, callSid) {
|
|
4242
|
+
let parsed;
|
|
4243
|
+
try {
|
|
4244
|
+
parsed = new URL(baseUrl);
|
|
4245
|
+
} catch (cause) {
|
|
4246
|
+
throw new ConfigurationError(
|
|
4247
|
+
`observerUrl cannot be derived from baseUrl: ${String(cause)}`
|
|
4248
|
+
);
|
|
4249
|
+
}
|
|
4250
|
+
let scheme;
|
|
4251
|
+
if (parsed.protocol === "https:" || parsed.protocol === "wss:") scheme = "wss:";
|
|
4252
|
+
else if (parsed.protocol === "http:" || parsed.protocol === "ws:") scheme = "ws:";
|
|
4253
|
+
else {
|
|
4254
|
+
throw new ConfigurationError(
|
|
4255
|
+
`observerUrl can only be derived from an http, https, ws, or wss baseUrl: ${baseUrl}`
|
|
4256
|
+
);
|
|
4257
|
+
}
|
|
4258
|
+
if (parsed.pathname !== "/" && parsed.pathname !== "") {
|
|
4259
|
+
throw new ConfigurationError(
|
|
4260
|
+
"observerUrl can only be derived from an origin-only baseUrl; pass observerUrl explicitly when using path-prefixed gateways"
|
|
4261
|
+
);
|
|
4262
|
+
}
|
|
4263
|
+
const out = new URL(`${scheme}//${parsed.host}/v1/${encodeURIComponent(workspaceId2)}/observers/${encodeURIComponent(callSid)}/ws`);
|
|
4264
|
+
return out;
|
|
4265
|
+
}
|
|
4266
|
+
function parseObserverFrame(data) {
|
|
4267
|
+
let text;
|
|
4268
|
+
if (typeof data === "string") {
|
|
4269
|
+
text = data;
|
|
4270
|
+
} else if (data instanceof ArrayBuffer) {
|
|
4271
|
+
text = new TextDecoder().decode(data);
|
|
4272
|
+
} else if (ArrayBuffer.isView(data)) {
|
|
4273
|
+
const view = data;
|
|
4274
|
+
text = new TextDecoder().decode(
|
|
4275
|
+
new Uint8Array(view.buffer, view.byteOffset, view.byteLength)
|
|
4276
|
+
);
|
|
4277
|
+
} else {
|
|
4278
|
+
return null;
|
|
4279
|
+
}
|
|
4280
|
+
let payload;
|
|
4281
|
+
try {
|
|
4282
|
+
payload = JSON.parse(text);
|
|
4283
|
+
} catch {
|
|
4284
|
+
return null;
|
|
4285
|
+
}
|
|
4286
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) return null;
|
|
4287
|
+
const obj = payload;
|
|
4288
|
+
if (typeof obj["type"] !== "string") return null;
|
|
4289
|
+
return obj;
|
|
4290
|
+
}
|
|
4291
|
+
|
|
3619
4292
|
// src/core/branded-types.ts
|
|
3620
4293
|
var workspaceId = (id) => id;
|
|
3621
4294
|
var apiKeyId = (id) => id;
|
|
@@ -4279,6 +4952,12 @@ var AmigoClient = class _AmigoClient {
|
|
|
4279
4952
|
compliance;
|
|
4280
4953
|
events;
|
|
4281
4954
|
functions;
|
|
4955
|
+
/**
|
|
4956
|
+
* Voice-call observer real-time stream. Subscribe with
|
|
4957
|
+
* ``client.observers.subscribe({ callSid, token, onEvent })``. See
|
|
4958
|
+
* {@link ObserversResource}.
|
|
4959
|
+
*/
|
|
4960
|
+
observers;
|
|
4282
4961
|
/** @internal — exposed for path-level type inference in GET/POST/PUT/etc. */
|
|
4283
4962
|
api;
|
|
4284
4963
|
constructor(config) {
|
|
@@ -4334,6 +5013,10 @@ var AmigoClient = class _AmigoClient {
|
|
|
4334
5013
|
allowEmptyBody: true
|
|
4335
5014
|
});
|
|
4336
5015
|
}
|
|
5016
|
+
defineRoute(method, path) {
|
|
5017
|
+
const dispatcher = this[method];
|
|
5018
|
+
return (init) => dispatcher.call(this, path, init);
|
|
5019
|
+
}
|
|
4337
5020
|
static fromPlatformClient(client, workspaceId2, baseUrl, agentBaseUrl) {
|
|
4338
5021
|
const instance = Object.create(_AmigoClient.prototype);
|
|
4339
5022
|
_AmigoClient.hydrate(instance, client, workspaceId2, baseUrl, agentBaseUrl);
|
|
@@ -4375,6 +5058,7 @@ var AmigoClient = class _AmigoClient {
|
|
|
4375
5058
|
mutable.compliance = new ComplianceResource(client, workspaceId2);
|
|
4376
5059
|
mutable.events = new EventsResource(client, workspaceId2);
|
|
4377
5060
|
mutable.functions = new FunctionsResource(client, workspaceId2);
|
|
5061
|
+
mutable.observers = new ObserversResource(client, workspaceId2, agentBaseUrl);
|
|
4378
5062
|
}
|
|
4379
5063
|
async resolveApiRequest(path, method, init) {
|
|
4380
5064
|
const { baseClient, options } = resolveScopedPlatformClient(this.api);
|
|
@@ -4432,9 +5116,11 @@ export {
|
|
|
4432
5116
|
MemoryTokenStorage,
|
|
4433
5117
|
NetworkError,
|
|
4434
5118
|
NotFoundError,
|
|
5119
|
+
ObserversResource,
|
|
4435
5120
|
ParseError,
|
|
4436
5121
|
PermissionError,
|
|
4437
5122
|
RateLimitError,
|
|
5123
|
+
ReconnectingWebSocketError,
|
|
4438
5124
|
RefreshTokenExpiredError,
|
|
4439
5125
|
RequestTimeoutError,
|
|
4440
5126
|
ServerError,
|
|
@@ -4442,12 +5128,14 @@ export {
|
|
|
4442
5128
|
TokenManager,
|
|
4443
5129
|
ValidationError,
|
|
4444
5130
|
WebhookVerificationError,
|
|
5131
|
+
WorkspaceEventStreamError,
|
|
4445
5132
|
actionId,
|
|
4446
5133
|
agentId,
|
|
4447
5134
|
apiKeyId,
|
|
4448
5135
|
buildLastResponse,
|
|
4449
5136
|
callId,
|
|
4450
5137
|
contextGraphId,
|
|
5138
|
+
createReconnectingWebSocket,
|
|
4451
5139
|
dataSourceId,
|
|
4452
5140
|
entityId,
|
|
4453
5141
|
eventId,
|
|
@@ -4459,10 +5147,20 @@ export {
|
|
|
4459
5147
|
integrationId,
|
|
4460
5148
|
isAmigoError,
|
|
4461
5149
|
isAuthenticationError,
|
|
5150
|
+
isConflictError,
|
|
5151
|
+
isHttpException,
|
|
5152
|
+
isHttpValidationError,
|
|
5153
|
+
isNetworkError,
|
|
4462
5154
|
isNotFoundError,
|
|
5155
|
+
isPermissionError,
|
|
4463
5156
|
isRateLimitError,
|
|
4464
5157
|
isRequestTimeoutError,
|
|
5158
|
+
isServerError,
|
|
5159
|
+
isUnparseableErrorBody,
|
|
5160
|
+
isValidationError,
|
|
5161
|
+
isWorkspaceEventStreamError,
|
|
4465
5162
|
loginWithDeviceCode,
|
|
5163
|
+
observerAuthProtocols,
|
|
4466
5164
|
openBrowser,
|
|
4467
5165
|
paginate,
|
|
4468
5166
|
parseRateLimitHeaders,
|