@fabric-platform/sdk 0.2.2

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/dist/index.js ADDED
@@ -0,0 +1,1921 @@
1
+ // src/auth.ts
2
+ async function resolveAuthHeader(auth, _opts) {
3
+ if (!auth) return void 0;
4
+ if (typeof auth === "function") {
5
+ const token = await auth();
6
+ return `Bearer ${token}`;
7
+ }
8
+ switch (auth.type) {
9
+ case "api-key":
10
+ return `Bearer ${auth.key}`;
11
+ case "bearer":
12
+ return `Bearer ${auth.token}`;
13
+ case "oauth":
14
+ return void 0;
15
+ }
16
+ }
17
+ var OAuthTokenManager = class {
18
+ constructor(clientId, clientSecret, tokenUrl, fetchFn = globalThis.fetch) {
19
+ this.clientId = clientId;
20
+ this.clientSecret = clientSecret;
21
+ this.tokenUrl = tokenUrl;
22
+ this.fetchFn = fetchFn;
23
+ }
24
+ cachedToken;
25
+ expiresAt = 0;
26
+ async getToken() {
27
+ if (this.cachedToken && Date.now() < this.expiresAt - 3e4) {
28
+ return this.cachedToken;
29
+ }
30
+ const res = await this.fetchFn(this.tokenUrl, {
31
+ method: "POST",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify({
34
+ grant_type: "client_credentials",
35
+ client_id: this.clientId,
36
+ client_secret: this.clientSecret
37
+ })
38
+ });
39
+ if (!res.ok) {
40
+ throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText}`);
41
+ }
42
+ const body = await res.json();
43
+ const accessToken = body.data?.access_token ?? body.access_token;
44
+ const expiresIn = body.data?.expires_in ?? body.expires_in ?? 900;
45
+ if (!accessToken) {
46
+ throw new Error("OAuth token exchange returned no access_token");
47
+ }
48
+ this.cachedToken = accessToken;
49
+ this.expiresAt = Date.now() + expiresIn * 1e3;
50
+ return accessToken;
51
+ }
52
+ };
53
+
54
+ // src/errors.ts
55
+ var FabricError = class extends Error {
56
+ code;
57
+ status;
58
+ requestId;
59
+ traceId;
60
+ constructor(params) {
61
+ super(params.message);
62
+ this.name = "FabricError";
63
+ this.code = params.code;
64
+ this.status = params.status;
65
+ this.requestId = params.requestId;
66
+ this.traceId = params.traceId;
67
+ }
68
+ };
69
+ var FabricValidationError = class extends FabricError {
70
+ constructor(params) {
71
+ super(params);
72
+ this.name = "FabricValidationError";
73
+ }
74
+ };
75
+ var FabricAuthError = class extends FabricError {
76
+ constructor(params) {
77
+ super(params);
78
+ this.name = "FabricAuthError";
79
+ }
80
+ };
81
+ var FabricForbiddenError = class extends FabricError {
82
+ constructor(params) {
83
+ super(params);
84
+ this.name = "FabricForbiddenError";
85
+ }
86
+ };
87
+ var FabricNotFoundError = class extends FabricError {
88
+ constructor(params) {
89
+ super(params);
90
+ this.name = "FabricNotFoundError";
91
+ }
92
+ };
93
+ var FabricConflictError = class extends FabricError {
94
+ constructor(params) {
95
+ super(params);
96
+ this.name = "FabricConflictError";
97
+ }
98
+ };
99
+ var FabricRateLimitError = class extends FabricError {
100
+ retryAfterMs;
101
+ constructor(params) {
102
+ super(params);
103
+ this.name = "FabricRateLimitError";
104
+ this.retryAfterMs = params.retryAfterMs;
105
+ }
106
+ };
107
+ var FabricServerError = class extends FabricError {
108
+ constructor(params) {
109
+ super(params);
110
+ this.name = "FabricServerError";
111
+ }
112
+ };
113
+ function createFabricError(params) {
114
+ switch (true) {
115
+ case params.status === 401:
116
+ return new FabricAuthError(params);
117
+ case params.status === 403:
118
+ return new FabricForbiddenError(params);
119
+ case params.status === 404:
120
+ return new FabricNotFoundError(params);
121
+ case params.status === 409:
122
+ return new FabricConflictError(params);
123
+ case params.status === 429:
124
+ return new FabricRateLimitError(params);
125
+ case (params.status >= 400 && params.status < 500):
126
+ return new FabricValidationError(params);
127
+ case params.status >= 500:
128
+ return new FabricServerError(params);
129
+ default:
130
+ return new FabricError(params);
131
+ }
132
+ }
133
+
134
+ // src/http.ts
135
+ var HttpTransport = class {
136
+ baseUrl;
137
+ auth;
138
+ organizationId;
139
+ teamId;
140
+ timeoutMs;
141
+ fetchFn;
142
+ retryConfig;
143
+ debug;
144
+ onRequest;
145
+ onResponse;
146
+ oauthManager;
147
+ constructor(config) {
148
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
149
+ this.auth = config.auth;
150
+ this.organizationId = config.organizationId;
151
+ this.teamId = config.teamId;
152
+ this.timeoutMs = config.timeout ?? 3e4;
153
+ this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
154
+ this.retryConfig = config.retry ?? { maxRetries: 2, baseDelayMs: 1e3 };
155
+ this.debug = config.debug ?? false;
156
+ this.onRequest = config.onRequest;
157
+ this.onResponse = config.onResponse;
158
+ if (config.auth && typeof config.auth !== "function" && config.auth.type === "oauth") {
159
+ this.oauthManager = new OAuthTokenManager(
160
+ config.auth.clientId,
161
+ config.auth.clientSecret,
162
+ `${this.baseUrl}/v1/oauth/token`,
163
+ this.fetchFn
164
+ );
165
+ }
166
+ }
167
+ /** Getters for context values (used by resources). */
168
+ getOrganizationId() {
169
+ return this.organizationId;
170
+ }
171
+ getTeamId() {
172
+ return this.teamId;
173
+ }
174
+ getBaseUrl() {
175
+ return this.baseUrl;
176
+ }
177
+ /** Make a request and unwrap the envelope, returning `data`. */
178
+ async request(method, path, opts) {
179
+ const res = await this.doFetch(method, path, opts);
180
+ const envelope = await res.json();
181
+ this.throwIfError(envelope, res);
182
+ return envelope.data;
183
+ }
184
+ /** Make a request and unwrap a paginated envelope. */
185
+ async requestPaginated(method, path, opts) {
186
+ const res = await this.doFetch(method, path, opts);
187
+ const envelope = await res.json();
188
+ if (envelope.error) {
189
+ throw createFabricError({
190
+ code: envelope.error.code,
191
+ status: envelope.meta.status,
192
+ message: envelope.error.message,
193
+ requestId: envelope.meta.request_id,
194
+ traceId: envelope.meta.trace_id
195
+ });
196
+ }
197
+ return {
198
+ items: envelope.data?.items ?? [],
199
+ pagination: envelope.data?.pagination ?? { count: 0, has_more: false }
200
+ };
201
+ }
202
+ /** Make a request and return the raw Response (for SSE, file uploads, etc). */
203
+ async requestRaw(method, path, opts) {
204
+ return this.doFetch(method, path, opts);
205
+ }
206
+ /** Build full headers for a request (used by streaming). */
207
+ async buildHeaders(extra) {
208
+ const headers = {
209
+ "Content-Type": "application/json",
210
+ ...extra
211
+ };
212
+ const authHeader = await this.resolveAuth();
213
+ if (authHeader) headers["Authorization"] = authHeader;
214
+ return headers;
215
+ }
216
+ // ── Internal ──────────────────────────────────────────────────────
217
+ async doFetch(method, path, opts) {
218
+ const url = this.buildUrl(path, opts?.query);
219
+ const headers = await this.buildHeaders(opts?.headers);
220
+ if (opts?.idempotencyKey) {
221
+ headers["idempotency-key"] = opts.idempotencyKey;
222
+ }
223
+ if (!headers["x-request-id"] && !headers["X-Request-ID"]) {
224
+ headers["X-Request-ID"] = generateRequestId();
225
+ }
226
+ if (method === "GET" || method === "DELETE") {
227
+ delete headers["Content-Type"];
228
+ }
229
+ await this.onRequest?.(method, url, headers);
230
+ if (this.debug) {
231
+ console.debug(`[fabric] ${method} ${url}`);
232
+ }
233
+ const init = {
234
+ method,
235
+ headers,
236
+ body: opts?.body !== void 0 ? JSON.stringify(opts.body) : void 0,
237
+ signal: opts?.signal ?? AbortSignal.timeout(this.timeoutMs),
238
+ ...opts?.requestInit
239
+ };
240
+ const start = Date.now();
241
+ const res = await this.fetchWithRetry(url, init);
242
+ const durationMs = Date.now() - start;
243
+ await this.onResponse?.(method, url, res.status, durationMs);
244
+ if (this.debug) {
245
+ console.debug(`[fabric] ${method} ${url} \u2192 ${res.status} (${durationMs}ms)`);
246
+ }
247
+ return res;
248
+ }
249
+ async fetchWithRetry(url, init) {
250
+ let lastError;
251
+ for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
252
+ try {
253
+ const res = await this.fetchFn(url, init);
254
+ if (res.status !== 429 || attempt >= this.retryConfig.maxRetries) {
255
+ return res;
256
+ }
257
+ const retryAfter = res.headers.get("retry-after");
258
+ const delayMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : this.retryConfig.baseDelayMs * Math.pow(2, attempt);
259
+ await sleep(delayMs);
260
+ } catch (err) {
261
+ if (err instanceof DOMException && err.name === "AbortError") throw err;
262
+ lastError = err instanceof Error ? err : new Error(String(err));
263
+ if (attempt >= this.retryConfig.maxRetries) break;
264
+ await sleep(this.retryConfig.baseDelayMs * Math.pow(2, attempt));
265
+ }
266
+ }
267
+ throw lastError ?? new Error("Request failed after retries");
268
+ }
269
+ async resolveAuth() {
270
+ if (this.oauthManager) {
271
+ const token = await this.oauthManager.getToken();
272
+ return `Bearer ${token}`;
273
+ }
274
+ return resolveAuthHeader(this.auth);
275
+ }
276
+ buildUrl(path, query) {
277
+ let url = `${this.baseUrl}${path}`;
278
+ const params = new URLSearchParams();
279
+ if (query) {
280
+ for (const [key, value] of Object.entries(query)) {
281
+ if (value !== void 0) params.set(key, String(value));
282
+ }
283
+ }
284
+ const qs = params.toString();
285
+ if (qs) url += (url.includes("?") ? "&" : "?") + qs;
286
+ return url;
287
+ }
288
+ throwIfError(envelope, res) {
289
+ if (envelope.error) {
290
+ const retryAfterHeader = res.headers.get("retry-after");
291
+ const retryAfterMs = retryAfterHeader ? parseInt(retryAfterHeader, 10) * 1e3 : void 0;
292
+ throw createFabricError({
293
+ code: envelope.error.code,
294
+ status: envelope.meta.status,
295
+ message: envelope.error.message,
296
+ requestId: envelope.meta.request_id,
297
+ traceId: envelope.meta.trace_id,
298
+ retryAfterMs
299
+ });
300
+ }
301
+ }
302
+ };
303
+ function sleep(ms) {
304
+ return new Promise((resolve) => setTimeout(resolve, ms));
305
+ }
306
+ function generateRequestId() {
307
+ const bytes = new Uint8Array(16);
308
+ crypto.getRandomValues(bytes);
309
+ let hex = "";
310
+ for (let i = 0; i < bytes.length; i++) {
311
+ hex += bytes[i].toString(16).padStart(2, "0");
312
+ }
313
+ return hex;
314
+ }
315
+
316
+ // src/resources/auth.resource.ts
317
+ var MfaResource = class {
318
+ constructor(http) {
319
+ this.http = http;
320
+ }
321
+ /** Enroll a new MFA factor (e.g., "totp"). */
322
+ async enroll(factorType, friendlyName) {
323
+ return this.http.request("POST", "/v1/auth/mfa/enroll", {
324
+ body: { factor_type: factorType, friendly_name: friendlyName }
325
+ });
326
+ }
327
+ /** Request an MFA challenge for a factor. */
328
+ async challenge(factorId) {
329
+ return this.http.request("POST", "/v1/auth/mfa/challenge", {
330
+ body: { factor_id: factorId }
331
+ });
332
+ }
333
+ /** Verify an MFA code. Returns new tokens on success. */
334
+ async verify(factorId, challengeId, code) {
335
+ return this.http.request("POST", "/v1/auth/mfa/verify", {
336
+ body: { factor_id: factorId, challenge_id: challengeId, code }
337
+ });
338
+ }
339
+ /** Remove an MFA factor. */
340
+ async unenroll(factorId) {
341
+ await this.http.request("DELETE", "/v1/auth/mfa/unenroll", {
342
+ body: { factor_id: factorId }
343
+ });
344
+ }
345
+ };
346
+ var AuthResource = class {
347
+ constructor(http) {
348
+ this.http = http;
349
+ this.mfa = new MfaResource(http);
350
+ }
351
+ mfa;
352
+ /** Sign up with email and password. Returns tokens + user. */
353
+ async signup(email, password) {
354
+ return this.http.request("POST", "/v1/auth/signup", {
355
+ body: { email, password }
356
+ });
357
+ }
358
+ /** Log in with email and password. Returns tokens + user. */
359
+ async login(email, password) {
360
+ return this.http.request("POST", "/v1/auth/login", {
361
+ body: { email, password }
362
+ });
363
+ }
364
+ /** Log out (revoke tokens). */
365
+ async logout() {
366
+ await this.http.request("POST", "/v1/auth/logout", { body: {} });
367
+ }
368
+ /** Refresh an access token using a refresh token. */
369
+ async refresh(refreshToken) {
370
+ return this.http.request("POST", "/v1/auth/token/refresh", {
371
+ body: { refresh_token: refreshToken }
372
+ });
373
+ }
374
+ /** Request a magic link email. */
375
+ async magicLink(email) {
376
+ await this.http.request("POST", "/v1/auth/magic-link", {
377
+ body: { email }
378
+ });
379
+ }
380
+ /** Request a password reset email. */
381
+ async forgotPassword(email) {
382
+ await this.http.request("POST", "/v1/auth/forgot-password", {
383
+ body: { email }
384
+ });
385
+ }
386
+ /** Reset password with a recovery token. */
387
+ async resetPassword(accessToken, newPassword) {
388
+ await this.http.request("POST", "/v1/auth/reset-password", {
389
+ body: { access_token: accessToken, new_password: newPassword }
390
+ });
391
+ }
392
+ /** Get the URL for social login redirect (e.g., "google", "github"). */
393
+ socialLoginUrl(provider) {
394
+ return `${this.http.getBaseUrl()}/v1/auth/social/${encodeURIComponent(provider)}`;
395
+ }
396
+ /** Verify an email address using a verification token. */
397
+ async verify(token) {
398
+ await this.http.request("GET", "/v1/auth/verify", {
399
+ query: { token }
400
+ });
401
+ }
402
+ };
403
+
404
+ // src/resources/me.resource.ts
405
+ var MeResource = class {
406
+ constructor(http) {
407
+ this.http = http;
408
+ }
409
+ /** Get current principal info. */
410
+ async get() {
411
+ return this.http.request("GET", "/v1/me");
412
+ }
413
+ /** List organizations the current user belongs to. */
414
+ async organizations() {
415
+ return this.http.request("GET", "/v1/me/organizations");
416
+ }
417
+ /** List teams the current user belongs to. */
418
+ async teams() {
419
+ return this.http.request("GET", "/v1/me/teams");
420
+ }
421
+ /** List effective permissions for the current user. */
422
+ async permissions() {
423
+ return this.http.request("GET", "/v1/me/permissions");
424
+ }
425
+ };
426
+
427
+ // src/resources/organizations.resource.ts
428
+ var OrganizationsResource = class {
429
+ constructor(http) {
430
+ this.http = http;
431
+ }
432
+ /** Create an organization. */
433
+ async create(opts) {
434
+ return this.http.request("POST", "/v1/organizations", { body: opts });
435
+ }
436
+ /** List organizations (paginated). */
437
+ async list(params) {
438
+ return this.http.requestPaginated("GET", "/v1/organizations", {
439
+ query: { limit: params?.limit, cursor: params?.cursor }
440
+ });
441
+ }
442
+ /** Get an organization by ID. */
443
+ async get(orgId) {
444
+ return this.http.request("GET", `/v1/organizations/${orgId}`);
445
+ }
446
+ /** Update an organization (e.g., rename). */
447
+ async update(orgId, opts) {
448
+ return this.http.request("PUT", `/v1/organizations/${orgId}`, { body: opts });
449
+ }
450
+ /** Archive an organization (soft-delete). */
451
+ async archive(orgId) {
452
+ return this.http.request("POST", `/v1/organizations/${orgId}/archive`, { body: {} });
453
+ }
454
+ /** List teams in an organization. */
455
+ async teams(orgId, params) {
456
+ return this.http.requestPaginated("GET", `/v1/organizations/${orgId}/teams`, {
457
+ query: { limit: params?.limit, cursor: params?.cursor }
458
+ });
459
+ }
460
+ /** List members in an organization. */
461
+ async members(orgId, params) {
462
+ return this.http.requestPaginated("GET", `/v1/organizations/${orgId}/members`, {
463
+ query: { limit: params?.limit, cursor: params?.cursor }
464
+ });
465
+ }
466
+ /** List permissions for an organization. */
467
+ async permissions(orgId) {
468
+ return this.http.request("GET", `/v1/organizations/${orgId}/permissions`);
469
+ }
470
+ /** Get usage summary for an organization. */
471
+ async usage(orgId) {
472
+ return this.http.request("GET", `/v1/organizations/${orgId}/usage`);
473
+ }
474
+ /** Get audit logs for an organization. */
475
+ async auditLogs(orgId, params) {
476
+ return this.http.requestPaginated("GET", `/v1/organizations/${orgId}/audit-logs`, {
477
+ query: { limit: params?.limit, cursor: params?.cursor }
478
+ });
479
+ }
480
+ /** Export organization data. */
481
+ async export(orgId) {
482
+ return this.http.request("POST", `/v1/organizations/${orgId}/export`, { body: {} });
483
+ }
484
+ /** Request organization deletion. */
485
+ async requestDeletion(orgId) {
486
+ await this.http.request("POST", `/v1/organizations/${orgId}/delete`, { body: {} });
487
+ }
488
+ // ── Budget ────────────────────────────────────────────────────────
489
+ /** Get budget configuration. */
490
+ async getBudget(orgId) {
491
+ return this.http.request("GET", `/v1/organizations/${orgId}/budget`);
492
+ }
493
+ /** Set budget limit. */
494
+ async setBudget(orgId, monthlyLimitUsd) {
495
+ return this.http.request("PUT", `/v1/organizations/${orgId}/budget`, {
496
+ body: { monthly_limit_usd: monthlyLimitUsd }
497
+ });
498
+ }
499
+ // ── Settings ─────────────────────────────────────────────────────
500
+ /** Get organization settings. */
501
+ async getSettings(orgId) {
502
+ return this.http.request("GET", `/v1/organizations/${orgId}/settings`);
503
+ }
504
+ /** Update organization settings. */
505
+ async updateSettings(orgId, settings) {
506
+ return this.http.request("PUT", `/v1/organizations/${orgId}/settings`, {
507
+ body: settings
508
+ });
509
+ }
510
+ /** Rotate the webhook signing secret (one-time reveal of new secret). */
511
+ async rotateWebhookSecret(orgId) {
512
+ return this.http.request("POST", `/v1/organizations/${orgId}/settings/webhook/rotate-secret`, {
513
+ body: {}
514
+ });
515
+ }
516
+ // ── Usage details ───────────────────────────────────────────────
517
+ /** Get daily usage rollup with optional grouping (provider, model, workflow). */
518
+ async usageDaily(orgId, params) {
519
+ return this.http.requestPaginated("GET", `/v1/organizations/${orgId}/usage/daily`, {
520
+ query: {
521
+ from: params?.from,
522
+ to: params?.to,
523
+ group_by: params?.group_by,
524
+ limit: params?.limit,
525
+ cursor: params?.cursor
526
+ }
527
+ });
528
+ }
529
+ /** Get detailed usage records (individual provider executions). */
530
+ async usageRecords(orgId) {
531
+ return this.http.request("GET", `/v1/organizations/${orgId}/usage/records`);
532
+ }
533
+ // ── Secrets ───────────────────────────────────────────────────────
534
+ /** List secrets for an organization. */
535
+ async listSecrets(orgId) {
536
+ return this.http.request("GET", `/v1/organizations/${orgId}/secrets`);
537
+ }
538
+ /** Create a secret. */
539
+ async createSecret(orgId, opts) {
540
+ return this.http.request("POST", `/v1/organizations/${orgId}/secrets`, { body: opts });
541
+ }
542
+ /** Delete a secret. */
543
+ async deleteSecret(orgId, name) {
544
+ await this.http.request("DELETE", `/v1/organizations/${orgId}/secrets/${encodeURIComponent(name)}`);
545
+ }
546
+ };
547
+
548
+ // src/resources/teams.resource.ts
549
+ var TeamsResource = class {
550
+ constructor(http) {
551
+ this.http = http;
552
+ }
553
+ /** Create a team within an organization. */
554
+ async create(opts) {
555
+ return this.http.request("POST", "/v1/teams", { body: opts });
556
+ }
557
+ /** Get a team by ID. */
558
+ async get(teamId) {
559
+ return this.http.request("GET", `/v1/teams/${teamId}`);
560
+ }
561
+ };
562
+
563
+ // src/types/events.ts
564
+ var TERMINAL_RUN_EVENTS = [
565
+ "workflow.run.completed",
566
+ "workflow.run.failed",
567
+ "workflow.run.cancelled"
568
+ ];
569
+ var NODE_EVENT_KINDS = [
570
+ "workflow.node.ready",
571
+ "workflow.node.claimed",
572
+ "workflow.node.started",
573
+ "workflow.node.progress",
574
+ "workflow.node.completed",
575
+ "workflow.node.failed",
576
+ "workflow.node.retried",
577
+ "workflow.node.skipped",
578
+ "workflow.node.cancelled",
579
+ "workflow.node.waiting_for_event",
580
+ "workflow.node.resumed"
581
+ ];
582
+
583
+ // src/streaming.ts
584
+ function connectSSE(options, onEvent, onError) {
585
+ const controller = new AbortController();
586
+ const fetchFn = options.fetch ?? globalThis.fetch;
587
+ const signal = options.signal ? combineSignals(options.signal, controller.signal) : controller.signal;
588
+ const done = (async () => {
589
+ const headers = {
590
+ ...options.headers,
591
+ Accept: "text/event-stream",
592
+ "Cache-Control": "no-cache"
593
+ };
594
+ if (options.lastEventId) {
595
+ headers["Last-Event-ID"] = options.lastEventId;
596
+ }
597
+ let res;
598
+ try {
599
+ res = await fetchFn(options.url, { headers, signal });
600
+ } catch (err) {
601
+ if (!isAbortError(err)) {
602
+ onError?.(err instanceof Error ? err : new Error(String(err)));
603
+ }
604
+ return;
605
+ }
606
+ if (!res.ok) {
607
+ onError?.(new Error(`SSE connection failed: ${res.status} ${res.statusText}`));
608
+ return;
609
+ }
610
+ const reader = res.body?.getReader();
611
+ if (!reader) {
612
+ onError?.(new Error("SSE response has no body"));
613
+ return;
614
+ }
615
+ const decoder = new TextDecoder();
616
+ let buffer = "";
617
+ let currentEvent = {};
618
+ let dataLines = [];
619
+ try {
620
+ while (true) {
621
+ const { done: streamDone, value } = await reader.read();
622
+ if (streamDone) break;
623
+ buffer += decoder.decode(value, { stream: true });
624
+ const lines = buffer.split("\n");
625
+ buffer = lines.pop() ?? "";
626
+ for (const line of lines) {
627
+ if (line === "") {
628
+ if (dataLines.length > 0) {
629
+ const dataStr = dataLines.join("\n");
630
+ let parsed;
631
+ try {
632
+ parsed = JSON.parse(dataStr);
633
+ } catch {
634
+ parsed = dataStr;
635
+ }
636
+ const sseEvent = {
637
+ event: currentEvent.event,
638
+ data: parsed,
639
+ id: currentEvent.id
640
+ };
641
+ onEvent(parsed, sseEvent);
642
+ }
643
+ currentEvent = {};
644
+ dataLines = [];
645
+ } else if (line.startsWith("data:")) {
646
+ dataLines.push(line.slice(line[5] === " " ? 6 : 5));
647
+ } else if (line.startsWith("event:")) {
648
+ currentEvent.event = line.slice(line[6] === " " ? 7 : 6);
649
+ } else if (line.startsWith("id:")) {
650
+ currentEvent.id = line.slice(line[3] === " " ? 4 : 3);
651
+ } else if (line.startsWith("retry:")) {
652
+ const ms = parseInt(line.slice(line[6] === " " ? 7 : 6), 10);
653
+ if (!isNaN(ms)) options.onRetry?.(ms);
654
+ }
655
+ }
656
+ }
657
+ } catch (err) {
658
+ if (!isAbortError(err)) {
659
+ onError?.(err instanceof Error ? err : new Error(String(err)));
660
+ }
661
+ } finally {
662
+ try {
663
+ reader.releaseLock();
664
+ } catch {
665
+ }
666
+ }
667
+ })();
668
+ return {
669
+ abort() {
670
+ controller.abort();
671
+ },
672
+ done
673
+ };
674
+ }
675
+ function isAbortError(err) {
676
+ return err instanceof DOMException && err.name === "AbortError";
677
+ }
678
+ function combineSignals(a, b) {
679
+ const controller = new AbortController();
680
+ const onAbort = () => controller.abort();
681
+ a.addEventListener("abort", onAbort, { once: true });
682
+ b.addEventListener("abort", onAbort, { once: true });
683
+ if (a.aborted || b.aborted) controller.abort();
684
+ return controller.signal;
685
+ }
686
+ function matchesFilter(event, filter) {
687
+ if (!filter) return true;
688
+ if (filter.kinds && filter.kinds.length > 0) {
689
+ if (!filter.kinds.includes(event.kind)) return false;
690
+ }
691
+ if (filter.nodeKeys && filter.nodeKeys.length > 0) {
692
+ if (event.node_key && !filter.nodeKeys.includes(event.node_key)) return false;
693
+ }
694
+ return true;
695
+ }
696
+ function connectReconnectingSSE(options, onEvent, onError) {
697
+ const controller = new AbortController();
698
+ const maxAttempts = options.maxReconnectAttempts ?? 10;
699
+ const baseDelay = options.reconnectBaseDelayMs ?? 1e3;
700
+ let lastEventId = options.lastEventId;
701
+ let serverRetryMs;
702
+ const done = (async () => {
703
+ let attempts = 0;
704
+ while (!controller.signal.aborted) {
705
+ let streamEndedCleanly = false;
706
+ const innerStream = connectSSE(
707
+ {
708
+ ...options,
709
+ lastEventId,
710
+ signal: controller.signal
711
+ },
712
+ (event, raw) => {
713
+ if (raw.id) lastEventId = raw.id;
714
+ attempts = 0;
715
+ if (!matchesFilter(event, options.filter)) return;
716
+ onEvent(event, raw);
717
+ },
718
+ (error) => {
719
+ if (!controller.signal.aborted) {
720
+ onError?.(error);
721
+ }
722
+ }
723
+ );
724
+ const origOnRetry = options.onRetry;
725
+ options.onRetry = (ms) => {
726
+ serverRetryMs = ms;
727
+ origOnRetry?.(ms);
728
+ };
729
+ await innerStream.done;
730
+ streamEndedCleanly = true;
731
+ if (controller.signal.aborted || !options.reconnect) break;
732
+ attempts++;
733
+ if (attempts > maxAttempts) {
734
+ onError?.(new Error(`SSE reconnection failed after ${maxAttempts} attempts`));
735
+ break;
736
+ }
737
+ const delay = serverRetryMs ?? baseDelay * Math.pow(2, Math.min(attempts - 1, 6));
738
+ await new Promise((resolve) => setTimeout(resolve, delay));
739
+ }
740
+ })();
741
+ return {
742
+ abort() {
743
+ controller.abort();
744
+ },
745
+ done
746
+ };
747
+ }
748
+
749
+ // src/resources/workflows.resource.ts
750
+ var WorkflowRegistryResource = class {
751
+ constructor(http) {
752
+ this.http = http;
753
+ }
754
+ /** Create a workflow definition in the registry. */
755
+ async create(opts) {
756
+ return this.http.request("POST", "/v1/workflow-registry", {
757
+ body: {
758
+ name: opts.name,
759
+ language: opts.language,
760
+ source: opts.source,
761
+ entry_point: opts.entry_point,
762
+ compose_from: opts.compose_from,
763
+ config: opts.config,
764
+ version: opts.version,
765
+ worker_tags: opts.worker_tags,
766
+ input_schema: opts.input_schema,
767
+ output_schema: opts.output_schema,
768
+ description: opts.description
769
+ }
770
+ });
771
+ }
772
+ /** List workflows visible to the current org (global + org + team). */
773
+ async list(params) {
774
+ return this.http.requestPaginated("GET", "/v1/workflow-registry", {
775
+ query: {
776
+ limit: params?.limit,
777
+ cursor: params?.cursor,
778
+ organization_id: params?.organization_id ?? this.http.getOrganizationId(),
779
+ team_id: params?.team_id ?? this.http.getTeamId()
780
+ }
781
+ });
782
+ }
783
+ /** Get a workflow by name (resolves hierarchically: team > org > global). */
784
+ async get(name, opts) {
785
+ const orgId = opts?.organization_id ?? this.http.getOrganizationId();
786
+ return this.http.request("GET", `/v1/workflow-registry/${encodeURIComponent(name)}`, {
787
+ query: { organization_id: orgId }
788
+ });
789
+ }
790
+ /** Delete an org/team-scoped workflow (not global). */
791
+ async delete(name, opts) {
792
+ const orgId = opts?.organization_id ?? this.http.getOrganizationId();
793
+ await this.http.request("DELETE", `/v1/workflow-registry/${encodeURIComponent(name)}`, {
794
+ query: { organization_id: orgId }
795
+ });
796
+ }
797
+ };
798
+ var WorkflowRunsResource = class {
799
+ constructor(http) {
800
+ this.http = http;
801
+ }
802
+ /** Submit a workflow run. Returns immediately with a run ID. */
803
+ async submit(workflowName, opts) {
804
+ return this.http.request("POST", "/v1/workflows/run", {
805
+ query: {
806
+ name: workflowName,
807
+ organization_id: opts?.organization_id ?? this.http.getOrganizationId(),
808
+ team_id: opts?.team_id ?? this.http.getTeamId()
809
+ },
810
+ body: {
811
+ input: opts?.input ?? {},
812
+ metadata: opts?.metadata,
813
+ priority: opts?.priority
814
+ },
815
+ idempotencyKey: opts?.idempotencyKey
816
+ });
817
+ }
818
+ /** List workflow runs. */
819
+ async list(params) {
820
+ return this.http.requestPaginated("GET", "/v1/workflows/runs", {
821
+ query: {
822
+ limit: params?.limit,
823
+ offset: params?.cursor,
824
+ organization_id: params?.organization_id ?? this.http.getOrganizationId(),
825
+ team_id: params?.team_id ?? this.http.getTeamId()
826
+ }
827
+ });
828
+ }
829
+ /** Get a run's status and progress. */
830
+ async get(runId) {
831
+ return this.http.request("GET", `/v1/workflows/runs/${runId}`);
832
+ }
833
+ /** Cancel a running workflow. */
834
+ async cancel(runId, reason) {
835
+ await this.http.request("POST", `/v1/workflows/runs/${runId}/cancel`, {
836
+ body: { reason }
837
+ });
838
+ }
839
+ /** Pause a running workflow. */
840
+ async pause(runId, reason) {
841
+ await this.http.request("POST", `/v1/workflows/runs/${runId}/pause`, {
842
+ body: { reason }
843
+ });
844
+ }
845
+ /** Resume a paused workflow. */
846
+ async resume(runId) {
847
+ await this.http.request("POST", `/v1/workflows/runs/${runId}/resume`, { body: {} });
848
+ }
849
+ /** Recover a stalled workflow from its last Sayiir checkpoint. */
850
+ async recover(runId) {
851
+ await this.http.request("POST", `/v1/workflows/runs/${runId}/recover`, { body: {} });
852
+ }
853
+ /** Send an external signal to a waiting workflow (e.g. HITL approval). */
854
+ async signal(runId, signalName, payload = {}) {
855
+ await this.http.request("POST", `/v1/workflows/runs/${runId}/signal`, {
856
+ body: { signal_name: signalName, payload }
857
+ });
858
+ }
859
+ /** Approve or reject a waiting workflow (convenience wrapper over signal). */
860
+ async approve(runId, opts) {
861
+ await this.http.request("POST", `/v1/workflows/runs/${runId}/approve`, {
862
+ body: opts
863
+ });
864
+ }
865
+ /** List workflow runs currently waiting for a signal (pending approvals). */
866
+ async listWaiting(params) {
867
+ return this.http.request("GET", "/v1/workflows/runs/waiting", {
868
+ query: {
869
+ organization_id: params?.organization_id ?? this.http.getOrganizationId(),
870
+ team_id: params?.team_id ?? this.http.getTeamId()
871
+ }
872
+ });
873
+ }
874
+ /**
875
+ * Stream SSE events for a workflow run.
876
+ *
877
+ * - Replays existing events, then streams live
878
+ * - Auto-reconnects via Last-Event-ID (when `reconnect: true`)
879
+ * - Client-side filtering by event kind and node key
880
+ * - Auto-closes on terminal events (completed/failed/cancelled)
881
+ *
882
+ * Returns an EventStream handle for cancellation.
883
+ */
884
+ streamEvents(runId, opts) {
885
+ const url = `${this.http.getBaseUrl()}/v1/workflow-runs/${runId}/events`;
886
+ const sseOpts = {
887
+ url,
888
+ headers: {},
889
+ lastEventId: opts.lastEventId,
890
+ signal: opts.signal,
891
+ filter: opts.filter,
892
+ reconnect: opts.reconnect,
893
+ maxReconnectAttempts: opts.maxReconnectAttempts,
894
+ fetch: async (input, init) => {
895
+ const headers = await this.http.buildHeaders({
896
+ ...init?.headers
897
+ });
898
+ return globalThis.fetch(input, { ...init, headers });
899
+ }
900
+ };
901
+ if (opts.reconnect) {
902
+ return connectReconnectingSSE(
903
+ sseOpts,
904
+ (event) => opts.onEvent(event),
905
+ opts.onError
906
+ );
907
+ }
908
+ return connectSSE(
909
+ sseOpts,
910
+ (event) => {
911
+ if (matchesFilter(event, opts.filter)) opts.onEvent(event);
912
+ },
913
+ opts.onError
914
+ );
915
+ }
916
+ /**
917
+ * Submit a workflow and wait for it to complete.
918
+ *
919
+ * Streams events via SSE while waiting. Returns the final WorkflowRun
920
+ * with status and output.
921
+ */
922
+ async submitAndWait(workflowName, opts) {
923
+ const run = await this.submit(workflowName, {
924
+ input: opts.input,
925
+ metadata: opts.metadata,
926
+ priority: opts.priority,
927
+ organization_id: opts.organization_id,
928
+ team_id: opts.team_id
929
+ });
930
+ const timeoutMs = opts.timeoutMs ?? 9e5;
931
+ return new Promise((resolve, reject) => {
932
+ const timeout = setTimeout(() => {
933
+ stream.abort();
934
+ reject(new Error(`Workflow run ${run.id} timed out after ${timeoutMs}ms`));
935
+ }, timeoutMs);
936
+ const stream = this.streamEvents(run.id, {
937
+ onEvent: (event) => {
938
+ opts.onEvent?.(event);
939
+ if (TERMINAL_RUN_EVENTS.includes(event.kind)) {
940
+ clearTimeout(timeout);
941
+ this.get(run.id).then(resolve).catch(reject);
942
+ }
943
+ },
944
+ onError: (error) => {
945
+ clearTimeout(timeout);
946
+ reject(error);
947
+ }
948
+ });
949
+ stream.done.then(() => {
950
+ clearTimeout(timeout);
951
+ this.get(run.id).then(resolve).catch(reject);
952
+ });
953
+ });
954
+ }
955
+ /** Get node execution attempts (logs) for a specific node. */
956
+ async getNodeAttempts(runId, nodeKey) {
957
+ return this.http.request(
958
+ "GET",
959
+ `/v1/workflows/runs/${runId}/nodes/${encodeURIComponent(nodeKey)}/attempts`
960
+ );
961
+ }
962
+ /** List artifacts produced by a workflow run. */
963
+ async artifacts(runId) {
964
+ return this.http.request("GET", `/v1/workflows/runs/${runId}/artifacts`);
965
+ }
966
+ /**
967
+ * List artifacts with signed download URLs for each asset.
968
+ *
969
+ * Fetches artifacts, then generates a signed URL for each one that has
970
+ * an `asset_id`. This is the recommended way for consumers to access
971
+ * output files (videos, images, audio, text) from completed workflows.
972
+ *
973
+ * @example
974
+ * ```ts
975
+ * const artifacts = await fabric.workflows.runs.artifactsWithUrls(runId);
976
+ * for (const a of artifacts) {
977
+ * console.log(a.filename, a.download_url); // signed URL ready for download
978
+ * }
979
+ * ```
980
+ */
981
+ async artifactsWithUrls(runId, expirySeconds) {
982
+ const artifacts = await this.artifacts(runId);
983
+ const withUrls = await Promise.all(
984
+ artifacts.map(async (artifact) => {
985
+ if (!artifact.asset_id) return artifact;
986
+ try {
987
+ const signed = await this.http.request(
988
+ "POST",
989
+ `/v1/asset-signed-urls/${artifact.asset_id}`,
990
+ { body: { expiry_seconds: expirySeconds } }
991
+ );
992
+ return { ...artifact, download_url: signed.url };
993
+ } catch {
994
+ return artifact;
995
+ }
996
+ })
997
+ );
998
+ return withUrls;
999
+ }
1000
+ /** Record an artifact produced by a workflow run (called by workers). */
1001
+ async recordArtifact(runId, artifact) {
1002
+ return this.http.request("POST", `/v1/workflows/runs/${runId}/artifacts`, {
1003
+ body: artifact
1004
+ });
1005
+ }
1006
+ /**
1007
+ * Watch a workflow run step-by-step with typed callbacks.
1008
+ *
1009
+ * High-level convenience that composes SSE streaming, client-side
1010
+ * filtering, auto-reconnection, and typed event dispatch.
1011
+ *
1012
+ * @example
1013
+ * ```ts
1014
+ * const watcher = fabric.workflows.runs.watch(runId, {
1015
+ * nodeKeys: ["transcribe", "render"],
1016
+ * onNodeStarted: (key) => console.log(`${key} started`),
1017
+ * onNodeProgress: (key, p) => console.log(`${key}: ${p.percentage}%`),
1018
+ * onNodeCompleted: (key) => console.log(`${key} done`),
1019
+ * onNodeFailed: (key, p) => console.error(`${key} failed:`, p),
1020
+ * onRunCompleted: () => console.log("Workflow finished!"),
1021
+ * onRunFailed: (p) => console.error("Workflow failed:", p),
1022
+ * });
1023
+ *
1024
+ * // Stop watching early
1025
+ * watcher.abort();
1026
+ *
1027
+ * // Or wait until completion
1028
+ * await watcher.done;
1029
+ * ```
1030
+ */
1031
+ watch(runId, opts = {}) {
1032
+ const filter = {};
1033
+ filter.kinds = [
1034
+ // Always include run lifecycle
1035
+ "workflow.run.completed",
1036
+ "workflow.run.failed",
1037
+ "workflow.run.cancelled",
1038
+ // Node events
1039
+ "workflow.node.started",
1040
+ "workflow.node.progress",
1041
+ "workflow.node.completed",
1042
+ "workflow.node.failed",
1043
+ "workflow.node.retried",
1044
+ "workflow.node.skipped",
1045
+ "workflow.node.waiting_for_event",
1046
+ "workflow.node.resumed"
1047
+ ];
1048
+ if (opts.nodeKeys && opts.nodeKeys.length > 0) {
1049
+ filter.nodeKeys = opts.nodeKeys;
1050
+ }
1051
+ const stream = this.streamEvents(runId, {
1052
+ lastEventId: opts.lastEventId,
1053
+ signal: opts.signal,
1054
+ reconnect: opts.reconnect ?? true,
1055
+ filter,
1056
+ onEvent: (event) => {
1057
+ opts.onEvent?.(event);
1058
+ const nodeKey = event.node_key ?? "unknown";
1059
+ const payload = event.payload;
1060
+ switch (event.kind) {
1061
+ case "workflow.node.started":
1062
+ opts.onNodeStarted?.(nodeKey, payload);
1063
+ break;
1064
+ case "workflow.node.progress":
1065
+ opts.onNodeProgress?.(nodeKey, payload);
1066
+ break;
1067
+ case "workflow.node.completed":
1068
+ opts.onNodeCompleted?.(nodeKey, payload);
1069
+ break;
1070
+ case "workflow.node.failed":
1071
+ opts.onNodeFailed?.(nodeKey, payload);
1072
+ break;
1073
+ case "workflow.run.completed":
1074
+ opts.onRunCompleted?.(payload);
1075
+ stream.abort();
1076
+ break;
1077
+ case "workflow.run.failed":
1078
+ opts.onRunFailed?.(payload);
1079
+ stream.abort();
1080
+ break;
1081
+ case "workflow.run.cancelled":
1082
+ opts.onRunCancelled?.(payload);
1083
+ stream.abort();
1084
+ break;
1085
+ }
1086
+ },
1087
+ onError: opts.onError
1088
+ });
1089
+ return stream;
1090
+ }
1091
+ };
1092
+ var WorkflowsResource = class {
1093
+ constructor(http) {
1094
+ this.http = http;
1095
+ this.registry = new WorkflowRegistryResource(http);
1096
+ this.runs = new WorkflowRunsResource(http);
1097
+ }
1098
+ registry;
1099
+ runs;
1100
+ /** Compose multiple workflows into a pipeline. */
1101
+ async compose(opts) {
1102
+ return this.http.request("POST", "/v1/workflows/compose", {
1103
+ body: {
1104
+ name: opts.name,
1105
+ steps: opts.steps,
1106
+ description: opts.description
1107
+ }
1108
+ });
1109
+ }
1110
+ /** Estimate cost of a workflow before running it. */
1111
+ async estimate(workflowName, opts) {
1112
+ return this.http.request("POST", "/v1/workflows/estimate", {
1113
+ query: {
1114
+ name: workflowName,
1115
+ organization_id: opts?.organization_id ?? this.http.getOrganizationId(),
1116
+ team_id: opts?.team_id ?? this.http.getTeamId()
1117
+ },
1118
+ body: {
1119
+ input: opts?.input,
1120
+ cost_profile: opts?.cost_profile
1121
+ }
1122
+ });
1123
+ }
1124
+ };
1125
+
1126
+ // src/resources/events.resource.ts
1127
+ var EventsResource = class {
1128
+ constructor(http) {
1129
+ this.http = http;
1130
+ }
1131
+ /** Build fetch wrapper that injects auth headers. */
1132
+ authFetch() {
1133
+ return async (input, init) => {
1134
+ const headers = await this.http.buildHeaders({
1135
+ ...init?.headers
1136
+ });
1137
+ return globalThis.fetch(input, { ...init, headers });
1138
+ };
1139
+ }
1140
+ /**
1141
+ * Stream all domain events via SSE.
1142
+ *
1143
+ * This is a long-lived connection — call `stream.abort()` to disconnect.
1144
+ */
1145
+ stream(opts) {
1146
+ const url = `${this.http.getBaseUrl()}/v1/events/stream`;
1147
+ const sseOpts = {
1148
+ url,
1149
+ headers: {},
1150
+ signal: opts.signal,
1151
+ lastEventId: opts.lastEventId,
1152
+ fetch: this.authFetch(),
1153
+ filter: opts.filter,
1154
+ reconnect: opts.reconnect,
1155
+ maxReconnectAttempts: opts.maxReconnectAttempts
1156
+ };
1157
+ if (opts.reconnect) {
1158
+ return connectReconnectingSSE(
1159
+ sseOpts,
1160
+ (event) => opts.onEvent(event),
1161
+ opts.onError
1162
+ );
1163
+ }
1164
+ return connectSSE(
1165
+ sseOpts,
1166
+ (event) => {
1167
+ if (matchesFilter(event, opts.filter)) opts.onEvent(event);
1168
+ },
1169
+ opts.onError
1170
+ );
1171
+ }
1172
+ /**
1173
+ * Stream events for a specific workflow run via SSE.
1174
+ *
1175
+ * Supports client-side filtering by event kind and node key, plus
1176
+ * auto-reconnection with Last-Event-ID replay.
1177
+ */
1178
+ streamRun(runId, opts) {
1179
+ const url = `${this.http.getBaseUrl()}/v1/workflow-runs/${runId}/events`;
1180
+ const sseOpts = {
1181
+ url,
1182
+ headers: {},
1183
+ lastEventId: opts.lastEventId,
1184
+ signal: opts.signal,
1185
+ fetch: this.authFetch(),
1186
+ filter: opts.filter,
1187
+ reconnect: opts.reconnect,
1188
+ maxReconnectAttempts: opts.maxReconnectAttempts
1189
+ };
1190
+ if (opts.reconnect) {
1191
+ return connectReconnectingSSE(
1192
+ sseOpts,
1193
+ (event) => opts.onEvent(event),
1194
+ opts.onError
1195
+ );
1196
+ }
1197
+ return connectSSE(
1198
+ sseOpts,
1199
+ (event) => {
1200
+ if (matchesFilter(event, opts.filter)) opts.onEvent(event);
1201
+ },
1202
+ opts.onError
1203
+ );
1204
+ }
1205
+ /**
1206
+ * Stream events for a specific job via SSE.
1207
+ *
1208
+ * A job is a single-node execution. Use this to watch one node
1209
+ * without receiving events from the rest of the workflow.
1210
+ */
1211
+ streamJob(jobId, opts) {
1212
+ const url = `${this.http.getBaseUrl()}/v1/jobs/${jobId}/events`;
1213
+ const sseOpts = {
1214
+ url,
1215
+ headers: {},
1216
+ lastEventId: opts.lastEventId,
1217
+ signal: opts.signal,
1218
+ fetch: this.authFetch(),
1219
+ filter: opts.filter,
1220
+ reconnect: opts.reconnect,
1221
+ maxReconnectAttempts: opts.maxReconnectAttempts
1222
+ };
1223
+ if (opts.reconnect) {
1224
+ return connectReconnectingSSE(
1225
+ sseOpts,
1226
+ (event) => opts.onEvent(event),
1227
+ opts.onError
1228
+ );
1229
+ }
1230
+ return connectSSE(
1231
+ sseOpts,
1232
+ (event) => {
1233
+ if (matchesFilter(event, opts.filter)) opts.onEvent(event);
1234
+ },
1235
+ opts.onError
1236
+ );
1237
+ }
1238
+ /**
1239
+ * Connect via WebSocket for bidirectional event streaming.
1240
+ *
1241
+ * Supports dynamic run subscription via `subscribeToRun()` / `unsubscribe()`.
1242
+ * Server acknowledgements are typed and delivered via `onAck`.
1243
+ * Only available in environments with WebSocket support (browser, Node.js 21+).
1244
+ */
1245
+ connectWebSocket(opts) {
1246
+ const baseUrl = this.http.getBaseUrl().replace(/^http/, "ws");
1247
+ const url = `${baseUrl}/v1/events/ws`;
1248
+ const ws = new WebSocket(url);
1249
+ ws.onmessage = (msg) => {
1250
+ try {
1251
+ const data = JSON.parse(msg.data);
1252
+ if ("subscribed_to_run" in data || "unsubscribed" in data) {
1253
+ opts.onAck?.(data);
1254
+ return;
1255
+ }
1256
+ const event = data;
1257
+ if (matchesFilter(event, opts.filter)) {
1258
+ opts.onEvent(event);
1259
+ }
1260
+ } catch {
1261
+ }
1262
+ };
1263
+ ws.onerror = (err) => opts.onError?.(err);
1264
+ ws.onclose = () => opts.onClose?.();
1265
+ return {
1266
+ subscribeToRun(runId) {
1267
+ const cmd = { subscribe_run: runId };
1268
+ ws.send(JSON.stringify(cmd));
1269
+ },
1270
+ unsubscribe() {
1271
+ const cmd = { unsubscribe: true };
1272
+ ws.send(JSON.stringify(cmd));
1273
+ },
1274
+ close() {
1275
+ ws.close();
1276
+ }
1277
+ };
1278
+ }
1279
+ };
1280
+
1281
+ // src/resources/assets.resource.ts
1282
+ var AssetsResource = class {
1283
+ constructor(http) {
1284
+ this.http = http;
1285
+ }
1286
+ /**
1287
+ * Upload an asset (max 100 MB).
1288
+ *
1289
+ * @param data - File data as Blob, ArrayBuffer, or ReadableStream
1290
+ * @param opts - Content type and optional filename
1291
+ */
1292
+ async upload(data, opts) {
1293
+ const headers = await this.http.buildHeaders({
1294
+ "Content-Type": opts?.contentType ?? "application/octet-stream"
1295
+ });
1296
+ if (opts?.filename) {
1297
+ headers["X-Filename"] = opts.filename;
1298
+ }
1299
+ const orgId = opts?.organization_id ?? this.http.getOrganizationId();
1300
+ const query = orgId ? `?organization_id=${orgId}` : "";
1301
+ const res = await globalThis.fetch(`${this.http.getBaseUrl()}/v1/assets${query}`, {
1302
+ method: "POST",
1303
+ headers,
1304
+ body: data
1305
+ });
1306
+ const json = await res.json();
1307
+ if (json.error) {
1308
+ throw new Error(`${json.error.code}: ${json.error.message}`);
1309
+ }
1310
+ return json.data;
1311
+ }
1312
+ /** List assets for the current organization. */
1313
+ async list(params) {
1314
+ return this.http.requestPaginated("GET", "/v1/assets", {
1315
+ query: {
1316
+ limit: params?.limit,
1317
+ cursor: params?.cursor,
1318
+ organization_id: params?.organization_id ?? this.http.getOrganizationId()
1319
+ }
1320
+ });
1321
+ }
1322
+ /** Generate a signed download URL for an asset. */
1323
+ async signedUrl(assetId, expirySeconds) {
1324
+ return this.http.request("POST", `/v1/asset-signed-urls/${assetId}`, {
1325
+ body: { expiry_seconds: expirySeconds }
1326
+ });
1327
+ }
1328
+ /** Download an asset by path. Returns the raw Response for streaming. */
1329
+ async download(path) {
1330
+ return this.http.requestRaw("GET", `/v1/assets/${path}`);
1331
+ }
1332
+ };
1333
+
1334
+ // src/resources/galleries.resource.ts
1335
+ var GalleriesResource = class {
1336
+ constructor(http) {
1337
+ this.http = http;
1338
+ }
1339
+ /** Create a gallery. */
1340
+ async create(opts) {
1341
+ return this.http.request("POST", "/v1/galleries", { body: opts });
1342
+ }
1343
+ /** List galleries. */
1344
+ async list(params) {
1345
+ return this.http.requestPaginated("GET", "/v1/galleries", {
1346
+ query: { limit: params?.limit, cursor: params?.cursor }
1347
+ });
1348
+ }
1349
+ /** Get a gallery by ID. */
1350
+ async get(galleryId) {
1351
+ return this.http.request("GET", `/v1/galleries/${galleryId}`);
1352
+ }
1353
+ /** Delete a gallery. */
1354
+ async delete(galleryId) {
1355
+ await this.http.request("DELETE", `/v1/galleries/${galleryId}`);
1356
+ }
1357
+ /** Add an item to a gallery. */
1358
+ async addItem(galleryId, opts) {
1359
+ return this.http.request("POST", `/v1/galleries/${galleryId}/items`, { body: opts });
1360
+ }
1361
+ /** List items in a gallery. */
1362
+ async listItems(galleryId, params) {
1363
+ return this.http.requestPaginated("GET", `/v1/galleries/${galleryId}/items`, {
1364
+ query: { limit: params?.limit, cursor: params?.cursor }
1365
+ });
1366
+ }
1367
+ /** Remove an item from a gallery. */
1368
+ async removeItem(itemId) {
1369
+ await this.http.request("DELETE", `/v1/gallery-items/${itemId}`);
1370
+ }
1371
+ };
1372
+
1373
+ // src/resources/api-keys.resource.ts
1374
+ var ApiKeysResource = class {
1375
+ constructor(http) {
1376
+ this.http = http;
1377
+ }
1378
+ /** Create an API key. Returns the raw secret (only shown once). */
1379
+ async create(opts) {
1380
+ return this.http.request("POST", "/v1/api-keys", { body: opts });
1381
+ }
1382
+ /** List API keys. */
1383
+ async list(params) {
1384
+ return this.http.requestPaginated("GET", "/v1/api-keys", {
1385
+ query: { limit: params?.limit, cursor: params?.cursor }
1386
+ });
1387
+ }
1388
+ /** Get an API key by ID. */
1389
+ async get(keyId) {
1390
+ return this.http.request("GET", `/v1/api-keys/${keyId}`);
1391
+ }
1392
+ /** Delete an API key. */
1393
+ async delete(keyId) {
1394
+ await this.http.request("DELETE", `/v1/api-keys/${keyId}`);
1395
+ }
1396
+ /** Disable an API key. */
1397
+ async disable(keyId) {
1398
+ await this.http.request("POST", `/v1/api-keys/${keyId}/disable`, { body: {} });
1399
+ }
1400
+ /** Rotate an API key (new secret issued). */
1401
+ async rotate(keyId) {
1402
+ return this.http.request("POST", `/v1/api-keys/${keyId}/rotate`, { body: {} });
1403
+ }
1404
+ };
1405
+
1406
+ // src/resources/invitations.resource.ts
1407
+ var InvitationsResource = class {
1408
+ constructor(http) {
1409
+ this.http = http;
1410
+ }
1411
+ /** Create an invitation. */
1412
+ async create(opts) {
1413
+ return this.http.request("POST", "/v1/invitations", { body: opts });
1414
+ }
1415
+ /** Accept an invitation. */
1416
+ async accept(invitationId) {
1417
+ await this.http.request("POST", `/v1/invitations/${invitationId}/accept`, { body: {} });
1418
+ }
1419
+ /** Revoke/cancel an invitation. */
1420
+ async revoke(invitationId) {
1421
+ await this.http.request("POST", `/v1/invitations/${invitationId}/revoke`, { body: {} });
1422
+ }
1423
+ };
1424
+
1425
+ // src/resources/permissions.resource.ts
1426
+ var PermissionsResource = class {
1427
+ constructor(http) {
1428
+ this.http = http;
1429
+ }
1430
+ /** Check a single permission. */
1431
+ async check(opts) {
1432
+ return this.http.request("POST", "/v1/authz/check", { body: opts });
1433
+ }
1434
+ /** Check multiple permissions in batch. */
1435
+ async checkBatch(checks) {
1436
+ return this.http.request("POST", "/v1/authz/check-batch", {
1437
+ body: { checks }
1438
+ });
1439
+ }
1440
+ /** Grant a permission (ACL entry). */
1441
+ async grant(opts) {
1442
+ return this.http.request("POST", "/v1/permissions", { body: opts });
1443
+ }
1444
+ /** List permissions. */
1445
+ async list(params) {
1446
+ return this.http.requestPaginated("GET", "/v1/permissions", {
1447
+ query: {
1448
+ limit: params?.limit,
1449
+ cursor: params?.cursor,
1450
+ resource_type: params?.resource_type,
1451
+ resource_id: params?.resource_id
1452
+ }
1453
+ });
1454
+ }
1455
+ /** Revoke a permission. */
1456
+ async revoke(permissionId) {
1457
+ await this.http.request("DELETE", `/v1/permissions/${permissionId}`);
1458
+ }
1459
+ };
1460
+
1461
+ // src/resources/webhooks.resource.ts
1462
+ var WebhooksResource = class {
1463
+ constructor(http) {
1464
+ this.http = http;
1465
+ }
1466
+ /** Create a webhook for an organization. */
1467
+ async create(orgId, opts) {
1468
+ return this.http.request("POST", `/v1/organizations/${orgId}/webhooks`, { body: opts });
1469
+ }
1470
+ /** List webhooks for an organization. */
1471
+ async list(orgId, params) {
1472
+ return this.http.requestPaginated("GET", `/v1/organizations/${orgId}/webhooks`, {
1473
+ query: { limit: params?.limit, cursor: params?.cursor }
1474
+ });
1475
+ }
1476
+ /** Get a webhook by ID. */
1477
+ async get(webhookId) {
1478
+ return this.http.request("GET", `/v1/webhooks/${webhookId}`);
1479
+ }
1480
+ /** Update a webhook. */
1481
+ async update(webhookId, opts) {
1482
+ return this.http.request("PATCH", `/v1/webhooks/${webhookId}`, { body: opts });
1483
+ }
1484
+ /** Delete a webhook. */
1485
+ async delete(webhookId) {
1486
+ await this.http.request("DELETE", `/v1/webhooks/${webhookId}`);
1487
+ }
1488
+ /** List delivery attempts for a webhook. */
1489
+ async deliveries(webhookId, params) {
1490
+ return this.http.requestPaginated("GET", `/v1/webhooks/${webhookId}/deliveries`, {
1491
+ query: { limit: params?.limit, cursor: params?.cursor }
1492
+ });
1493
+ }
1494
+ };
1495
+
1496
+ // src/resources/service-accounts.resource.ts
1497
+ var ServiceAccountsResource = class {
1498
+ constructor(http) {
1499
+ this.http = http;
1500
+ }
1501
+ /** Create a service account. */
1502
+ async create(opts) {
1503
+ return this.http.request("POST", "/v1/service-accounts", { body: opts });
1504
+ }
1505
+ /** List service accounts. */
1506
+ async list(params) {
1507
+ return this.http.requestPaginated("GET", "/v1/service-accounts", {
1508
+ query: { limit: params?.limit, cursor: params?.cursor }
1509
+ });
1510
+ }
1511
+ /** Get a service account by ID. */
1512
+ async get(id) {
1513
+ return this.http.request("GET", `/v1/service-accounts/${id}`);
1514
+ }
1515
+ /** Disable a service account. */
1516
+ async disable(id) {
1517
+ await this.http.request("POST", `/v1/service-accounts/${id}/disable`, { body: {} });
1518
+ }
1519
+ /** Enable a service account. */
1520
+ async enable(id) {
1521
+ await this.http.request("POST", `/v1/service-accounts/${id}/enable`, { body: {} });
1522
+ }
1523
+ /** Create an API key for a service account. */
1524
+ async createApiKey(id) {
1525
+ return this.http.request("POST", `/v1/service-accounts/${id}/api-keys`, { body: {} });
1526
+ }
1527
+ /** List API keys for a service account. */
1528
+ async listApiKeys(id) {
1529
+ return this.http.request("GET", `/v1/service-accounts/${id}/api-keys`);
1530
+ }
1531
+ /** Revoke an API key for a service account. */
1532
+ async revokeApiKey(id, keyId) {
1533
+ await this.http.request("DELETE", `/v1/service-accounts/${id}/api-keys/${keyId}`);
1534
+ }
1535
+ /** Rotate an API key for a service account. */
1536
+ async rotateApiKey(id, keyId) {
1537
+ return this.http.request("POST", `/v1/service-accounts/${id}/api-keys/${keyId}/rotate`, { body: {} });
1538
+ }
1539
+ };
1540
+
1541
+ // src/resources/oauth.resource.ts
1542
+ var OAuthResource = class {
1543
+ constructor(http) {
1544
+ this.http = http;
1545
+ }
1546
+ /** Create an OAuth client for an organization. */
1547
+ async createClient(opts) {
1548
+ return this.http.request("POST", "/v1/oauth/clients", { body: opts });
1549
+ }
1550
+ /** List OAuth clients. */
1551
+ async listClients() {
1552
+ return this.http.request("GET", "/v1/oauth/clients");
1553
+ }
1554
+ /** Delete an OAuth client. */
1555
+ async deleteClient(clientId) {
1556
+ await this.http.request("DELETE", `/v1/oauth/clients/${clientId}`);
1557
+ }
1558
+ /** Exchange client credentials for an access token. */
1559
+ async token(clientId, clientSecret) {
1560
+ return this.http.request("POST", "/v1/oauth/token", {
1561
+ body: {
1562
+ grant_type: "client_credentials",
1563
+ client_id: clientId,
1564
+ client_secret: clientSecret
1565
+ }
1566
+ });
1567
+ }
1568
+ /** Refresh an access token. */
1569
+ async refresh(refreshToken) {
1570
+ return this.http.request("POST", "/v1/oauth/token", {
1571
+ body: {
1572
+ grant_type: "refresh_token",
1573
+ refresh_token: refreshToken
1574
+ }
1575
+ });
1576
+ }
1577
+ /** Revoke an OAuth token. */
1578
+ async revoke(token) {
1579
+ await this.http.request("POST", "/v1/oauth/revoke", {
1580
+ body: { token }
1581
+ });
1582
+ }
1583
+ };
1584
+
1585
+ // src/resources/admin.resource.ts
1586
+ var AdminResource = class {
1587
+ constructor(http) {
1588
+ this.http = http;
1589
+ }
1590
+ /** Bootstrap the system (dev mode: creates org + admin). */
1591
+ async bootstrap() {
1592
+ return this.http.request("POST", "/v1/admin/bootstrap", { body: {} });
1593
+ }
1594
+ /** List concurrency limits. */
1595
+ async listConcurrencyLimits() {
1596
+ return this.http.request("GET", "/v1/admin/concurrency-limits");
1597
+ }
1598
+ /** Set a concurrency limit for a scope (e.g., "org:<uuid>"). */
1599
+ async setConcurrencyLimit(scope, maxConcurrentRuns) {
1600
+ return this.http.request("PUT", "/v1/admin/concurrency-limits", {
1601
+ body: { scope, max_concurrent_runs: maxConcurrentRuns }
1602
+ });
1603
+ }
1604
+ /** Get system information (version, features, uptime). */
1605
+ async systemInfo() {
1606
+ return this.http.request("GET", "/v1/system/info");
1607
+ }
1608
+ /** Get detailed system status (database, event bus health). */
1609
+ async systemStatus() {
1610
+ return this.http.request("GET", "/v1/system/status");
1611
+ }
1612
+ /** List audit logs (standalone, not org-scoped). */
1613
+ async auditLogs(params) {
1614
+ return this.http.requestPaginated("GET", "/v1/audit-logs", {
1615
+ query: { limit: params?.limit, cursor: params?.cursor }
1616
+ });
1617
+ }
1618
+ };
1619
+
1620
+ // src/resources/schedules.resource.ts
1621
+ var SchedulesResource = class {
1622
+ constructor(http) {
1623
+ this.http = http;
1624
+ }
1625
+ /** Create a schedule for a workflow definition. */
1626
+ async create(workflowDefId, opts) {
1627
+ return this.http.request("POST", `/v1/workflow-definitions/${workflowDefId}/schedules`, { body: opts });
1628
+ }
1629
+ /** List schedules for a workflow definition. */
1630
+ async list(workflowDefId) {
1631
+ return this.http.request("GET", `/v1/workflow-definitions/${workflowDefId}/schedules`);
1632
+ }
1633
+ /** Get a schedule by ID. */
1634
+ async get(scheduleId) {
1635
+ return this.http.request("GET", `/v1/schedules/${scheduleId}`);
1636
+ }
1637
+ /** Update a schedule. */
1638
+ async update(scheduleId, opts) {
1639
+ return this.http.request("PATCH", `/v1/schedules/${scheduleId}`, { body: opts });
1640
+ }
1641
+ /** Delete a schedule. */
1642
+ async delete(scheduleId) {
1643
+ await this.http.request("DELETE", `/v1/schedules/${scheduleId}`);
1644
+ }
1645
+ /** Manually trigger a scheduled workflow run. */
1646
+ async trigger(scheduleId) {
1647
+ return this.http.request("POST", `/v1/schedules/${scheduleId}/trigger`);
1648
+ }
1649
+ /** List run history for a schedule. */
1650
+ async history(scheduleId) {
1651
+ return this.http.request("GET", `/v1/schedules/${scheduleId}/history`);
1652
+ }
1653
+ };
1654
+
1655
+ // src/resources/providers.resource.ts
1656
+ var ProvidersResource = class {
1657
+ constructor(http) {
1658
+ this.http = http;
1659
+ }
1660
+ /** List all available provider capabilities. */
1661
+ async list() {
1662
+ return this.http.request("GET", "/v1/providers");
1663
+ }
1664
+ /** Execute a provider (request/response). */
1665
+ async execute(request) {
1666
+ return this.http.request("POST", "/v1/providers/execute", {
1667
+ body: request
1668
+ });
1669
+ }
1670
+ /**
1671
+ * Execute a provider with streaming (SSE).
1672
+ *
1673
+ * Streams token-level chunks during LLM inference.
1674
+ * Events: `chunk` (delta), `complete` (final response + usage), `error`.
1675
+ */
1676
+ executeStream(request, opts) {
1677
+ const url = `${this.http.getBaseUrl()}/v1/providers/execute/stream`;
1678
+ return connectSSE(
1679
+ {
1680
+ url,
1681
+ headers: {},
1682
+ signal: opts.signal,
1683
+ fetch: async (input, init) => {
1684
+ const headers = await this.http.buildHeaders({
1685
+ ...init?.headers
1686
+ });
1687
+ return globalThis.fetch(input, {
1688
+ ...init,
1689
+ method: "POST",
1690
+ headers,
1691
+ body: JSON.stringify(request)
1692
+ });
1693
+ }
1694
+ },
1695
+ (event, raw) => {
1696
+ if (raw.event === "chunk") {
1697
+ opts.onChunk(event);
1698
+ } else if (raw.event === "complete") {
1699
+ opts.onComplete?.(event);
1700
+ }
1701
+ },
1702
+ opts.onError
1703
+ );
1704
+ }
1705
+ /** Estimate the cost of a provider execution before running it. */
1706
+ async estimate(request) {
1707
+ return this.http.request("POST", "/v1/providers/estimate", {
1708
+ body: request
1709
+ });
1710
+ }
1711
+ };
1712
+
1713
+ // src/resources/packages.resource.ts
1714
+ var PackagesResource = class {
1715
+ constructor(http) {
1716
+ this.http = http;
1717
+ }
1718
+ /** List all installed domain packages. */
1719
+ async list() {
1720
+ return this.http.request("GET", "/v1/packages");
1721
+ }
1722
+ };
1723
+
1724
+ // src/client.ts
1725
+ var DEFAULT_BASE_URL = "http://localhost:3001";
1726
+ var FabricClient = class {
1727
+ auth;
1728
+ me;
1729
+ organizations;
1730
+ teams;
1731
+ workflows;
1732
+ events;
1733
+ assets;
1734
+ galleries;
1735
+ apiKeys;
1736
+ invitations;
1737
+ permissions;
1738
+ webhooks;
1739
+ serviceAccounts;
1740
+ oauth;
1741
+ admin;
1742
+ schedules;
1743
+ providers;
1744
+ packages;
1745
+ constructor(config = {}) {
1746
+ const transport = new HttpTransport({
1747
+ baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
1748
+ auth: config.auth,
1749
+ organizationId: config.organizationId,
1750
+ teamId: config.teamId,
1751
+ timeout: config.timeout,
1752
+ fetch: config.fetch,
1753
+ debug: config.debug,
1754
+ onRequest: config.onRequest,
1755
+ onResponse: config.onResponse
1756
+ });
1757
+ this.auth = new AuthResource(transport);
1758
+ this.me = new MeResource(transport);
1759
+ this.organizations = new OrganizationsResource(transport);
1760
+ this.teams = new TeamsResource(transport);
1761
+ this.workflows = new WorkflowsResource(transport);
1762
+ this.events = new EventsResource(transport);
1763
+ this.assets = new AssetsResource(transport);
1764
+ this.galleries = new GalleriesResource(transport);
1765
+ this.apiKeys = new ApiKeysResource(transport);
1766
+ this.invitations = new InvitationsResource(transport);
1767
+ this.permissions = new PermissionsResource(transport);
1768
+ this.webhooks = new WebhooksResource(transport);
1769
+ this.serviceAccounts = new ServiceAccountsResource(transport);
1770
+ this.oauth = new OAuthResource(transport);
1771
+ this.admin = new AdminResource(transport);
1772
+ this.schedules = new SchedulesResource(transport);
1773
+ this.providers = new ProvidersResource(transport);
1774
+ this.packages = new PackagesResource(transport);
1775
+ }
1776
+ };
1777
+
1778
+ // src/pagination.ts
1779
+ async function* paginate(fetcher, options) {
1780
+ let cursor;
1781
+ do {
1782
+ const page = await fetcher({ limit: options?.limit, cursor });
1783
+ yield page.items;
1784
+ cursor = page.pagination.has_more ? page.pagination.next_cursor : void 0;
1785
+ } while (cursor);
1786
+ }
1787
+ async function* paginateItems(fetcher, options) {
1788
+ for await (const page of paginate(fetcher, options)) {
1789
+ for (const item of page) {
1790
+ yield item;
1791
+ }
1792
+ }
1793
+ }
1794
+ async function paginateAll(fetcher, options) {
1795
+ const all = [];
1796
+ for await (const page of paginate(fetcher, options)) {
1797
+ all.push(...page);
1798
+ }
1799
+ return all;
1800
+ }
1801
+
1802
+ // src/verify-webhook.ts
1803
+ async function verifyWebhookSignature(rawBody, signature, secret) {
1804
+ const expected = await computeSignature(rawBody, secret);
1805
+ return constantTimeEqual(expected, signature);
1806
+ }
1807
+ async function constructWebhookEvent(rawBody, signature, secret) {
1808
+ const valid = await verifyWebhookSignature(rawBody, signature, secret);
1809
+ if (!valid) {
1810
+ throw new Error("Invalid webhook signature");
1811
+ }
1812
+ return JSON.parse(rawBody);
1813
+ }
1814
+ var encoder = new TextEncoder();
1815
+ async function computeSignature(payload, secret) {
1816
+ const key = await crypto.subtle.importKey(
1817
+ "raw",
1818
+ encoder.encode(secret),
1819
+ { name: "HMAC", hash: "SHA-256" },
1820
+ false,
1821
+ ["sign"]
1822
+ );
1823
+ const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(payload));
1824
+ return `sha256=${hexEncode(new Uint8Array(sig))}`;
1825
+ }
1826
+ function hexEncode(bytes) {
1827
+ let hex = "";
1828
+ for (let i = 0; i < bytes.length; i++) {
1829
+ hex += bytes[i].toString(16).padStart(2, "0");
1830
+ }
1831
+ return hex;
1832
+ }
1833
+ function constantTimeEqual(a, b) {
1834
+ if (a.length !== b.length) return false;
1835
+ let result = 0;
1836
+ for (let i = 0; i < a.length; i++) {
1837
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
1838
+ }
1839
+ return result === 0;
1840
+ }
1841
+
1842
+ // src/_compat.ts
1843
+ var ansi = {
1844
+ reset: "\x1B[0m",
1845
+ dim: "\x1B[2m",
1846
+ bold: "\x1B[1m",
1847
+ green: "\x1B[32m",
1848
+ red: "\x1B[31m",
1849
+ cyan: "\x1B[36m"
1850
+ };
1851
+ var nodeTimers = {};
1852
+ var ts = () => (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 12);
1853
+ var logEvents = (event) => {
1854
+ const t = `${ansi.dim}${ts()}${ansi.reset}`;
1855
+ const key = event.node_key;
1856
+ switch (event.kind) {
1857
+ case "workflow.run.started":
1858
+ console.log(`${t} ${ansi.green}\u25B6 Workflow started${ansi.reset}`);
1859
+ break;
1860
+ case "workflow.node.started":
1861
+ if (key) nodeTimers[key] = Date.now();
1862
+ console.log(`${t} ${ansi.cyan}\u27F3 ${key}${ansi.reset} running`);
1863
+ break;
1864
+ case "workflow.node.completed": {
1865
+ const ms = key && nodeTimers[key] ? Date.now() - nodeTimers[key] : 0;
1866
+ console.log(`${t} ${ansi.green}\u2713 ${key}${ansi.reset} ${ms ? `${(ms / 1e3).toFixed(1)}s` : ""}`);
1867
+ break;
1868
+ }
1869
+ case "workflow.node.failed":
1870
+ console.log(`${t} ${ansi.red}\u2717 ${key} FAILED${ansi.reset} ${event.payload?.error ?? ""}`);
1871
+ break;
1872
+ case "workflow.run.completed":
1873
+ console.log(`${t} ${ansi.green}${ansi.bold}\u2713 Workflow completed!${ansi.reset}`);
1874
+ break;
1875
+ case "workflow.run.failed":
1876
+ console.log(`${t} ${ansi.red}${ansi.bold}\u2717 Workflow failed${ansi.reset} ${event.payload?.error ?? ""}`);
1877
+ break;
1878
+ }
1879
+ };
1880
+ export {
1881
+ AdminResource,
1882
+ ApiKeysResource,
1883
+ AssetsResource,
1884
+ AuthResource,
1885
+ EventsResource,
1886
+ FabricAuthError,
1887
+ FabricClient,
1888
+ FabricConflictError,
1889
+ FabricError,
1890
+ FabricForbiddenError,
1891
+ FabricNotFoundError,
1892
+ FabricRateLimitError,
1893
+ FabricServerError,
1894
+ FabricValidationError,
1895
+ GalleriesResource,
1896
+ InvitationsResource,
1897
+ MeResource,
1898
+ NODE_EVENT_KINDS,
1899
+ OAuthResource,
1900
+ OrganizationsResource,
1901
+ PackagesResource,
1902
+ PermissionsResource,
1903
+ ProvidersResource,
1904
+ SchedulesResource,
1905
+ ServiceAccountsResource,
1906
+ TERMINAL_RUN_EVENTS,
1907
+ TeamsResource,
1908
+ WebhooksResource,
1909
+ WorkflowRegistryResource,
1910
+ WorkflowRunsResource,
1911
+ WorkflowsResource,
1912
+ connectReconnectingSSE,
1913
+ constructWebhookEvent,
1914
+ logEvents,
1915
+ matchesFilter,
1916
+ paginate,
1917
+ paginateAll,
1918
+ paginateItems,
1919
+ verifyWebhookSignature
1920
+ };
1921
+ //# sourceMappingURL=index.js.map