@gravity-rail/sdk 0.47.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +117 -9
  2. package/dist/agui.cjs +17 -2
  3. package/dist/agui.cjs.map +1 -1
  4. package/dist/agui.d.cts +9 -1
  5. package/dist/agui.d.ts +9 -1
  6. package/dist/agui.js +15 -1
  7. package/dist/agui.js.map +1 -1
  8. package/dist/{chat-interaction-Bqj3Vbst.d.cts → chat-interaction-CmGKKlnL.d.ts} +244 -37
  9. package/dist/{chat-interaction-DiZVtDRE.d.ts → chat-interaction-THDGF4ko.d.cts} +244 -37
  10. package/dist/{chunk-72SWNLVD.js → chunk-MMDSZ25F.js} +1 -1
  11. package/dist/chunk-MMDSZ25F.js.map +1 -0
  12. package/dist/{chunk-N4GQWNGU.js → chunk-QRZVXPR4.js} +204 -50
  13. package/dist/chunk-QRZVXPR4.js.map +1 -0
  14. package/dist/{chunk-67QXTQVL.js → chunk-TGL72KPS.js} +59 -118
  15. package/dist/chunk-TGL72KPS.js.map +1 -0
  16. package/dist/helpers.cjs.map +1 -1
  17. package/dist/helpers.d.cts +4 -4
  18. package/dist/helpers.d.ts +4 -4
  19. package/dist/helpers.js +1 -1
  20. package/dist/index.cjs +262 -164
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +7 -6
  23. package/dist/index.d.ts +7 -6
  24. package/dist/index.js +9 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/internal.cjs +262 -164
  27. package/dist/internal.cjs.map +1 -1
  28. package/dist/internal.d.cts +148 -6
  29. package/dist/internal.d.ts +148 -6
  30. package/dist/internal.js +9 -3
  31. package/dist/internal.js.map +1 -1
  32. package/dist/{member-import-D7U4kDIy.d.cts → member-import-9zHkUjcn.d.cts} +1 -1
  33. package/dist/{member-import-C2Xt_o5d.d.ts → member-import-ocJ_K474.d.ts} +1 -1
  34. package/dist/{revision-state-ZC4qP3CS.d.cts → path-BQgkft9c.d.ts} +64 -3
  35. package/dist/{revision-state-DaVz2528.d.ts → path-DZbDwvpS.d.cts} +64 -3
  36. package/dist/schemas.cjs +59 -16
  37. package/dist/schemas.cjs.map +1 -1
  38. package/dist/schemas.d.cts +22 -3
  39. package/dist/schemas.d.ts +22 -3
  40. package/dist/schemas.js +59 -17
  41. package/dist/schemas.js.map +1 -1
  42. package/dist/{tasks-Ca6yfsj2.d.cts → tasks-DsNsbco5.d.cts} +66 -14
  43. package/dist/{tasks-Ca6yfsj2.d.ts → tasks-DsNsbco5.d.ts} +66 -14
  44. package/package.json +2 -2
  45. package/dist/chunk-67QXTQVL.js.map +0 -1
  46. package/dist/chunk-72SWNLVD.js.map +0 -1
  47. package/dist/chunk-N4GQWNGU.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -243,6 +243,7 @@ __export(src_exports, {
243
243
  getFeaturesByCategory: () => getFeaturesByCategory,
244
244
  getFeaturesByVisibility: () => getFeaturesByVisibility,
245
245
  getMissingDependencies: () => getMissingDependencies,
246
+ getPathDefinition: () => getPathDefinition,
246
247
  getResourceMetadata: () => getResourceMetadata,
247
248
  getRevisionState: () => getRevisionState,
248
249
  getTTSProvider: () => getTTSProvider,
@@ -258,6 +259,8 @@ __export(src_exports, {
258
259
  isRegistryInitialized: () => isRegistryInitialized,
259
260
  isSMSDeliveryFailureStatus: () => isSMSDeliveryFailureStatus,
260
261
  parseOrgAuthChallenge: () => parseOrgAuthChallenge,
262
+ pathDraftFromStorage: () => pathDraftFromStorage,
263
+ pathDraftToStorage: () => pathDraftToStorage,
261
264
  requiresAssistantParticipant: () => requiresAssistantParticipant,
262
265
  runWorkspaceScript: () => runWorkspaceScript,
263
266
  toSafeMemberImportPreview: () => toSafeMemberImportPreview,
@@ -323,27 +326,16 @@ function parseOrgAuthChallenge(wwwAuthenticate) {
323
326
  if (!wwwAuthenticate) return null;
324
327
  if (!wwwAuthenticate.includes('realm="org"')) return null;
325
328
  const orgUuidMatch = wwwAuthenticate.match(/org_uuid="([^"]+)"/);
326
- const cookieNameMatch = wwwAuthenticate.match(/cookie_name="([^"]+)"/);
327
329
  const authUrlMatch = wwwAuthenticate.match(/auth_url="([^"]+)"/);
328
- if (!orgUuidMatch?.[1] || !cookieNameMatch?.[1] || !authUrlMatch?.[1]) {
330
+ if (!orgUuidMatch?.[1] || !authUrlMatch?.[1]) {
329
331
  console.warn("Invalid org auth challenge header: missing required fields");
330
332
  return null;
331
333
  }
332
334
  return {
333
335
  orgUuid: orgUuidMatch[1],
334
- cookieName: cookieNameMatch[1],
335
336
  authUrl: authUrlMatch[1]
336
337
  };
337
338
  }
338
- function getRequestOrgCookieName(cookieName) {
339
- if (cookieName.startsWith("orgToken")) {
340
- return cookieName.replace(/^orgToken/, "requestOrgToken");
341
- }
342
- if (cookieName.startsWith("orgSession")) {
343
- return cookieName.replace(/^orgSession/, "requestOrgSession");
344
- }
345
- return null;
346
- }
347
339
  function orgAuthHeaderName(token) {
348
340
  return token.startsWith("gr_sess_") ? "X-Org-Session" : "X-Org-Token";
349
341
  }
@@ -400,7 +392,7 @@ var BaseApiClient = class {
400
392
  this.apiKey = newApiKey;
401
393
  }
402
394
  /**
403
- * Set the opaque org session credential for cross-domain requests.
395
+ * Set the opaque org session credential a bearer client sends as `X-Org-Session`.
404
396
  * Opaque gr_sess_ values use X-Org-Session. Legacy orgToken JWE values still
405
397
  * use X-Org-Token through setOrgToken() during the migration window.
406
398
  *
@@ -420,7 +412,42 @@ var BaseApiClient = class {
420
412
  setOrgToken(token, orgUuid) {
421
413
  this.setOrgSession(token, orgUuid);
422
414
  }
423
- async fetch(endpoint, options) {
415
+ /**
416
+ * The `credentials` a request carries: none for a bearer client (the fetch
417
+ * default), the page's own-origin cookies for a same-origin session.
418
+ */
419
+ credentialsInit() {
420
+ return this.apiKey ? {} : { credentials: "same-origin" };
421
+ }
422
+ /**
423
+ * Run the org-auth handler once for concurrent challenges. A bearer client's
424
+ * handler sets the org session with `setOrgSession`; a same-origin session's
425
+ * handler leaves an httpOnly org-session cookie on the page's origin instead,
426
+ * which the retry presents. A bearer client whose handler issued nothing has
427
+ * nothing to retry with.
428
+ */
429
+ async answerOrgAuthChallenge(orgAuthInfo) {
430
+ const handler = this.orgAuthHandler;
431
+ if (!handler) return;
432
+ if (!this.orgAuthInProgress) {
433
+ this.orgAuthInProgress = (async () => {
434
+ try {
435
+ await handler(orgAuthInfo);
436
+ } finally {
437
+ this.orgAuthInProgress = null;
438
+ }
439
+ })();
440
+ }
441
+ await this.orgAuthInProgress;
442
+ if (this.orgSession) {
443
+ this.orgSessionOrgUuid = orgAuthInfo.orgUuid;
444
+ return;
445
+ }
446
+ if (this.apiKey) {
447
+ throw new ApiError("Organization authentication did not issue a session", 401);
448
+ }
449
+ }
450
+ async fetch(endpoint, options, orgAuthRetry = false) {
424
451
  try {
425
452
  const headers = new Headers({
426
453
  // Don't set Content-Type for FormData — the browser must set it
@@ -430,17 +457,12 @@ var BaseApiClient = class {
430
457
  });
431
458
  if (this.apiKey) {
432
459
  headers.set("Authorization", `Bearer ${this.apiKey}`);
433
- } else if (this.isCrossDomain) {
434
- const requestToken = getCookieValue("requestToken");
435
- if (requestToken) {
436
- headers.set("Authorization", `Bearer ${requestToken}`);
437
- }
438
460
  }
439
461
  setOrgAuthHeader(headers, this.orgSession);
440
462
  const fullUrl = `${this.baseUrl}/api/v2/${endpoint}`;
441
463
  const response = await this.fetchFunction(fullUrl, {
442
464
  ...options,
443
- ...this.apiKey ? {} : { credentials: "include" },
465
+ ...this.credentialsInit(),
444
466
  ...this.isCrossDomain ? { mode: "cors" } : {},
445
467
  headers
446
468
  });
@@ -471,48 +493,14 @@ var BaseApiClient = class {
471
493
  this.orgSession = void 0;
472
494
  this.orgSessionOrgUuid = void 0;
473
495
  }
474
- if (orgAuthInfo && !this.orgSession) {
475
- const requestCookieName = getRequestOrgCookieName(orgAuthInfo.cookieName);
476
- const cachedOrgSession = requestCookieName ? getCookieValue(requestCookieName) : void 0;
477
- if (cachedOrgSession) {
478
- this.orgSession = cachedOrgSession;
479
- this.orgSessionOrgUuid = orgAuthInfo.orgUuid;
480
- try {
481
- return await this.fetch(endpoint, options);
482
- } catch (retryError) {
483
- this.orgSession = void 0;
484
- this.orgSessionOrgUuid = void 0;
485
- throw retryError;
486
- }
487
- }
488
- if (this.orgAuthHandler) {
489
- if (!this.orgAuthInProgress) {
490
- const handler = this.orgAuthHandler;
491
- this.orgAuthInProgress = (async () => {
492
- try {
493
- await handler(orgAuthInfo);
494
- } finally {
495
- this.orgAuthInProgress = null;
496
- }
497
- })();
498
- }
499
- await this.orgAuthInProgress;
500
- const postHandlerSession = (requestCookieName ? getCookieValue(requestCookieName) : void 0) ?? this.orgSession;
501
- if (!postHandlerSession) {
502
- throw new ApiError(
503
- "Organization authentication did not issue a session",
504
- 401
505
- );
506
- }
507
- this.orgSession = postHandlerSession;
508
- this.orgSessionOrgUuid = orgAuthInfo.orgUuid;
509
- try {
510
- return await this.fetch(endpoint, options);
511
- } catch (retryError) {
512
- this.orgSession = void 0;
513
- this.orgSessionOrgUuid = void 0;
514
- throw retryError;
515
- }
496
+ if (orgAuthInfo && !this.orgSession && !orgAuthRetry && this.orgAuthHandler) {
497
+ await this.answerOrgAuthChallenge(orgAuthInfo);
498
+ try {
499
+ return await this.fetch(endpoint, options, true);
500
+ } catch (retryError) {
501
+ this.orgSession = void 0;
502
+ this.orgSessionOrgUuid = void 0;
503
+ throw retryError;
516
504
  }
517
505
  }
518
506
  }
@@ -574,23 +562,18 @@ ${formattedErrors}`, response.status);
574
562
  throw error;
575
563
  }
576
564
  }
577
- async fetchRaw(endpoint, options, allowedErrorStatuses = []) {
565
+ async fetchRaw(endpoint, options, allowedErrorStatuses = [], orgAuthRetry = false) {
578
566
  try {
579
567
  const headers = new Headers({
580
568
  ...options?.headers || {}
581
569
  });
582
570
  if (this.apiKey) {
583
571
  headers.set("Authorization", `Bearer ${this.apiKey}`);
584
- } else if (this.isCrossDomain) {
585
- const requestToken = getCookieValue("requestToken");
586
- if (requestToken) {
587
- headers.set("Authorization", `Bearer ${requestToken}`);
588
- }
589
572
  }
590
573
  setOrgAuthHeader(headers, this.orgSession);
591
574
  const response = await this.fetchFunction(`${this.baseUrl}/api/v2/${endpoint}`, {
592
575
  ...options,
593
- ...this.apiKey ? {} : { credentials: "include" },
576
+ ...this.credentialsInit(),
594
577
  ...this.isCrossDomain ? { mode: "cors" } : {},
595
578
  headers
596
579
  });
@@ -621,48 +604,14 @@ ${formattedErrors}`, response.status);
621
604
  this.orgSession = void 0;
622
605
  this.orgSessionOrgUuid = void 0;
623
606
  }
624
- if (orgAuthInfo && !this.orgSession) {
625
- const requestCookieName = getRequestOrgCookieName(orgAuthInfo.cookieName);
626
- const cachedOrgSession = requestCookieName ? getCookieValue(requestCookieName) : void 0;
627
- if (cachedOrgSession) {
628
- this.orgSession = cachedOrgSession;
629
- this.orgSessionOrgUuid = orgAuthInfo.orgUuid;
630
- try {
631
- return await this.fetchRaw(endpoint, options, allowedErrorStatuses);
632
- } catch (retryError) {
633
- this.orgSession = void 0;
634
- this.orgSessionOrgUuid = void 0;
635
- throw retryError;
636
- }
637
- }
638
- if (this.orgAuthHandler) {
639
- if (!this.orgAuthInProgress) {
640
- const handler = this.orgAuthHandler;
641
- this.orgAuthInProgress = (async () => {
642
- try {
643
- await handler(orgAuthInfo);
644
- } finally {
645
- this.orgAuthInProgress = null;
646
- }
647
- })();
648
- }
649
- await this.orgAuthInProgress;
650
- const postHandlerSession = (requestCookieName ? getCookieValue(requestCookieName) : void 0) ?? this.orgSession;
651
- if (!postHandlerSession) {
652
- throw new ApiError(
653
- "Organization authentication did not issue a session",
654
- 401
655
- );
656
- }
657
- this.orgSession = postHandlerSession;
658
- this.orgSessionOrgUuid = orgAuthInfo.orgUuid;
659
- try {
660
- return await this.fetchRaw(endpoint, options, allowedErrorStatuses);
661
- } catch (retryError) {
662
- this.orgSession = void 0;
663
- this.orgSessionOrgUuid = void 0;
664
- throw retryError;
665
- }
607
+ if (orgAuthInfo && !this.orgSession && !orgAuthRetry && this.orgAuthHandler) {
608
+ await this.answerOrgAuthChallenge(orgAuthInfo);
609
+ try {
610
+ return await this.fetchRaw(endpoint, options, allowedErrorStatuses, true);
611
+ } catch (retryError) {
612
+ this.orgSession = void 0;
613
+ this.orgSessionOrgUuid = void 0;
614
+ throw retryError;
666
615
  }
667
616
  }
668
617
  }
@@ -690,17 +639,12 @@ ${formattedErrors}`, response.status);
690
639
  });
691
640
  if (this.apiKey) {
692
641
  headers.set("Authorization", `Bearer ${this.apiKey}`);
693
- } else if (this.isCrossDomain) {
694
- const requestToken = getCookieValue("requestToken");
695
- if (requestToken) {
696
- headers.set("Authorization", `Bearer ${requestToken}`);
697
- }
698
642
  }
699
643
  setOrgAuthHeader(headers, this.orgSession);
700
644
  const fullUrl = `${this.baseUrl}/${path}`;
701
645
  const response = await this.fetchFunction(fullUrl, {
702
646
  ...options,
703
- ...this.apiKey ? {} : { credentials: "include" },
647
+ ...this.credentialsInit(),
704
648
  ...this.isCrossDomain ? { mode: "cors" } : {},
705
649
  headers
706
650
  });
@@ -1748,18 +1692,13 @@ var AuthApi = class extends BaseApiClient {
1748
1692
  }
1749
1693
  return await response.json();
1750
1694
  }
1751
- /** Request a cross-domain authentication token for single sign-on across domains. */
1695
+ /** @deprecated Browser continuity uses top-level /auth/continue navigation. */
1752
1696
  async requestCrossDomainToken() {
1753
- return this.fetch("auth/cross-domain-token", {
1754
- method: "POST"
1755
- });
1697
+ throw new Error("Use top-level /auth/continue navigation. CLI login uses OAuth with PKCE.");
1756
1698
  }
1757
- /** Exchange a cross-domain token for an authenticated session token. */
1758
- async exchangeToken(token) {
1759
- return this.fetch("auth/exchange-token", {
1760
- method: "POST",
1761
- body: JSON.stringify({ token })
1762
- });
1699
+ /** @deprecated Browser handoffs redeem only at the destination Next server. */
1700
+ async exchangeToken(_token) {
1701
+ throw new Error("Use top-level /auth/continue navigation. CLI login uses OAuth with PKCE.");
1763
1702
  }
1764
1703
  /** Exchange a global Account login for an opaque org-scoped session handle. */
1765
1704
  async exchangeSession(request) {
@@ -1940,9 +1879,17 @@ var AuthApi = class extends BaseApiClient {
1940
1879
  );
1941
1880
  }
1942
1881
  // ===== ORGANIZATION MEMBERSHIP METHODS =====
1943
- /** List all organizations the current account belongs to. */
1944
- async getMyOrganizations() {
1945
- return this.fetch("o/mine");
1882
+ /** A searchable page of the current account's organizations. */
1883
+ async getMyOrganizations(options) {
1884
+ const params = new URLSearchParams();
1885
+ if (options?.page) params.set("page", String(options.page));
1886
+ if (options?.pageSize) params.set("pageSize", String(options.pageSize));
1887
+ if (options?.canCreateWorkspace) params.set("canCreateWorkspace", "true");
1888
+ if (options?.search) params.set("search", options.search);
1889
+ if (options?.organizationSlug !== void 0)
1890
+ params.set("organizationSlug", options.organizationSlug);
1891
+ for (const uuid of options?.organizationUuids ?? []) params.append("organizationUuids", uuid);
1892
+ return this.fetch(`o/mine?${params}`);
1946
1893
  }
1947
1894
  // ===== CREDENTIAL CHANGE METHODS =====
1948
1895
  /**
@@ -5144,14 +5091,7 @@ var InquiriesApi = class extends BaseApiClient {
5144
5091
  }
5145
5092
  const queryString = params.toString();
5146
5093
  const url = queryString ? `inquiries/export/csv?${queryString}` : "inquiries/export/csv";
5147
- const response = await fetch(`${this.baseUrl}/api/v2/${url}`, {
5148
- method: "GET",
5149
- credentials: "include"
5150
- });
5151
- if (!response.ok) {
5152
- const error = await response.json();
5153
- throw new Error(error.detail || "Export failed");
5154
- }
5094
+ const response = await this.fetchRaw(url, { method: "GET" });
5155
5095
  return response.blob();
5156
5096
  }
5157
5097
  };
@@ -6719,8 +6659,12 @@ var OrgApi = class extends BaseApiClient {
6719
6659
  * figure — the caps belong to the organization, so `cap - oneWorkspace`
6720
6660
  * describes nothing.
6721
6661
  */
6722
- async getOrgWorkspaceUsage(orgIdOrUuid) {
6723
- return this.fetch(`o/${orgIdOrUuid}/usage/workspaces`);
6662
+ async getOrgWorkspaceUsage(orgIdOrUuid, options) {
6663
+ const params = new URLSearchParams();
6664
+ if (options?.page) params.set("page", String(options.page));
6665
+ if (options?.pageSize) params.set("pageSize", String(options.pageSize));
6666
+ if (options?.search) params.set("search", options.search);
6667
+ return this.fetch(`o/${orgIdOrUuid}/usage/workspaces?${params}`);
6724
6668
  }
6725
6669
  /**
6726
6670
  * List members of an organization.
@@ -6844,8 +6788,14 @@ var OrgApi = class extends BaseApiClient {
6844
6788
  * counts. Any org member may call it — members get the workspaces they
6845
6789
  * belong to, org:read holders get all of them.
6846
6790
  */
6847
- async getOrganizationWorkspaceSummaries(orgIdOrUuid) {
6848
- return this.fetch(`o/${orgIdOrUuid}/workspaces/summary`);
6791
+ async getOrganizationWorkspaceSummaries(orgIdOrUuid, options) {
6792
+ const params = new URLSearchParams();
6793
+ if (options?.page) params.set("page", String(options.page));
6794
+ if (options?.pageSize) params.set("pageSize", String(options.pageSize));
6795
+ if (options?.search) params.set("search", options.search);
6796
+ return this.fetch(
6797
+ `o/${orgIdOrUuid}/workspaces/summary?${params}`
6798
+ );
6849
6799
  }
6850
6800
  /**
6851
6801
  * Workspace-schema aggregates for one card, plus the caller's own member
@@ -7582,18 +7532,18 @@ function businessProfilePath(orgUuid, legalEntityUuid) {
7582
7532
  // src/api/oauth.ts
7583
7533
  function getOAuthPath(providerSlug, action) {
7584
7534
  if (providerSlug === "google_calendar") {
7585
- return `oauth/google/calendar/${action}`;
7535
+ return `api/v2/oauth/google/calendar/${action}`;
7586
7536
  }
7587
7537
  if (providerSlug === "gmail") {
7588
- return `oauth/google/gmail/${action}`;
7538
+ return `api/v2/oauth/google/gmail/${action}`;
7589
7539
  }
7590
7540
  if (providerSlug === "gdrive") {
7591
- return `oauth/google/drive/${action}`;
7541
+ return `api/v2/oauth/google/drive/${action}`;
7592
7542
  }
7593
7543
  if (providerSlug === "gsheets") {
7594
- return `oauth/google/sheets/${action}`;
7544
+ return `api/v2/oauth/google/sheets/${action}`;
7595
7545
  }
7596
- return `oauth/${providerSlug}/${action}`;
7546
+ return `api/v2/oauth/${providerSlug}/${action}`;
7597
7547
  }
7598
7548
  function buildAuthorizeQuery(options) {
7599
7549
  if (!options) return "";
@@ -10413,7 +10363,8 @@ var WorkflowsApi = class extends BaseApiClient {
10413
10363
  /**
10414
10364
  * Classify the prompts of a Workflow's draft revision.
10415
10365
  *
10416
- * A decision model reads each Task that has a prompt and reports which
10366
+ * A decision model reads each live Task with Workflow or Task instructions
10367
+ * and reports which
10417
10368
  * prompt classifications probably apply. Each call asks the model again.
10418
10369
  */
10419
10370
  async getWorkflowPromptClassifications(wid, workflowId) {
@@ -11861,22 +11812,32 @@ function planFields(options) {
11861
11812
  }
11862
11813
  return fields;
11863
11814
  }
11815
+ function workspaceDirectoryParams(options = {}) {
11816
+ const params = new URLSearchParams();
11817
+ if (options.page !== void 0) params.set("page", String(options.page));
11818
+ if (options.pageSize !== void 0) params.set("pageSize", String(options.pageSize));
11819
+ if (options.search) params.set("search", options.search);
11820
+ if (options.organizationUuid) params.set("organizationUuid", options.organizationUuid);
11821
+ for (const uuid of options.workspaceUuids ?? []) params.append("workspaceUuids", uuid);
11822
+ for (const id of options.workspaceIds ?? []) params.append("workspaceIds", String(id));
11823
+ return params;
11824
+ }
11864
11825
  var WorkspacesApi = class extends BaseApiClient {
11865
- /** List all workspaces accessible to the current user. */
11866
- async getWorkspaces() {
11867
- return this.fetch("w/");
11826
+ /** A bounded page of workspaces accessible to the current account. */
11827
+ async getWorkspaces(options) {
11828
+ return this.fetch(`w/?${workspaceDirectoryParams(options)}`);
11868
11829
  }
11869
- /**
11870
- * Compact rows for the workspaces a companion device could enter — the
11871
- * Lantern picker. Filtered by the same admission policy a device
11872
- * credential is gated by, without needing the device credential.
11873
- */
11874
- async getDeviceAdmissibleWorkspaces() {
11875
- return this.fetch("w/?can_use_device=1");
11830
+ /** A bounded page of companion-device candidates, with admission checked per row. */
11831
+ async getDeviceAdmissibleWorkspaces(options) {
11832
+ const params = workspaceDirectoryParams(options);
11833
+ params.set("can_use_device", "1");
11834
+ return this.fetch(`w/?${params}`);
11876
11835
  }
11877
- /** List all publicly visible workspaces. */
11878
- async getPublicWorkspaces() {
11879
- return this.fetch("w/public");
11836
+ /** A bounded page of publicly visible workspaces. */
11837
+ async getPublicWorkspaces(options) {
11838
+ return this.fetch(
11839
+ `w/public?${workspaceDirectoryParams(options)}`
11840
+ );
11880
11841
  }
11881
11842
  /** Get a single workspace by ID. */
11882
11843
  async getWorkspace(wid) {
@@ -12159,13 +12120,22 @@ var WorkspacesApi = class extends BaseApiClient {
12159
12120
  * @param scope - Export scope ("workflows" for all workflows only). Cannot be combined with workflowId.
12160
12121
  * @param exclude - Comma-separated entity categories to exclude (e.g. "channels")
12161
12122
  */
12162
- async exportWorkspace(wid, workflowId, scope, exclude) {
12123
+ async exportWorkspace(wid, workflowId, scope, exclude, options) {
12163
12124
  const searchParams = new URLSearchParams();
12164
12125
  if (workflowId !== void 0) searchParams.set("workflow_id", String(workflowId));
12165
12126
  if (scope !== void 0) searchParams.set("scope", scope);
12166
12127
  if (exclude !== void 0) searchParams.set("exclude", exclude);
12128
+ if (options?.revisionId !== void 0)
12129
+ searchParams.set("revision_id", String(options.revisionId));
12130
+ if (options?.revisionMode !== void 0) {
12131
+ searchParams.set("revision_mode", options.revisionMode);
12132
+ } else if (options?.revisionId === void 0) {
12133
+ searchParams.set("revision_mode", "active");
12134
+ }
12167
12135
  const qs = searchParams.toString();
12168
- return this.fetch(`w/${wid}/export${qs ? `?${qs}` : ""}`);
12136
+ const data = await this.fetch(`w/${wid}/export${qs ? `?${qs}` : ""}`);
12137
+ this.verifyExportSelection(data, workflowId, options);
12138
+ return data;
12169
12139
  }
12170
12140
  /** Preview the result of importing workspace configuration without applying changes.
12171
12141
  *
@@ -12224,15 +12194,60 @@ var WorkspacesApi = class extends BaseApiClient {
12224
12194
  * target workspace.
12225
12195
  */
12226
12196
  /** Download a workspace export ZIP (``export.json`` + file blobs). */
12227
- async exportWorkspaceZip(wid, workflowId, scope, exclude) {
12197
+ async exportWorkspaceZip(wid, workflowId, scope, exclude, options) {
12228
12198
  const searchParams = new URLSearchParams();
12229
12199
  if (workflowId !== void 0) searchParams.set("workflow_id", String(workflowId));
12230
12200
  if (scope !== void 0) searchParams.set("scope", scope);
12231
12201
  if (exclude !== void 0) searchParams.set("exclude", exclude);
12202
+ if (options?.revisionId !== void 0)
12203
+ searchParams.set("revision_id", String(options.revisionId));
12204
+ if (options?.revisionMode !== void 0) {
12205
+ searchParams.set("revision_mode", options.revisionMode);
12206
+ } else if (options?.revisionId === void 0) {
12207
+ searchParams.set("revision_mode", "active");
12208
+ }
12232
12209
  const qs = searchParams.toString();
12233
12210
  const response = await this.fetchRaw(`w/${wid}/export.zip${qs ? `?${qs}` : ""}`);
12211
+ if (options?.revisionId !== void 0 || options?.revisionMode === "all") {
12212
+ const version = response.headers.get("X-Gravityrail-Export-Version");
12213
+ const selection = response.headers.get("X-Gravityrail-Export-Selection");
12214
+ const selected = options?.revisionId !== void 0;
12215
+ if (version !== (selected ? "1.0" : "2.0") || selection !== (selected ? "selected" : "all") || selected && (workflowId === void 0 || !response.headers.get("X-Gravityrail-Export-Revision-Uuid")?.trim() || !response.headers.get("X-Gravityrail-Export-Workflow-Uuid")?.trim())) {
12216
+ try {
12217
+ await response.body?.cancel();
12218
+ } catch {
12219
+ }
12220
+ throw new Error(
12221
+ "Server did not return verified Workflow revision export headers. Request an explicit active snapshot or use a server that supports export provenance."
12222
+ );
12223
+ }
12224
+ }
12234
12225
  return response.arrayBuffer();
12235
12226
  }
12227
+ // Compatibility shape check only. The backend WorkspaceExportData
12228
+ // _validate_revision_archive owns full graph/publication invariants.
12229
+ verifyExportSelection(data, workflowId, options) {
12230
+ const hasUuid = (value) => typeof value === "string" && value.trim().length > 0;
12231
+ if (options?.revisionId !== void 0) {
12232
+ const revisions = data?.workflowRevisions;
12233
+ if (workflowId === void 0 || data?.version !== "1.0" || data.workflowRevisionSelection !== "selected" || !Array.isArray(revisions) || revisions.length !== 1) {
12234
+ throw new Error(
12235
+ "Server did not return the requested Workflow revision. Use a server that supports revision selection."
12236
+ );
12237
+ }
12238
+ if (!hasUuid(revisions[0]?.uuid) || !hasUuid(revisions[0]?.workflow?.uuid) || !hasUuid(data.workflows?.[0]?.uuid) || data.workflows?.length !== 1 || revisions[0]?.workflow?.uuid !== data.workflows[0]?.uuid) {
12239
+ throw new Error("Server export does not match the requested Workflow revision.");
12240
+ }
12241
+ } else if (options?.revisionMode === "all" && (data?.version !== "2.0" || data.workflowRevisionSelection !== "all" || !Array.isArray(data.workflowRevisions) || !Array.isArray(data.workflows) || data.workflows.some(
12242
+ (workflow) => !hasUuid(workflow?.uuid) || !data.workflowRevisions?.some(
12243
+ (revision) => hasUuid(revision?.uuid) && revision?.workflow?.uuid === workflow.uuid
12244
+ )
12245
+ ))) {
12246
+ throw new Error(
12247
+ "Server did not return all Workflow revisions. Request an explicit active snapshot or use a server that supports revision archives."
12248
+ );
12249
+ }
12250
+ }
12236
12251
  /** Import workspace configuration from exported JSON, or from a ZIP archive.
12237
12252
  * Pass ``archive`` (the ZIP from ``exportWorkspaceZip``) to restore file
12238
12253
  * contents. ``exportData`` may be omitted when the ZIP contains it.
@@ -20185,6 +20200,86 @@ function toSafeMemberImportSummary(event) {
20185
20200
  }))
20186
20201
  };
20187
20202
  }
20203
+
20204
+ // src/workflows/path.ts
20205
+ function getPathDefinition(path) {
20206
+ if (path.routing != null) {
20207
+ const routing = path.routing;
20208
+ if (typeof routing !== "object" || Array.isArray(routing)) return null;
20209
+ const fields = routing;
20210
+ if (fields.kind !== void 0 && fields.kind !== "outcome" || typeof fields.outcome !== "string" || !/^[a-z][a-z0-9_]{0,31}$/.test(fields.outcome) || Object.keys(fields).some((key) => key !== "kind" && key !== "outcome"))
20211
+ return null;
20212
+ return {
20213
+ availability: { kind: "always", expression: null, decisionPrompt: null },
20214
+ selection: {
20215
+ mode: "automatic",
20216
+ rule: "task_outcome",
20217
+ choicePrompt: null,
20218
+ condition: null,
20219
+ outcome: fields.outcome,
20220
+ policy: "matching_outcome",
20221
+ priority: null
20222
+ }
20223
+ };
20224
+ }
20225
+ const expression = path.celCondition?.trim() ? path.celCondition : null;
20226
+ const automatic = expression !== null && Boolean(path.required || path.autoNext);
20227
+ return {
20228
+ availability: {
20229
+ kind: expression === null ? "always" : "cel",
20230
+ expression,
20231
+ decisionPrompt: null
20232
+ },
20233
+ selection: {
20234
+ mode: automatic ? "automatic" : "choice",
20235
+ rule: automatic ? "when_available" : "choice",
20236
+ choicePrompt: automatic ? null : path.choicePrompt?.trim() || null,
20237
+ condition: null,
20238
+ outcome: null,
20239
+ policy: automatic ? "first_match" : "choose_one",
20240
+ priority: automatic ? path.order ?? 0 : null
20241
+ }
20242
+ };
20243
+ }
20244
+ function pathDraftFromStorage(path) {
20245
+ const definition = getPathDefinition(path);
20246
+ if (!definition || definition.selection.rule === "task_outcome") {
20247
+ throw new Error("This Path requires its dedicated routing editor.");
20248
+ }
20249
+ return {
20250
+ availabilityCondition: path.celCondition ?? "",
20251
+ selectionMode: definition.selection.mode,
20252
+ choicePrompt: path.choicePrompt ?? "",
20253
+ selectionPriority: path.order ?? 0
20254
+ };
20255
+ }
20256
+ function pathDraftToStorage(draft, original) {
20257
+ const initial = pathDraftFromStorage(original);
20258
+ const hasCondition = draft.availabilityCondition.trim() !== "";
20259
+ if (draft.selectionMode === "automatic" && !hasCondition) {
20260
+ throw new Error("Automatic Path selection requires a CEL condition.");
20261
+ }
20262
+ if (draft.availabilityCondition === initial.availabilityCondition && draft.selectionMode === initial.selectionMode && draft.choicePrompt === initial.choicePrompt && draft.selectionPriority === initial.selectionPriority)
20263
+ return original;
20264
+ const celCondition = draft.availabilityCondition === initial.availabilityCondition ? original.celCondition : draft.availabilityCondition.trim() ? draft.availabilityCondition : null;
20265
+ const choicePrompt = draft.choicePrompt === initial.choicePrompt ? original.choicePrompt : draft.choicePrompt.trim() ? draft.choicePrompt : null;
20266
+ let autoNext = original.autoNext;
20267
+ let required = original.required;
20268
+ if (draft.selectionMode === "automatic" && initial.selectionMode !== "automatic") {
20269
+ autoNext = true;
20270
+ } else if (draft.selectionMode === "choice" && (hasCondition || initial.availabilityCondition.trim() !== "") && Boolean(autoNext || required)) {
20271
+ autoNext = false;
20272
+ required = false;
20273
+ }
20274
+ return {
20275
+ ...original,
20276
+ celCondition,
20277
+ choicePrompt,
20278
+ autoNext,
20279
+ required,
20280
+ ...draft.selectionPriority === initial.selectionPriority ? {} : { order: draft.selectionPriority }
20281
+ };
20282
+ }
20188
20283
  // Annotate the CommonJS export names for ESM import in node:
20189
20284
  0 && (module.exports = {
20190
20285
  AGENT_NOTE_ORIGINS,
@@ -20410,6 +20505,7 @@ function toSafeMemberImportSummary(event) {
20410
20505
  getFeaturesByCategory,
20411
20506
  getFeaturesByVisibility,
20412
20507
  getMissingDependencies,
20508
+ getPathDefinition,
20413
20509
  getResourceMetadata,
20414
20510
  getRevisionState,
20415
20511
  getTTSProvider,
@@ -20425,6 +20521,8 @@ function toSafeMemberImportSummary(event) {
20425
20521
  isRegistryInitialized,
20426
20522
  isSMSDeliveryFailureStatus,
20427
20523
  parseOrgAuthChallenge,
20524
+ pathDraftFromStorage,
20525
+ pathDraftToStorage,
20428
20526
  requiresAssistantParticipant,
20429
20527
  runWorkspaceScript,
20430
20528
  toSafeMemberImportPreview,