stentor-models 1.72.4 → 1.73.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.
@@ -322,9 +322,17 @@ export interface BusyDayDescription {
322
322
  */
323
323
  readonly blockCurrentDay?: boolean;
324
324
  /**
325
- * Blocks the current day until the specified time. This is in the format of HH:MM.
325
+ * The current day stays available *until* the specified time, in HH:MM (24-hour) format.
326
326
  *
327
- * For example, "14:00" would make the current day unavailable until 2:00 PM.
327
+ * For example, "14:00" keeps today bookable up to 2:00 PM; after that, today is no longer offered.
328
+ *
329
+ * NOTE: the previous doc comment here described the inverse ("unavailable until 2:00 PM"). It was
330
+ * wrong: consumers disable the current day once the current time is past this value, and the Studio
331
+ * UI ("same-day booking allowed until…") has always matched that behavior rather than the old
332
+ * comment. Corrected here so the semantics cannot be implemented backwards downstream.
333
+ *
334
+ * Same meaning as AvailabilityClass.currentDayAvailableUntil, which overrides this for jobs
335
+ * resolved to a class.
328
336
  */
329
337
  readonly currentDayAvailableUntil?: string;
330
338
  /**
@@ -34,6 +34,42 @@ export interface AvailabilityClass {
34
34
  * If true, this availability class is only for leads and not for appointments as they typically require more information and followup.
35
35
  */
36
36
  leadOnly?: boolean;
37
+ /**
38
+ * The current day stays available *until* this time, in HH:MM (24-hour) format, wall-clock in the
39
+ * business timezone.
40
+ *
41
+ * For example, "16:00" lets a job in this class still be booked for today up to 4:00 PM; at or after
42
+ * 4:00 PM, today is no longer offered. Same meaning as BusyDayDescription.currentDayAvailableUntil,
43
+ * which this overrides for jobs resolved to this class.
44
+ *
45
+ * Only meaningful when numberOfDaysOut is 0 or absent (i.e. same-day is possible at all).
46
+ */
47
+ currentDayAvailableUntil?: string;
48
+ }
49
+ /**
50
+ * A deterministic mapping from an FSM/CRM job type to an availability class.
51
+ *
52
+ * This is the symmetric counterpart to CrmServiceAvailabilitySettings.delayedJobTypes, which is
53
+ * also keyed on the FSM job-type id: delayedJobTypes pushes a job type further out, this maps a
54
+ * job type onto a class (which may pull it in — e.g. same-day for emergency work).
55
+ */
56
+ export interface JobTypeAvailabilityClass {
57
+ /**
58
+ * The FSM/CRM job type id, stringified (ServiceTitan job type ids are numbers).
59
+ */
60
+ jobTypeId: string;
61
+ /**
62
+ * AvailabilityClass.id
63
+ */
64
+ classId: string;
65
+ /**
66
+ * Denormalized for display in Studio. Not used for matching.
67
+ */
68
+ jobTypeName?: string;
69
+ /**
70
+ * Provenance: "AI" = suggested by the class suggester, "USER" = confirmed/edited by a human.
71
+ */
72
+ source?: "AI" | "USER";
37
73
  }
38
74
  /**
39
75
  * Settings for the availability of the CRM service.
@@ -67,6 +103,18 @@ export interface CrmServiceAvailabilitySettings {
67
103
  * The default busy days for the business. This is used when the FSM/Scheduling backend does not provide busy days
68
104
  */
69
105
  defaultBusyDays?: BusyDayDescription;
106
+ /**
107
+ * Deterministic job type -> class mapping. Beats the LLM's guess.
108
+ */
109
+ jobTypeClasses?: JobTypeAvailabilityClass[];
110
+ /**
111
+ * Forces every booking in this scope into the given class, regardless of job type.
112
+ *
113
+ * This is deliberately NOT defaultAvailabilityClass: that field is a *fallback* (it loses to
114
+ * jobType.class), so it cannot express "force". Used by campaign booking widgets, which carry
115
+ * their own availability settings.
116
+ */
117
+ forceAvailabilityClass?: string;
70
118
  }
71
119
  export interface CrmServiceTimeAvailability {
72
120
  /**
@@ -165,8 +213,25 @@ export interface CrmService {
165
213
  * Returns the job type (id) for the free text job description (AI call usually)
166
214
  *
167
215
  * @param message
216
+ * @param externalLead
217
+ * @param options Availability settings in scope for this request (e.g. a widget's
218
+ * forceAvailabilityClass or jobTypeClasses), needed to resolve the job type's class.
219
+ *
220
+ * Deliberately typed as the settings-only CrmServiceAvailabilitySettings rather than
221
+ * CrmServiceAvailabilityOptions: this method *determines* the job type, so the `jobType` member of
222
+ * the Options type would be meaningless (and misleading) here.
223
+ */
224
+ getJobType?(message: string, externalLead?: ExternalLead, options?: CrmServiceAvailabilitySettings): Promise<CrmServiceJobType>;
225
+ /**
226
+ * Lists the tenant's job types from the FSM. Backs a Studio picker.
227
+ */
228
+ listJobTypes?(): Promise<CrmServiceJobType[]>;
229
+ /**
230
+ * Returns a suggested job-type -> class map. Does not persist anything.
231
+ *
232
+ * @param availabilityClasses
168
233
  */
169
- getJobType(message: string, externalLead?: ExternalLead): Promise<CrmServiceJobType>;
234
+ suggestJobTypeClasses?(availabilityClasses?: AvailabilityClass[]): Promise<JobTypeAvailabilityClass[]>;
170
235
  }
171
236
  export type CrmServiceProps = CrmServiceAvailabilitySettings;
