@gravity-rail/sdk 0.15.0 → 0.17.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 (42) hide show
  1. package/dist/agui.cjs +13 -1
  2. package/dist/agui.cjs.map +1 -1
  3. package/dist/agui.d.cts +5 -1
  4. package/dist/agui.d.ts +5 -1
  5. package/dist/agui.js +12 -1
  6. package/dist/agui.js.map +1 -1
  7. package/dist/{chunk-QTJQTTIR.js → chunk-CEFOCGYO.js} +521 -69
  8. package/dist/chunk-CEFOCGYO.js.map +1 -0
  9. package/dist/{chunk-GP6ICMWF.js → chunk-PJFEGUHM.js} +8 -1
  10. package/dist/chunk-PJFEGUHM.js.map +1 -0
  11. package/dist/{client-BLuz00Qr.d.cts → client-8xakCsVs.d.cts} +2245 -232
  12. package/dist/{client-CefA5Mxe.d.ts → client-ASnNEN1U.d.ts} +2245 -232
  13. package/dist/helpers.cjs +7 -0
  14. package/dist/helpers.cjs.map +1 -1
  15. package/dist/helpers.d.cts +2 -2
  16. package/dist/helpers.d.ts +2 -2
  17. package/dist/helpers.js +1 -1
  18. package/dist/index.cjs +898 -87
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +182 -9
  21. package/dist/index.d.ts +182 -9
  22. package/dist/index.js +397 -23
  23. package/dist/index.js.map +1 -1
  24. package/dist/internal.cjs +607 -68
  25. package/dist/internal.cjs.map +1 -1
  26. package/dist/internal.d.cts +328 -7
  27. package/dist/internal.d.ts +328 -7
  28. package/dist/internal.js +86 -4
  29. package/dist/internal.js.map +1 -1
  30. package/dist/{revision-state-axZ62kJk.d.cts → revision-state-BDsQo_xD.d.cts} +4 -2
  31. package/dist/{revision-state-DL1ViZ57.d.ts → revision-state-Cz3mcUHc.d.ts} +4 -2
  32. package/dist/schemas.cjs +179 -217
  33. package/dist/schemas.cjs.map +1 -1
  34. package/dist/schemas.d.cts +2 -2
  35. package/dist/schemas.d.ts +2 -2
  36. package/dist/schemas.js +179 -210
  37. package/dist/schemas.js.map +1 -1
  38. package/dist/{tasks-Boi6AxGp.d.cts → tasks-Z4GcIqgO.d.cts} +200 -81
  39. package/dist/{tasks-Boi6AxGp.d.ts → tasks-Z4GcIqgO.d.ts} +200 -81
  40. package/package.json +3 -3
  41. package/dist/chunk-GP6ICMWF.js.map +0 -1
  42. package/dist/chunk-QTJQTTIR.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -88,6 +88,7 @@ __export(src_exports, {
88
88
  MemberType: () => MemberType,
89
89
  MenuItemResponseItemType: () => MenuItemResponseItemType,
90
90
  MenuItemType: () => MenuItemResponseItemType,
91
+ MergeMemberRolesRequestAccessStrategy: () => MergeMemberRolesRequestAccessStrategy,
91
92
  ModelProvider: () => ModelProvider,
92
93
  ModelType: () => ModelType,
93
94
  NO_ASSISTANT_PARTICIPANT_CHAT_TYPES: () => NO_ASSISTANT_PARTICIPANT_CHAT_TYPES,
@@ -110,6 +111,7 @@ __export(src_exports, {
110
111
  PIDS_SOURCES: () => PIDS_SOURCES,
111
112
  POSITIVE_RATING_THRESHOLD: () => POSITIVE_RATING_THRESHOLD,
112
113
  ProductType: () => ProductType,
114
+ PromoCodeStatus: () => PromoCodeStatus,
113
115
  QUERY_VALUELESS_OPS: () => QUERY_VALUELESS_OPS,
114
116
  QueriesApi: () => QueriesApi,
115
117
  REALTIME_MODEL_CUSTOM: () => REALTIME_MODEL_CUSTOM,
@@ -150,10 +152,14 @@ __export(src_exports, {
150
152
  WorkflowAccessWarningResourceType: () => WorkflowAccessWarningResourceType,
151
153
  WorkflowBuilder: () => WorkflowBuilder,
152
154
  WorkflowResourceType: () => WorkflowAccessWarningResourceType,
155
+ WorkflowRoutingMode: () => WorkflowRoutingMode,
153
156
  WorkspaceBuilder: () => WorkspaceBuilder,
157
+ WorkspaceBuilderResource: () => WorkspaceBuilderResource,
154
158
  WorkspaceFeature: () => WorkspaceFeature,
155
159
  WorkspaceProvisionStatus: () => WorkspaceProvisionStatus,
160
+ archivedMemberConflictId: () => archivedMemberConflictId,
156
161
  areDependenciesSatisfied: () => areDependenciesSatisfied,
162
+ asIdentifiedMemberContactConflict: () => asIdentifiedMemberContactConflict,
157
163
  canPreviewVoice: () => canPreviewVoice,
158
164
  clearRegistry: () => clearRegistry,
159
165
  createWorkspaceClient: () => createWorkspaceClient,
@@ -177,9 +183,12 @@ __export(src_exports, {
177
183
  getTTSProvider: () => getTTSProvider,
178
184
  getVoiceModelId: () => getVoiceModelId,
179
185
  initializeFeatures: () => initializeFeatures,
186
+ isAccountContactConflict: () => isAccountContactConflict,
180
187
  isAgentNoteOrigin: () => isAgentNoteOrigin,
181
188
  isChatType: () => isChatType,
182
189
  isFeatureAvailable: () => isFeatureAvailable,
190
+ isIdentifiedMemberContactConflict: () => isIdentifiedMemberContactConflict,
191
+ isMemberContactConflict: () => isMemberContactConflict,
183
192
  isPositiveRating: () => isPositiveRating,
184
193
  isRegistryInitialized: () => isRegistryInitialized,
185
194
  isSMSDeliveryFailureStatus: () => isSMSDeliveryFailureStatus,
@@ -224,6 +233,13 @@ var ApiError = class extends Error {
224
233
  * Populated when the backend returns a WorkflowValidationErrorResponse.
225
234
  */
226
235
  validationErrors;
236
+ /**
237
+ * The raw structured `detail` object when the backend returned one (a body
238
+ * with `error: true` or a `code`). Declared here rather than bolted on with
239
+ * `as any` at the throw site so consumers can narrow it with a type guard —
240
+ * see `isMemberContactConflict` in `types/member-types`.
241
+ */
242
+ errorData;
227
243
  constructor(message, statusCode, errors, validationErrors) {
228
244
  super(message);
229
245
  this.statusCode = statusCode;
@@ -924,6 +940,18 @@ var AIModelsApi = class extends BaseApiClient {
924
940
  const url = queryString ? `ai-models/realtime?${queryString}` : "ai-models/realtime";
925
941
  return this.fetch(url);
926
942
  }
943
+ /**
944
+ * Get the voice presets offered by the simplified voice picker.
945
+ *
946
+ * A preset bundles a realtime speech-to-speech model with one of its native
947
+ * voices and the settings recommended alongside it, so choosing a voice is
948
+ * a single decision. Apply one by assigning its `config` wholesale; compare
949
+ * against it to tell a preset selection from a customised ("Custom") one.
950
+ * The full engine/voice/settings matrix lives on `getRealtimeModels`.
951
+ */
952
+ async getVoicePresets() {
953
+ return this.fetch("ai-models/voice-presets");
954
+ }
927
955
  /**
928
956
  * Get available voice models with metadata
929
957
  */
@@ -2053,6 +2081,10 @@ var ChatsApi = class extends BaseApiClient {
2053
2081
  `w/${wid}/chats/${chatId}/skills`
2054
2082
  );
2055
2083
  }
2084
+ /** List built-in skills selectable before a Manager Chat (and on Routine manager tasks). */
2085
+ async getManagerSkills(wid) {
2086
+ return this.fetch(`w/${wid}/chats/manager/skills`);
2087
+ }
2056
2088
  /** List chat IDs that need a response. */
2057
2089
  async getChatsNeedsResponse(wid) {
2058
2090
  return this.fetch(`w/${wid}/chats/needs-response`);
@@ -2562,6 +2594,32 @@ var DashboardsApi = class extends BaseApiClient {
2562
2594
  `w/${wid}/dashboards/stats/workflow-assignments`
2563
2595
  );
2564
2596
  }
2597
+ /**
2598
+ * Current saved-configuration health across every family (Workflow
2599
+ * configuration, Journey authoring, Workflow access, Routine → Workflow
2600
+ * access, and the workspace lint).
2601
+ *
2602
+ * Requires ALL of `workflows:read`, `journeys:read`, `automations:read`,
2603
+ * `datatypes:read`, `members:read`, and `member_roles:read` — a pruned
2604
+ * subset would render as "all configuration is healthy".
2605
+ *
2606
+ * `page`/`pageSize` bound the response only; every family is evaluated in
2607
+ * full before the issue list is sliced. `check`/`severity` narrow the issue
2608
+ * list server-side, before pagination — filtering a single page in the
2609
+ * client cannot find a match that lives on a later one. `summary` and
2610
+ * `checks` are always workspace-global.
2611
+ */
2612
+ async getConfigurationHealth(wid, options) {
2613
+ const params = new URLSearchParams();
2614
+ if (options?.page !== void 0) params.append("page", options.page.toString());
2615
+ if (options?.pageSize !== void 0) params.append("pageSize", options.pageSize.toString());
2616
+ if (options?.check !== void 0) params.append("check", options.check);
2617
+ if (options?.severity !== void 0) params.append("severity", options.severity);
2618
+ const query = params.toString();
2619
+ return this.fetch(
2620
+ `w/${wid}/configuration-health${query ? `?${query}` : ""}`
2621
+ );
2622
+ }
2565
2623
  };
2566
2624
 
2567
2625
  // src/api/data-types.ts
@@ -3680,9 +3738,9 @@ var DocumoFaxApi = class extends BaseApiClient {
3680
3738
  params?.status?.forEach((value) => query.append("status", value));
3681
3739
  if (params?.receivedAfter) query.set("receivedAfter", params.receivedAfter);
3682
3740
  if (params?.receivedBefore) query.set("receivedBefore", params.receivedBefore);
3683
- const suffix = query.toString() === "" ? "" : `?${query.toString()}`;
3741
+ const suffix2 = query.toString() === "" ? "" : `?${query.toString()}`;
3684
3742
  return this.fetch(
3685
- `w/${wid}/app-connections/documo-fax/faxes${suffix}`
3743
+ `w/${wid}/app-connections/documo-fax/faxes${suffix2}`
3686
3744
  );
3687
3745
  }
3688
3746
  /**
@@ -4756,12 +4814,34 @@ var MembersApi = class extends BaseApiClient {
4756
4814
  body: JSON.stringify(memberRole)
4757
4815
  });
4758
4816
  }
4759
- /** Delete a member role. */
4817
+ /** Delete a member role. Default roles (``systemKey`` set) return 403. */
4760
4818
  async deleteMemberRole(wid, id) {
4761
4819
  return this.fetch(`w/${wid}/member-roles/${id}`, {
4762
4820
  method: "DELETE"
4763
4821
  });
4764
4822
  }
4823
+ /**
4824
+ * Describe legacy duplicate default roles in this workspace. Read-only.
4825
+ *
4826
+ * Workspaces seeded by older versions of the product can carry the same
4827
+ * default role under several spellings ("manager" next to "Manager"). This
4828
+ * reports which ones should be merged and exactly how many members and
4829
+ * references each merge would move.
4830
+ */
4831
+ async getMemberRoleCleanupPlan(wid) {
4832
+ return this.fetch(`w/${wid}/member-roles/cleanup-plan`);
4833
+ }
4834
+ /**
4835
+ * Move every member and reference from one role to another, then delete the
4836
+ * source role. Requires `member_roles:admin`. The source cannot be a default
4837
+ * role.
4838
+ */
4839
+ async mergeMemberRoles(wid, request) {
4840
+ return this.fetch(`w/${wid}/member-roles/cleanup/merge`, {
4841
+ method: "POST",
4842
+ body: JSON.stringify(request)
4843
+ });
4844
+ }
4765
4845
  // Import/Export Members API
4766
4846
  /**
4767
4847
  * Read-only preview classifying each CSV row before any write (GRA-5545).
@@ -5064,46 +5144,6 @@ var MembersApi = class extends BaseApiClient {
5064
5144
  }
5065
5145
  };
5066
5146
 
5067
- // src/api/milestones.ts
5068
- var MilestonesApi = class extends BaseApiClient {
5069
- /** List milestones in a workspace with optional pagination and sorting. */
5070
- async getMilestones(wid, options = {}) {
5071
- const params = new URLSearchParams();
5072
- if (options.page) params.append("page", options.page.toString());
5073
- if (options.pageSize) params.append("pageSize", options.pageSize.toString());
5074
- if (options.sortBy) params.append("sortBy", options.sortBy);
5075
- if (options.sortOrder) params.append("sortOrder", options.sortOrder);
5076
- if (options.search) params.append("search", options.search);
5077
- return this.fetch(
5078
- `w/${wid}/milestones${params.toString() ? `?${params.toString()}` : ""}`
5079
- );
5080
- }
5081
- /** Get a single milestone by ID. */
5082
- async getMilestone(wid, id) {
5083
- return this.fetch(`w/${wid}/milestones/${id}`);
5084
- }
5085
- /** Create a new milestone in a workspace. */
5086
- async createMilestone(wid, milestone) {
5087
- return this.fetch(`w/${wid}/milestones`, {
5088
- method: "POST",
5089
- body: JSON.stringify(milestone)
5090
- });
5091
- }
5092
- /** Update an existing milestone with partial data. */
5093
- async updateMilestone(wid, id, milestone) {
5094
- return this.fetch(`w/${wid}/milestones/${id}`, {
5095
- method: "PUT",
5096
- body: JSON.stringify(milestone)
5097
- });
5098
- }
5099
- /** Delete a milestone by ID. */
5100
- async deleteMilestone(wid, id) {
5101
- return this.fetch(`w/${wid}/milestones/${id}`, {
5102
- method: "DELETE"
5103
- });
5104
- }
5105
- };
5106
-
5107
5147
  // src/api/motd.ts
5108
5148
  var MotdApi = class extends BaseApiClient {
5109
5149
  /**
@@ -5289,6 +5329,23 @@ var MondayIntegrationApi = class extends BaseApiClient {
5289
5329
  }
5290
5330
  };
5291
5331
 
5332
+ // src/api/intervention-requests.ts
5333
+ var InterventionRequestsApi = class extends BaseApiClient {
5334
+ /** List intervention requests in a workspace, newest first. */
5335
+ async getInterventionRequests(wid, params = {}) {
5336
+ const query = new URLSearchParams();
5337
+ if (params.kind) query.set("kind", params.kind);
5338
+ if (params.openOnly) query.set("openOnly", "true");
5339
+ if (params.chatId !== void 0) query.set("chatId", String(params.chatId));
5340
+ if (params.unroutedOnly) query.set("unroutedOnly", "true");
5341
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
5342
+ const qs = query.toString();
5343
+ return this.fetch(
5344
+ `w/${wid}/intervention-requests${qs ? `?${qs}` : ""}`
5345
+ );
5346
+ }
5347
+ };
5348
+
5292
5349
  // src/api/notification-rules.ts
5293
5350
  var NotificationRulesApi = class extends BaseApiClient {
5294
5351
  /** List all notification rules in a workspace. */
@@ -5412,6 +5469,41 @@ var OrgApi = class extends BaseApiClient {
5412
5469
  async getCurrentOrgMember(orgIdOrUuid) {
5413
5470
  return this.fetch(`o/${orgIdOrUuid}/me`);
5414
5471
  }
5472
+ /**
5473
+ * Update the settings an org admin owns: name, slug and contact details.
5474
+ *
5475
+ * Deliberately NOT the admin organization update — `primary` and
5476
+ * `enforceCreditLimit` are superuser-only and are not fields on this
5477
+ * endpoint's request model at all.
5478
+ */
5479
+ async updateOrganizationSettings(orgIdOrUuid, data) {
5480
+ return this.fetch(`o/${orgIdOrUuid}`, {
5481
+ method: "PATCH",
5482
+ body: JSON.stringify(data)
5483
+ });
5484
+ }
5485
+ /**
5486
+ * Read this organization's SSO configuration.
5487
+ *
5488
+ * Org-scoped (`org:admin`), unlike the SSO fields on the superuser admin
5489
+ * organization update — an org admin owns their own identity provider.
5490
+ */
5491
+ async getOrgSsoConfig(orgIdOrUuid) {
5492
+ return this.fetch(`o/${orgIdOrUuid}/sso`);
5493
+ }
5494
+ /** Configure this organization's SSO. Requires `org:admin`. */
5495
+ async updateOrgSsoConfig(orgIdOrUuid, data) {
5496
+ return this.fetch(`o/${orgIdOrUuid}/sso`, {
5497
+ method: "PUT",
5498
+ body: JSON.stringify(data)
5499
+ });
5500
+ }
5501
+ /** Remove this organization's SSO configuration. Requires `org:admin`. */
5502
+ async deleteOrgSsoConfig(orgIdOrUuid) {
5503
+ return this.fetch(`o/${orgIdOrUuid}/sso`, {
5504
+ method: "DELETE"
5505
+ });
5506
+ }
5415
5507
  /**
5416
5508
  * Get the billing customer UUID for an organization.
5417
5509
  */
@@ -5532,6 +5624,22 @@ var OrgApi = class extends BaseApiClient {
5532
5624
  async getOrganizationWorkspace(orgIdOrUuid, workspaceUuid) {
5533
5625
  return this.fetch(`o/${orgIdOrUuid}/workspaces/${workspaceUuid}`);
5534
5626
  }
5627
+ /**
5628
+ * Workspace cards for the organization page: identity plus the GLB-side
5629
+ * counts. Any org member may call it — members get the workspaces they
5630
+ * belong to, org:read holders get all of them.
5631
+ */
5632
+ async getOrganizationWorkspaceSummaries(orgIdOrUuid) {
5633
+ return this.fetch(`o/${orgIdOrUuid}/workspaces/summary`);
5634
+ }
5635
+ /**
5636
+ * Workspace-schema aggregates for one card, plus the caller's own member
5637
+ * role. Separate from the list because it opens a session against the
5638
+ * workspace's own schema — each card fetches its own.
5639
+ */
5640
+ async getOrganizationWorkspaceStats(orgIdOrUuid, workspaceUuid) {
5641
+ return this.fetch(`o/${orgIdOrUuid}/workspaces/${workspaceUuid}/stats`);
5642
+ }
5535
5643
  /**
5536
5644
  * Create a workspace in an organization.
5537
5645
  */
@@ -5756,15 +5864,19 @@ var OrgApi = class extends BaseApiClient {
5756
5864
  async getA2PStatus(orgUuid) {
5757
5865
  return this.fetch(`o/${orgUuid}/phone-numbers/a2p/status`);
5758
5866
  }
5867
+ /** Return fixed phone-number and outbound-messaging prices. */
5868
+ async getPhoneBillingPricing(orgUuid) {
5869
+ return this.fetch(`o/${orgUuid}/phone-numbers/pricing`);
5870
+ }
5759
5871
  /**
5760
5872
  * Start A2P brand registration under a legal entity. `legalEntityUuid`
5761
5873
  * is required — brands register per legal entity (Customer Profile);
5762
5874
  * there is no primary-entity fallback.
5763
5875
  */
5764
- async startA2PRegistration(orgUuid, legalEntityUuid, brandName, brandDescription) {
5876
+ async startA2PRegistration(orgUuid, legalEntityUuid, brandName, brandDescription, brandUuid = null) {
5765
5877
  return this.fetch(`o/${orgUuid}/phone-numbers/a2p/start`, {
5766
5878
  method: "POST",
5767
- body: JSON.stringify({ legalEntityUuid, brandName, brandDescription })
5879
+ body: JSON.stringify({ legalEntityUuid, brandName, brandDescription, brandUuid })
5768
5880
  });
5769
5881
  }
5770
5882
  /**
@@ -5970,14 +6082,34 @@ var OrgApi = class extends BaseApiClient {
5970
6082
  );
5971
6083
  }
5972
6084
  /**
5973
- * The brand-addressable enrollment form URL (carries `?brand=…`). Outreach
5974
- * appends each patient's `external_id`. `url` is null until a Site is linked.
6085
+ * The brand's enrollment-form template URL (carries `?brand=…`, no
6086
+ * credential). `url` is null until a Site is linked. Do not append a
6087
+ * patient identifier to this URL — use {@link mintA2PBrandEnrollmentLink}
6088
+ * to get a patient-ready link instead.
5975
6089
  */
5976
6090
  async getA2PBrandEnrollmentUrl(orgUuid, brandUuid) {
5977
6091
  return this.fetch(
5978
6092
  `o/${orgUuid}/a2p-brands/${brandUuid}/enrollment-url`
5979
6093
  );
5980
6094
  }
6095
+ /**
6096
+ * Mint a patient-ready enrollment link for one patient.
6097
+ *
6098
+ * The returned URL carries a fresh, expiring, single-use `?grant=…` bound to
6099
+ * the member that `externalId` resolves to. `externalId` (the patient's
6100
+ * CRM/EHR identifier) travels in the request body, never the query string,
6101
+ * so it stays out of access logs. When it matches no member, the
6102
+ * credential-free template URL is returned rather than an error.
6103
+ */
6104
+ async mintA2PBrandEnrollmentLink(orgUuid, brandUuid, externalId) {
6105
+ return this.fetch(
6106
+ `o/${orgUuid}/a2p-brands/${brandUuid}/enrollment-url`,
6107
+ {
6108
+ method: "POST",
6109
+ body: JSON.stringify({ externalId })
6110
+ }
6111
+ );
6112
+ }
5981
6113
  /**
5982
6114
  * List available member roles for a workspace in the organization.
5983
6115
  */
@@ -6438,6 +6570,67 @@ var PersonasApi = class extends BaseApiClient {
6438
6570
  }
6439
6571
  };
6440
6572
 
6573
+ // src/api/metrics.ts
6574
+ var MetricsApi = class extends BaseApiClient {
6575
+ /** List metric definitions in the workspace, paginated. */
6576
+ async listMetrics(wid, params) {
6577
+ const q = new URLSearchParams();
6578
+ if (params?.page !== void 0) q.set("page", String(params.page));
6579
+ if (params?.pageSize !== void 0) q.set("pageSize", String(params.pageSize));
6580
+ if (params?.includeArchived !== void 0)
6581
+ q.set("includeArchived", String(params.includeArchived));
6582
+ if (params?.source) q.set("source", params.source);
6583
+ const qs = q.toString() ? `?${q.toString()}` : "";
6584
+ return this.fetch(`w/${wid}/metrics${qs}`);
6585
+ }
6586
+ async getMetric(wid, id) {
6587
+ return this.fetch(`w/${wid}/metrics/${id}`);
6588
+ }
6589
+ async createMetric(wid, data) {
6590
+ return this.fetch(`w/${wid}/metrics`, {
6591
+ method: "POST",
6592
+ body: JSON.stringify(data)
6593
+ });
6594
+ }
6595
+ async updateMetric(wid, id, data) {
6596
+ return this.fetch(`w/${wid}/metrics/${id}`, {
6597
+ method: "PUT",
6598
+ body: JSON.stringify(data)
6599
+ });
6600
+ }
6601
+ /** Soft-archive a metric (observations retained). */
6602
+ async deleteMetric(wid, id) {
6603
+ return this.fetch(`w/${wid}/metrics/${id}`, { method: "DELETE" });
6604
+ }
6605
+ async listMetricObservations(wid, metricId, params) {
6606
+ const q = new URLSearchParams();
6607
+ q.set("start", params.start);
6608
+ q.set("end", params.end);
6609
+ if (params.page !== void 0) q.set("page", String(params.page));
6610
+ if (params.pageSize !== void 0) q.set("pageSize", String(params.pageSize));
6611
+ return this.fetch(
6612
+ `w/${wid}/metrics/${metricId}/observations?${q.toString()}`
6613
+ );
6614
+ }
6615
+ async getMetricSeries(wid, metricId, params) {
6616
+ const q = new URLSearchParams();
6617
+ q.set("start", params.start);
6618
+ q.set("end", params.end);
6619
+ if (params.bucket) q.set("bucket", params.bucket);
6620
+ if (params.aggregation) q.set("aggregation", params.aggregation);
6621
+ return this.fetch(
6622
+ `w/${wid}/metrics/${metricId}/series?${q.toString()}`
6623
+ );
6624
+ }
6625
+ /** On-demand compute of enabled chat-source metrics for one chat. */
6626
+ async computeChatMetrics(wid, data) {
6627
+ return this.fetch(`w/${wid}/metrics/compute-for-chat`, {
6628
+ method: "POST",
6629
+ body: JSON.stringify(data)
6630
+ });
6631
+ }
6632
+ };
6633
+
6441
6634
  // src/api/queries.ts
6442
6635
  var QueriesApi = class extends BaseApiClient {
6443
6636
  /** Queryable namespace: native fields, operators per type, DataType record fields. */
@@ -7780,6 +7973,118 @@ var ToolkitsApi = class extends BaseApiClient {
7780
7973
  }
7781
7974
  };
7782
7975
 
7976
+ // src/api/tracked-links.ts
7977
+ function withFilters(params, options) {
7978
+ if (options.dateFrom) params.append("dateFrom", options.dateFrom);
7979
+ if (options.dateTo) params.append("dateTo", options.dateTo);
7980
+ if (options.workflowId !== void 0) params.append("workflowId", String(options.workflowId));
7981
+ return params;
7982
+ }
7983
+ function suffix(params) {
7984
+ const query = params.toString();
7985
+ return query ? `?${query}` : "";
7986
+ }
7987
+ var TrackedLinksApi = class extends BaseApiClient {
7988
+ /** Header counters plus whether shortening is configured and enabled. */
7989
+ async getTrackedLinkSummary(wid, options = {}) {
7990
+ const params = withFilters(new URLSearchParams(), options);
7991
+ return this.fetch(
7992
+ `w/${wid}/tracked-links/summary${suffix(params)}`
7993
+ );
7994
+ }
7995
+ /**
7996
+ * Known destination URLs, most recent first. Powers the "Clicked link"
7997
+ * member-filter autocomplete, so it stays unaggregated and cheap.
7998
+ */
7999
+ async getTrackedLinkDestinations(wid, options = {}) {
8000
+ const params = new URLSearchParams();
8001
+ if (options.q) params.append("q", options.q);
8002
+ if (options.limit !== void 0) params.append("limit", String(options.limit));
8003
+ return this.fetch(
8004
+ `w/${wid}/tracked-links/destinations${suffix(params)}`
8005
+ );
8006
+ }
8007
+ /**
8008
+ * Register a destination an author can reference as `{{links.<key>}}`.
8009
+ *
8010
+ * The URL is deduplicated server-side, so registering one the workspace
8011
+ * already knows adopts that destination — including a row the retired
8012
+ * auto-harvest left unnamed, whose click history then carries forward
8013
+ * under the new key. Registering a URL that already has a *different* key
8014
+ * is a 409: renaming is what `updateTrackedLinkDestination` is for.
8015
+ *
8016
+ * Keys use the same grammar as snippet keys: lowercase letters, digits,
8017
+ * underscores and dots, starting with a letter (`intake_form`,
8018
+ * `docs.privacy`). No hyphens — Jinja2 reads `links.spring-2026` as
8019
+ * subtraction.
8020
+ */
8021
+ async createTrackedLinkDestination(wid, data) {
8022
+ return this.fetch(`w/${wid}/tracked-links/destinations`, {
8023
+ method: "POST",
8024
+ body: JSON.stringify(data)
8025
+ });
8026
+ }
8027
+ /**
8028
+ * Re-key or relabel a destination.
8029
+ *
8030
+ * Changing `key` breaks templates: `{{links.old}}` stops resolving and the
8031
+ * message ships without its link. Relabelling (`name`) is always safe.
8032
+ * Passing `key: null` releases the handle so another destination can take
8033
+ * it — the non-destructive alternative to deleting, which would take the
8034
+ * click history with it. The URL is not editable.
8035
+ */
8036
+ async updateTrackedLinkDestination(wid, destinationId, data) {
8037
+ return this.fetch(
8038
+ `w/${wid}/tracked-links/destinations/${destinationId}`,
8039
+ { method: "PUT", body: JSON.stringify(data) }
8040
+ );
8041
+ }
8042
+ /** Per-destination sent / clicks / unique clickers / CTR for the window. */
8043
+ async getTrackedLinkStats(wid, options = {}) {
8044
+ const params = withFilters(new URLSearchParams(), options);
8045
+ if (options.page !== void 0) params.append("page", String(options.page));
8046
+ if (options.pageSize !== void 0) params.append("pageSize", String(options.pageSize));
8047
+ if (options.q) params.append("q", options.q);
8048
+ if (options.sortBy) params.append("sortBy", options.sortBy);
8049
+ if (options.sortOrder) params.append("sortOrder", options.sortOrder);
8050
+ return this.fetch(
8051
+ `w/${wid}/tracked-links${suffix(params)}`
8052
+ );
8053
+ }
8054
+ /** Clicks over time for the current filter selection. */
8055
+ async getTrackedLinkTimeseries(wid, options = {}) {
8056
+ const params = withFilters(new URLSearchParams(), options);
8057
+ if (options.destinationId !== void 0) {
8058
+ params.append("destinationId", String(options.destinationId));
8059
+ }
8060
+ if (options.granularity) params.append("granularity", options.granularity);
8061
+ if (options.tz) params.append("tz", options.tz);
8062
+ return this.fetch(
8063
+ `w/${wid}/tracked-links/timeseries${suffix(params)}`
8064
+ );
8065
+ }
8066
+ /**
8067
+ * Delete one destination: its short links stop resolving and its recorded
8068
+ * clicks are removed.
8069
+ *
8070
+ * Turning the workspace setting off only stops NEW links being minted —
8071
+ * links already delivered to members keep working. This is the deliberate
8072
+ * way to break them.
8073
+ */
8074
+ async deleteTrackedLinkDestination(wid, destinationId) {
8075
+ return this.fetch(
8076
+ `w/${wid}/tracked-links/destinations/${destinationId}`,
8077
+ { method: "DELETE" }
8078
+ );
8079
+ }
8080
+ /** Delete every destination, its links, and its clicks. Irreversible. */
8081
+ async clearTrackedLinkDestinations(wid) {
8082
+ return this.fetch(`w/${wid}/tracked-links/destinations`, {
8083
+ method: "DELETE"
8084
+ });
8085
+ }
8086
+ };
8087
+
7783
8088
  // src/api/journeys.ts
7784
8089
  var JourneysApi = class extends BaseApiClient {
7785
8090
  /**
@@ -8552,6 +8857,12 @@ var MemberImportPreviewRowAction = {
8552
8857
  error: "error"
8553
8858
  };
8554
8859
 
8860
+ // src/types/generated/member_role.ts
8861
+ var MergeMemberRolesRequestAccessStrategy = {
8862
+ union: "union",
8863
+ target_only: "target_only"
8864
+ };
8865
+
8555
8866
  // src/types/member-types.ts
8556
8867
  var MemberType = /* @__PURE__ */ ((MemberType2) => {
8557
8868
  MemberType2["ANONYMOUS"] = "anonymous";
@@ -8560,6 +8871,37 @@ var MemberType = /* @__PURE__ */ ((MemberType2) => {
8560
8871
  MemberType2["AGENT"] = "agent";
8561
8872
  return MemberType2;
8562
8873
  })(MemberType || {});
8874
+ function structuredErrorDetail(error) {
8875
+ if (!error || typeof error !== "object") return null;
8876
+ const detail = error.errorData;
8877
+ if (!detail || typeof detail !== "object") return null;
8878
+ return detail;
8879
+ }
8880
+ function isMemberContactConflict(error) {
8881
+ const d = structuredErrorDetail(error);
8882
+ if (!d || d.code !== "MEMBER_CONTACT_CONFLICT") return null;
8883
+ if (d.conflictingMemberId !== null && typeof d.conflictingMemberId !== "number") {
8884
+ return null;
8885
+ }
8886
+ return d;
8887
+ }
8888
+ function isAccountContactConflict(error) {
8889
+ const d = structuredErrorDetail(error);
8890
+ if (!d || d.code !== "ACCOUNT_CONTACT_CONFLICT") return null;
8891
+ return d;
8892
+ }
8893
+ function archivedMemberConflictId(error) {
8894
+ const d = structuredErrorDetail(error);
8895
+ if (!d || d.code !== "ARCHIVED_MEMBER_CONFLICT") return null;
8896
+ return typeof d.archivedMemberId === "number" ? d.archivedMemberId : null;
8897
+ }
8898
+ function isIdentifiedMemberContactConflict(conflict) {
8899
+ return !!conflict && conflict.conflictingMemberId !== null;
8900
+ }
8901
+ function asIdentifiedMemberContactConflict(error) {
8902
+ const conflict = isMemberContactConflict(error);
8903
+ return isIdentifiedMemberContactConflict(conflict) ? conflict : null;
8904
+ }
8563
8905
 
8564
8906
  // src/types/mcp-server-types.ts
8565
8907
  var McpServerState = /* @__PURE__ */ ((McpServerState2) => {
@@ -8605,6 +8947,7 @@ var EventRuleEventType = /* @__PURE__ */ ((EventRuleEventType2) => {
8605
8947
  EventRuleEventType2["DATA_RECORD_UPDATED"] = "data_record:updated";
8606
8948
  EventRuleEventType2["DATA_RECORD_CHANGED"] = "data_record:changed";
8607
8949
  EventRuleEventType2["CHAT_CREATED"] = "chat:created";
8950
+ EventRuleEventType2["CHAT_SUMMARY"] = "chat:summary";
8608
8951
  EventRuleEventType2["CHAT_CALLBACK"] = "chat:callback";
8609
8952
  EventRuleEventType2["MEMBER_UPDATED"] = "member:updated";
8610
8953
  EventRuleEventType2["ROUTINE_TRIGGERED"] = "routine:triggered";
@@ -9370,6 +9713,20 @@ var WorkspacesApi = class extends BaseApiClient {
9370
9713
  if (featured !== void 0) params.set("featured", String(featured));
9371
9714
  return this.fetch(`products?${params.toString()}`);
9372
9715
  }
9716
+ /**
9717
+ * Check whether a promo code is usable, without redeeming it.
9718
+ *
9719
+ * Reserves nothing, so it is safe to call as a form field settles. Redemption
9720
+ * happens server-side after checkout completes, when the organization and its
9721
+ * subscription exist.
9722
+ */
9723
+ async previewPromoCode(code, options) {
9724
+ return this.fetch("promo-codes/preview", {
9725
+ method: "POST",
9726
+ body: JSON.stringify({ code }),
9727
+ signal: options?.signal
9728
+ });
9729
+ }
9373
9730
  /** Get a publicly accessible product by ID. */
9374
9731
  async getPublicProduct(id) {
9375
9732
  return this.fetch(`products/${id}`);
@@ -9587,10 +9944,11 @@ function createApiModules(apiKey, baseUrl, customFetch) {
9587
9944
  connectionSync: new ConnectionSyncApi(apiKey, baseUrl, customFetch),
9588
9945
  mcpServers: new McpServersApi(apiKey, baseUrl, customFetch),
9589
9946
  members: new MembersApi(apiKey, baseUrl, customFetch),
9590
- milestones: new MilestonesApi(apiKey, baseUrl, customFetch),
9591
9947
  motd: new MotdApi(apiKey, baseUrl, customFetch),
9948
+ trackedLinks: new TrackedLinksApi(apiKey, baseUrl, customFetch),
9592
9949
  confluence: new ConfluenceApi(apiKey, baseUrl, customFetch),
9593
9950
  mondayIntegration: new MondayIntegrationApi(apiKey, baseUrl, customFetch),
9951
+ interventionRequests: new InterventionRequestsApi(apiKey, baseUrl, customFetch),
9594
9952
  notificationRules: new NotificationRulesApi(apiKey, baseUrl, customFetch),
9595
9953
  oauth: new OAuthApi(apiKey, baseUrl, customFetch),
9596
9954
  operatorGroups: new OperatorApi(apiKey, baseUrl, customFetch),
@@ -9600,6 +9958,7 @@ function createApiModules(apiKey, baseUrl, customFetch) {
9600
9958
  pronunciations: new PronunciationsApi(apiKey, baseUrl, customFetch),
9601
9959
  qualifications: new QualificationsApi(apiKey, baseUrl, customFetch),
9602
9960
  personas: new PersonasApi(apiKey, baseUrl, customFetch),
9961
+ metrics: new MetricsApi(apiKey, baseUrl, customFetch),
9603
9962
  queries: new QueriesApi(apiKey, baseUrl, customFetch),
9604
9963
  reports: new ReportsApi(apiKey, baseUrl, customFetch),
9605
9964
  salesforce: new SalesforceApi(apiKey, baseUrl, customFetch),
@@ -9654,6 +10013,7 @@ var WORKSPACE_METHOD_NAMES = [
9654
10013
  "checkSiteSlugAvailability",
9655
10014
  "clearConnectionMemberExclusion",
9656
10015
  "clearMemberSwitch",
10016
+ "clearTrackedLinkDestinations",
9657
10017
  "clickWorkspaceSupportRequestResource",
9658
10018
  "cloneDataType",
9659
10019
  "cloneTask",
@@ -9712,7 +10072,6 @@ var WORKSPACE_METHOD_NAMES = [
9712
10072
  "createMemberMemory",
9713
10073
  "createMemberRole",
9714
10074
  "createMenuItem",
9715
- "createMilestone",
9716
10075
  "createNotificationRule",
9717
10076
  "createOperatorGroup",
9718
10077
  "createPage",
@@ -9729,6 +10088,7 @@ var WORKSPACE_METHOD_NAMES = [
9729
10088
  "createSupervisor",
9730
10089
  "createTask",
9731
10090
  "createTeamsApp",
10091
+ "createTrackedLinkDestination",
9732
10092
  "createWorkflow",
9733
10093
  "createWorkflowContributor",
9734
10094
  "createWorkflowFromTemplate",
@@ -9778,7 +10138,6 @@ var WORKSPACE_METHOD_NAMES = [
9778
10138
  "deleteMemberMemory",
9779
10139
  "deleteMemberRole",
9780
10140
  "deleteMenuItem",
9781
- "deleteMilestone",
9782
10141
  "deleteMondayConnection",
9783
10142
  "deleteNotificationRule",
9784
10143
  "deleteOperatorGroup",
@@ -9794,6 +10153,7 @@ var WORKSPACE_METHOD_NAMES = [
9794
10153
  "deleteSupervisor",
9795
10154
  "deleteTask",
9796
10155
  "deleteTeamsApp",
10156
+ "deleteTrackedLinkDestination",
9797
10157
  "deleteWidgetDomain",
9798
10158
  "deleteWorkflow",
9799
10159
  "deleteWorkflowContributor",
@@ -9918,6 +10278,7 @@ var WORKSPACE_METHOD_NAMES = [
9918
10278
  "getChatModelOverride",
9919
10279
  "getChatPhoneCalls",
9920
10280
  "getChatSkills",
10281
+ "getManagerSkills",
9921
10282
  "getChatTodos",
9922
10283
  "getChatTokenUsage",
9923
10284
  "getChatToolCallMessages",
@@ -9927,6 +10288,7 @@ var WORKSPACE_METHOD_NAMES = [
9927
10288
  "getChatsNeedsResponse",
9928
10289
  "getChildThreadMessages",
9929
10290
  "getClientWorkspace",
10291
+ "getConfigurationHealth",
9930
10292
  "getConfluenceStatus",
9931
10293
  "getConnectionSyncCapabilities",
9932
10294
  "getConnectionSyncCheckpoint",
@@ -10053,6 +10415,7 @@ var WORKSPACE_METHOD_NAMES = [
10053
10415
  "getMemberMemory",
10054
10416
  "getMemberRecordCounts",
10055
10417
  "getMemberRole",
10418
+ "getMemberRoleCleanupPlan",
10056
10419
  "getMemberRoleByUuid",
10057
10420
  "getMemberRoles",
10058
10421
  "getMemberSyncLinks",
@@ -10061,8 +10424,6 @@ var WORKSPACE_METHOD_NAMES = [
10061
10424
  "getMembersMessageActivity",
10062
10425
  "getMenuItems",
10063
10426
  "getMessageTiming",
10064
- "getMilestone",
10065
- "getMilestones",
10066
10427
  "getMondayConnectionBoardColumns",
10067
10428
  "getMondayConnectionBoardGroups",
10068
10429
  "getMondayConnectionBoards",
@@ -10098,6 +10459,7 @@ var WORKSPACE_METHOD_NAMES = [
10098
10459
  "getPublicFolder",
10099
10460
  "getPublicFolderFiles",
10100
10461
  "getPublicProducts",
10462
+ "previewPromoCode",
10101
10463
  "getQualification",
10102
10464
  "getQualifications",
10103
10465
  "getRecordingInfo",
@@ -10144,6 +10506,10 @@ var WORKSPACE_METHOD_NAMES = [
10144
10506
  "getTool",
10145
10507
  "getToolCallNames",
10146
10508
  "getToolkits",
10509
+ "getTrackedLinkDestinations",
10510
+ "getTrackedLinkStats",
10511
+ "getTrackedLinkSummary",
10512
+ "getTrackedLinkTimeseries",
10147
10513
  "getUnreadNotificationCount",
10148
10514
  "getUsageDashboard",
10149
10515
  "getVariableRegistry",
@@ -10220,6 +10586,14 @@ var WORKSPACE_METHOD_NAMES = [
10220
10586
  "listHealthiePatients",
10221
10587
  "listHealthieProviders",
10222
10588
  "listPersonas",
10589
+ "listMetrics",
10590
+ "getMetric",
10591
+ "createMetric",
10592
+ "updateMetric",
10593
+ "deleteMetric",
10594
+ "listMetricObservations",
10595
+ "getMetricSeries",
10596
+ "computeChatMetrics",
10223
10597
  "listPushSubscriptions",
10224
10598
  "listSalesforceObjects",
10225
10599
  "listScenarios",
@@ -10230,6 +10604,7 @@ var WORKSPACE_METHOD_NAMES = [
10230
10604
  "markEmailAsRead",
10231
10605
  "markEmailAsUnread",
10232
10606
  "markNotificationAsRead",
10607
+ "mergeMemberRoles",
10233
10608
  "previewImportMembers",
10234
10609
  "previewImportWorkspace",
10235
10610
  "previewRoutineWorkflowAccess",
@@ -10358,7 +10733,6 @@ var WORKSPACE_METHOD_NAMES = [
10358
10733
  "updateMemberLabel",
10359
10734
  "updateMemberRole",
10360
10735
  "updateMenuItem",
10361
- "updateMilestone",
10362
10736
  "updateMondaySyncConfig",
10363
10737
  "updateNotificationRule",
10364
10738
  "updateOperatorGroup",
@@ -10378,6 +10752,7 @@ var WORKSPACE_METHOD_NAMES = [
10378
10752
  "updateTask",
10379
10753
  "updateTeamsApp",
10380
10754
  "updateThemeSettings",
10755
+ "updateTrackedLinkDestination",
10381
10756
  "uploadFile",
10382
10757
  "updateVoicemailStatus",
10383
10758
  "updateWorkflow",
@@ -10475,6 +10850,7 @@ function bindChatsMethods(target, chats) {
10475
10850
  target.getChatTokenUsage = chats.getChatTokenUsage.bind(chats);
10476
10851
  target.getChatTodos = chats.getChatTodos.bind(chats);
10477
10852
  target.getChatSkills = chats.getChatSkills.bind(chats);
10853
+ target.getManagerSkills = chats.getManagerSkills.bind(chats);
10478
10854
  target.getChatsNeedsResponse = chats.getChatsNeedsResponse.bind(chats);
10479
10855
  target.getChatsDailyCreationStats = chats.getChatsDailyCreationStats.bind(chats);
10480
10856
  target.getToolCallNames = chats.getToolCallNames.bind(chats);
@@ -10541,6 +10917,7 @@ function bindDashboardsMethods(target, dashboards) {
10541
10917
  target.deleteDashboard = dashboards.deleteDashboard.bind(dashboards);
10542
10918
  target.getDashboardChannelStats = dashboards.getDashboardChannelStats.bind(dashboards);
10543
10919
  target.getDashboardWorkflowAssignmentStats = dashboards.getDashboardWorkflowAssignmentStats.bind(dashboards);
10920
+ target.getConfigurationHealth = dashboards.getConfigurationHealth.bind(dashboards);
10544
10921
  }
10545
10922
 
10546
10923
  // src/client/bindings/motd.ts
@@ -10548,6 +10925,18 @@ function bindMotdMethods(target, motd) {
10548
10925
  target.getMotd = motd.getMotd.bind(motd);
10549
10926
  }
10550
10927
 
10928
+ // src/client/bindings/tracked-links.ts
10929
+ function bindTrackedLinksMethods(target, trackedLinks) {
10930
+ target.getTrackedLinkSummary = trackedLinks.getTrackedLinkSummary.bind(trackedLinks);
10931
+ target.getTrackedLinkDestinations = trackedLinks.getTrackedLinkDestinations.bind(trackedLinks);
10932
+ target.getTrackedLinkStats = trackedLinks.getTrackedLinkStats.bind(trackedLinks);
10933
+ target.getTrackedLinkTimeseries = trackedLinks.getTrackedLinkTimeseries.bind(trackedLinks);
10934
+ target.createTrackedLinkDestination = trackedLinks.createTrackedLinkDestination.bind(trackedLinks);
10935
+ target.updateTrackedLinkDestination = trackedLinks.updateTrackedLinkDestination.bind(trackedLinks);
10936
+ target.deleteTrackedLinkDestination = trackedLinks.deleteTrackedLinkDestination.bind(trackedLinks);
10937
+ target.clearTrackedLinkDestinations = trackedLinks.clearTrackedLinkDestinations.bind(trackedLinks);
10938
+ }
10939
+
10551
10940
  // src/client/bindings/data-types.ts
10552
10941
  function bindDataTypesMethods(target, dataTypes) {
10553
10942
  target.getDataTypes = dataTypes.getDataTypes.bind(dataTypes);
@@ -10949,7 +11338,7 @@ function bindWorkflowsMethods(target, workflows, workflowNotes, voice, superviso
10949
11338
  }
10950
11339
 
10951
11340
  // src/client/bindings/calendars.ts
10952
- function bindCalendarsMethods(target, calendars, milestones) {
11341
+ function bindCalendarsMethods(target, calendars) {
10953
11342
  target.getCalendars = calendars.getCalendars.bind(calendars);
10954
11343
  target.getCalendar = calendars.getCalendar.bind(calendars);
10955
11344
  target.createCalendar = calendars.createCalendar.bind(calendars);
@@ -10981,11 +11370,6 @@ function bindCalendarsMethods(target, calendars, milestones) {
10981
11370
  target.linkCalendarToGoogle = calendars.linkCalendarToGoogle.bind(calendars);
10982
11371
  target.unlinkCalendarFromGoogle = calendars.unlinkCalendarFromGoogle.bind(calendars);
10983
11372
  target.syncCalendarWithGoogle = calendars.syncCalendarWithGoogle.bind(calendars);
10984
- target.getMilestones = milestones.getMilestones.bind(milestones);
10985
- target.getMilestone = milestones.getMilestone.bind(milestones);
10986
- target.createMilestone = milestones.createMilestone.bind(milestones);
10987
- target.updateMilestone = milestones.updateMilestone.bind(milestones);
10988
- target.deleteMilestone = milestones.deleteMilestone.bind(milestones);
10989
11373
  }
10990
11374
 
10991
11375
  // src/client/bindings/communications.ts
@@ -11043,6 +11427,7 @@ function bindToolkitsMethods(target, toolkits, templates, aiModels, customToolki
11043
11427
  target.getSTTModels = aiModels.getSTTModels.bind(aiModels);
11044
11428
  target.getTTSModels = aiModels.getTTSModels.bind(aiModels);
11045
11429
  target.getVoiceModels = aiModels.getVoiceModels.bind(aiModels);
11430
+ target.getVoicePresets = aiModels.getVoicePresets.bind(aiModels);
11046
11431
  target.getAllModels = aiModels.getAllModels.bind(aiModels);
11047
11432
  target.getCustomToolkits = customToolkits.getCustomToolkits.bind(customToolkits);
11048
11433
  target.getCustomToolkit = customToolkits.getCustomToolkit.bind(customToolkits);
@@ -11341,6 +11726,11 @@ function bindOrgMethods(target, org) {
11341
11726
  target.updateBusinessProfile = org.updateBusinessProfile.bind(org);
11342
11727
  target.submitBusinessProfile = org.submitBusinessProfile.bind(org);
11343
11728
  target.cancelBusinessProfile = org.cancelBusinessProfile.bind(org);
11729
+ target.listLegalEntities = org.listLegalEntities.bind(org);
11730
+ target.getLegalEntity = org.getLegalEntity.bind(org);
11731
+ target.createLegalEntity = org.createLegalEntity.bind(org);
11732
+ target.getVoiceTrustProducts = org.getVoiceTrustProducts.bind(org);
11733
+ target.syncVoiceTrustProducts = org.syncVoiceTrustProducts.bind(org);
11344
11734
  target.createOrganizationWorkspace = org.createOrganizationWorkspace.bind(org);
11345
11735
  target.getOrgBillingCustomer = org.getOrgBillingCustomer.bind(org);
11346
11736
  }
@@ -11424,6 +11814,18 @@ function bindPersonasMethods(target, personas) {
11424
11814
  target.deletePersona = personas.deletePersona.bind(personas);
11425
11815
  }
11426
11816
 
11817
+ // src/client/bindings/metrics.ts
11818
+ function bindMetricsMethods(target, metrics) {
11819
+ target.listMetrics = metrics.listMetrics.bind(metrics);
11820
+ target.getMetric = metrics.getMetric.bind(metrics);
11821
+ target.createMetric = metrics.createMetric.bind(metrics);
11822
+ target.updateMetric = metrics.updateMetric.bind(metrics);
11823
+ target.deleteMetric = metrics.deleteMetric.bind(metrics);
11824
+ target.listMetricObservations = metrics.listMetricObservations.bind(metrics);
11825
+ target.getMetricSeries = metrics.getMetricSeries.bind(metrics);
11826
+ target.computeChatMetrics = metrics.computeChatMetrics.bind(metrics);
11827
+ }
11828
+
11427
11829
  // src/client/bindings/queries.ts
11428
11830
  function bindQueriesMethods(target, queries) {
11429
11831
  target.getQueryFields = queries.getQueryFields.bind(queries);
@@ -11514,6 +11916,7 @@ var GravityRailClient = class {
11514
11916
  getChatTokenUsage;
11515
11917
  getChatTodos;
11516
11918
  getChatSkills;
11919
+ getManagerSkills;
11517
11920
  getChatsNeedsResponse;
11518
11921
  getChatsDailyCreationStats;
11519
11922
  getToolCallNames;
@@ -11631,6 +12034,8 @@ var GravityRailClient = class {
11631
12034
  createMemberRole;
11632
12035
  updateMemberRole;
11633
12036
  deleteMemberRole;
12037
+ getMemberRoleCleanupPlan;
12038
+ mergeMemberRoles;
11634
12039
  // Member Fields
11635
12040
  getMemberFields;
11636
12041
  getMemberFieldDefinitions;
@@ -11691,6 +12096,15 @@ var GravityRailClient = class {
11691
12096
  createPersona;
11692
12097
  updatePersona;
11693
12098
  deletePersona;
12099
+ // Metrics API (customer-defined outcome metrics)
12100
+ listMetrics;
12101
+ getMetric;
12102
+ createMetric;
12103
+ updateMetric;
12104
+ deleteMetric;
12105
+ listMetricObservations;
12106
+ getMetricSeries;
12107
+ computeChatMetrics;
11694
12108
  // Dashboards API
11695
12109
  getDashboards;
11696
12110
  getDashboard;
@@ -11699,8 +12113,18 @@ var GravityRailClient = class {
11699
12113
  deleteDashboard;
11700
12114
  getDashboardChannelStats;
11701
12115
  getDashboardWorkflowAssignmentStats;
12116
+ getConfigurationHealth;
11702
12117
  // MOTD API
11703
12118
  getMotd;
12119
+ // Tracked Links analytics (#10934)
12120
+ getTrackedLinkSummary;
12121
+ getTrackedLinkDestinations;
12122
+ getTrackedLinkStats;
12123
+ getTrackedLinkTimeseries;
12124
+ createTrackedLinkDestination;
12125
+ updateTrackedLinkDestination;
12126
+ deleteTrackedLinkDestination;
12127
+ clearTrackedLinkDestinations;
11704
12128
  // Journeys API
11705
12129
  getJourneys;
11706
12130
  getJourney;
@@ -11805,6 +12229,7 @@ var GravityRailClient = class {
11805
12229
  getProduct;
11806
12230
  getWorkspaceProduct;
11807
12231
  getPublicProducts;
12232
+ previewPromoCode;
11808
12233
  getPublicProduct;
11809
12234
  createProduct;
11810
12235
  updateProduct;
@@ -11842,6 +12267,11 @@ var GravityRailClient = class {
11842
12267
  updateBusinessProfile;
11843
12268
  submitBusinessProfile;
11844
12269
  cancelBusinessProfile;
12270
+ listLegalEntities;
12271
+ getLegalEntity;
12272
+ createLegalEntity;
12273
+ getVoiceTrustProducts;
12274
+ syncVoiceTrustProducts;
11845
12275
  createOrganizationWorkspace;
11846
12276
  getOrgBillingCustomer;
11847
12277
  getVapidPublicKey;
@@ -12103,11 +12533,6 @@ var GravityRailClient = class {
12103
12533
  linkCalendarToGoogle;
12104
12534
  unlinkCalendarFromGoogle;
12105
12535
  syncCalendarWithGoogle;
12106
- getMilestones;
12107
- getMilestone;
12108
- createMilestone;
12109
- updateMilestone;
12110
- deleteMilestone;
12111
12536
  // Communications API
12112
12537
  getPhoneNumbers;
12113
12538
  getAvailablePhoneNumbers;
@@ -12159,6 +12584,7 @@ var GravityRailClient = class {
12159
12584
  getSTTModels;
12160
12585
  getTTSModels;
12161
12586
  getVoiceModels;
12587
+ getVoicePresets;
12162
12588
  getAllModels;
12163
12589
  getCustomToolkits;
12164
12590
  getCustomToolkit;
@@ -12486,9 +12912,11 @@ var GravityRailClient = class {
12486
12912
  bindAgentsMethods(this, apis.agents);
12487
12913
  bindQualificationsMethods(this, apis.qualifications);
12488
12914
  bindPersonasMethods(this, apis.personas);
12915
+ bindMetricsMethods(this, apis.metrics);
12489
12916
  bindQueriesMethods(this, apis.queries);
12490
12917
  bindDashboardsMethods(this, apis.dashboards);
12491
12918
  bindMotdMethods(this, apis.motd);
12919
+ bindTrackedLinksMethods(this, apis.trackedLinks);
12492
12920
  bindJourneysMethods(this, apis.journeys);
12493
12921
  bindExperimentsMethods(this, apis.experiments);
12494
12922
  bindOperatorMethods(this, apis.operatorGroups);
@@ -12501,7 +12929,7 @@ var GravityRailClient = class {
12501
12929
  bindFilesMethods(this, apis.files);
12502
12930
  bindEventsMethods(this, apis.events);
12503
12931
  bindWorkflowsMethods(this, apis.workflows, apis.workflowNotes, apis.voice, apis.supervisors);
12504
- bindCalendarsMethods(this, apis.calendars, apis.milestones);
12932
+ bindCalendarsMethods(this, apis.calendars);
12505
12933
  bindCommunicationsMethods(this, apis.phoneNumbers, apis.inboxes, apis.notificationRules);
12506
12934
  bindToolkitsMethods(
12507
12935
  this,
@@ -12681,6 +13109,14 @@ var WorkspaceBuilderResource = class {
12681
13109
  }
12682
13110
  return this._uuid;
12683
13111
  }
13112
+ /**
13113
+ * True for resources the server creates on our behalf (currently a
13114
+ * journey's `Start` step). They are kept in the resource list so edges can
13115
+ * reference them, but they are never created, printed, or counted.
13116
+ */
13117
+ get isImplicit() {
13118
+ return false;
13119
+ }
12684
13120
  matchKey() {
12685
13121
  return void 0;
12686
13122
  }
@@ -12703,6 +13139,19 @@ function resolveRefValue(value) {
12703
13139
  }
12704
13140
  return out;
12705
13141
  }
13142
+ function resolveIdRefs(value) {
13143
+ return resolveIdRefValue(value);
13144
+ }
13145
+ function resolveIdRefValue(value) {
13146
+ if (value instanceof WorkspaceBuilderResource) return value.id;
13147
+ if (Array.isArray(value)) return value.map(resolveIdRefValue);
13148
+ if (!isPlainRecord(value)) return value;
13149
+ const out = {};
13150
+ for (const [key, nestedValue] of Object.entries(value)) {
13151
+ out[key] = resolveIdRefValue(nestedValue);
13152
+ }
13153
+ return out;
13154
+ }
12706
13155
 
12707
13156
  // src/workspace-builder/automation.ts
12708
13157
  var MemberFilterBuilder = class extends WorkspaceBuilderResource {
@@ -12716,7 +13165,12 @@ var MemberFilterBuilder = class extends WorkspaceBuilderResource {
12716
13165
  description;
12717
13166
  /** Query-engine predicate (JSON IR) authored on MemberFilter.query. */
12718
13167
  query = null;
12719
- /** Set the filter's query-engine predicate (JSON IR). */
13168
+ /**
13169
+ * Set the filter's query-engine predicate (JSON IR).
13170
+ *
13171
+ * Anywhere the IR wants a numeric id you may pass the builder that will own
13172
+ * it (e.g. a label in a `member.labelId` value); refs resolve at apply time.
13173
+ */
12720
13174
  setQuery(query) {
12721
13175
  this.query = query;
12722
13176
  return this;
@@ -12725,10 +13179,12 @@ var MemberFilterBuilder = class extends WorkspaceBuilderResource {
12725
13179
  return `MemberFilter: ${this.name}${this.query ? " (query)" : ""}`;
12726
13180
  }
12727
13181
  async apply(client) {
13182
+ if (this._existed) return;
12728
13183
  const payload = {
12729
13184
  name: this.name,
12730
13185
  description: this.description,
12731
- query: this.query
13186
+ // Builder refs inside the IR become ids here; see resolveIdRefs.
13187
+ query: resolveIdRefs(this.query)
12732
13188
  };
12733
13189
  const result = await client.createMemberFilter(payload);
12734
13190
  this._id = result.id;
@@ -13023,35 +13479,134 @@ var MemberLabelBuilder = class extends WorkspaceBuilderResource {
13023
13479
  };
13024
13480
 
13025
13481
  // src/workspace-builder/journeys.ts
13482
+ var SECONDS_PER_DAY = 86400;
13483
+ function edgeKey(parentId, childId) {
13484
+ return `${parentId}:${childId}`;
13485
+ }
13486
+ function edgeCondition(options) {
13487
+ const clauses = [];
13488
+ if (options.afterDays !== void 0) {
13489
+ clauses.push(`days_since(parent_step.completed_at) >= ${options.afterDays}`);
13490
+ }
13491
+ if (options.when) clauses.push(`(${options.when})`);
13492
+ if (!clauses.length) return void 0;
13493
+ return clauses.join(" && ");
13494
+ }
13026
13495
  var JourneyStepBuilder = class extends WorkspaceBuilderResource {
13027
13496
  // journey-decoupling Phase 7: a Journey step no longer links to a Workflow.
13028
13497
  // A step nudges via EventRule actions instead of running a Workflow, so the
13029
13498
  // builder no longer accepts or emits a workflow reference.
13030
- constructor(name, journey, order = 0, description = "") {
13499
+ constructor(name, journey, order = 0, description = "", options = {}) {
13031
13500
  super();
13032
13501
  this.name = name;
13033
13502
  this.journey = journey;
13034
13503
  this.order = order;
13035
13504
  this.description = description;
13505
+ this.assigneeId = options.assigneeId;
13506
+ this.posX = options.posX;
13507
+ this.posY = options.posY;
13036
13508
  }
13037
13509
  name;
13038
13510
  journey;
13039
13511
  order;
13040
13512
  description;
13041
13513
  connections = [];
13042
- connectsTo(child, condition, required = false, timeoutSeconds) {
13043
- this.connections.push({ parent: this, child, condition, required, timeoutSeconds });
13514
+ rules = [];
13515
+ assigneeId;
13516
+ posX;
13517
+ posY;
13518
+ /** Wire an edge to `child` and return the CHILD, so chains read linearly. */
13519
+ connectsTo(child, options = {}) {
13520
+ if (child === this) {
13521
+ throw new Error(`Journey step '${this.name}' cannot connect to itself`);
13522
+ }
13523
+ const abandonSeconds = options.abandonAfterDays !== void 0 ? options.abandonAfterDays * SECONDS_PER_DAY : options.timeoutSeconds;
13524
+ this.connections.push({
13525
+ parent: this,
13526
+ child,
13527
+ condition: edgeCondition(options),
13528
+ required: options.required ?? false,
13529
+ timeoutSeconds: abandonSeconds,
13530
+ order: options.order,
13531
+ filterId: options.filterId
13532
+ });
13533
+ return child;
13534
+ }
13535
+ /**
13536
+ * Attach a `JOURNEY_STEP_EXECUTE` action — what this step actually DOES
13537
+ * when a member reaches it. A step with no rules is inert: the member
13538
+ * lands on it, nothing is sent, and the journey moves on.
13539
+ */
13540
+ onExecute(actionType, params = {}, options = {}) {
13541
+ this.rules.push({
13542
+ uuid: crypto.randomUUID(),
13543
+ actionType,
13544
+ actionParams: params,
13545
+ options
13546
+ });
13044
13547
  return this;
13045
13548
  }
13549
+ /**
13550
+ * Text the member. `phoneNumberUUID` is a workspace PhoneNumber with SMS
13551
+ * enabled. Pass `workflowUUID` to start an SMS workflow chat, or
13552
+ * `messageTemplate` for a one-off send.
13553
+ */
13554
+ sendsSms(params, options = {}) {
13555
+ return this.onExecute("sms:send" /* SMS_SEND */, params, options);
13556
+ }
13557
+ /**
13558
+ * Call the member. Both the workspace PhoneNumber uuid (voice enabled) and
13559
+ * the Workflow uuid that drives the call are required.
13560
+ */
13561
+ callsMember(params, options = {}) {
13562
+ return this.onExecute("phone:call" /* PHONE_CALL */, params, options);
13563
+ }
13564
+ /** Email the member from a workspace inbox. */
13565
+ sendsEmail(params, options = {}) {
13566
+ return this.onExecute("email:send" /* EMAIL_SEND */, params, options);
13567
+ }
13568
+ /** Label the member on arrival — pass label builders, not ids. */
13569
+ addsLabels(labels, options = {}) {
13570
+ return this.onExecute(
13571
+ "member:label" /* MEMBER_LABEL_ACTION */,
13572
+ { addLabelIds: labels },
13573
+ options
13574
+ );
13575
+ }
13576
+ /** True once this step has something to do when a member reaches it. */
13577
+ get hasOutreach() {
13578
+ return this.rules.length > 0;
13579
+ }
13580
+ eventRuleInputs() {
13581
+ return this.rules.map((rule) => ({
13582
+ uuid: rule.uuid,
13583
+ eventType: "journey_step:execute" /* JOURNEY_STEP_EXECUTE */,
13584
+ actionType: rule.actionType,
13585
+ actionParams: resolveRefs(rule.actionParams),
13586
+ ...rule.options.name ? { name: rule.options.name } : {},
13587
+ ...rule.options.when ? { conditions: rule.options.when } : {},
13588
+ ...rule.options.delaySeconds ? { delay: rule.options.delaySeconds } : {},
13589
+ active: rule.options.active ?? true
13590
+ }));
13591
+ }
13046
13592
  planLine() {
13047
- return `Step: ${this.name}`;
13593
+ const actions = this.rules.map((rule) => rule.actionType).join(" + ");
13594
+ return `Step: ${this.name}${actions ? ` (${actions})` : ""}`;
13048
13595
  }
13049
13596
  async apply(client) {
13597
+ if (this._existed) return;
13050
13598
  if (this.journey._id === void 0) return;
13599
+ const rules = this.eventRuleInputs();
13051
13600
  const payload = {
13052
13601
  name: this.name,
13053
13602
  description: this.description,
13054
- order: this.order
13603
+ order: this.order,
13604
+ ...this.assigneeId !== void 0 ? { assigneeId: this.assigneeId } : {},
13605
+ ...this.posX !== void 0 ? { posX: this.posX } : {},
13606
+ ...this.posY !== void 0 ? { posY: this.posY } : {},
13607
+ // Saved atomically with the step, so a partial failure cannot leave
13608
+ // an inert step behind.
13609
+ ...rules.length ? { eventRules: rules } : {}
13055
13610
  };
13056
13611
  const result = await client.createStep(this.journey._id, payload);
13057
13612
  this._id = result.id;
@@ -13059,26 +13614,59 @@ var JourneyStepBuilder = class extends WorkspaceBuilderResource {
13059
13614
  this._created = true;
13060
13615
  }
13061
13616
  };
13617
+ var StartStepBuilder = class extends JourneyStepBuilder {
13618
+ get isImplicit() {
13619
+ return true;
13620
+ }
13621
+ planLine() {
13622
+ return "Step: Start (auto-created)";
13623
+ }
13624
+ async apply() {
13625
+ }
13626
+ };
13062
13627
  var JourneyBuilder = class extends WorkspaceBuilderResource {
13063
13628
  constructor(name, options = {}) {
13064
13629
  super();
13065
13630
  this.name = name;
13066
13631
  this.description = options.description ?? "";
13632
+ this.start = new StartStepBuilder("Start", this, 0);
13633
+ this.steps.push(this.start);
13067
13634
  }
13068
13635
  name;
13069
13636
  description;
13070
13637
  steps = [];
13071
13638
  goals = [];
13639
+ /** The auto-created `Start` step — connect the first real step to it. */
13640
+ start;
13641
+ /** `parentId:childId` for every edge the server already has (see `adopt`). */
13642
+ existingEdges = /* @__PURE__ */ new Set();
13072
13643
  step(name, options = {}) {
13073
13644
  const step = new JourneyStepBuilder(
13074
13645
  name,
13075
13646
  this,
13076
- options.order ?? 0,
13077
- options.description ?? ""
13647
+ options.order ?? this.steps.length,
13648
+ options.description ?? "",
13649
+ options
13078
13650
  );
13079
13651
  this.steps.push(step);
13080
13652
  return step;
13081
13653
  }
13654
+ /**
13655
+ * Declare a linear cadence: `Start → steps[0] → steps[1] → …`, each edge
13656
+ * carrying the matching entry from `spacing`.
13657
+ *
13658
+ * Chaining is not optional polish. A step created with no incoming edge is
13659
+ * a ROOT, and every root fires the moment a member enrols — a "three
13660
+ * follow-ups over four days" journey built without edges sends all three
13661
+ * at once.
13662
+ */
13663
+ sequence(steps, spacing = []) {
13664
+ let parent = this.start;
13665
+ steps.forEach((step, index) => {
13666
+ parent = parent.connectsTo(step, spacing[index] ?? {});
13667
+ });
13668
+ return this;
13669
+ }
13082
13670
  goal(name, options = {}) {
13083
13671
  this.goals.push({
13084
13672
  name,
@@ -13086,17 +13674,85 @@ var JourneyBuilder = class extends WorkspaceBuilderResource {
13086
13674
  step: options.step,
13087
13675
  completionCel: options.completionCel ?? options.completion_cel,
13088
13676
  value: options.value,
13089
- order: options.order ?? 0
13677
+ order: options.order ?? this.goals.length
13090
13678
  });
13091
13679
  return this;
13092
13680
  }
13681
+ /**
13682
+ * Authoring problems that make a journey silently misbehave at runtime.
13683
+ * Reported at plan/preview time, before anything is written.
13684
+ */
13685
+ validate() {
13686
+ const problems = [];
13687
+ const withParents = /* @__PURE__ */ new Set();
13688
+ for (const step of this.steps) {
13689
+ for (const connection of step.connections) withParents.add(connection.child);
13690
+ }
13691
+ for (const step of this.steps) {
13692
+ if (step === this.start) continue;
13693
+ if (!withParents.has(step)) {
13694
+ problems.push(
13695
+ `step '${step.name}' has no incoming edge \u2014 it is a root and fires for every member the moment they enrol. Connect it from journey.start or a prior step.`
13696
+ );
13697
+ }
13698
+ if (!step.hasOutreach) {
13699
+ problems.push(
13700
+ `step '${step.name}' has no JOURNEY_STEP_EXECUTE action \u2014 a member reaching it gets nothing. Add one with .sendsSms / .callsMember / .sendsEmail / .onExecute.`
13701
+ );
13702
+ }
13703
+ }
13704
+ if (!this.goals.length) {
13705
+ problems.push(`journey '${this.name}' has no goals \u2014 nothing measures whether it works.`);
13706
+ }
13707
+ return problems;
13708
+ }
13709
+ /**
13710
+ * Adopt an existing journey, its steps, and its EDGES, matched by name.
13711
+ *
13712
+ * Re-running a builder script is normal — a program is usually built in
13713
+ * stages as provisioning lands — and without adoption the second run would
13714
+ * create a duplicate journey and a duplicate set of steps beside the live
13715
+ * one, with members enrolled in neither.
13716
+ *
13717
+ * The edge set is recorded from the server's own `childConnections` rather
13718
+ * than inferred from "both steps exist". A first run that created the steps
13719
+ * and then failed before writing an edge leaves exactly that state, and
13720
+ * inferring would skip the missing edge on every subsequent run — leaving a
13721
+ * permanent root step that fires for every member at enrolment, silently.
13722
+ * The journey detail read eager-loads connections, so the real answer is
13723
+ * already in hand; there is no reason to guess.
13724
+ */
13725
+ adopt(existing) {
13726
+ super.adopt(existing);
13727
+ const existingSteps = existing.steps ?? [];
13728
+ const byName = new Map(existingSteps.map((step) => [step.name, step]));
13729
+ const startStep = existingSteps.find((step) => step.id === existing.startStepId) ?? byName.get("Start");
13730
+ if (startStep) this.start.adopt(startStep);
13731
+ for (const step of this.steps) {
13732
+ if (step === this.start) continue;
13733
+ const match = byName.get(step.name);
13734
+ if (match) step.adopt(match);
13735
+ }
13736
+ for (const step of existingSteps) {
13737
+ for (const edge of step.childConnections ?? []) {
13738
+ this.existingEdges.add(edgeKey(edge.parentStepId, edge.childStepId));
13739
+ }
13740
+ }
13741
+ }
13742
+ /** True when the server already has this exact edge. */
13743
+ hasEdge(parent, child) {
13744
+ if (parent._id === void 0 || child._id === void 0) return false;
13745
+ return this.existingEdges.has(edgeKey(parent._id, child._id));
13746
+ }
13093
13747
  planLine() {
13094
13748
  const parts = [];
13095
- if (this.steps.length) parts.push(`${this.steps.length} steps`);
13749
+ const real = this.steps.filter((step) => step !== this.start);
13750
+ if (real.length) parts.push(`${real.length} steps`);
13096
13751
  if (this.goals.length) parts.push(`${this.goals.length} goals`);
13097
13752
  return `Journey: ${this.name}${parts.length ? ` (${parts.join(", ")})` : ""}`;
13098
13753
  }
13099
13754
  async apply(client) {
13755
+ if (this._existed) return;
13100
13756
  const result = await client.createJourney({
13101
13757
  name: this.name,
13102
13758
  description: this.description
@@ -13104,6 +13760,15 @@ var JourneyBuilder = class extends WorkspaceBuilderResource {
13104
13760
  this._id = result.id;
13105
13761
  this._uuid = result.uuid;
13106
13762
  this._created = true;
13763
+ const startStep = (result.steps ?? []).find(
13764
+ (step) => step.id === result.startStepId || step.name === "Start"
13765
+ );
13766
+ if (!startStep) {
13767
+ throw new Error(
13768
+ `Journey '${this.name}' was created without a Start step; edges from journey.start cannot be wired.`
13769
+ );
13770
+ }
13771
+ this.start.adopt(startStep);
13107
13772
  }
13108
13773
  };
13109
13774
  function buildJourneyConnectionPayload(connection) {
@@ -13113,7 +13778,9 @@ function buildJourneyConnectionPayload(connection) {
13113
13778
  childStepUuid: connection.child._uuid,
13114
13779
  ...connection.condition ? { celCondition: connection.condition } : {},
13115
13780
  ...connection.required ? { required: true } : {},
13116
- ...connection.timeoutSeconds ? { timeoutSeconds: connection.timeoutSeconds } : {}
13781
+ ...connection.timeoutSeconds ? { timeoutSeconds: connection.timeoutSeconds } : {},
13782
+ ...connection.order !== void 0 ? { order: connection.order } : {},
13783
+ ...connection.filterId !== void 0 ? { filterId: connection.filterId } : {}
13117
13784
  };
13118
13785
  }
13119
13786
  function buildJourneyGoalPayload(goal) {
@@ -13217,6 +13884,16 @@ var TaskBuilder = class extends WorkspaceBuilderResource {
13217
13884
  description;
13218
13885
  transitions = [];
13219
13886
  eventRules = [];
13887
+ /** Child task ids the server already has, recorded when this task is adopted. */
13888
+ existingChildIds = /* @__PURE__ */ new Set();
13889
+ /** Record the edges an adopted task already carries, so a re-run adds only what is missing. */
13890
+ adopt(existing) {
13891
+ super.adopt(existing);
13892
+ for (const child of existing.childTasks ?? []) {
13893
+ const id = child.taskId ?? child.id;
13894
+ if (typeof id === "number") this.existingChildIds.add(id);
13895
+ }
13896
+ }
13220
13897
  transitionsTo(child, when, autoNext = false, required = false, celCondition) {
13221
13898
  if (child === this) {
13222
13899
  throw new Error(`Task '${this.name}' cannot transition to itself`);
@@ -13399,6 +14076,15 @@ var PHASES = /* @__PURE__ */ new Map([
13399
14076
  [JourneyBuilder, 7],
13400
14077
  [JourneyStepBuilder, 8]
13401
14078
  ]);
14079
+ function phaseFor(resource) {
14080
+ let ctor = resource.constructor;
14081
+ while (ctor) {
14082
+ const phase = PHASES.get(ctor);
14083
+ if (phase !== void 0) return phase;
14084
+ ctor = Object.getPrototypeOf(ctor);
14085
+ }
14086
+ return 99;
14087
+ }
13402
14088
  var WorkspaceBuilder = class {
13403
14089
  constructor(client) {
13404
14090
  this.client = client;
@@ -13461,7 +14147,8 @@ var WorkspaceBuilder = class {
13461
14147
  ${"=".repeat(50)}`);
13462
14148
  writeLine("Plan");
13463
14149
  writeLine("=".repeat(50));
13464
- for (const resource of resources) {
14150
+ const declared = resources.filter((resource) => !resource.isImplicit);
14151
+ for (const resource of declared) {
13465
14152
  writeLine(` + ${resource.planLine()}`);
13466
14153
  }
13467
14154
  const wiring = this.collectWiringSummary(resources);
@@ -13469,8 +14156,9 @@ ${"=".repeat(50)}`);
13469
14156
  writeLine("\n Wiring:");
13470
14157
  for (const line of wiring) writeLine(` ${line}`);
13471
14158
  }
14159
+ this.reportJourneyWarnings();
13472
14160
  writeLine(`
13473
- Total: ${resources.length} resources, ${wiring.length} connections`);
14161
+ Total: ${declared.length} resources, ${wiring.length} connections`);
13474
14162
  writeLine(`${"=".repeat(50)}
13475
14163
  `);
13476
14164
  }
@@ -13481,7 +14169,8 @@ ${"=".repeat(50)}`);
13481
14169
  ${"=".repeat(50)}`);
13482
14170
  writeLine("Preview");
13483
14171
  writeLine("=".repeat(50));
13484
- for (const resource of resources) {
14172
+ const declared = resources.filter((resource) => !resource.isImplicit);
14173
+ for (const resource of declared) {
13485
14174
  if (resource._existed) {
13486
14175
  writeLine(` = ${resource.planLine()} (exists, id=${resource._id})`);
13487
14176
  } else {
@@ -13493,8 +14182,9 @@ ${"=".repeat(50)}`);
13493
14182
  writeLine("\n Wiring:");
13494
14183
  for (const line of wiring) writeLine(` ${line}`);
13495
14184
  }
13496
- const toCreate = resources.filter((resource) => !resource._existed);
13497
- const existing = resources.filter((resource) => resource._existed);
14185
+ this.reportJourneyWarnings();
14186
+ const toCreate = declared.filter((resource) => !resource._existed);
14187
+ const existing = declared.filter((resource) => resource._existed);
13498
14188
  writeLine(
13499
14189
  `
13500
14190
  Total: ${toCreate.length} to create, ${existing.length} existing, ${wiring.length} connections`
@@ -13502,13 +14192,72 @@ ${"=".repeat(50)}`);
13502
14192
  writeLine(`${"=".repeat(50)}
13503
14193
  `);
13504
14194
  }
14195
+ /**
14196
+ * Print journey authoring problems that only bite at runtime — a step with
14197
+ * no incoming edge fires for every member at enrolment, and a step with no
14198
+ * action does nothing at all. Both look fine in the editor, so they are
14199
+ * surfaced before the write rather than discovered from a member's phone.
14200
+ */
14201
+ reportJourneyWarnings() {
14202
+ const problems = this.resources.filter((resource) => resource instanceof JourneyBuilder).flatMap((journey) => journey.validate());
14203
+ if (!problems.length) return;
14204
+ writeLine("\n Journey warnings:");
14205
+ for (const problem of problems) writeLine(` ! ${problem}`);
14206
+ }
14207
+ /**
14208
+ * Problems that make the plan unwritable, found before the first write.
14209
+ *
14210
+ * The API validates each CEL when you save it, and its diagnosis is right —
14211
+ * but it fires per-write, so a plan whose edges reference a non-collection
14212
+ * form gets four labels, two forms, a workflow and six tasks created before
14213
+ * the seventh call rejects it. The operator is left with a half-built
14214
+ * program to hand-repair. Checking here costs nothing and writes nothing.
14215
+ *
14216
+ * Deliberately narrow: only cross-resource facts the builder can see with
14217
+ * certainty. Per-field CEL schema checking stays server-side, where the
14218
+ * real validator lives — duplicating it here would drift.
14219
+ */
14220
+ preflight() {
14221
+ const problems = [];
14222
+ const forms = this.resources.filter(
14223
+ (resource) => resource instanceof FormBuilder
14224
+ );
14225
+ const collectionBySlug = new Map(forms.map((form) => [form.slug, form.collection]));
14226
+ const reference = /assignment\.collections\.([A-Za-z0-9_]+)/g;
14227
+ for (const resource of this.sortedResources()) {
14228
+ if (!(resource instanceof TaskBuilder)) continue;
14229
+ for (const transition of resource.transitions) {
14230
+ const cel = transition.celCondition;
14231
+ if (!cel) continue;
14232
+ for (const [, slug] of cel.matchAll(reference)) {
14233
+ if (!collectionBySlug.has(slug)) continue;
14234
+ if (!collectionBySlug.get(slug)) {
14235
+ problems.push(
14236
+ `task '${transition.parent.name}' \u2192 '${transition.child.name}': CEL reads assignment.collections.${slug}, but this plan creates '${slug}' as a non-collection form. Declare it with { collection: true }.`
14237
+ );
14238
+ }
14239
+ }
14240
+ }
14241
+ }
14242
+ return [...new Set(problems)];
14243
+ }
13505
14244
  async apply() {
14245
+ const problems = this.preflight();
14246
+ if (problems.length) {
14247
+ writeLine("\nPlan rejected \u2014 nothing was created:");
14248
+ for (const problem of problems) writeLine(` ! ${problem}`);
14249
+ throw new Error(
14250
+ `Plan has ${problems.length} problem(s) and was not applied:
14251
+ ` + problems.map((problem) => ` - ${problem}`).join("\n")
14252
+ );
14253
+ }
13506
14254
  const resources = this.sortedResources();
13507
14255
  await this.resolveExisting(resources);
13508
14256
  const summary = {};
13509
14257
  writeLine("Applying...");
13510
14258
  for (const resource of resources) {
13511
14259
  try {
14260
+ if (resource.isImplicit) continue;
13512
14261
  if (resource._existed) {
13513
14262
  const key = resourceKey(resource);
13514
14263
  summary[key] ??= [];
@@ -13566,6 +14315,29 @@ Done! Created ${count} resources.`);
13566
14315
  }
13567
14316
  }
13568
14317
  }
14318
+ const filterNames = new Map(
14319
+ resources.filter(
14320
+ (resource) => resource instanceof MemberFilterBuilder
14321
+ ).map((resource) => [resource.name, resource])
14322
+ );
14323
+ if (filterNames.size) {
14324
+ for (const existing of await this.client.getMemberFilters()) {
14325
+ if (existing.name && filterNames.has(existing.name)) {
14326
+ filterNames.get(existing.name).adopt(existing);
14327
+ }
14328
+ }
14329
+ }
14330
+ const journeyNames = new Map(
14331
+ resources.filter((resource) => resource instanceof JourneyBuilder).map((resource) => [resource.name, resource])
14332
+ );
14333
+ if (journeyNames.size) {
14334
+ const existingJourneys = await this.client.getJourneys();
14335
+ for (const existing of existingJourneys.items) {
14336
+ if (!existing.name || !journeyNames.has(existing.name)) continue;
14337
+ const detail = await this.client.getJourney(existing.id);
14338
+ journeyNames.get(existing.name).adopt(detail);
14339
+ }
14340
+ }
13569
14341
  if (!workflowNames.size) return;
13570
14342
  const existingWorkflows = await this.client.getWorkflows();
13571
14343
  for (const { workflow: existing } of existingWorkflows.items) {
@@ -13616,9 +14388,7 @@ Done! Created ${count} resources.`);
13616
14388
  all.push(...resource.steps);
13617
14389
  }
13618
14390
  }
13619
- return all.sort(
13620
- (a, b) => (PHASES.get(a.constructor) ?? 99) - (PHASES.get(b.constructor) ?? 99)
13621
- );
14391
+ return all.sort((a, b) => phaseFor(a) - phaseFor(b));
13622
14392
  }
13623
14393
  collectWiringSummary(resources) {
13624
14394
  const lines = [];
@@ -13639,7 +14409,11 @@ Done! Created ${count} resources.`);
13639
14409
  lines.push(`${rule.actionType} rule on '${resource.name}'`);
13640
14410
  } else if (resource instanceof JourneyStepBuilder) {
13641
14411
  for (const connection of resource.connections) {
13642
- lines.push(`${connection.parent.name} -> ${connection.child.name}`);
14412
+ const guard = connection.condition ? ` [${connection.condition}]` : "";
14413
+ lines.push(`${connection.parent.name} -> ${connection.child.name}${guard}`);
14414
+ }
14415
+ for (const rule of resource.rules) {
14416
+ lines.push(`${rule.actionType} on step '${resource.name}'`);
13643
14417
  }
13644
14418
  } else if (resource instanceof JourneyBuilder) {
13645
14419
  for (const goal of resource.goals) lines.push(`Goal: ${goal.name}`);
@@ -13663,6 +14437,7 @@ Done! Created ${count} resources.`);
13663
14437
  const childTasks = transitions.flatMap((transition) => {
13664
14438
  const taskId = transition.child._id;
13665
14439
  if (taskId === void 0 || taskId === parent._id) return [];
14440
+ if (parent.existingChildIds.has(taskId)) return [];
13666
14441
  return [
13667
14442
  {
13668
14443
  taskId,
@@ -13755,6 +14530,10 @@ Done! Created ${count} resources.`);
13755
14530
  if (!(resource instanceof JourneyStepBuilder)) continue;
13756
14531
  for (const connection of resource.connections) {
13757
14532
  if (resource.journey._id === void 0) continue;
14533
+ if (resource.journey.hasEdge(connection.parent, connection.child)) {
14534
+ writeLine(` Exists: ${connection.parent.name} -> ${connection.child.name}`);
14535
+ continue;
14536
+ }
13758
14537
  const payload = buildJourneyConnectionPayload(connection);
13759
14538
  if (!payload) continue;
13760
14539
  await this.client.createConnection(resource.journey._id, payload);
@@ -13765,6 +14544,12 @@ Done! Created ${count} resources.`);
13765
14544
  async applyJourneyGoals(resources) {
13766
14545
  for (const resource of resources) {
13767
14546
  if (!(resource instanceof JourneyBuilder) || resource._id === void 0) continue;
14547
+ if (resource._existed) {
14548
+ for (const goal of resource.goals) {
14549
+ writeLine(` Skipped (journey already exists): Goal: ${goal.name}`);
14550
+ }
14551
+ continue;
14552
+ }
13768
14553
  for (const goal of resource.goals) {
13769
14554
  await this.client.createGoal(resource._id, buildJourneyGoalPayload(goal));
13770
14555
  writeLine(` Created goal: ${goal.name}`);
@@ -14175,7 +14960,9 @@ var AbilityConfigIssueCode = {
14175
14960
  invalid_state: "invalid_state",
14176
14961
  feature_disabled: "feature_disabled",
14177
14962
  missing_connection: "missing_connection",
14178
- external_drift: "external_drift"
14963
+ external_drift: "external_drift",
14964
+ missing_task_instructions: "missing_task_instructions",
14965
+ no_qualification_scenarios: "no_qualification_scenarios"
14179
14966
  };
14180
14967
  var AbilityConfigIssueSeverity = {
14181
14968
  warning: "warning",
@@ -14188,9 +14975,24 @@ var WorkflowAccessWarningResourceType = {
14188
14975
  calendar: "calendar"
14189
14976
  };
14190
14977
 
14978
+ // src/types/generated/workflow.ts
14979
+ var WorkflowRoutingMode = {
14980
+ open_world: "open_world",
14981
+ strict: "strict"
14982
+ };
14983
+
14191
14984
  // src/types/widget-domain-types.ts
14192
14985
  var WIDGET_SLUGS = ["chat", "operator", "operator-tools", "chat-app"];
14193
14986
 
14987
+ // src/types/generated/promo_code_service.ts
14988
+ var PromoCodeStatus = {
14989
+ active: "active",
14990
+ scheduled: "scheduled",
14991
+ expired: "expired",
14992
+ inactive: "inactive",
14993
+ exhausted: "exhausted"
14994
+ };
14995
+
14194
14996
  // src/features/registry.ts
14195
14997
  var FeatureCategory = /* @__PURE__ */ ((FeatureCategory2) => {
14196
14998
  FeatureCategory2["COMMUNICATION"] = "communication";
@@ -15181,6 +15983,7 @@ function getRevisionState(workflow, revision) {
15181
15983
  MemberType,
15182
15984
  MenuItemResponseItemType,
15183
15985
  MenuItemType,
15986
+ MergeMemberRolesRequestAccessStrategy,
15184
15987
  ModelProvider,
15185
15988
  ModelType,
15186
15989
  NO_ASSISTANT_PARTICIPANT_CHAT_TYPES,
@@ -15203,6 +16006,7 @@ function getRevisionState(workflow, revision) {
15203
16006
  PIDS_SOURCES,
15204
16007
  POSITIVE_RATING_THRESHOLD,
15205
16008
  ProductType,
16009
+ PromoCodeStatus,
15206
16010
  QUERY_VALUELESS_OPS,
15207
16011
  QueriesApi,
15208
16012
  REALTIME_MODEL_CUSTOM,
@@ -15243,10 +16047,14 @@ function getRevisionState(workflow, revision) {
15243
16047
  WorkflowAccessWarningResourceType,
15244
16048
  WorkflowBuilder,
15245
16049
  WorkflowResourceType,
16050
+ WorkflowRoutingMode,
15246
16051
  WorkspaceBuilder,
16052
+ WorkspaceBuilderResource,
15247
16053
  WorkspaceFeature,
15248
16054
  WorkspaceProvisionStatus,
16055
+ archivedMemberConflictId,
15249
16056
  areDependenciesSatisfied,
16057
+ asIdentifiedMemberContactConflict,
15250
16058
  canPreviewVoice,
15251
16059
  clearRegistry,
15252
16060
  createWorkspaceClient,
@@ -15270,9 +16078,12 @@ function getRevisionState(workflow, revision) {
15270
16078
  getTTSProvider,
15271
16079
  getVoiceModelId,
15272
16080
  initializeFeatures,
16081
+ isAccountContactConflict,
15273
16082
  isAgentNoteOrigin,
15274
16083
  isChatType,
15275
16084
  isFeatureAvailable,
16085
+ isIdentifiedMemberContactConflict,
16086
+ isMemberContactConflict,
15276
16087
  isPositiveRating,
15277
16088
  isRegistryInitialized,
15278
16089
  isSMSDeliveryFailureStatus,