@gravity-rail/sdk 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agui.cjs +13 -1
- package/dist/agui.cjs.map +1 -1
- package/dist/agui.d.cts +5 -1
- package/dist/agui.d.ts +5 -1
- package/dist/agui.js +12 -1
- package/dist/agui.js.map +1 -1
- package/dist/{chunk-QTJQTTIR.js → chunk-4B7T6MBH.js} +223 -7
- package/dist/chunk-4B7T6MBH.js.map +1 -0
- package/dist/{client-CefA5Mxe.d.ts → client-3xYGmF3t.d.ts} +1172 -10
- package/dist/{client-BLuz00Qr.d.cts → client-BhO_UFFz.d.cts} +1172 -10
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +545 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +164 -9
- package/dist/index.d.ts +164 -9
- package/dist/index.js +325 -22
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +248 -6
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +301 -6
- package/dist/internal.d.ts +301 -6
- package/dist/internal.js +26 -1
- package/dist/internal.js.map +1 -1
- package/dist/{revision-state-DL1ViZ57.d.ts → revision-state-Dma10N9s.d.ts} +4 -2
- package/dist/{revision-state-axZ62kJk.d.cts → revision-state-Dx8gCQIj.d.cts} +4 -2
- package/dist/schemas.cjs +9 -1
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +2 -2
- package/dist/schemas.d.ts +2 -2
- package/dist/schemas.js +9 -1
- package/dist/schemas.js.map +1 -1
- package/dist/{tasks-Boi6AxGp.d.cts → tasks-vupYoJgG.d.cts} +11 -9
- package/dist/{tasks-Boi6AxGp.d.ts → tasks-vupYoJgG.d.ts} +11 -9
- package/package.json +2 -2
- package/dist/chunk-QTJQTTIR.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -110,6 +110,7 @@ __export(src_exports, {
|
|
|
110
110
|
PIDS_SOURCES: () => PIDS_SOURCES,
|
|
111
111
|
POSITIVE_RATING_THRESHOLD: () => POSITIVE_RATING_THRESHOLD,
|
|
112
112
|
ProductType: () => ProductType,
|
|
113
|
+
PromoCodeStatus: () => PromoCodeStatus,
|
|
113
114
|
QUERY_VALUELESS_OPS: () => QUERY_VALUELESS_OPS,
|
|
114
115
|
QueriesApi: () => QueriesApi,
|
|
115
116
|
REALTIME_MODEL_CUSTOM: () => REALTIME_MODEL_CUSTOM,
|
|
@@ -151,6 +152,7 @@ __export(src_exports, {
|
|
|
151
152
|
WorkflowBuilder: () => WorkflowBuilder,
|
|
152
153
|
WorkflowResourceType: () => WorkflowAccessWarningResourceType,
|
|
153
154
|
WorkspaceBuilder: () => WorkspaceBuilder,
|
|
155
|
+
WorkspaceBuilderResource: () => WorkspaceBuilderResource,
|
|
154
156
|
WorkspaceFeature: () => WorkspaceFeature,
|
|
155
157
|
WorkspaceProvisionStatus: () => WorkspaceProvisionStatus,
|
|
156
158
|
areDependenciesSatisfied: () => areDependenciesSatisfied,
|
|
@@ -924,6 +926,18 @@ var AIModelsApi = class extends BaseApiClient {
|
|
|
924
926
|
const url = queryString ? `ai-models/realtime?${queryString}` : "ai-models/realtime";
|
|
925
927
|
return this.fetch(url);
|
|
926
928
|
}
|
|
929
|
+
/**
|
|
930
|
+
* Get the voice presets offered by the simplified voice picker.
|
|
931
|
+
*
|
|
932
|
+
* A preset bundles a realtime speech-to-speech model with one of its native
|
|
933
|
+
* voices and the settings recommended alongside it, so choosing a voice is
|
|
934
|
+
* a single decision. Apply one by assigning its `config` wholesale; compare
|
|
935
|
+
* against it to tell a preset selection from a customised ("Custom") one.
|
|
936
|
+
* The full engine/voice/settings matrix lives on `getRealtimeModels`.
|
|
937
|
+
*/
|
|
938
|
+
async getVoicePresets() {
|
|
939
|
+
return this.fetch("ai-models/voice-presets");
|
|
940
|
+
}
|
|
927
941
|
/**
|
|
928
942
|
* Get available voice models with metadata
|
|
929
943
|
*/
|
|
@@ -2053,6 +2067,10 @@ var ChatsApi = class extends BaseApiClient {
|
|
|
2053
2067
|
`w/${wid}/chats/${chatId}/skills`
|
|
2054
2068
|
);
|
|
2055
2069
|
}
|
|
2070
|
+
/** List built-in skills that can be selected before starting a Manager Chat. */
|
|
2071
|
+
async getManagerSkills(wid) {
|
|
2072
|
+
return this.fetch(`w/${wid}/chats/manager/skills`);
|
|
2073
|
+
}
|
|
2056
2074
|
/** List chat IDs that need a response. */
|
|
2057
2075
|
async getChatsNeedsResponse(wid) {
|
|
2058
2076
|
return this.fetch(`w/${wid}/chats/needs-response`);
|
|
@@ -3680,9 +3698,9 @@ var DocumoFaxApi = class extends BaseApiClient {
|
|
|
3680
3698
|
params?.status?.forEach((value) => query.append("status", value));
|
|
3681
3699
|
if (params?.receivedAfter) query.set("receivedAfter", params.receivedAfter);
|
|
3682
3700
|
if (params?.receivedBefore) query.set("receivedBefore", params.receivedBefore);
|
|
3683
|
-
const
|
|
3701
|
+
const suffix2 = query.toString() === "" ? "" : `?${query.toString()}`;
|
|
3684
3702
|
return this.fetch(
|
|
3685
|
-
`w/${wid}/app-connections/documo-fax/faxes${
|
|
3703
|
+
`w/${wid}/app-connections/documo-fax/faxes${suffix2}`
|
|
3686
3704
|
);
|
|
3687
3705
|
}
|
|
3688
3706
|
/**
|
|
@@ -5756,15 +5774,19 @@ var OrgApi = class extends BaseApiClient {
|
|
|
5756
5774
|
async getA2PStatus(orgUuid) {
|
|
5757
5775
|
return this.fetch(`o/${orgUuid}/phone-numbers/a2p/status`);
|
|
5758
5776
|
}
|
|
5777
|
+
/** Return fixed phone-number and outbound-messaging prices. */
|
|
5778
|
+
async getPhoneBillingPricing(orgUuid) {
|
|
5779
|
+
return this.fetch(`o/${orgUuid}/phone-numbers/pricing`);
|
|
5780
|
+
}
|
|
5759
5781
|
/**
|
|
5760
5782
|
* Start A2P brand registration under a legal entity. `legalEntityUuid`
|
|
5761
5783
|
* is required — brands register per legal entity (Customer Profile);
|
|
5762
5784
|
* there is no primary-entity fallback.
|
|
5763
5785
|
*/
|
|
5764
|
-
async startA2PRegistration(orgUuid, legalEntityUuid, brandName, brandDescription) {
|
|
5786
|
+
async startA2PRegistration(orgUuid, legalEntityUuid, brandName, brandDescription, brandUuid = null) {
|
|
5765
5787
|
return this.fetch(`o/${orgUuid}/phone-numbers/a2p/start`, {
|
|
5766
5788
|
method: "POST",
|
|
5767
|
-
body: JSON.stringify({ legalEntityUuid, brandName, brandDescription })
|
|
5789
|
+
body: JSON.stringify({ legalEntityUuid, brandName, brandDescription, brandUuid })
|
|
5768
5790
|
});
|
|
5769
5791
|
}
|
|
5770
5792
|
/**
|
|
@@ -5970,14 +5992,34 @@ var OrgApi = class extends BaseApiClient {
|
|
|
5970
5992
|
);
|
|
5971
5993
|
}
|
|
5972
5994
|
/**
|
|
5973
|
-
* The brand
|
|
5974
|
-
*
|
|
5995
|
+
* The brand's enrollment-form template URL (carries `?brand=…`, no
|
|
5996
|
+
* credential). `url` is null until a Site is linked. Do not append a
|
|
5997
|
+
* patient identifier to this URL — use {@link mintA2PBrandEnrollmentLink}
|
|
5998
|
+
* to get a patient-ready link instead.
|
|
5975
5999
|
*/
|
|
5976
6000
|
async getA2PBrandEnrollmentUrl(orgUuid, brandUuid) {
|
|
5977
6001
|
return this.fetch(
|
|
5978
6002
|
`o/${orgUuid}/a2p-brands/${brandUuid}/enrollment-url`
|
|
5979
6003
|
);
|
|
5980
6004
|
}
|
|
6005
|
+
/**
|
|
6006
|
+
* Mint a patient-ready enrollment link for one patient.
|
|
6007
|
+
*
|
|
6008
|
+
* The returned URL carries a fresh, expiring, single-use `?grant=…` bound to
|
|
6009
|
+
* the member that `externalId` resolves to. `externalId` (the patient's
|
|
6010
|
+
* CRM/EHR identifier) travels in the request body, never the query string,
|
|
6011
|
+
* so it stays out of access logs. When it matches no member, the
|
|
6012
|
+
* credential-free template URL is returned rather than an error.
|
|
6013
|
+
*/
|
|
6014
|
+
async mintA2PBrandEnrollmentLink(orgUuid, brandUuid, externalId) {
|
|
6015
|
+
return this.fetch(
|
|
6016
|
+
`o/${orgUuid}/a2p-brands/${brandUuid}/enrollment-url`,
|
|
6017
|
+
{
|
|
6018
|
+
method: "POST",
|
|
6019
|
+
body: JSON.stringify({ externalId })
|
|
6020
|
+
}
|
|
6021
|
+
);
|
|
6022
|
+
}
|
|
5981
6023
|
/**
|
|
5982
6024
|
* List available member roles for a workspace in the organization.
|
|
5983
6025
|
*/
|
|
@@ -7780,6 +7822,118 @@ var ToolkitsApi = class extends BaseApiClient {
|
|
|
7780
7822
|
}
|
|
7781
7823
|
};
|
|
7782
7824
|
|
|
7825
|
+
// src/api/tracked-links.ts
|
|
7826
|
+
function withFilters(params, options) {
|
|
7827
|
+
if (options.dateFrom) params.append("dateFrom", options.dateFrom);
|
|
7828
|
+
if (options.dateTo) params.append("dateTo", options.dateTo);
|
|
7829
|
+
if (options.workflowId !== void 0) params.append("workflowId", String(options.workflowId));
|
|
7830
|
+
return params;
|
|
7831
|
+
}
|
|
7832
|
+
function suffix(params) {
|
|
7833
|
+
const query = params.toString();
|
|
7834
|
+
return query ? `?${query}` : "";
|
|
7835
|
+
}
|
|
7836
|
+
var TrackedLinksApi = class extends BaseApiClient {
|
|
7837
|
+
/** Header counters plus whether shortening is configured and enabled. */
|
|
7838
|
+
async getTrackedLinkSummary(wid, options = {}) {
|
|
7839
|
+
const params = withFilters(new URLSearchParams(), options);
|
|
7840
|
+
return this.fetch(
|
|
7841
|
+
`w/${wid}/tracked-links/summary${suffix(params)}`
|
|
7842
|
+
);
|
|
7843
|
+
}
|
|
7844
|
+
/**
|
|
7845
|
+
* Known destination URLs, most recent first. Powers the "Clicked link"
|
|
7846
|
+
* member-filter autocomplete, so it stays unaggregated and cheap.
|
|
7847
|
+
*/
|
|
7848
|
+
async getTrackedLinkDestinations(wid, options = {}) {
|
|
7849
|
+
const params = new URLSearchParams();
|
|
7850
|
+
if (options.q) params.append("q", options.q);
|
|
7851
|
+
if (options.limit !== void 0) params.append("limit", String(options.limit));
|
|
7852
|
+
return this.fetch(
|
|
7853
|
+
`w/${wid}/tracked-links/destinations${suffix(params)}`
|
|
7854
|
+
);
|
|
7855
|
+
}
|
|
7856
|
+
/**
|
|
7857
|
+
* Register a destination an author can reference as `{{links.<key>}}`.
|
|
7858
|
+
*
|
|
7859
|
+
* The URL is deduplicated server-side, so registering one the workspace
|
|
7860
|
+
* already knows adopts that destination — including a row the retired
|
|
7861
|
+
* auto-harvest left unnamed, whose click history then carries forward
|
|
7862
|
+
* under the new key. Registering a URL that already has a *different* key
|
|
7863
|
+
* is a 409: renaming is what `updateTrackedLinkDestination` is for.
|
|
7864
|
+
*
|
|
7865
|
+
* Keys use the same grammar as snippet keys: lowercase letters, digits,
|
|
7866
|
+
* underscores and dots, starting with a letter (`intake_form`,
|
|
7867
|
+
* `docs.privacy`). No hyphens — Jinja2 reads `links.spring-2026` as
|
|
7868
|
+
* subtraction.
|
|
7869
|
+
*/
|
|
7870
|
+
async createTrackedLinkDestination(wid, data) {
|
|
7871
|
+
return this.fetch(`w/${wid}/tracked-links/destinations`, {
|
|
7872
|
+
method: "POST",
|
|
7873
|
+
body: JSON.stringify(data)
|
|
7874
|
+
});
|
|
7875
|
+
}
|
|
7876
|
+
/**
|
|
7877
|
+
* Re-key or relabel a destination.
|
|
7878
|
+
*
|
|
7879
|
+
* Changing `key` breaks templates: `{{links.old}}` stops resolving and the
|
|
7880
|
+
* message ships without its link. Relabelling (`name`) is always safe.
|
|
7881
|
+
* Passing `key: null` releases the handle so another destination can take
|
|
7882
|
+
* it — the non-destructive alternative to deleting, which would take the
|
|
7883
|
+
* click history with it. The URL is not editable.
|
|
7884
|
+
*/
|
|
7885
|
+
async updateTrackedLinkDestination(wid, destinationId, data) {
|
|
7886
|
+
return this.fetch(
|
|
7887
|
+
`w/${wid}/tracked-links/destinations/${destinationId}`,
|
|
7888
|
+
{ method: "PUT", body: JSON.stringify(data) }
|
|
7889
|
+
);
|
|
7890
|
+
}
|
|
7891
|
+
/** Per-destination sent / clicks / unique clickers / CTR for the window. */
|
|
7892
|
+
async getTrackedLinkStats(wid, options = {}) {
|
|
7893
|
+
const params = withFilters(new URLSearchParams(), options);
|
|
7894
|
+
if (options.page !== void 0) params.append("page", String(options.page));
|
|
7895
|
+
if (options.pageSize !== void 0) params.append("pageSize", String(options.pageSize));
|
|
7896
|
+
if (options.q) params.append("q", options.q);
|
|
7897
|
+
if (options.sortBy) params.append("sortBy", options.sortBy);
|
|
7898
|
+
if (options.sortOrder) params.append("sortOrder", options.sortOrder);
|
|
7899
|
+
return this.fetch(
|
|
7900
|
+
`w/${wid}/tracked-links${suffix(params)}`
|
|
7901
|
+
);
|
|
7902
|
+
}
|
|
7903
|
+
/** Clicks over time for the current filter selection. */
|
|
7904
|
+
async getTrackedLinkTimeseries(wid, options = {}) {
|
|
7905
|
+
const params = withFilters(new URLSearchParams(), options);
|
|
7906
|
+
if (options.destinationId !== void 0) {
|
|
7907
|
+
params.append("destinationId", String(options.destinationId));
|
|
7908
|
+
}
|
|
7909
|
+
if (options.granularity) params.append("granularity", options.granularity);
|
|
7910
|
+
if (options.tz) params.append("tz", options.tz);
|
|
7911
|
+
return this.fetch(
|
|
7912
|
+
`w/${wid}/tracked-links/timeseries${suffix(params)}`
|
|
7913
|
+
);
|
|
7914
|
+
}
|
|
7915
|
+
/**
|
|
7916
|
+
* Delete one destination: its short links stop resolving and its recorded
|
|
7917
|
+
* clicks are removed.
|
|
7918
|
+
*
|
|
7919
|
+
* Turning the workspace setting off only stops NEW links being minted —
|
|
7920
|
+
* links already delivered to members keep working. This is the deliberate
|
|
7921
|
+
* way to break them.
|
|
7922
|
+
*/
|
|
7923
|
+
async deleteTrackedLinkDestination(wid, destinationId) {
|
|
7924
|
+
return this.fetch(
|
|
7925
|
+
`w/${wid}/tracked-links/destinations/${destinationId}`,
|
|
7926
|
+
{ method: "DELETE" }
|
|
7927
|
+
);
|
|
7928
|
+
}
|
|
7929
|
+
/** Delete every destination, its links, and its clicks. Irreversible. */
|
|
7930
|
+
async clearTrackedLinkDestinations(wid) {
|
|
7931
|
+
return this.fetch(`w/${wid}/tracked-links/destinations`, {
|
|
7932
|
+
method: "DELETE"
|
|
7933
|
+
});
|
|
7934
|
+
}
|
|
7935
|
+
};
|
|
7936
|
+
|
|
7783
7937
|
// src/api/journeys.ts
|
|
7784
7938
|
var JourneysApi = class extends BaseApiClient {
|
|
7785
7939
|
/**
|
|
@@ -8605,6 +8759,7 @@ var EventRuleEventType = /* @__PURE__ */ ((EventRuleEventType2) => {
|
|
|
8605
8759
|
EventRuleEventType2["DATA_RECORD_UPDATED"] = "data_record:updated";
|
|
8606
8760
|
EventRuleEventType2["DATA_RECORD_CHANGED"] = "data_record:changed";
|
|
8607
8761
|
EventRuleEventType2["CHAT_CREATED"] = "chat:created";
|
|
8762
|
+
EventRuleEventType2["CHAT_SUMMARY"] = "chat:summary";
|
|
8608
8763
|
EventRuleEventType2["CHAT_CALLBACK"] = "chat:callback";
|
|
8609
8764
|
EventRuleEventType2["MEMBER_UPDATED"] = "member:updated";
|
|
8610
8765
|
EventRuleEventType2["ROUTINE_TRIGGERED"] = "routine:triggered";
|
|
@@ -9370,6 +9525,20 @@ var WorkspacesApi = class extends BaseApiClient {
|
|
|
9370
9525
|
if (featured !== void 0) params.set("featured", String(featured));
|
|
9371
9526
|
return this.fetch(`products?${params.toString()}`);
|
|
9372
9527
|
}
|
|
9528
|
+
/**
|
|
9529
|
+
* Check whether a promo code is usable, without redeeming it.
|
|
9530
|
+
*
|
|
9531
|
+
* Reserves nothing, so it is safe to call as a form field settles. Redemption
|
|
9532
|
+
* happens server-side after checkout completes, when the organization and its
|
|
9533
|
+
* subscription exist.
|
|
9534
|
+
*/
|
|
9535
|
+
async previewPromoCode(code, options) {
|
|
9536
|
+
return this.fetch("promo-codes/preview", {
|
|
9537
|
+
method: "POST",
|
|
9538
|
+
body: JSON.stringify({ code }),
|
|
9539
|
+
signal: options?.signal
|
|
9540
|
+
});
|
|
9541
|
+
}
|
|
9373
9542
|
/** Get a publicly accessible product by ID. */
|
|
9374
9543
|
async getPublicProduct(id) {
|
|
9375
9544
|
return this.fetch(`products/${id}`);
|
|
@@ -9589,6 +9758,7 @@ function createApiModules(apiKey, baseUrl, customFetch) {
|
|
|
9589
9758
|
members: new MembersApi(apiKey, baseUrl, customFetch),
|
|
9590
9759
|
milestones: new MilestonesApi(apiKey, baseUrl, customFetch),
|
|
9591
9760
|
motd: new MotdApi(apiKey, baseUrl, customFetch),
|
|
9761
|
+
trackedLinks: new TrackedLinksApi(apiKey, baseUrl, customFetch),
|
|
9592
9762
|
confluence: new ConfluenceApi(apiKey, baseUrl, customFetch),
|
|
9593
9763
|
mondayIntegration: new MondayIntegrationApi(apiKey, baseUrl, customFetch),
|
|
9594
9764
|
notificationRules: new NotificationRulesApi(apiKey, baseUrl, customFetch),
|
|
@@ -9654,6 +9824,7 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
9654
9824
|
"checkSiteSlugAvailability",
|
|
9655
9825
|
"clearConnectionMemberExclusion",
|
|
9656
9826
|
"clearMemberSwitch",
|
|
9827
|
+
"clearTrackedLinkDestinations",
|
|
9657
9828
|
"clickWorkspaceSupportRequestResource",
|
|
9658
9829
|
"cloneDataType",
|
|
9659
9830
|
"cloneTask",
|
|
@@ -9729,6 +9900,7 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
9729
9900
|
"createSupervisor",
|
|
9730
9901
|
"createTask",
|
|
9731
9902
|
"createTeamsApp",
|
|
9903
|
+
"createTrackedLinkDestination",
|
|
9732
9904
|
"createWorkflow",
|
|
9733
9905
|
"createWorkflowContributor",
|
|
9734
9906
|
"createWorkflowFromTemplate",
|
|
@@ -9794,6 +9966,7 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
9794
9966
|
"deleteSupervisor",
|
|
9795
9967
|
"deleteTask",
|
|
9796
9968
|
"deleteTeamsApp",
|
|
9969
|
+
"deleteTrackedLinkDestination",
|
|
9797
9970
|
"deleteWidgetDomain",
|
|
9798
9971
|
"deleteWorkflow",
|
|
9799
9972
|
"deleteWorkflowContributor",
|
|
@@ -9918,6 +10091,7 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
9918
10091
|
"getChatModelOverride",
|
|
9919
10092
|
"getChatPhoneCalls",
|
|
9920
10093
|
"getChatSkills",
|
|
10094
|
+
"getManagerSkills",
|
|
9921
10095
|
"getChatTodos",
|
|
9922
10096
|
"getChatTokenUsage",
|
|
9923
10097
|
"getChatToolCallMessages",
|
|
@@ -10098,6 +10272,7 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
10098
10272
|
"getPublicFolder",
|
|
10099
10273
|
"getPublicFolderFiles",
|
|
10100
10274
|
"getPublicProducts",
|
|
10275
|
+
"previewPromoCode",
|
|
10101
10276
|
"getQualification",
|
|
10102
10277
|
"getQualifications",
|
|
10103
10278
|
"getRecordingInfo",
|
|
@@ -10144,6 +10319,10 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
10144
10319
|
"getTool",
|
|
10145
10320
|
"getToolCallNames",
|
|
10146
10321
|
"getToolkits",
|
|
10322
|
+
"getTrackedLinkDestinations",
|
|
10323
|
+
"getTrackedLinkStats",
|
|
10324
|
+
"getTrackedLinkSummary",
|
|
10325
|
+
"getTrackedLinkTimeseries",
|
|
10147
10326
|
"getUnreadNotificationCount",
|
|
10148
10327
|
"getUsageDashboard",
|
|
10149
10328
|
"getVariableRegistry",
|
|
@@ -10378,6 +10557,7 @@ var WORKSPACE_METHOD_NAMES = [
|
|
|
10378
10557
|
"updateTask",
|
|
10379
10558
|
"updateTeamsApp",
|
|
10380
10559
|
"updateThemeSettings",
|
|
10560
|
+
"updateTrackedLinkDestination",
|
|
10381
10561
|
"uploadFile",
|
|
10382
10562
|
"updateVoicemailStatus",
|
|
10383
10563
|
"updateWorkflow",
|
|
@@ -10475,6 +10655,7 @@ function bindChatsMethods(target, chats) {
|
|
|
10475
10655
|
target.getChatTokenUsage = chats.getChatTokenUsage.bind(chats);
|
|
10476
10656
|
target.getChatTodos = chats.getChatTodos.bind(chats);
|
|
10477
10657
|
target.getChatSkills = chats.getChatSkills.bind(chats);
|
|
10658
|
+
target.getManagerSkills = chats.getManagerSkills.bind(chats);
|
|
10478
10659
|
target.getChatsNeedsResponse = chats.getChatsNeedsResponse.bind(chats);
|
|
10479
10660
|
target.getChatsDailyCreationStats = chats.getChatsDailyCreationStats.bind(chats);
|
|
10480
10661
|
target.getToolCallNames = chats.getToolCallNames.bind(chats);
|
|
@@ -10548,6 +10729,18 @@ function bindMotdMethods(target, motd) {
|
|
|
10548
10729
|
target.getMotd = motd.getMotd.bind(motd);
|
|
10549
10730
|
}
|
|
10550
10731
|
|
|
10732
|
+
// src/client/bindings/tracked-links.ts
|
|
10733
|
+
function bindTrackedLinksMethods(target, trackedLinks) {
|
|
10734
|
+
target.getTrackedLinkSummary = trackedLinks.getTrackedLinkSummary.bind(trackedLinks);
|
|
10735
|
+
target.getTrackedLinkDestinations = trackedLinks.getTrackedLinkDestinations.bind(trackedLinks);
|
|
10736
|
+
target.getTrackedLinkStats = trackedLinks.getTrackedLinkStats.bind(trackedLinks);
|
|
10737
|
+
target.getTrackedLinkTimeseries = trackedLinks.getTrackedLinkTimeseries.bind(trackedLinks);
|
|
10738
|
+
target.createTrackedLinkDestination = trackedLinks.createTrackedLinkDestination.bind(trackedLinks);
|
|
10739
|
+
target.updateTrackedLinkDestination = trackedLinks.updateTrackedLinkDestination.bind(trackedLinks);
|
|
10740
|
+
target.deleteTrackedLinkDestination = trackedLinks.deleteTrackedLinkDestination.bind(trackedLinks);
|
|
10741
|
+
target.clearTrackedLinkDestinations = trackedLinks.clearTrackedLinkDestinations.bind(trackedLinks);
|
|
10742
|
+
}
|
|
10743
|
+
|
|
10551
10744
|
// src/client/bindings/data-types.ts
|
|
10552
10745
|
function bindDataTypesMethods(target, dataTypes) {
|
|
10553
10746
|
target.getDataTypes = dataTypes.getDataTypes.bind(dataTypes);
|
|
@@ -11043,6 +11236,7 @@ function bindToolkitsMethods(target, toolkits, templates, aiModels, customToolki
|
|
|
11043
11236
|
target.getSTTModels = aiModels.getSTTModels.bind(aiModels);
|
|
11044
11237
|
target.getTTSModels = aiModels.getTTSModels.bind(aiModels);
|
|
11045
11238
|
target.getVoiceModels = aiModels.getVoiceModels.bind(aiModels);
|
|
11239
|
+
target.getVoicePresets = aiModels.getVoicePresets.bind(aiModels);
|
|
11046
11240
|
target.getAllModels = aiModels.getAllModels.bind(aiModels);
|
|
11047
11241
|
target.getCustomToolkits = customToolkits.getCustomToolkits.bind(customToolkits);
|
|
11048
11242
|
target.getCustomToolkit = customToolkits.getCustomToolkit.bind(customToolkits);
|
|
@@ -11514,6 +11708,7 @@ var GravityRailClient = class {
|
|
|
11514
11708
|
getChatTokenUsage;
|
|
11515
11709
|
getChatTodos;
|
|
11516
11710
|
getChatSkills;
|
|
11711
|
+
getManagerSkills;
|
|
11517
11712
|
getChatsNeedsResponse;
|
|
11518
11713
|
getChatsDailyCreationStats;
|
|
11519
11714
|
getToolCallNames;
|
|
@@ -11701,6 +11896,15 @@ var GravityRailClient = class {
|
|
|
11701
11896
|
getDashboardWorkflowAssignmentStats;
|
|
11702
11897
|
// MOTD API
|
|
11703
11898
|
getMotd;
|
|
11899
|
+
// Tracked Links analytics (#10934)
|
|
11900
|
+
getTrackedLinkSummary;
|
|
11901
|
+
getTrackedLinkDestinations;
|
|
11902
|
+
getTrackedLinkStats;
|
|
11903
|
+
getTrackedLinkTimeseries;
|
|
11904
|
+
createTrackedLinkDestination;
|
|
11905
|
+
updateTrackedLinkDestination;
|
|
11906
|
+
deleteTrackedLinkDestination;
|
|
11907
|
+
clearTrackedLinkDestinations;
|
|
11704
11908
|
// Journeys API
|
|
11705
11909
|
getJourneys;
|
|
11706
11910
|
getJourney;
|
|
@@ -11805,6 +12009,7 @@ var GravityRailClient = class {
|
|
|
11805
12009
|
getProduct;
|
|
11806
12010
|
getWorkspaceProduct;
|
|
11807
12011
|
getPublicProducts;
|
|
12012
|
+
previewPromoCode;
|
|
11808
12013
|
getPublicProduct;
|
|
11809
12014
|
createProduct;
|
|
11810
12015
|
updateProduct;
|
|
@@ -12159,6 +12364,7 @@ var GravityRailClient = class {
|
|
|
12159
12364
|
getSTTModels;
|
|
12160
12365
|
getTTSModels;
|
|
12161
12366
|
getVoiceModels;
|
|
12367
|
+
getVoicePresets;
|
|
12162
12368
|
getAllModels;
|
|
12163
12369
|
getCustomToolkits;
|
|
12164
12370
|
getCustomToolkit;
|
|
@@ -12489,6 +12695,7 @@ var GravityRailClient = class {
|
|
|
12489
12695
|
bindQueriesMethods(this, apis.queries);
|
|
12490
12696
|
bindDashboardsMethods(this, apis.dashboards);
|
|
12491
12697
|
bindMotdMethods(this, apis.motd);
|
|
12698
|
+
bindTrackedLinksMethods(this, apis.trackedLinks);
|
|
12492
12699
|
bindJourneysMethods(this, apis.journeys);
|
|
12493
12700
|
bindExperimentsMethods(this, apis.experiments);
|
|
12494
12701
|
bindOperatorMethods(this, apis.operatorGroups);
|
|
@@ -12681,6 +12888,14 @@ var WorkspaceBuilderResource = class {
|
|
|
12681
12888
|
}
|
|
12682
12889
|
return this._uuid;
|
|
12683
12890
|
}
|
|
12891
|
+
/**
|
|
12892
|
+
* True for resources the server creates on our behalf (currently a
|
|
12893
|
+
* journey's `Start` step). They are kept in the resource list so edges can
|
|
12894
|
+
* reference them, but they are never created, printed, or counted.
|
|
12895
|
+
*/
|
|
12896
|
+
get isImplicit() {
|
|
12897
|
+
return false;
|
|
12898
|
+
}
|
|
12684
12899
|
matchKey() {
|
|
12685
12900
|
return void 0;
|
|
12686
12901
|
}
|
|
@@ -12703,6 +12918,19 @@ function resolveRefValue(value) {
|
|
|
12703
12918
|
}
|
|
12704
12919
|
return out;
|
|
12705
12920
|
}
|
|
12921
|
+
function resolveIdRefs(value) {
|
|
12922
|
+
return resolveIdRefValue(value);
|
|
12923
|
+
}
|
|
12924
|
+
function resolveIdRefValue(value) {
|
|
12925
|
+
if (value instanceof WorkspaceBuilderResource) return value.id;
|
|
12926
|
+
if (Array.isArray(value)) return value.map(resolveIdRefValue);
|
|
12927
|
+
if (!isPlainRecord(value)) return value;
|
|
12928
|
+
const out = {};
|
|
12929
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
12930
|
+
out[key] = resolveIdRefValue(nestedValue);
|
|
12931
|
+
}
|
|
12932
|
+
return out;
|
|
12933
|
+
}
|
|
12706
12934
|
|
|
12707
12935
|
// src/workspace-builder/automation.ts
|
|
12708
12936
|
var MemberFilterBuilder = class extends WorkspaceBuilderResource {
|
|
@@ -12716,7 +12944,12 @@ var MemberFilterBuilder = class extends WorkspaceBuilderResource {
|
|
|
12716
12944
|
description;
|
|
12717
12945
|
/** Query-engine predicate (JSON IR) authored on MemberFilter.query. */
|
|
12718
12946
|
query = null;
|
|
12719
|
-
/**
|
|
12947
|
+
/**
|
|
12948
|
+
* Set the filter's query-engine predicate (JSON IR).
|
|
12949
|
+
*
|
|
12950
|
+
* Anywhere the IR wants a numeric id you may pass the builder that will own
|
|
12951
|
+
* it (e.g. a label in a `member.labelId` value); refs resolve at apply time.
|
|
12952
|
+
*/
|
|
12720
12953
|
setQuery(query) {
|
|
12721
12954
|
this.query = query;
|
|
12722
12955
|
return this;
|
|
@@ -12725,10 +12958,12 @@ var MemberFilterBuilder = class extends WorkspaceBuilderResource {
|
|
|
12725
12958
|
return `MemberFilter: ${this.name}${this.query ? " (query)" : ""}`;
|
|
12726
12959
|
}
|
|
12727
12960
|
async apply(client) {
|
|
12961
|
+
if (this._existed) return;
|
|
12728
12962
|
const payload = {
|
|
12729
12963
|
name: this.name,
|
|
12730
12964
|
description: this.description,
|
|
12731
|
-
|
|
12965
|
+
// Builder refs inside the IR become ids here; see resolveIdRefs.
|
|
12966
|
+
query: resolveIdRefs(this.query)
|
|
12732
12967
|
};
|
|
12733
12968
|
const result = await client.createMemberFilter(payload);
|
|
12734
12969
|
this._id = result.id;
|
|
@@ -13023,35 +13258,134 @@ var MemberLabelBuilder = class extends WorkspaceBuilderResource {
|
|
|
13023
13258
|
};
|
|
13024
13259
|
|
|
13025
13260
|
// src/workspace-builder/journeys.ts
|
|
13261
|
+
var SECONDS_PER_DAY = 86400;
|
|
13262
|
+
function edgeKey(parentId, childId) {
|
|
13263
|
+
return `${parentId}:${childId}`;
|
|
13264
|
+
}
|
|
13265
|
+
function edgeCondition(options) {
|
|
13266
|
+
const clauses = [];
|
|
13267
|
+
if (options.afterDays !== void 0) {
|
|
13268
|
+
clauses.push(`days_since(parent_step.completed_at) >= ${options.afterDays}`);
|
|
13269
|
+
}
|
|
13270
|
+
if (options.when) clauses.push(`(${options.when})`);
|
|
13271
|
+
if (!clauses.length) return void 0;
|
|
13272
|
+
return clauses.join(" && ");
|
|
13273
|
+
}
|
|
13026
13274
|
var JourneyStepBuilder = class extends WorkspaceBuilderResource {
|
|
13027
13275
|
// journey-decoupling Phase 7: a Journey step no longer links to a Workflow.
|
|
13028
13276
|
// A step nudges via EventRule actions instead of running a Workflow, so the
|
|
13029
13277
|
// builder no longer accepts or emits a workflow reference.
|
|
13030
|
-
constructor(name, journey, order = 0, description = "") {
|
|
13278
|
+
constructor(name, journey, order = 0, description = "", options = {}) {
|
|
13031
13279
|
super();
|
|
13032
13280
|
this.name = name;
|
|
13033
13281
|
this.journey = journey;
|
|
13034
13282
|
this.order = order;
|
|
13035
13283
|
this.description = description;
|
|
13284
|
+
this.assigneeId = options.assigneeId;
|
|
13285
|
+
this.posX = options.posX;
|
|
13286
|
+
this.posY = options.posY;
|
|
13036
13287
|
}
|
|
13037
13288
|
name;
|
|
13038
13289
|
journey;
|
|
13039
13290
|
order;
|
|
13040
13291
|
description;
|
|
13041
13292
|
connections = [];
|
|
13042
|
-
|
|
13043
|
-
|
|
13293
|
+
rules = [];
|
|
13294
|
+
assigneeId;
|
|
13295
|
+
posX;
|
|
13296
|
+
posY;
|
|
13297
|
+
/** Wire an edge to `child` and return the CHILD, so chains read linearly. */
|
|
13298
|
+
connectsTo(child, options = {}) {
|
|
13299
|
+
if (child === this) {
|
|
13300
|
+
throw new Error(`Journey step '${this.name}' cannot connect to itself`);
|
|
13301
|
+
}
|
|
13302
|
+
const abandonSeconds = options.abandonAfterDays !== void 0 ? options.abandonAfterDays * SECONDS_PER_DAY : options.timeoutSeconds;
|
|
13303
|
+
this.connections.push({
|
|
13304
|
+
parent: this,
|
|
13305
|
+
child,
|
|
13306
|
+
condition: edgeCondition(options),
|
|
13307
|
+
required: options.required ?? false,
|
|
13308
|
+
timeoutSeconds: abandonSeconds,
|
|
13309
|
+
order: options.order,
|
|
13310
|
+
filterId: options.filterId
|
|
13311
|
+
});
|
|
13312
|
+
return child;
|
|
13313
|
+
}
|
|
13314
|
+
/**
|
|
13315
|
+
* Attach a `JOURNEY_STEP_EXECUTE` action — what this step actually DOES
|
|
13316
|
+
* when a member reaches it. A step with no rules is inert: the member
|
|
13317
|
+
* lands on it, nothing is sent, and the journey moves on.
|
|
13318
|
+
*/
|
|
13319
|
+
onExecute(actionType, params = {}, options = {}) {
|
|
13320
|
+
this.rules.push({
|
|
13321
|
+
uuid: crypto.randomUUID(),
|
|
13322
|
+
actionType,
|
|
13323
|
+
actionParams: params,
|
|
13324
|
+
options
|
|
13325
|
+
});
|
|
13044
13326
|
return this;
|
|
13045
13327
|
}
|
|
13328
|
+
/**
|
|
13329
|
+
* Text the member. `phoneNumberUUID` is a workspace PhoneNumber with SMS
|
|
13330
|
+
* enabled. Pass `workflowUUID` to start an SMS workflow chat, or
|
|
13331
|
+
* `messageTemplate` for a one-off send.
|
|
13332
|
+
*/
|
|
13333
|
+
sendsSms(params, options = {}) {
|
|
13334
|
+
return this.onExecute("sms:send" /* SMS_SEND */, params, options);
|
|
13335
|
+
}
|
|
13336
|
+
/**
|
|
13337
|
+
* Call the member. Both the workspace PhoneNumber uuid (voice enabled) and
|
|
13338
|
+
* the Workflow uuid that drives the call are required.
|
|
13339
|
+
*/
|
|
13340
|
+
callsMember(params, options = {}) {
|
|
13341
|
+
return this.onExecute("phone:call" /* PHONE_CALL */, params, options);
|
|
13342
|
+
}
|
|
13343
|
+
/** Email the member from a workspace inbox. */
|
|
13344
|
+
sendsEmail(params, options = {}) {
|
|
13345
|
+
return this.onExecute("email:send" /* EMAIL_SEND */, params, options);
|
|
13346
|
+
}
|
|
13347
|
+
/** Label the member on arrival — pass label builders, not ids. */
|
|
13348
|
+
addsLabels(labels, options = {}) {
|
|
13349
|
+
return this.onExecute(
|
|
13350
|
+
"member:label" /* MEMBER_LABEL_ACTION */,
|
|
13351
|
+
{ addLabelIds: labels },
|
|
13352
|
+
options
|
|
13353
|
+
);
|
|
13354
|
+
}
|
|
13355
|
+
/** True once this step has something to do when a member reaches it. */
|
|
13356
|
+
get hasOutreach() {
|
|
13357
|
+
return this.rules.length > 0;
|
|
13358
|
+
}
|
|
13359
|
+
eventRuleInputs() {
|
|
13360
|
+
return this.rules.map((rule) => ({
|
|
13361
|
+
uuid: rule.uuid,
|
|
13362
|
+
eventType: "journey_step:execute" /* JOURNEY_STEP_EXECUTE */,
|
|
13363
|
+
actionType: rule.actionType,
|
|
13364
|
+
actionParams: resolveRefs(rule.actionParams),
|
|
13365
|
+
...rule.options.name ? { name: rule.options.name } : {},
|
|
13366
|
+
...rule.options.when ? { conditions: rule.options.when } : {},
|
|
13367
|
+
...rule.options.delaySeconds ? { delay: rule.options.delaySeconds } : {},
|
|
13368
|
+
active: rule.options.active ?? true
|
|
13369
|
+
}));
|
|
13370
|
+
}
|
|
13046
13371
|
planLine() {
|
|
13047
|
-
|
|
13372
|
+
const actions = this.rules.map((rule) => rule.actionType).join(" + ");
|
|
13373
|
+
return `Step: ${this.name}${actions ? ` (${actions})` : ""}`;
|
|
13048
13374
|
}
|
|
13049
13375
|
async apply(client) {
|
|
13376
|
+
if (this._existed) return;
|
|
13050
13377
|
if (this.journey._id === void 0) return;
|
|
13378
|
+
const rules = this.eventRuleInputs();
|
|
13051
13379
|
const payload = {
|
|
13052
13380
|
name: this.name,
|
|
13053
13381
|
description: this.description,
|
|
13054
|
-
order: this.order
|
|
13382
|
+
order: this.order,
|
|
13383
|
+
...this.assigneeId !== void 0 ? { assigneeId: this.assigneeId } : {},
|
|
13384
|
+
...this.posX !== void 0 ? { posX: this.posX } : {},
|
|
13385
|
+
...this.posY !== void 0 ? { posY: this.posY } : {},
|
|
13386
|
+
// Saved atomically with the step, so a partial failure cannot leave
|
|
13387
|
+
// an inert step behind.
|
|
13388
|
+
...rules.length ? { eventRules: rules } : {}
|
|
13055
13389
|
};
|
|
13056
13390
|
const result = await client.createStep(this.journey._id, payload);
|
|
13057
13391
|
this._id = result.id;
|
|
@@ -13059,26 +13393,59 @@ var JourneyStepBuilder = class extends WorkspaceBuilderResource {
|
|
|
13059
13393
|
this._created = true;
|
|
13060
13394
|
}
|
|
13061
13395
|
};
|
|
13396
|
+
var StartStepBuilder = class extends JourneyStepBuilder {
|
|
13397
|
+
get isImplicit() {
|
|
13398
|
+
return true;
|
|
13399
|
+
}
|
|
13400
|
+
planLine() {
|
|
13401
|
+
return "Step: Start (auto-created)";
|
|
13402
|
+
}
|
|
13403
|
+
async apply() {
|
|
13404
|
+
}
|
|
13405
|
+
};
|
|
13062
13406
|
var JourneyBuilder = class extends WorkspaceBuilderResource {
|
|
13063
13407
|
constructor(name, options = {}) {
|
|
13064
13408
|
super();
|
|
13065
13409
|
this.name = name;
|
|
13066
13410
|
this.description = options.description ?? "";
|
|
13411
|
+
this.start = new StartStepBuilder("Start", this, 0);
|
|
13412
|
+
this.steps.push(this.start);
|
|
13067
13413
|
}
|
|
13068
13414
|
name;
|
|
13069
13415
|
description;
|
|
13070
13416
|
steps = [];
|
|
13071
13417
|
goals = [];
|
|
13418
|
+
/** The auto-created `Start` step — connect the first real step to it. */
|
|
13419
|
+
start;
|
|
13420
|
+
/** `parentId:childId` for every edge the server already has (see `adopt`). */
|
|
13421
|
+
existingEdges = /* @__PURE__ */ new Set();
|
|
13072
13422
|
step(name, options = {}) {
|
|
13073
13423
|
const step = new JourneyStepBuilder(
|
|
13074
13424
|
name,
|
|
13075
13425
|
this,
|
|
13076
|
-
options.order ??
|
|
13077
|
-
options.description ?? ""
|
|
13426
|
+
options.order ?? this.steps.length,
|
|
13427
|
+
options.description ?? "",
|
|
13428
|
+
options
|
|
13078
13429
|
);
|
|
13079
13430
|
this.steps.push(step);
|
|
13080
13431
|
return step;
|
|
13081
13432
|
}
|
|
13433
|
+
/**
|
|
13434
|
+
* Declare a linear cadence: `Start → steps[0] → steps[1] → …`, each edge
|
|
13435
|
+
* carrying the matching entry from `spacing`.
|
|
13436
|
+
*
|
|
13437
|
+
* Chaining is not optional polish. A step created with no incoming edge is
|
|
13438
|
+
* a ROOT, and every root fires the moment a member enrols — a "three
|
|
13439
|
+
* follow-ups over four days" journey built without edges sends all three
|
|
13440
|
+
* at once.
|
|
13441
|
+
*/
|
|
13442
|
+
sequence(steps, spacing = []) {
|
|
13443
|
+
let parent = this.start;
|
|
13444
|
+
steps.forEach((step, index) => {
|
|
13445
|
+
parent = parent.connectsTo(step, spacing[index] ?? {});
|
|
13446
|
+
});
|
|
13447
|
+
return this;
|
|
13448
|
+
}
|
|
13082
13449
|
goal(name, options = {}) {
|
|
13083
13450
|
this.goals.push({
|
|
13084
13451
|
name,
|
|
@@ -13086,17 +13453,85 @@ var JourneyBuilder = class extends WorkspaceBuilderResource {
|
|
|
13086
13453
|
step: options.step,
|
|
13087
13454
|
completionCel: options.completionCel ?? options.completion_cel,
|
|
13088
13455
|
value: options.value,
|
|
13089
|
-
order: options.order ??
|
|
13456
|
+
order: options.order ?? this.goals.length
|
|
13090
13457
|
});
|
|
13091
13458
|
return this;
|
|
13092
13459
|
}
|
|
13460
|
+
/**
|
|
13461
|
+
* Authoring problems that make a journey silently misbehave at runtime.
|
|
13462
|
+
* Reported at plan/preview time, before anything is written.
|
|
13463
|
+
*/
|
|
13464
|
+
validate() {
|
|
13465
|
+
const problems = [];
|
|
13466
|
+
const withParents = /* @__PURE__ */ new Set();
|
|
13467
|
+
for (const step of this.steps) {
|
|
13468
|
+
for (const connection of step.connections) withParents.add(connection.child);
|
|
13469
|
+
}
|
|
13470
|
+
for (const step of this.steps) {
|
|
13471
|
+
if (step === this.start) continue;
|
|
13472
|
+
if (!withParents.has(step)) {
|
|
13473
|
+
problems.push(
|
|
13474
|
+
`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.`
|
|
13475
|
+
);
|
|
13476
|
+
}
|
|
13477
|
+
if (!step.hasOutreach) {
|
|
13478
|
+
problems.push(
|
|
13479
|
+
`step '${step.name}' has no JOURNEY_STEP_EXECUTE action \u2014 a member reaching it gets nothing. Add one with .sendsSms / .callsMember / .sendsEmail / .onExecute.`
|
|
13480
|
+
);
|
|
13481
|
+
}
|
|
13482
|
+
}
|
|
13483
|
+
if (!this.goals.length) {
|
|
13484
|
+
problems.push(`journey '${this.name}' has no goals \u2014 nothing measures whether it works.`);
|
|
13485
|
+
}
|
|
13486
|
+
return problems;
|
|
13487
|
+
}
|
|
13488
|
+
/**
|
|
13489
|
+
* Adopt an existing journey, its steps, and its EDGES, matched by name.
|
|
13490
|
+
*
|
|
13491
|
+
* Re-running a builder script is normal — a program is usually built in
|
|
13492
|
+
* stages as provisioning lands — and without adoption the second run would
|
|
13493
|
+
* create a duplicate journey and a duplicate set of steps beside the live
|
|
13494
|
+
* one, with members enrolled in neither.
|
|
13495
|
+
*
|
|
13496
|
+
* The edge set is recorded from the server's own `childConnections` rather
|
|
13497
|
+
* than inferred from "both steps exist". A first run that created the steps
|
|
13498
|
+
* and then failed before writing an edge leaves exactly that state, and
|
|
13499
|
+
* inferring would skip the missing edge on every subsequent run — leaving a
|
|
13500
|
+
* permanent root step that fires for every member at enrolment, silently.
|
|
13501
|
+
* The journey detail read eager-loads connections, so the real answer is
|
|
13502
|
+
* already in hand; there is no reason to guess.
|
|
13503
|
+
*/
|
|
13504
|
+
adopt(existing) {
|
|
13505
|
+
super.adopt(existing);
|
|
13506
|
+
const existingSteps = existing.steps ?? [];
|
|
13507
|
+
const byName = new Map(existingSteps.map((step) => [step.name, step]));
|
|
13508
|
+
const startStep = existingSteps.find((step) => step.id === existing.startStepId) ?? byName.get("Start");
|
|
13509
|
+
if (startStep) this.start.adopt(startStep);
|
|
13510
|
+
for (const step of this.steps) {
|
|
13511
|
+
if (step === this.start) continue;
|
|
13512
|
+
const match = byName.get(step.name);
|
|
13513
|
+
if (match) step.adopt(match);
|
|
13514
|
+
}
|
|
13515
|
+
for (const step of existingSteps) {
|
|
13516
|
+
for (const edge of step.childConnections ?? []) {
|
|
13517
|
+
this.existingEdges.add(edgeKey(edge.parentStepId, edge.childStepId));
|
|
13518
|
+
}
|
|
13519
|
+
}
|
|
13520
|
+
}
|
|
13521
|
+
/** True when the server already has this exact edge. */
|
|
13522
|
+
hasEdge(parent, child) {
|
|
13523
|
+
if (parent._id === void 0 || child._id === void 0) return false;
|
|
13524
|
+
return this.existingEdges.has(edgeKey(parent._id, child._id));
|
|
13525
|
+
}
|
|
13093
13526
|
planLine() {
|
|
13094
13527
|
const parts = [];
|
|
13095
|
-
|
|
13528
|
+
const real = this.steps.filter((step) => step !== this.start);
|
|
13529
|
+
if (real.length) parts.push(`${real.length} steps`);
|
|
13096
13530
|
if (this.goals.length) parts.push(`${this.goals.length} goals`);
|
|
13097
13531
|
return `Journey: ${this.name}${parts.length ? ` (${parts.join(", ")})` : ""}`;
|
|
13098
13532
|
}
|
|
13099
13533
|
async apply(client) {
|
|
13534
|
+
if (this._existed) return;
|
|
13100
13535
|
const result = await client.createJourney({
|
|
13101
13536
|
name: this.name,
|
|
13102
13537
|
description: this.description
|
|
@@ -13104,6 +13539,15 @@ var JourneyBuilder = class extends WorkspaceBuilderResource {
|
|
|
13104
13539
|
this._id = result.id;
|
|
13105
13540
|
this._uuid = result.uuid;
|
|
13106
13541
|
this._created = true;
|
|
13542
|
+
const startStep = (result.steps ?? []).find(
|
|
13543
|
+
(step) => step.id === result.startStepId || step.name === "Start"
|
|
13544
|
+
);
|
|
13545
|
+
if (!startStep) {
|
|
13546
|
+
throw new Error(
|
|
13547
|
+
`Journey '${this.name}' was created without a Start step; edges from journey.start cannot be wired.`
|
|
13548
|
+
);
|
|
13549
|
+
}
|
|
13550
|
+
this.start.adopt(startStep);
|
|
13107
13551
|
}
|
|
13108
13552
|
};
|
|
13109
13553
|
function buildJourneyConnectionPayload(connection) {
|
|
@@ -13113,7 +13557,9 @@ function buildJourneyConnectionPayload(connection) {
|
|
|
13113
13557
|
childStepUuid: connection.child._uuid,
|
|
13114
13558
|
...connection.condition ? { celCondition: connection.condition } : {},
|
|
13115
13559
|
...connection.required ? { required: true } : {},
|
|
13116
|
-
...connection.timeoutSeconds ? { timeoutSeconds: connection.timeoutSeconds } : {}
|
|
13560
|
+
...connection.timeoutSeconds ? { timeoutSeconds: connection.timeoutSeconds } : {},
|
|
13561
|
+
...connection.order !== void 0 ? { order: connection.order } : {},
|
|
13562
|
+
...connection.filterId !== void 0 ? { filterId: connection.filterId } : {}
|
|
13117
13563
|
};
|
|
13118
13564
|
}
|
|
13119
13565
|
function buildJourneyGoalPayload(goal) {
|
|
@@ -13399,6 +13845,15 @@ var PHASES = /* @__PURE__ */ new Map([
|
|
|
13399
13845
|
[JourneyBuilder, 7],
|
|
13400
13846
|
[JourneyStepBuilder, 8]
|
|
13401
13847
|
]);
|
|
13848
|
+
function phaseFor(resource) {
|
|
13849
|
+
let ctor = resource.constructor;
|
|
13850
|
+
while (ctor) {
|
|
13851
|
+
const phase = PHASES.get(ctor);
|
|
13852
|
+
if (phase !== void 0) return phase;
|
|
13853
|
+
ctor = Object.getPrototypeOf(ctor);
|
|
13854
|
+
}
|
|
13855
|
+
return 99;
|
|
13856
|
+
}
|
|
13402
13857
|
var WorkspaceBuilder = class {
|
|
13403
13858
|
constructor(client) {
|
|
13404
13859
|
this.client = client;
|
|
@@ -13461,7 +13916,8 @@ var WorkspaceBuilder = class {
|
|
|
13461
13916
|
${"=".repeat(50)}`);
|
|
13462
13917
|
writeLine("Plan");
|
|
13463
13918
|
writeLine("=".repeat(50));
|
|
13464
|
-
|
|
13919
|
+
const declared = resources.filter((resource) => !resource.isImplicit);
|
|
13920
|
+
for (const resource of declared) {
|
|
13465
13921
|
writeLine(` + ${resource.planLine()}`);
|
|
13466
13922
|
}
|
|
13467
13923
|
const wiring = this.collectWiringSummary(resources);
|
|
@@ -13469,8 +13925,9 @@ ${"=".repeat(50)}`);
|
|
|
13469
13925
|
writeLine("\n Wiring:");
|
|
13470
13926
|
for (const line of wiring) writeLine(` ${line}`);
|
|
13471
13927
|
}
|
|
13928
|
+
this.reportJourneyWarnings();
|
|
13472
13929
|
writeLine(`
|
|
13473
|
-
Total: ${
|
|
13930
|
+
Total: ${declared.length} resources, ${wiring.length} connections`);
|
|
13474
13931
|
writeLine(`${"=".repeat(50)}
|
|
13475
13932
|
`);
|
|
13476
13933
|
}
|
|
@@ -13481,7 +13938,8 @@ ${"=".repeat(50)}`);
|
|
|
13481
13938
|
${"=".repeat(50)}`);
|
|
13482
13939
|
writeLine("Preview");
|
|
13483
13940
|
writeLine("=".repeat(50));
|
|
13484
|
-
|
|
13941
|
+
const declared = resources.filter((resource) => !resource.isImplicit);
|
|
13942
|
+
for (const resource of declared) {
|
|
13485
13943
|
if (resource._existed) {
|
|
13486
13944
|
writeLine(` = ${resource.planLine()} (exists, id=${resource._id})`);
|
|
13487
13945
|
} else {
|
|
@@ -13493,8 +13951,9 @@ ${"=".repeat(50)}`);
|
|
|
13493
13951
|
writeLine("\n Wiring:");
|
|
13494
13952
|
for (const line of wiring) writeLine(` ${line}`);
|
|
13495
13953
|
}
|
|
13496
|
-
|
|
13497
|
-
const
|
|
13954
|
+
this.reportJourneyWarnings();
|
|
13955
|
+
const toCreate = declared.filter((resource) => !resource._existed);
|
|
13956
|
+
const existing = declared.filter((resource) => resource._existed);
|
|
13498
13957
|
writeLine(
|
|
13499
13958
|
`
|
|
13500
13959
|
Total: ${toCreate.length} to create, ${existing.length} existing, ${wiring.length} connections`
|
|
@@ -13502,6 +13961,18 @@ ${"=".repeat(50)}`);
|
|
|
13502
13961
|
writeLine(`${"=".repeat(50)}
|
|
13503
13962
|
`);
|
|
13504
13963
|
}
|
|
13964
|
+
/**
|
|
13965
|
+
* Print journey authoring problems that only bite at runtime — a step with
|
|
13966
|
+
* no incoming edge fires for every member at enrolment, and a step with no
|
|
13967
|
+
* action does nothing at all. Both look fine in the editor, so they are
|
|
13968
|
+
* surfaced before the write rather than discovered from a member's phone.
|
|
13969
|
+
*/
|
|
13970
|
+
reportJourneyWarnings() {
|
|
13971
|
+
const problems = this.resources.filter((resource) => resource instanceof JourneyBuilder).flatMap((journey) => journey.validate());
|
|
13972
|
+
if (!problems.length) return;
|
|
13973
|
+
writeLine("\n Journey warnings:");
|
|
13974
|
+
for (const problem of problems) writeLine(` ! ${problem}`);
|
|
13975
|
+
}
|
|
13505
13976
|
async apply() {
|
|
13506
13977
|
const resources = this.sortedResources();
|
|
13507
13978
|
await this.resolveExisting(resources);
|
|
@@ -13509,6 +13980,7 @@ ${"=".repeat(50)}`);
|
|
|
13509
13980
|
writeLine("Applying...");
|
|
13510
13981
|
for (const resource of resources) {
|
|
13511
13982
|
try {
|
|
13983
|
+
if (resource.isImplicit) continue;
|
|
13512
13984
|
if (resource._existed) {
|
|
13513
13985
|
const key = resourceKey(resource);
|
|
13514
13986
|
summary[key] ??= [];
|
|
@@ -13566,6 +14038,29 @@ Done! Created ${count} resources.`);
|
|
|
13566
14038
|
}
|
|
13567
14039
|
}
|
|
13568
14040
|
}
|
|
14041
|
+
const filterNames = new Map(
|
|
14042
|
+
resources.filter(
|
|
14043
|
+
(resource) => resource instanceof MemberFilterBuilder
|
|
14044
|
+
).map((resource) => [resource.name, resource])
|
|
14045
|
+
);
|
|
14046
|
+
if (filterNames.size) {
|
|
14047
|
+
for (const existing of await this.client.getMemberFilters()) {
|
|
14048
|
+
if (existing.name && filterNames.has(existing.name)) {
|
|
14049
|
+
filterNames.get(existing.name).adopt(existing);
|
|
14050
|
+
}
|
|
14051
|
+
}
|
|
14052
|
+
}
|
|
14053
|
+
const journeyNames = new Map(
|
|
14054
|
+
resources.filter((resource) => resource instanceof JourneyBuilder).map((resource) => [resource.name, resource])
|
|
14055
|
+
);
|
|
14056
|
+
if (journeyNames.size) {
|
|
14057
|
+
const existingJourneys = await this.client.getJourneys();
|
|
14058
|
+
for (const existing of existingJourneys.items) {
|
|
14059
|
+
if (!existing.name || !journeyNames.has(existing.name)) continue;
|
|
14060
|
+
const detail = await this.client.getJourney(existing.id);
|
|
14061
|
+
journeyNames.get(existing.name).adopt(detail);
|
|
14062
|
+
}
|
|
14063
|
+
}
|
|
13569
14064
|
if (!workflowNames.size) return;
|
|
13570
14065
|
const existingWorkflows = await this.client.getWorkflows();
|
|
13571
14066
|
for (const { workflow: existing } of existingWorkflows.items) {
|
|
@@ -13616,9 +14111,7 @@ Done! Created ${count} resources.`);
|
|
|
13616
14111
|
all.push(...resource.steps);
|
|
13617
14112
|
}
|
|
13618
14113
|
}
|
|
13619
|
-
return all.sort(
|
|
13620
|
-
(a, b) => (PHASES.get(a.constructor) ?? 99) - (PHASES.get(b.constructor) ?? 99)
|
|
13621
|
-
);
|
|
14114
|
+
return all.sort((a, b) => phaseFor(a) - phaseFor(b));
|
|
13622
14115
|
}
|
|
13623
14116
|
collectWiringSummary(resources) {
|
|
13624
14117
|
const lines = [];
|
|
@@ -13639,7 +14132,11 @@ Done! Created ${count} resources.`);
|
|
|
13639
14132
|
lines.push(`${rule.actionType} rule on '${resource.name}'`);
|
|
13640
14133
|
} else if (resource instanceof JourneyStepBuilder) {
|
|
13641
14134
|
for (const connection of resource.connections) {
|
|
13642
|
-
|
|
14135
|
+
const guard = connection.condition ? ` [${connection.condition}]` : "";
|
|
14136
|
+
lines.push(`${connection.parent.name} -> ${connection.child.name}${guard}`);
|
|
14137
|
+
}
|
|
14138
|
+
for (const rule of resource.rules) {
|
|
14139
|
+
lines.push(`${rule.actionType} on step '${resource.name}'`);
|
|
13643
14140
|
}
|
|
13644
14141
|
} else if (resource instanceof JourneyBuilder) {
|
|
13645
14142
|
for (const goal of resource.goals) lines.push(`Goal: ${goal.name}`);
|
|
@@ -13755,6 +14252,10 @@ Done! Created ${count} resources.`);
|
|
|
13755
14252
|
if (!(resource instanceof JourneyStepBuilder)) continue;
|
|
13756
14253
|
for (const connection of resource.connections) {
|
|
13757
14254
|
if (resource.journey._id === void 0) continue;
|
|
14255
|
+
if (resource.journey.hasEdge(connection.parent, connection.child)) {
|
|
14256
|
+
writeLine(` Exists: ${connection.parent.name} -> ${connection.child.name}`);
|
|
14257
|
+
continue;
|
|
14258
|
+
}
|
|
13758
14259
|
const payload = buildJourneyConnectionPayload(connection);
|
|
13759
14260
|
if (!payload) continue;
|
|
13760
14261
|
await this.client.createConnection(resource.journey._id, payload);
|
|
@@ -13765,6 +14266,12 @@ Done! Created ${count} resources.`);
|
|
|
13765
14266
|
async applyJourneyGoals(resources) {
|
|
13766
14267
|
for (const resource of resources) {
|
|
13767
14268
|
if (!(resource instanceof JourneyBuilder) || resource._id === void 0) continue;
|
|
14269
|
+
if (resource._existed) {
|
|
14270
|
+
for (const goal of resource.goals) {
|
|
14271
|
+
writeLine(` Skipped (journey already exists): Goal: ${goal.name}`);
|
|
14272
|
+
}
|
|
14273
|
+
continue;
|
|
14274
|
+
}
|
|
13768
14275
|
for (const goal of resource.goals) {
|
|
13769
14276
|
await this.client.createGoal(resource._id, buildJourneyGoalPayload(goal));
|
|
13770
14277
|
writeLine(` Created goal: ${goal.name}`);
|
|
@@ -14191,6 +14698,15 @@ var WorkflowAccessWarningResourceType = {
|
|
|
14191
14698
|
// src/types/widget-domain-types.ts
|
|
14192
14699
|
var WIDGET_SLUGS = ["chat", "operator", "operator-tools", "chat-app"];
|
|
14193
14700
|
|
|
14701
|
+
// src/types/generated/promo_code_service.ts
|
|
14702
|
+
var PromoCodeStatus = {
|
|
14703
|
+
active: "active",
|
|
14704
|
+
scheduled: "scheduled",
|
|
14705
|
+
expired: "expired",
|
|
14706
|
+
inactive: "inactive",
|
|
14707
|
+
exhausted: "exhausted"
|
|
14708
|
+
};
|
|
14709
|
+
|
|
14194
14710
|
// src/features/registry.ts
|
|
14195
14711
|
var FeatureCategory = /* @__PURE__ */ ((FeatureCategory2) => {
|
|
14196
14712
|
FeatureCategory2["COMMUNICATION"] = "communication";
|
|
@@ -15203,6 +15719,7 @@ function getRevisionState(workflow, revision) {
|
|
|
15203
15719
|
PIDS_SOURCES,
|
|
15204
15720
|
POSITIVE_RATING_THRESHOLD,
|
|
15205
15721
|
ProductType,
|
|
15722
|
+
PromoCodeStatus,
|
|
15206
15723
|
QUERY_VALUELESS_OPS,
|
|
15207
15724
|
QueriesApi,
|
|
15208
15725
|
REALTIME_MODEL_CUSTOM,
|
|
@@ -15244,6 +15761,7 @@ function getRevisionState(workflow, revision) {
|
|
|
15244
15761
|
WorkflowBuilder,
|
|
15245
15762
|
WorkflowResourceType,
|
|
15246
15763
|
WorkspaceBuilder,
|
|
15764
|
+
WorkspaceBuilderResource,
|
|
15247
15765
|
WorkspaceFeature,
|
|
15248
15766
|
WorkspaceProvisionStatus,
|
|
15249
15767
|
areDependenciesSatisfied,
|