172
237
  export declare class AbstractCrmService implements CrmService {
@@ -177,6 +242,6 @@ export declare class AbstractCrmService implements CrmService {
177
242
  constructor(props: CrmServiceProps);
178
243
  send(externalLead: ExternalLead, extras?: Record<string, unknown>): Promise<CrmResponse>;
179
244
  getAvailability(range: DateTimeRange, options?: CrmServiceAvailabilityOptions): Promise<CrmServiceAvailability>;
180
- getJobType(message: string, externalLead?: ExternalLead): Promise<CrmServiceJobType>;
245
+ getJobType(message: string, externalLead?: ExternalLead, options?: CrmServiceAvailabilitySettings): Promise<CrmServiceJobType>;
181
246
  update?(externalLead: ExternalLead, extras?: Record<string, unknown>): Promise<CrmResponse>;
182
247
  }
@@ -23,7 +23,7 @@ class AbstractCrmService {
23
23
  if (typeof props.maxTotalDailyAppointments === "number") {
24
24
  this.maxTotalDailyAppointments = props.maxTotalDailyAppointments;
25
25
  }
26
- if (typeof props.delayedJobTypes) {
26
+ if (props.delayedJobTypes) {
27
27
  this.delayedJobTypes = props.delayedJobTypes;
28
28
  }
29
29
  }
@@ -44,7 +44,7 @@ class AbstractCrmService {
44
44
  };
45
45
  });
46
46
  }
47
- getJobType(message, externalLead) {
47
+ getJobType(message, externalLead, options) {
48
48
  return __awaiter(this, void 0, void 0, function* () {
49
49
  throw new Error("Method not implemented.");
50
50
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CrmService.js","sourceRoot":"","sources":["../../src/Services/CrmService.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,oCAAoC;;;;;;;;;;;;AA6MpC,MAAa,kBAAkB;IAS7B,YAAmB,KAAsB;QACvC,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACxB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAC3C,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QACvC,CAAC;QAED,IAAI,OAAO,KAAK,CAAC,yBAAyB,KAAK,QAAQ,EAAE,CAAC;YACxD,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAC,yBAAyB,CAAC;QACnE,CAAC;QAED,IAAI,OAAO,KAAK,CAAC,eAAe,EAAE,CAAC;YACjC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAC/C,CAAC;IACH,CAAC;IAEY,IAAI,CACf,YAA0B,EAC1B,MAAgC;;YAEhC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;KAAA;IAEY,eAAe,CAC1B,KAAoB,EACpB,OAAuC;;YAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAC1C,MAAM,QAAQ,GAAG,uCAAuC,WAAW,EAAE,CAAC;YAEtE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,6DAA6D,CAAC,CAAC;YAEvF,4DAA4D;YAC5D,OAAO;gBACL,KAAK;gBACL,gBAAgB,EAAE,EAAE;aACrB,CAAC;QACJ,CAAC;KAAA;IAEY,UAAU,CACrB,OAAe,EACf,YAA2B;;YAE3B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;KAAA;IAEY,MAAM,CACjB,YAA0B,EAC1B,MAAgC;;YAEhC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;KAAA;CACF;AA/DD,gDA+DC"}
1
+ {"version":3,"file":"CrmService.js","sourceRoot":"","sources":["../../src/Services/CrmService.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,oCAAoC;;;;;;;;;;;;AAkRpC,MAAa,kBAAkB;IAS7B,YAAmB,KAAsB;QACvC,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACxB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAC3C,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QACvC,CAAC;QAED,IAAI,OAAO,KAAK,CAAC,yBAAyB,KAAK,QAAQ,EAAE,CAAC;YACxD,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAC,yBAAyB,CAAC;QACnE,CAAC;QAED,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAC/C,CAAC;IACH,CAAC;IAEY,IAAI,CACf,YAA0B,EAC1B,MAAgC;;YAEhC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;KAAA;IAEY,eAAe,CAC1B,KAAoB,EACpB,OAAuC;;YAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAC1C,MAAM,QAAQ,GAAG,uCAAuC,WAAW,EAAE,CAAC;YAEtE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,6DAA6D,CAAC,CAAC;YAEvF,4DAA4D;YAC5D,OAAO;gBACL,KAAK;gBACL,gBAAgB,EAAE,EAAE;aACrB,CAAC;QACJ,CAAC;KAAA;IAEY,UAAU,CACrB,OAAe,EACf,YAA2B,EAC3B,OAAwC;;YAExC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;KAAA;IAEY,MAAM,CACjB,YAA0B,EAC1B,MAAgC;;YAEhC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;KAAA;CACF;AAhED,gDAgEC"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "1.72.4",
7
+ "version": "1.73.0",
8
8
  "description": "Models for 📣 stentor",
9
9
  "types": "lib/index",
10
10
  "typings": "lib/index",
@@ -17,7 +17,7 @@
17
17
  "node": "^12 || ^14 || ^16 || ^18 || ^20 || ^22 || ^24.0.0"
18
18
  },
19
19
  "devDependencies": {
20
- "@microsoft/api-extractor": "7.58.7",
20
+ "@microsoft/api-extractor": "7.58.9",
21
21
  "@rollup/plugin-typescript": "12.3.0",
22
22
  "@xapp/config": "0.3.0",
23
23
  "rollup": "3.30.0",
@@ -33,5 +33,5 @@
33
33
  "dependencies": {
34
34
  "@xapp/patterns": "2.0.3"
35
35
  },
36
- "gitHead": "5d3123fc10bf122daae1bbbe23a3dc5c8ad1d39a"
36
+ "gitHead": "179d4c04b58ab103248ac0c7d4d44f8ce4c7d2d4"
37
37
  }