@amigo-ai/platform-sdk 0.22.0 → 0.24.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 +5 -1
- package/dist/index.cjs +421 -9
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +421 -9
- package/dist/index.mjs.map +4 -4
- package/dist/resources/conversations.js +144 -0
- package/dist/resources/conversations.js.map +1 -1
- package/dist/resources/events.js +452 -0
- package/dist/resources/events.js.map +1 -0
- package/dist/resources/workspaces.js +4 -8
- package/dist/resources/workspaces.js.map +1 -1
- package/dist/types/generated/api.d.ts +11 -52
- package/dist/types/generated/api.d.ts.map +1 -1
- package/dist/types/index.d.cts +4 -1
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/resources/conversations.d.ts +27 -0
- package/dist/types/resources/conversations.d.ts.map +1 -1
- package/dist/types/resources/events.d.ts +160 -0
- package/dist/types/resources/events.d.ts.map +1 -0
- package/dist/types/resources/functions.d.ts.map +1 -1
- package/dist/types/resources/metrics.d.ts.map +1 -1
- package/dist/types/resources/operators.d.ts.map +1 -1
- package/dist/types/resources/settings.d.ts.map +1 -1
- package/dist/types/resources/workspaces.d.ts +4 -15
- package/dist/types/resources/workspaces.d.ts.map +1 -1
- package/package.json +1 -1
package/api.md
CHANGED
|
@@ -66,7 +66,6 @@ All workspace-scoped resources also expose `withOptions(options)`.
|
|
|
66
66
|
|
|
67
67
|
### `workspaces`
|
|
68
68
|
|
|
69
|
-
- `create`
|
|
70
69
|
- `createSelfService`
|
|
71
70
|
- `list`
|
|
72
71
|
- `listAutoPaging`
|
|
@@ -240,6 +239,7 @@ All workspace-scoped resources also expose `withOptions(options)`.
|
|
|
240
239
|
- `close`
|
|
241
240
|
- `createTurn`
|
|
242
241
|
- `createTurnStream`
|
|
242
|
+
- `streamTurn`
|
|
243
243
|
- `textStreamUrl`
|
|
244
244
|
- `sessionConnectUrl`
|
|
245
245
|
|
|
@@ -417,6 +417,10 @@ All workspace-scoped resources also expose `withOptions(options)`.
|
|
|
417
417
|
- `getHipaa`
|
|
418
418
|
- `getAccessReview`
|
|
419
419
|
|
|
420
|
+
### `events`
|
|
421
|
+
|
|
422
|
+
- `subscribeToWorkspace`
|
|
423
|
+
|
|
420
424
|
### `functions`
|
|
421
425
|
|
|
422
426
|
- `list`
|
package/dist/index.cjs
CHANGED
|
@@ -882,14 +882,6 @@ function resolveScopedPlatformClient(client) {
|
|
|
882
882
|
|
|
883
883
|
// src/resources/workspaces.ts
|
|
884
884
|
var WorkspacesResource = class extends WorkspaceScopedResource {
|
|
885
|
-
/** Create a new workspace (unauthenticated — no owner membership created) */
|
|
886
|
-
async create(body) {
|
|
887
|
-
return extractData(
|
|
888
|
-
await this.client.POST("/v1/workspaces", {
|
|
889
|
-
body
|
|
890
|
-
})
|
|
891
|
-
);
|
|
892
|
-
}
|
|
893
885
|
/** Create a workspace for the authenticated user and attach owner access */
|
|
894
886
|
async createSelfService(body) {
|
|
895
887
|
return extractData(
|
|
@@ -2024,7 +2016,10 @@ var ConversationsResource = class extends WorkspaceScopedResource {
|
|
|
2024
2016
|
"/v1/{workspace_id}/conversations/{conversation_id}/turns",
|
|
2025
2017
|
{
|
|
2026
2018
|
params: {
|
|
2027
|
-
path: { workspace_id: this.workspaceId, conversation_id: conversationId }
|
|
2019
|
+
path: { workspace_id: this.workspaceId, conversation_id: conversationId },
|
|
2020
|
+
...options?.includeToolCalls !== void 0 && {
|
|
2021
|
+
query: { include_tool_calls: options.includeToolCalls }
|
|
2022
|
+
}
|
|
2028
2023
|
},
|
|
2029
2024
|
body: request,
|
|
2030
2025
|
headers: { Accept: "text/event-stream" },
|
|
@@ -2037,6 +2032,35 @@ var ConversationsResource = class extends WorkspaceScopedResource {
|
|
|
2037
2032
|
}
|
|
2038
2033
|
return result.data;
|
|
2039
2034
|
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Send a message and receive the agent's response as a typed
|
|
2037
|
+
* `TurnStreamEvent` async iterable.
|
|
2038
|
+
*
|
|
2039
|
+
* The bytes-and-parser dance from `createTurnStream` is now hidden inside
|
|
2040
|
+
* the SDK — consumers iterate strongly typed events directly. Each yielded
|
|
2041
|
+
* value is a member of the `TurnStreamEvent` discriminated union (`token`,
|
|
2042
|
+
* `thinking`, `tool_call_started`, `tool_call_completed`, `message`,
|
|
2043
|
+
* `done`, `error`), validated as a record with a known `event`
|
|
2044
|
+
* discriminator. Unknown / malformed frames are dropped silently — this
|
|
2045
|
+
* matches the wire-format-drift behavior of the lower-level
|
|
2046
|
+
* `createTurnStream` while keeping the strict `TurnStreamEvent` static
|
|
2047
|
+
* contract intact for consumers.
|
|
2048
|
+
*
|
|
2049
|
+
* @example
|
|
2050
|
+
* ```ts
|
|
2051
|
+
* for await (const event of client.conversations.streamTurn(convId, { message: "Hello" })) {
|
|
2052
|
+
* if (event.event === "token") process.stdout.write(event.text);
|
|
2053
|
+
* else if (event.event === "done") break;
|
|
2054
|
+
* }
|
|
2055
|
+
* ```
|
|
2056
|
+
*/
|
|
2057
|
+
async *streamTurn(conversationId, request, options) {
|
|
2058
|
+
const byteStream = await this.createTurnStream(conversationId, request, options);
|
|
2059
|
+
for await (const frame of parseSSEFrames(byteStream)) {
|
|
2060
|
+
const event = parseTurnStreamFrame(frame.event, frame.data);
|
|
2061
|
+
if (event) yield event;
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2040
2064
|
/** Build the real-time text WebSocket URL for browser or custom clients. */
|
|
2041
2065
|
textStreamUrl(params) {
|
|
2042
2066
|
const url = buildTextStreamUrl({
|
|
@@ -2228,6 +2252,80 @@ function describeInvalidSubprotocolChars(token) {
|
|
|
2228
2252
|
}
|
|
2229
2253
|
return [...chars].map((char) => JSON.stringify(char)).join(", ");
|
|
2230
2254
|
}
|
|
2255
|
+
async function* parseSSEFrames(stream) {
|
|
2256
|
+
const reader = stream.getReader();
|
|
2257
|
+
const decoder = new TextDecoder();
|
|
2258
|
+
let buffer = "";
|
|
2259
|
+
function* drain(text) {
|
|
2260
|
+
buffer += text;
|
|
2261
|
+
while (true) {
|
|
2262
|
+
const idx = findFrameTerminator(buffer);
|
|
2263
|
+
if (idx === null) break;
|
|
2264
|
+
const block = buffer.slice(0, idx.terminatorStart);
|
|
2265
|
+
buffer = buffer.slice(idx.terminatorEnd);
|
|
2266
|
+
const frame = parseSSEBlock(block);
|
|
2267
|
+
if (frame) yield frame;
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
try {
|
|
2271
|
+
while (true) {
|
|
2272
|
+
const { done, value } = await reader.read();
|
|
2273
|
+
if (done) break;
|
|
2274
|
+
yield* drain(decoder.decode(value, { stream: true }));
|
|
2275
|
+
}
|
|
2276
|
+
yield* drain(decoder.decode());
|
|
2277
|
+
if (buffer.trim().length > 0) {
|
|
2278
|
+
const frame = parseSSEBlock(buffer);
|
|
2279
|
+
if (frame) yield frame;
|
|
2280
|
+
buffer = "";
|
|
2281
|
+
}
|
|
2282
|
+
} finally {
|
|
2283
|
+
reader.releaseLock();
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
function findFrameTerminator(s) {
|
|
2287
|
+
const lf = s.indexOf("\n\n");
|
|
2288
|
+
const crlf = s.indexOf("\r\n\r\n");
|
|
2289
|
+
if (lf < 0 && crlf < 0) return null;
|
|
2290
|
+
if (lf < 0) return { terminatorStart: crlf, terminatorEnd: crlf + 4 };
|
|
2291
|
+
if (crlf < 0) return { terminatorStart: lf, terminatorEnd: lf + 2 };
|
|
2292
|
+
return lf < crlf ? { terminatorStart: lf, terminatorEnd: lf + 2 } : { terminatorStart: crlf, terminatorEnd: crlf + 4 };
|
|
2293
|
+
}
|
|
2294
|
+
function parseSSEBlock(block) {
|
|
2295
|
+
let event = "";
|
|
2296
|
+
const dataLines = [];
|
|
2297
|
+
for (const line of block.split(/\r?\n/)) {
|
|
2298
|
+
if (line === "" || line.startsWith(":")) continue;
|
|
2299
|
+
const colon = line.indexOf(":");
|
|
2300
|
+
const field = colon < 0 ? line : line.slice(0, colon);
|
|
2301
|
+
let value = colon < 0 ? "" : line.slice(colon + 1);
|
|
2302
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
2303
|
+
if (field === "event") event = value;
|
|
2304
|
+
else if (field === "data") dataLines.push(value);
|
|
2305
|
+
}
|
|
2306
|
+
if (!event || dataLines.length === 0) return null;
|
|
2307
|
+
return { event, data: dataLines.join("\n") };
|
|
2308
|
+
}
|
|
2309
|
+
var KNOWN_TURN_STREAM_EVENTS = /* @__PURE__ */ new Set([
|
|
2310
|
+
"token",
|
|
2311
|
+
"thinking",
|
|
2312
|
+
"tool_call_started",
|
|
2313
|
+
"tool_call_completed",
|
|
2314
|
+
"message",
|
|
2315
|
+
"done",
|
|
2316
|
+
"error"
|
|
2317
|
+
]);
|
|
2318
|
+
function parseTurnStreamFrame(eventName, dataJson) {
|
|
2319
|
+
if (!KNOWN_TURN_STREAM_EVENTS.has(eventName)) return null;
|
|
2320
|
+
let payload;
|
|
2321
|
+
try {
|
|
2322
|
+
payload = JSON.parse(dataJson);
|
|
2323
|
+
} catch {
|
|
2324
|
+
return null;
|
|
2325
|
+
}
|
|
2326
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) return null;
|
|
2327
|
+
return { ...payload, event: eventName };
|
|
2328
|
+
}
|
|
2231
2329
|
|
|
2232
2330
|
// src/resources/phone-numbers.ts
|
|
2233
2331
|
var PhoneNumbersResource = class extends WorkspaceScopedResource {
|
|
@@ -3246,6 +3344,318 @@ var ComplianceResource = class extends WorkspaceScopedResource {
|
|
|
3246
3344
|
}
|
|
3247
3345
|
};
|
|
3248
3346
|
|
|
3347
|
+
// src/resources/events.ts
|
|
3348
|
+
var DEFAULT_INITIAL_DELAY_MS = 3e3;
|
|
3349
|
+
var DEFAULT_MAX_DELAY_MS = 3e4;
|
|
3350
|
+
var DEFAULT_MAX_RECONNECTS = 10;
|
|
3351
|
+
var MAX_FRAME_BYTES = 1048576;
|
|
3352
|
+
var EventsResource = class extends WorkspaceScopedResource {
|
|
3353
|
+
constructor(client, workspaceId2) {
|
|
3354
|
+
super(client, workspaceId2);
|
|
3355
|
+
}
|
|
3356
|
+
/**
|
|
3357
|
+
* Subscribe to the workspace event stream.
|
|
3358
|
+
*
|
|
3359
|
+
* Establishes an SSE connection to ``/v1/{workspace_id}/events/stream``
|
|
3360
|
+
* and invokes ``onEvent`` once per typed {@link WorkspaceSSEEvent}.
|
|
3361
|
+
* Unrecoverable failures (auth errors, exhausted reconnect budget,
|
|
3362
|
+
* caller abort) surface through ``onError``.
|
|
3363
|
+
*
|
|
3364
|
+
* Reconnection is automatic: on a network drop or 5xx, the helper
|
|
3365
|
+
* backs off (initial delay derived from the ``retry:`` directive,
|
|
3366
|
+
* default 3s, doubling with full jitter up to ``maxDelayMs``) and
|
|
3367
|
+
* resumes with the most recently seen ``Last-Event-ID``. The platform
|
|
3368
|
+
* buffers 5 minutes of events for gapless replay.
|
|
3369
|
+
*
|
|
3370
|
+
* @returns a {@link SubscriptionHandle} for cleanup. Aborting the
|
|
3371
|
+
* caller's ``signal`` is equivalent to calling ``unsubscribe()``.
|
|
3372
|
+
*/
|
|
3373
|
+
subscribeToWorkspace(options) {
|
|
3374
|
+
const localController = new AbortController();
|
|
3375
|
+
const cleanups = [];
|
|
3376
|
+
if (options.signal) {
|
|
3377
|
+
if (options.signal.aborted) {
|
|
3378
|
+
localController.abort(options.signal.reason);
|
|
3379
|
+
} else {
|
|
3380
|
+
const onAbort = () => localController.abort(options.signal?.reason);
|
|
3381
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
3382
|
+
cleanups.push(() => options.signal?.removeEventListener("abort", onAbort));
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
const done = runSubscription(
|
|
3386
|
+
this.client,
|
|
3387
|
+
this.workspaceId,
|
|
3388
|
+
options,
|
|
3389
|
+
localController.signal
|
|
3390
|
+
).finally(() => {
|
|
3391
|
+
for (const cleanup of cleanups) cleanup();
|
|
3392
|
+
});
|
|
3393
|
+
return {
|
|
3394
|
+
done,
|
|
3395
|
+
unsubscribe: () => localController.abort()
|
|
3396
|
+
};
|
|
3397
|
+
}
|
|
3398
|
+
};
|
|
3399
|
+
async function runSubscription(client, workspaceId2, options, signal) {
|
|
3400
|
+
let lastEventId = options.lastEventId;
|
|
3401
|
+
let attempt = 0;
|
|
3402
|
+
let delayMs = options.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
|
|
3403
|
+
const maxDelayMs = options.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
3404
|
+
const maxReconnects = options.maxReconnects ?? DEFAULT_MAX_RECONNECTS;
|
|
3405
|
+
let errorReported = false;
|
|
3406
|
+
const reportError = (error) => {
|
|
3407
|
+
if (errorReported) return;
|
|
3408
|
+
errorReported = true;
|
|
3409
|
+
try {
|
|
3410
|
+
options.onError?.(error);
|
|
3411
|
+
} catch {
|
|
3412
|
+
}
|
|
3413
|
+
};
|
|
3414
|
+
while (!signal.aborted) {
|
|
3415
|
+
if (attempt > 0) {
|
|
3416
|
+
try {
|
|
3417
|
+
options.onReconnect?.(attempt);
|
|
3418
|
+
} catch {
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
let outcome;
|
|
3422
|
+
try {
|
|
3423
|
+
outcome = await runOneConnection({
|
|
3424
|
+
client,
|
|
3425
|
+
workspaceId: workspaceId2,
|
|
3426
|
+
lastEventId,
|
|
3427
|
+
signal,
|
|
3428
|
+
onEvent: options.onEvent,
|
|
3429
|
+
onIdAdvance: (id) => {
|
|
3430
|
+
lastEventId = id;
|
|
3431
|
+
},
|
|
3432
|
+
onRetryDirective: (ms) => {
|
|
3433
|
+
delayMs = clampDelay(ms, options.initialDelayMs, maxDelayMs);
|
|
3434
|
+
}
|
|
3435
|
+
});
|
|
3436
|
+
} catch (err) {
|
|
3437
|
+
reportError(err instanceof Error ? err : new Error(String(err)));
|
|
3438
|
+
return;
|
|
3439
|
+
}
|
|
3440
|
+
if (signal.aborted || outcome.kind === "aborted") {
|
|
3441
|
+
return;
|
|
3442
|
+
}
|
|
3443
|
+
if (outcome.kind === "auth-error") {
|
|
3444
|
+
reportError(outcome.error);
|
|
3445
|
+
return;
|
|
3446
|
+
}
|
|
3447
|
+
if (attempt >= maxReconnects) {
|
|
3448
|
+
reportError(
|
|
3449
|
+
new Error(
|
|
3450
|
+
`SSE subscription exhausted reconnect budget (${maxReconnects}): ${outcome.reason}`
|
|
3451
|
+
)
|
|
3452
|
+
);
|
|
3453
|
+
return;
|
|
3454
|
+
}
|
|
3455
|
+
attempt += 1;
|
|
3456
|
+
const sleepMs = jitter(delayMs);
|
|
3457
|
+
delayMs = Math.min(delayMs * 2, maxDelayMs);
|
|
3458
|
+
const slept = await abortableSleep(sleepMs, signal);
|
|
3459
|
+
if (!slept) return;
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3462
|
+
async function runOneConnection(args) {
|
|
3463
|
+
const headers = { Accept: "text/event-stream" };
|
|
3464
|
+
if (args.lastEventId !== void 0) {
|
|
3465
|
+
headers["Last-Event-ID"] = args.lastEventId;
|
|
3466
|
+
}
|
|
3467
|
+
let result;
|
|
3468
|
+
try {
|
|
3469
|
+
result = await args.client.GET("/v1/{workspace_id}/events/stream", {
|
|
3470
|
+
params: { path: { workspace_id: args.workspaceId } },
|
|
3471
|
+
headers,
|
|
3472
|
+
parseAs: "stream",
|
|
3473
|
+
signal: args.signal
|
|
3474
|
+
});
|
|
3475
|
+
} catch (err) {
|
|
3476
|
+
if (args.signal.aborted) return { kind: "aborted" };
|
|
3477
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
3478
|
+
const status = readStatus(error);
|
|
3479
|
+
if (status === 401 || status === 403) {
|
|
3480
|
+
return { kind: "auth-error", error };
|
|
3481
|
+
}
|
|
3482
|
+
return { kind: "transport-error", reason: error.message };
|
|
3483
|
+
}
|
|
3484
|
+
if (result.error !== void 0) {
|
|
3485
|
+
return { kind: "transport-error", reason: `API error: ${safeStringify(result.error)}` };
|
|
3486
|
+
}
|
|
3487
|
+
const body = result.data;
|
|
3488
|
+
if (!(body instanceof ReadableStream)) {
|
|
3489
|
+
return { kind: "transport-error", reason: "Expected ReadableStream body for SSE" };
|
|
3490
|
+
}
|
|
3491
|
+
try {
|
|
3492
|
+
for await (const frame of parseSSEFrames2(body, args.signal)) {
|
|
3493
|
+
if (args.signal.aborted) return { kind: "aborted" };
|
|
3494
|
+
if (frame.retry !== void 0) {
|
|
3495
|
+
args.onRetryDirective(frame.retry);
|
|
3496
|
+
}
|
|
3497
|
+
if (frame.id !== void 0) {
|
|
3498
|
+
args.onIdAdvance(frame.id);
|
|
3499
|
+
}
|
|
3500
|
+
if (frame.event && frame.data !== void 0) {
|
|
3501
|
+
const event = parseWorkspaceFrame(frame.event, frame.data);
|
|
3502
|
+
if (event) {
|
|
3503
|
+
try {
|
|
3504
|
+
args.onEvent(event);
|
|
3505
|
+
} catch {
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
} catch (err) {
|
|
3511
|
+
if (args.signal.aborted) return { kind: "aborted" };
|
|
3512
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
3513
|
+
return { kind: "transport-error", reason };
|
|
3514
|
+
}
|
|
3515
|
+
if (args.signal.aborted) return { kind: "aborted" };
|
|
3516
|
+
return { kind: "transport-error", reason: "Stream closed by server" };
|
|
3517
|
+
}
|
|
3518
|
+
async function* parseSSEFrames2(stream, signal) {
|
|
3519
|
+
const reader = stream.getReader();
|
|
3520
|
+
const decoder = new TextDecoder();
|
|
3521
|
+
let buffer = "";
|
|
3522
|
+
let cancelled = false;
|
|
3523
|
+
const onAbort = () => {
|
|
3524
|
+
if (cancelled) return;
|
|
3525
|
+
cancelled = true;
|
|
3526
|
+
void reader.cancel().catch(() => {
|
|
3527
|
+
});
|
|
3528
|
+
};
|
|
3529
|
+
let removeAbortHandler;
|
|
3530
|
+
if (signal.aborted) {
|
|
3531
|
+
onAbort();
|
|
3532
|
+
} else {
|
|
3533
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3534
|
+
removeAbortHandler = () => signal.removeEventListener("abort", onAbort);
|
|
3535
|
+
}
|
|
3536
|
+
function* drain(text) {
|
|
3537
|
+
buffer += text;
|
|
3538
|
+
if (buffer.length > MAX_FRAME_BYTES) {
|
|
3539
|
+
throw new Error(`SSE frame buffer exceeded ${MAX_FRAME_BYTES} bytes without terminator`);
|
|
3540
|
+
}
|
|
3541
|
+
while (true) {
|
|
3542
|
+
const idx = findFrameTerminator2(buffer);
|
|
3543
|
+
if (idx === null) break;
|
|
3544
|
+
const block = buffer.slice(0, idx.terminatorStart);
|
|
3545
|
+
buffer = buffer.slice(idx.terminatorEnd);
|
|
3546
|
+
const frame = parseSSEBlock2(block);
|
|
3547
|
+
if (frame) yield frame;
|
|
3548
|
+
}
|
|
3549
|
+
}
|
|
3550
|
+
try {
|
|
3551
|
+
while (true) {
|
|
3552
|
+
const { done, value } = await reader.read();
|
|
3553
|
+
if (done) break;
|
|
3554
|
+
yield* drain(decoder.decode(value, { stream: true }));
|
|
3555
|
+
}
|
|
3556
|
+
yield* drain(decoder.decode());
|
|
3557
|
+
if (buffer.trim().length > 0) {
|
|
3558
|
+
const frame = parseSSEBlock2(buffer);
|
|
3559
|
+
if (frame) yield frame;
|
|
3560
|
+
buffer = "";
|
|
3561
|
+
}
|
|
3562
|
+
} finally {
|
|
3563
|
+
removeAbortHandler?.();
|
|
3564
|
+
try {
|
|
3565
|
+
reader.releaseLock();
|
|
3566
|
+
} catch {
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
function findFrameTerminator2(s) {
|
|
3571
|
+
const lf = s.indexOf("\n\n");
|
|
3572
|
+
const crlf = s.indexOf("\r\n\r\n");
|
|
3573
|
+
if (lf < 0 && crlf < 0) return null;
|
|
3574
|
+
if (lf < 0) return { terminatorStart: crlf, terminatorEnd: crlf + 4 };
|
|
3575
|
+
if (crlf < 0) return { terminatorStart: lf, terminatorEnd: lf + 2 };
|
|
3576
|
+
return lf < crlf ? { terminatorStart: lf, terminatorEnd: lf + 2 } : { terminatorStart: crlf, terminatorEnd: crlf + 4 };
|
|
3577
|
+
}
|
|
3578
|
+
function parseSSEBlock2(block) {
|
|
3579
|
+
let event = "";
|
|
3580
|
+
let id;
|
|
3581
|
+
let retry;
|
|
3582
|
+
const dataLines = [];
|
|
3583
|
+
for (const line of block.split(/\r?\n/)) {
|
|
3584
|
+
if (line === "" || line.startsWith(":")) continue;
|
|
3585
|
+
const colon = line.indexOf(":");
|
|
3586
|
+
const field = colon < 0 ? line : line.slice(0, colon);
|
|
3587
|
+
let value = colon < 0 ? "" : line.slice(colon + 1);
|
|
3588
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
3589
|
+
if (field === "event") {
|
|
3590
|
+
event = value;
|
|
3591
|
+
} else if (field === "data") {
|
|
3592
|
+
dataLines.push(value);
|
|
3593
|
+
} else if (field === "id") {
|
|
3594
|
+
id = value;
|
|
3595
|
+
} else if (field === "retry") {
|
|
3596
|
+
const parsed = Number.parseInt(value, 10);
|
|
3597
|
+
if (Number.isFinite(parsed) && parsed >= 0) retry = parsed;
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
if (!event && dataLines.length === 0 && id === void 0 && retry === void 0) {
|
|
3601
|
+
return null;
|
|
3602
|
+
}
|
|
3603
|
+
return {
|
|
3604
|
+
event,
|
|
3605
|
+
data: dataLines.length > 0 ? dataLines.join("\n") : void 0,
|
|
3606
|
+
id,
|
|
3607
|
+
retry
|
|
3608
|
+
};
|
|
3609
|
+
}
|
|
3610
|
+
function parseWorkspaceFrame(eventName, dataJson) {
|
|
3611
|
+
let payload;
|
|
3612
|
+
try {
|
|
3613
|
+
payload = JSON.parse(dataJson);
|
|
3614
|
+
} catch {
|
|
3615
|
+
return null;
|
|
3616
|
+
}
|
|
3617
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) return null;
|
|
3618
|
+
return {
|
|
3619
|
+
...payload,
|
|
3620
|
+
event_type: eventName
|
|
3621
|
+
};
|
|
3622
|
+
}
|
|
3623
|
+
function readStatus(error) {
|
|
3624
|
+
if (typeof error !== "object" || error === null) return void 0;
|
|
3625
|
+
const status = error.statusCode;
|
|
3626
|
+
return typeof status === "number" ? status : void 0;
|
|
3627
|
+
}
|
|
3628
|
+
function safeStringify(value) {
|
|
3629
|
+
try {
|
|
3630
|
+
return JSON.stringify(value);
|
|
3631
|
+
} catch {
|
|
3632
|
+
return String(value);
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
function jitter(ms) {
|
|
3636
|
+
return Math.floor(Math.random() * Math.max(1, ms));
|
|
3637
|
+
}
|
|
3638
|
+
function clampDelay(ms, floor, ceiling) {
|
|
3639
|
+
const lo = floor ?? DEFAULT_INITIAL_DELAY_MS;
|
|
3640
|
+
if (!Number.isFinite(ms) || ms <= 0) return lo;
|
|
3641
|
+
return Math.min(Math.max(ms, lo), ceiling);
|
|
3642
|
+
}
|
|
3643
|
+
async function abortableSleep(ms, signal) {
|
|
3644
|
+
if (signal.aborted) return false;
|
|
3645
|
+
return new Promise((resolve) => {
|
|
3646
|
+
const timer = setTimeout(() => {
|
|
3647
|
+
signal.removeEventListener("abort", onAbort);
|
|
3648
|
+
resolve(true);
|
|
3649
|
+
}, ms);
|
|
3650
|
+
const onAbort = () => {
|
|
3651
|
+
clearTimeout(timer);
|
|
3652
|
+
signal.removeEventListener("abort", onAbort);
|
|
3653
|
+
resolve(false);
|
|
3654
|
+
};
|
|
3655
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3656
|
+
});
|
|
3657
|
+
}
|
|
3658
|
+
|
|
3249
3659
|
// src/resources/functions.ts
|
|
3250
3660
|
var FunctionsResource = class extends WorkspaceScopedResource {
|
|
3251
3661
|
async list() {
|
|
@@ -3961,6 +4371,7 @@ var AmigoClient = class _AmigoClient {
|
|
|
3961
4371
|
webhookDestinations;
|
|
3962
4372
|
safety;
|
|
3963
4373
|
compliance;
|
|
4374
|
+
events;
|
|
3964
4375
|
functions;
|
|
3965
4376
|
/** @internal — exposed for path-level type inference in GET/POST/PUT/etc. */
|
|
3966
4377
|
api;
|
|
@@ -4056,6 +4467,7 @@ var AmigoClient = class _AmigoClient {
|
|
|
4056
4467
|
mutable.webhookDestinations = new WebhookDestinationsResource(client, workspaceId2);
|
|
4057
4468
|
mutable.safety = new SafetyResource(client, workspaceId2);
|
|
4058
4469
|
mutable.compliance = new ComplianceResource(client, workspaceId2);
|
|
4470
|
+
mutable.events = new EventsResource(client, workspaceId2);
|
|
4059
4471
|
mutable.functions = new FunctionsResource(client, workspaceId2);
|
|
4060
4472
|
}
|
|
4061
4473
|
async resolveApiRequest(path, method, init) {
|