@servicetitan/titan-chatbot-api 7.1.2 → 9.0.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 (178) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/api-client/__mocks__/chatbot-api-client.mock.d.ts +1 -0
  3. package/dist/api-client/__mocks__/chatbot-api-client.mock.d.ts.map +1 -1
  4. package/dist/api-client/__mocks__/chatbot-api-client.mock.js +22 -47
  5. package/dist/api-client/__mocks__/chatbot-api-client.mock.js.map +1 -1
  6. package/dist/api-client/base/chatbot-api-client.d.ts +7 -0
  7. package/dist/api-client/base/chatbot-api-client.d.ts.map +1 -1
  8. package/dist/api-client/base/chatbot-api-client.js +3 -4
  9. package/dist/api-client/base/chatbot-api-client.js.map +1 -1
  10. package/dist/api-client/index.d.ts +2 -2
  11. package/dist/api-client/index.d.ts.map +1 -1
  12. package/dist/api-client/index.js +12 -7
  13. package/dist/api-client/index.js.map +1 -1
  14. package/dist/api-client/models/__mocks__/models.mock.js +154 -124
  15. package/dist/api-client/models/__mocks__/models.mock.js.map +1 -1
  16. package/dist/api-client/models/index.d.ts +2 -1
  17. package/dist/api-client/models/index.d.ts.map +1 -1
  18. package/dist/api-client/models/index.js +8 -7
  19. package/dist/api-client/models/index.js.map +1 -1
  20. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.d.ts +2 -0
  21. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.d.ts.map +1 -0
  22. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.js +240 -0
  23. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.js.map +1 -0
  24. package/dist/api-client/titan-chat/__tests__/native-client.test.js +6 -6
  25. package/dist/api-client/titan-chat/__tests__/native-client.test.js.map +1 -1
  26. package/dist/api-client/titan-chat/chatbot-api-client.d.ts +11 -0
  27. package/dist/api-client/titan-chat/chatbot-api-client.d.ts.map +1 -1
  28. package/dist/api-client/titan-chat/chatbot-api-client.js +69 -35
  29. package/dist/api-client/titan-chat/chatbot-api-client.js.map +1 -1
  30. package/dist/api-client/titan-chat/index.d.ts +2 -1
  31. package/dist/api-client/titan-chat/index.d.ts.map +1 -1
  32. package/dist/api-client/titan-chat/index.js +1 -0
  33. package/dist/api-client/titan-chat/index.js.map +1 -1
  34. package/dist/api-client/titan-chat/native-client.js +359 -812
  35. package/dist/api-client/titan-chat/native-client.js.map +1 -1
  36. package/dist/api-client/utils/__tests__/model-utils.test.js +454 -191
  37. package/dist/api-client/utils/__tests__/model-utils.test.js.map +1 -1
  38. package/dist/api-client/utils/model-utils.d.ts.map +1 -1
  39. package/dist/api-client/utils/model-utils.js +28 -25
  40. package/dist/api-client/utils/model-utils.js.map +1 -1
  41. package/dist/hooks/use-customization-chatbot.js +2 -1
  42. package/dist/hooks/use-customization-chatbot.js.map +1 -1
  43. package/dist/index.d.ts +3 -2
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +7 -5
  46. package/dist/index.js.map +1 -1
  47. package/dist/models/__tests__/chatbot-customizations.test.d.ts +2 -0
  48. package/dist/models/__tests__/chatbot-customizations.test.d.ts.map +1 -0
  49. package/dist/models/__tests__/chatbot-customizations.test.js +36 -0
  50. package/dist/models/__tests__/chatbot-customizations.test.js.map +1 -0
  51. package/dist/models/chatbot-customizations.d.ts +17 -0
  52. package/dist/models/chatbot-customizations.d.ts.map +1 -1
  53. package/dist/models/chatbot-customizations.js +7 -1
  54. package/dist/models/chatbot-customizations.js.map +1 -1
  55. package/dist/models/index.js +1 -0
  56. package/dist/models/index.js.map +1 -1
  57. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.d.ts +2 -0
  58. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.d.ts.map +1 -0
  59. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.js +107 -0
  60. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.js.map +1 -0
  61. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.d.ts +2 -0
  62. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.d.ts.map +1 -0
  63. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.js +312 -0
  64. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.js.map +1 -0
  65. package/dist/stores/__tests__/chatbot-ui-backend.store.test.js +267 -172
  66. package/dist/stores/__tests__/chatbot-ui-backend.store.test.js.map +1 -1
  67. package/dist/stores/__tests__/chatbot-ui.store.test.js +61 -64
  68. package/dist/stores/__tests__/chatbot-ui.store.test.js.map +1 -1
  69. package/dist/stores/__tests__/filter.store.test.js +243 -116
  70. package/dist/stores/__tests__/filter.store.test.js.map +1 -1
  71. package/dist/stores/__tests__/initialize.store.test.js +9 -8
  72. package/dist/stores/__tests__/initialize.store.test.js.map +1 -1
  73. package/dist/stores/__tests__/message-feedback-guardrail.store.test.js +8 -7
  74. package/dist/stores/__tests__/message-feedback-guardrail.store.test.js.map +1 -1
  75. package/dist/stores/__tests__/message-feedback.store.test.js +34 -27
  76. package/dist/stores/__tests__/message-feedback.store.test.js.map +1 -1
  77. package/dist/stores/__tests__/session-feedback.store.test.js +9 -8
  78. package/dist/stores/__tests__/session-feedback.store.test.js.map +1 -1
  79. package/dist/stores/chatbot-ui-backend.store.d.ts +26 -2
  80. package/dist/stores/chatbot-ui-backend.store.d.ts.map +1 -1
  81. package/dist/stores/chatbot-ui-backend.store.js +295 -239
  82. package/dist/stores/chatbot-ui-backend.store.js.map +1 -1
  83. package/dist/stores/chatbot-ui.store.js +73 -46
  84. package/dist/stores/chatbot-ui.store.js.map +1 -1
  85. package/dist/stores/filter.store.js +298 -378
  86. package/dist/stores/filter.store.js.map +1 -1
  87. package/dist/stores/index.d.ts +5 -3
  88. package/dist/stores/index.d.ts.map +1 -1
  89. package/dist/stores/index.js +3 -2
  90. package/dist/stores/index.js.map +1 -1
  91. package/dist/stores/initialize.store.js +55 -51
  92. package/dist/stores/initialize.store.js.map +1 -1
  93. package/dist/stores/message-feedback-base.store.js +2 -1
  94. package/dist/stores/message-feedback-base.store.js.map +1 -1
  95. package/dist/stores/message-feedback-guardrail.store.js +50 -47
  96. package/dist/stores/message-feedback-guardrail.store.js.map +1 -1
  97. package/dist/stores/message-feedback.store.js +84 -89
  98. package/dist/stores/message-feedback.store.js.map +1 -1
  99. package/dist/stores/session-feedback.store.js +46 -39
  100. package/dist/stores/session-feedback.store.js.map +1 -1
  101. package/dist/streaming/__tests__/agent-stream.test.d.ts +2 -0
  102. package/dist/streaming/__tests__/agent-stream.test.d.ts.map +1 -0
  103. package/dist/streaming/__tests__/agent-stream.test.js +92 -0
  104. package/dist/streaming/__tests__/agent-stream.test.js.map +1 -0
  105. package/dist/streaming/agent-stream.d.ts +83 -0
  106. package/dist/streaming/agent-stream.d.ts.map +1 -0
  107. package/dist/streaming/agent-stream.js +28 -0
  108. package/dist/streaming/agent-stream.js.map +1 -0
  109. package/dist/streaming/index.d.ts +3 -0
  110. package/dist/streaming/index.d.ts.map +1 -0
  111. package/dist/streaming/index.js +4 -0
  112. package/dist/streaming/index.js.map +1 -0
  113. package/dist/streaming/run-agent-stream.d.ts +23 -0
  114. package/dist/streaming/run-agent-stream.d.ts.map +1 -0
  115. package/dist/streaming/run-agent-stream.js +83 -0
  116. package/dist/streaming/run-agent-stream.js.map +1 -0
  117. package/dist/utils/__tests__/axios-utils.test.js +8 -7
  118. package/dist/utils/__tests__/axios-utils.test.js.map +1 -1
  119. package/dist/utils/axios-utils.js +9 -7
  120. package/dist/utils/axios-utils.js.map +1 -1
  121. package/dist/utils/test-utils.js +5 -5
  122. package/dist/utils/test-utils.js.map +1 -1
  123. package/package.json +6 -3
  124. package/src/api-client/__mocks__/chatbot-api-client.mock.ts +1 -0
  125. package/src/api-client/base/chatbot-api-client.ts +11 -0
  126. package/src/api-client/index.ts +2 -7
  127. package/src/api-client/models/index.ts +15 -13
  128. package/src/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.ts +208 -0
  129. package/src/api-client/titan-chat/chatbot-api-client.ts +46 -0
  130. package/src/api-client/titan-chat/index.ts +2 -1
  131. package/src/api-client/utils/model-utils.ts +4 -8
  132. package/src/index.ts +7 -2
  133. package/src/models/__tests__/chatbot-customizations.test.ts +26 -0
  134. package/src/models/chatbot-customizations.ts +20 -0
  135. package/src/stores/__tests__/chatbot-ui-backend.store.observability.test.ts +105 -0
  136. package/src/stores/__tests__/chatbot-ui-backend.store.streaming.test.ts +261 -0
  137. package/src/stores/chatbot-ui-backend.store.ts +179 -4
  138. package/src/stores/index.ts +5 -12
  139. package/src/streaming/__tests__/agent-stream.test.ts +80 -0
  140. package/src/streaming/agent-stream.ts +103 -0
  141. package/src/streaming/index.ts +2 -0
  142. package/src/streaming/run-agent-stream.ts +109 -0
  143. package/tsconfig.tsbuildinfo +1 -1
  144. package/dist/api-client/help-center/__tests__/converter-from-models.test.d.ts +0 -2
  145. package/dist/api-client/help-center/__tests__/converter-from-models.test.d.ts.map +0 -1
  146. package/dist/api-client/help-center/__tests__/converter-from-models.test.js +0 -34
  147. package/dist/api-client/help-center/__tests__/converter-from-models.test.js.map +0 -1
  148. package/dist/api-client/help-center/__tests__/converter-to-models.test.d.ts +0 -2
  149. package/dist/api-client/help-center/__tests__/converter-to-models.test.d.ts.map +0 -1
  150. package/dist/api-client/help-center/__tests__/converter-to-models.test.js +0 -82
  151. package/dist/api-client/help-center/__tests__/converter-to-models.test.js.map +0 -1
  152. package/dist/api-client/help-center/chatbot-api-client.d.ts +0 -32
  153. package/dist/api-client/help-center/chatbot-api-client.d.ts.map +0 -1
  154. package/dist/api-client/help-center/chatbot-api-client.js +0 -102
  155. package/dist/api-client/help-center/chatbot-api-client.js.map +0 -1
  156. package/dist/api-client/help-center/converter-from-models.d.ts +0 -13
  157. package/dist/api-client/help-center/converter-from-models.d.ts.map +0 -1
  158. package/dist/api-client/help-center/converter-from-models.js +0 -114
  159. package/dist/api-client/help-center/converter-from-models.js.map +0 -1
  160. package/dist/api-client/help-center/converter-to-models.d.ts +0 -13
  161. package/dist/api-client/help-center/converter-to-models.d.ts.map +0 -1
  162. package/dist/api-client/help-center/converter-to-models.js +0 -98
  163. package/dist/api-client/help-center/converter-to-models.js.map +0 -1
  164. package/dist/api-client/help-center/index.d.ts +0 -2
  165. package/dist/api-client/help-center/index.d.ts.map +0 -1
  166. package/dist/api-client/help-center/index.js +0 -2
  167. package/dist/api-client/help-center/index.js.map +0 -1
  168. package/dist/api-client/help-center/native-client.d.ts +0 -1268
  169. package/dist/api-client/help-center/native-client.d.ts.map +0 -1
  170. package/dist/api-client/help-center/native-client.js +0 -6242
  171. package/dist/api-client/help-center/native-client.js.map +0 -1
  172. package/src/api-client/help-center/__tests__/converter-from-models.test.ts +0 -41
  173. package/src/api-client/help-center/__tests__/converter-to-models.test.ts +0 -89
  174. package/src/api-client/help-center/chatbot-api-client.ts +0 -122
  175. package/src/api-client/help-center/converter-from-models.ts +0 -133
  176. package/src/api-client/help-center/converter-to-models.ts +0 -127
  177. package/src/api-client/help-center/index.ts +0 -1
  178. package/src/api-client/help-center/native-client.ts +0 -5727
@@ -1,207 +1,48 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
2
15
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
16
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
18
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
19
+ }
20
+ function _ts_metadata(k, v) {
8
21
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { Log } from '@servicetitan/log-service';
22
+ }
23
+ import { ILog, Log } from '@servicetitan/log-service';
11
24
  import { inject, injectable, symbolToken } from '@servicetitan/react-ioc';
12
- import { ChatError, ChatMessageState, ChatRunState, ChatUiEvent, } from '@servicetitan/titan-chat-ui-common';
25
+ import { ChatError, ChatMessageState, ChatRunState, ChatUiEvent, StreamingProgressModel } from '@servicetitan/titan-chat-ui-common';
13
26
  import axios from 'axios';
14
27
  import { makeObservable, runInAction } from 'mobx';
15
- import { CHATBOT_API_CLIENT, Models, ModelsUtils } from '../api-client';
28
+ import { CHATBOT_API_CLIENT, IChatbotApiClient, Models, ModelsUtils } from '../api-client';
29
+ import { DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS, isChatbotStreamingEnabled } from '../models/chatbot-customizations';
30
+ import { AgentStreamError } from '../streaming';
16
31
  import { withTimeout } from '../utils/axios-utils';
17
- import { CHATBOT_UI_STORE_TOKEN, ChatbotUiEvent } from './chatbot-ui.store';
32
+ import { CHATBOT_UI_STORE_TOKEN, ChatbotUiEvent, IChatbotUiStore } from './chatbot-ui.store';
18
33
  import { InitializeStore } from './initialize.store';
19
34
  const DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS = 31000; // 31 seconds
20
- const isAbortedError = (error) => axios.isCancel(error) || (error === null || error === void 0 ? void 0 : error.name) === 'AbortError';
35
+ const STREAMING_KEEPALIVE_TEXT = 'Still working on it…';
36
+ const STREAMING_STEP_ERROR = 'Something went wrong during this step. Please try again.';
37
+ const isAbortedError = (error)=>axios.isCancel(error) || (error === null || error === void 0 ? void 0 : error.name) === 'AbortError';
21
38
  export const CHATBOT_UI_BACKEND_STORE_TOKEN = symbolToken('CHATBOT_UI_BACKEND_STORE_TOKEN');
22
- let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore {
39
+ export class ChatbotUiBackendStore extends InitializeStore {
23
40
  get logService() {
24
41
  return this.log;
25
42
  }
26
43
  get customizations() {
27
44
  return this.chatUiStore.customizations;
28
45
  }
29
- constructor() {
30
- super();
31
- Object.defineProperty(this, "session", {
32
- enumerable: true,
33
- configurable: true,
34
- writable: true,
35
- value: void 0
36
- });
37
- Object.defineProperty(this, "abortController", {
38
- enumerable: true,
39
- configurable: true,
40
- writable: true,
41
- value: void 0
42
- });
43
- Object.defineProperty(this, "chatbotApiClient", {
44
- enumerable: true,
45
- configurable: true,
46
- writable: true,
47
- value: void 0
48
- });
49
- Object.defineProperty(this, "chatUiStore", {
50
- enumerable: true,
51
- configurable: true,
52
- writable: true,
53
- value: void 0
54
- });
55
- Object.defineProperty(this, "log", {
56
- enumerable: true,
57
- configurable: true,
58
- writable: true,
59
- value: void 0
60
- });
61
- Object.defineProperty(this, "sessionPromise", {
62
- enumerable: true,
63
- configurable: true,
64
- writable: true,
65
- value: void 0
66
- });
67
- Object.defineProperty(this, "handleRun", {
68
- enumerable: true,
69
- configurable: true,
70
- writable: true,
71
- value: async (resolve) => {
72
- await this.run();
73
- resolve();
74
- }
75
- });
76
- Object.defineProperty(this, "handleDestroy", {
77
- enumerable: true,
78
- configurable: true,
79
- writable: true,
80
- value: async (resolve) => {
81
- await this.destroy();
82
- resolve();
83
- }
84
- });
85
- Object.defineProperty(this, "handleRestart", {
86
- enumerable: true,
87
- configurable: true,
88
- writable: true,
89
- value: async (resolve) => {
90
- await this.destroy();
91
- this.deleteFromSessionStorage();
92
- await this.run();
93
- resolve();
94
- }
95
- });
96
- Object.defineProperty(this, "handleMessageSend", {
97
- enumerable: true,
98
- configurable: true,
99
- writable: true,
100
- value: async (resolve, _, messageModel, selections, timeoutMs) => {
101
- await this.sendMessage(messageModel, selections, timeoutMs);
102
- resolve();
103
- }
104
- });
105
- Object.defineProperty(this, "handleMessageSendRetry", {
106
- enumerable: true,
107
- configurable: true,
108
- writable: true,
109
- value: async (resolve, _, messageModel) => {
110
- var _a, _b;
111
- if (messageModel.type !== 'message') {
112
- resolve();
113
- return;
114
- }
115
- const selections = (_a = messageModel.data) === null || _a === void 0 ? void 0 : _a.selections;
116
- const timeoutMs = (_b = messageModel.data) === null || _b === void 0 ? void 0 : _b.timeoutMs;
117
- await this.sendMessage(messageModel, selections, timeoutMs);
118
- resolve();
119
- }
120
- });
121
- Object.defineProperty(this, "handleSessionStart", {
122
- enumerable: true,
123
- configurable: true,
124
- writable: true,
125
- value: async (resolve, _, sessionData, forceRecreate) => {
126
- const session = await this.startSession(sessionData, forceRecreate);
127
- resolve({
128
- session,
129
- });
130
- }
131
- });
132
- Object.defineProperty(this, "handleSessionFeedback", {
133
- enumerable: true,
134
- configurable: true,
135
- writable: true,
136
- value: async (resolve, _, draft) => {
137
- let feedbackState;
138
- let feedbackResult = draft
139
- ? new Models.Feedback(draft)
140
- : undefined;
141
- try {
142
- if (!draft) {
143
- throw new ChatError('Session feedback is missing.', {
144
- recoverStrategy: false,
145
- });
146
- }
147
- if (typeof draft.messageId !== 'undefined') {
148
- throw new ChatError('Session feedback should not contain messageId.', {
149
- recoverStrategy: false,
150
- });
151
- }
152
- await this.startSession();
153
- const feedback = new Models.Feedback({ ...draft, sessionId: this.session.id });
154
- feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);
155
- feedbackState = Models.ChatbotFeedbackState.Success;
156
- }
157
- catch (error) {
158
- this.setError('FailedToSendFeedback', 'Send session feedback', 'Failed to send feedback', error);
159
- feedbackState = Models.ChatbotFeedbackState.Failure;
160
- }
161
- resolve({
162
- state: feedbackState,
163
- feedback: feedbackResult,
164
- });
165
- }
166
- });
167
- Object.defineProperty(this, "handleMessageFeedback", {
168
- enumerable: true,
169
- configurable: true,
170
- writable: true,
171
- value: async (resolve, _, draft) => {
172
- let feedbackState;
173
- let feedbackResult = draft
174
- ? new Models.Feedback(draft)
175
- : undefined;
176
- try {
177
- if (!draft) {
178
- throw new ChatError('Message feedback is missing.', {
179
- recoverStrategy: false,
180
- });
181
- }
182
- if (!draft.messageId) {
183
- throw new ChatError('Message feedback is missing messageId.', {
184
- recoverStrategy: false,
185
- });
186
- }
187
- await this.startSession();
188
- const feedback = new Models.Feedback({ ...draft, sessionId: this.session.id });
189
- feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);
190
- feedbackState = Models.ChatbotFeedbackState.Success;
191
- }
192
- catch (error) {
193
- this.setError('FailedToSendMessageFeedback', 'Send message feedback', 'Failed to send message feedback', error);
194
- feedbackState = Models.ChatbotFeedbackState.Failure;
195
- }
196
- resolve({
197
- state: feedbackState,
198
- feedback: feedbackResult,
199
- });
200
- }
201
- });
202
- makeObservable(this);
203
- this.initializeAbortController();
204
- }
205
46
  subscribe() {
206
47
  this.unsubscribe();
207
48
  this.chatUiStore.on(ChatUiEvent.eventRun, this.handleRun);
@@ -226,19 +67,16 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
226
67
  async getSessionData() {
227
68
  return Promise.resolve(undefined);
228
69
  }
229
- restoreChatSession() { }
230
- saveCurrentState() { }
231
- deleteFromSessionStorage() { }
232
- restartTimers() { }
70
+ restoreChatSession() {}
71
+ saveCurrentState() {}
72
+ deleteFromSessionStorage() {}
73
+ restartTimers() {}
233
74
  ensureWelcomeMessage() {
234
75
  if (this.chatUiStore.messages.length) {
235
76
  return;
236
77
  }
237
- this.withSaveState(() => {
238
- this.chatUiStore.addMessageWelcome(`Hi there! I’m ${this.chatUiStore.agent.name}, an AI chatbot powered by Titan Intelligence. ` +
239
- 'I’m here to answer your questions about using ServiceTitan. ' +
240
- 'You can ask me things like "How to merge duplicate customers?". ' +
241
- 'Do you have a question for me?');
78
+ this.withSaveState(()=>{
79
+ this.chatUiStore.addMessageWelcome(`Hi there! I’m ${this.chatUiStore.agent.name}, an AI chatbot powered by Titan Intelligence. ` + 'I’m here to answer your questions about using ServiceTitan. ' + 'You can ask me things like "How to merge duplicate customers?". ' + 'Do you have a question for me?');
242
80
  });
243
81
  }
244
82
  logError(code, message, error) {
@@ -249,16 +87,16 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
249
87
  error,
250
88
  message,
251
89
  category: 'TitanChatbot',
252
- code: `TitanChatbot_${code}`,
90
+ code: `TitanChatbot_${code}`
253
91
  });
254
92
  }
255
93
  async initializeInternal() {
256
94
  await super.initializeInternal();
257
95
  const options = await this.chatbotApiClient.getOptions();
258
- runInAction(() => {
259
- var _a, _b;
96
+ runInAction(()=>{
97
+ var _this_customizations_filters, _this_customizations;
260
98
  this.chatUiStore.filterStore.initFilters(options, {
261
- isDefaultSelected: (_b = (_a = this.customizations) === null || _a === void 0 ? void 0 : _a.filters) === null || _b === void 0 ? void 0 : _b.isDefaultSelected,
99
+ isDefaultSelected: (_this_customizations = this.customizations) === null || _this_customizations === void 0 ? void 0 : (_this_customizations_filters = _this_customizations.filters) === null || _this_customizations_filters === void 0 ? void 0 : _this_customizations_filters.isDefaultSelected
262
100
  });
263
101
  });
264
102
  }
@@ -270,8 +108,7 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
270
108
  this.ensureWelcomeMessage();
271
109
  this.restartTimers();
272
110
  this.chatUiStore.setStatus(ChatRunState.Started);
273
- }
274
- catch (error) {
111
+ } catch (error) {
275
112
  this.setError('FailedToInitialize', 'Initialization Error', 'Unable to start the chatbot service. Please check your connection and refresh the page.', error);
276
113
  }
277
114
  }
@@ -289,50 +126,173 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
289
126
  processBotAnswer(answer) {
290
127
  this.chatUiStore.addMessage(true, answer.answer, answer);
291
128
  }
129
+ /**
130
+ * Routes a send to the SSE streaming path when enabled (and supported by the client),
131
+ * otherwise to the existing non-streaming path. Default is non-streaming.
132
+ */ routeSend(messageModel, selections, timeoutMs) {
133
+ if (isChatbotStreamingEnabled(this.customizations) && this.chatbotApiClient.streamMessage) {
134
+ return this.sendMessageStreaming(messageModel, selections, timeoutMs);
135
+ }
136
+ return this.sendMessage(messageModel, selections, timeoutMs);
137
+ }
292
138
  async sendMessage(messageModel, selections, timeoutMs) {
293
- var _a, _b, _c;
294
139
  const question = messageModel.message;
295
140
  const perRequestController = new AbortController();
296
- const forwardStoreAbort = () => perRequestController.abort(this.abortController.signal.reason);
297
- this.abortController.signal.addEventListener('abort', forwardStoreAbort, { once: true });
141
+ const forwardStoreAbort = ()=>perRequestController.abort(this.abortController.signal.reason);
142
+ this.abortController.signal.addEventListener('abort', forwardStoreAbort, {
143
+ once: true
144
+ });
298
145
  try {
146
+ var _ref;
147
+ var _this_customizations_timeouts, _this_customizations;
299
148
  await this.startSession();
300
149
  this.chatUiStore.setAgentTyping(true);
301
150
  const answer = await withTimeout(this.api('postMessage', new Models.UserMessage({
302
151
  sessionId: this.session.id,
303
152
  question,
304
153
  experience: Models.Experience.MultiTurn,
305
- selections,
306
- }), perRequestController.signal), (_c = timeoutMs !== null && timeoutMs !== void 0 ? timeoutMs : (_b = (_a = this.customizations) === null || _a === void 0 ? void 0 : _a.timeouts) === null || _b === void 0 ? void 0 : _b.chatbotRequestTimeoutMs) !== null && _c !== void 0 ? _c : DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS, perRequestController);
307
- this.withSaveState(() => {
154
+ selections
155
+ }), perRequestController.signal), (_ref = timeoutMs !== null && timeoutMs !== void 0 ? timeoutMs : (_this_customizations = this.customizations) === null || _this_customizations === void 0 ? void 0 : (_this_customizations_timeouts = _this_customizations.timeouts) === null || _this_customizations_timeouts === void 0 ? void 0 : _this_customizations_timeouts.chatbotRequestTimeoutMs) !== null && _ref !== void 0 ? _ref : DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS, perRequestController);
156
+ this.withSaveState(()=>{
308
157
  // Set message state to Delivered and preserve selections and bot answer id to the user question (to have a link between question and answer)
309
158
  this.chatUiStore.setMessageState(messageModel, ChatMessageState.Delivered, {
310
159
  answerId: answer.id,
311
- selections,
160
+ selections
312
161
  });
313
162
  this.processBotAnswer(answer);
314
163
  this.chatUiStore.resetError(ChatRunState.Started);
315
164
  });
316
- }
317
- catch (error) {
318
- this.withSaveState(() => {
165
+ } catch (error) {
166
+ this.withSaveState(()=>{
319
167
  this.chatUiStore.setMessageState(messageModel, ChatMessageState.Failed, {
320
168
  selections,
321
- ...(timeoutMs !== undefined ? { timeoutMs } : {}),
169
+ ...timeoutMs !== undefined ? {
170
+ timeoutMs
171
+ } : {}
322
172
  });
323
173
  });
324
174
  if (error instanceof ChatError) {
325
175
  this.setChatError('FailedToSendMessage', error);
326
- }
327
- else {
176
+ } else {
328
177
  this.setError('FailedToSendMessage', 'Send message', 'Failed to send message', error);
329
178
  }
179
+ } finally{
180
+ this.abortController.signal.removeEventListener('abort', forwardStoreAbort);
181
+ this.chatUiStore.setAgentTyping(false);
330
182
  }
331
- finally {
183
+ }
184
+ /**
185
+ * Streaming send-path: consumes the SSE agent-progress stream, rendering live progress and
186
+ * resolving the final answer on `run.finished`. Applies an inactivity-only timeout (no hard
187
+ * request timeout). Falls back transparently to {@link sendMessage} when the stream is
188
+ * unreachable at connect time — propagating the original per-message `timeoutMs` so the
189
+ * fallback behaves identically to the non-streaming path; surfaces a step error if the
190
+ * connection fails after connecting.
191
+ */ async sendMessageStreaming(messageModel, selections, timeoutMs) {
192
+ const question = messageModel.message;
193
+ const perRequestController = new AbortController();
194
+ const forwardStoreAbort = ()=>perRequestController.abort(this.abortController.signal.reason);
195
+ this.abortController.signal.addEventListener('abort', forwardStoreAbort, {
196
+ once: true
197
+ });
198
+ let connected = false;
199
+ try {
200
+ var _ref;
201
+ var _this_customizations_streaming, _this_customizations;
202
+ await this.startSession();
203
+ this.chatUiStore.setAgentTyping(true);
204
+ runInAction(()=>this.streamingProgress.reset());
205
+ const inactivityTimeoutMs = (_ref = (_this_customizations = this.customizations) === null || _this_customizations === void 0 ? void 0 : (_this_customizations_streaming = _this_customizations.streaming) === null || _this_customizations_streaming === void 0 ? void 0 : _this_customizations_streaming.inactivityTimeoutMs) !== null && _ref !== void 0 ? _ref : DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS;
206
+ // Apply a progress mutation, then scroll so the newest event stays in view.
207
+ const updateProgress = (mutate)=>{
208
+ runInAction(mutate);
209
+ this.chatUiStore.triggerScroll();
210
+ };
211
+ const handlers = {
212
+ inactivityTimeoutMs,
213
+ onStatus: (text)=>updateProgress(()=>{
214
+ this.streamingProgress.clearKeepalive();
215
+ this.streamingProgress.setStatus(text);
216
+ }),
217
+ onText: (text)=>updateProgress(()=>{
218
+ this.streamingProgress.clearKeepalive();
219
+ this.streamingProgress.appendLog(text);
220
+ }),
221
+ onPlan: (steps)=>updateProgress(()=>{
222
+ this.streamingProgress.clearKeepalive();
223
+ this.streamingProgress.setSteps(steps);
224
+ }),
225
+ onStepActive: (id)=>updateProgress(()=>{
226
+ this.streamingProgress.clearKeepalive();
227
+ this.streamingProgress.setActiveStep(id);
228
+ }),
229
+ onInactivity: ()=>updateProgress(()=>this.streamingProgress.setKeepalive(STREAMING_KEEPALIVE_TEXT)),
230
+ onConnected: ()=>{
231
+ connected = true;
232
+ this.logStreaming('connected');
233
+ },
234
+ onDisconnected: ()=>this.logStreaming('disconnected'),
235
+ onTimeout: ()=>this.logStreaming('timed_out'),
236
+ onCompleted: ()=>this.logStreaming('completed')
237
+ };
238
+ const answer = await this.api('streamMessage', new Models.UserMessage({
239
+ sessionId: this.session.id,
240
+ question,
241
+ experience: Models.Experience.MultiTurn,
242
+ selections
243
+ }), handlers, perRequestController.signal);
244
+ this.withSaveState(()=>{
245
+ this.chatUiStore.setMessageState(messageModel, ChatMessageState.Delivered, {
246
+ answerId: answer.id,
247
+ selections
248
+ });
249
+ this.processBotAnswer(answer);
250
+ this.chatUiStore.resetError(ChatRunState.Started);
251
+ });
252
+ /*
253
+ * Mark every plan step done and clear the transient keepalive; the rendered trail is
254
+ * faded by the UI once the final answer is shown. The next streamed send resets the model.
255
+ */ runInAction(()=>{
256
+ this.streamingProgress.completeAllSteps();
257
+ this.streamingProgress.clearKeepalive();
258
+ });
259
+ } catch (error) {
260
+ if (isAbortedError(error)) {
261
+ return;
262
+ }
263
+ // Never connected → the endpoint was unreachable at connect time: fall back silently.
264
+ if (!connected) {
265
+ this.streamingFallbackCount += 1;
266
+ this.logStreaming('fallback');
267
+ runInAction(()=>this.streamingProgress.reset());
268
+ await this.sendMessage(messageModel, selections, timeoutMs);
269
+ return;
270
+ }
271
+ // Connected then failed: surface the step error (the agent's message if provided).
272
+ this.withSaveState(()=>{
273
+ this.chatUiStore.setMessageState(messageModel, ChatMessageState.Failed, {
274
+ selections
275
+ });
276
+ });
277
+ runInAction(()=>this.streamingProgress.reset());
278
+ const message = error instanceof AgentStreamError ? error.message : STREAMING_STEP_ERROR;
279
+ if (error instanceof ChatError) {
280
+ this.setChatError('FailedToSendMessage', error);
281
+ } else {
282
+ this.setError('FailedToSendMessage', 'Send message', message, error);
283
+ }
284
+ } finally{
332
285
  this.abortController.signal.removeEventListener('abort', forwardStoreAbort);
333
286
  this.chatUiStore.setAgentTyping(false);
334
287
  }
335
288
  }
289
+ /** Logs a streaming connection lifecycle phase (connected, disconnected, timed_out, completed, fallback). */ logStreaming(phase) {
290
+ this.logService.info({
291
+ message: `Streaming ${phase}`,
292
+ category: 'TitanChatbot',
293
+ code: `TitanChatbot_Streaming_${phase}`
294
+ });
295
+ }
336
296
  setSession(session) {
337
297
  this.session = session;
338
298
  }
@@ -345,23 +305,27 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
345
305
  return this.session;
346
306
  }
347
307
  if (!this.sessionPromise) {
348
- this.sessionPromise = (async () => {
308
+ this.sessionPromise = (async ()=>{
349
309
  let data = await this.getSessionData();
350
310
  if (sessionData) {
351
- data = { ...data, ...sessionData };
311
+ data = {
312
+ ...data,
313
+ ...sessionData
314
+ };
352
315
  }
353
- return this.api('postSession', ModelsUtils.createNewSessionModel({ data }), this.abortController.signal);
316
+ return this.api('postSession', ModelsUtils.createNewSessionModel({
317
+ data
318
+ }), this.abortController.signal);
354
319
  })();
355
320
  const session = await this.sessionPromise;
356
321
  this.setSession(session);
357
- this.withSaveState(() => {
322
+ this.withSaveState(()=>{
358
323
  this.chatUiStore.resetError(ChatRunState.Started);
359
324
  });
360
325
  }
361
326
  try {
362
327
  await this.sessionPromise;
363
- }
364
- finally {
328
+ } finally{
365
329
  this.sessionPromise = undefined;
366
330
  }
367
331
  return this.session;
@@ -371,8 +335,7 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
371
335
  if (method) {
372
336
  try {
373
337
  return method.call(this.chatbotApiClient, ...args);
374
- }
375
- finally {
338
+ } finally{
376
339
  this.restartTimers();
377
340
  }
378
341
  }
@@ -385,7 +348,7 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
385
348
  }
386
349
  setChatError(code, error) {
387
350
  this.logError(code, error.message, error);
388
- this.withSaveState(() => {
351
+ this.withSaveState(()=>{
389
352
  this.chatUiStore.setChatError(error);
390
353
  });
391
354
  }
@@ -394,33 +357,126 @@ let ChatbotUiBackendStore = class ChatbotUiBackendStore extends InitializeStore
394
357
  return;
395
358
  }
396
359
  this.logError(code, message, error);
397
- this.withSaveState(() => {
398
- var _a;
399
- this.chatUiStore.setError(message, (_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error);
360
+ this.withSaveState(()=>{
361
+ var _ref;
362
+ this.chatUiStore.setError(message, (_ref = error === null || error === void 0 ? void 0 : error.message) !== null && _ref !== void 0 ? _ref : error);
400
363
  });
401
364
  }
402
365
  initializeAbortController() {
403
366
  this.abortController = new AbortController();
404
- this.abortController.signal.addEventListener('abort', () => {
367
+ this.abortController.signal.addEventListener('abort', ()=>{
405
368
  this.initializeAbortController();
406
369
  });
407
370
  }
408
- };
409
- __decorate([
371
+ constructor(){
372
+ super(), _define_property(this, "session", void 0), _define_property(this, "abortController", void 0), /** Live progress for the in-flight streamed run (status line, activity log, steps, keepalive). */ _define_property(this, "streamingProgress", new StreamingProgressModel()), /** Count of streaming → non-streaming fallbacks, tracked separately for regression detection. */ _define_property(this, "streamingFallbackCount", 0), _define_property(this, "chatbotApiClient", void 0), _define_property(this, "chatUiStore", void 0), _define_property(this, "log", void 0), _define_property(this, "sessionPromise", void 0), _define_property(this, "handleRun", async (resolve)=>{
373
+ await this.run();
374
+ resolve();
375
+ }), _define_property(this, "handleDestroy", async (resolve)=>{
376
+ await this.destroy();
377
+ resolve();
378
+ }), _define_property(this, "handleRestart", async (resolve)=>{
379
+ await this.destroy();
380
+ this.deleteFromSessionStorage();
381
+ await this.run();
382
+ resolve();
383
+ }), _define_property(this, "handleMessageSend", async (resolve, _, messageModel, selections, timeoutMs)=>{
384
+ await this.routeSend(messageModel, selections, timeoutMs);
385
+ resolve();
386
+ }), _define_property(this, "handleMessageSendRetry", async (resolve, _, messageModel)=>{
387
+ var _messageModel_data, _messageModel_data1;
388
+ if (messageModel.type !== 'message') {
389
+ resolve();
390
+ return;
391
+ }
392
+ const selections = (_messageModel_data = messageModel.data) === null || _messageModel_data === void 0 ? void 0 : _messageModel_data.selections;
393
+ const timeoutMs = (_messageModel_data1 = messageModel.data) === null || _messageModel_data1 === void 0 ? void 0 : _messageModel_data1.timeoutMs;
394
+ await this.routeSend(messageModel, selections, timeoutMs);
395
+ resolve();
396
+ }), _define_property(this, "handleSessionStart", async (resolve, _, sessionData, forceRecreate)=>{
397
+ const session = await this.startSession(sessionData, forceRecreate);
398
+ resolve({
399
+ session
400
+ });
401
+ }), _define_property(this, "handleSessionFeedback", async (resolve, _, draft)=>{
402
+ let feedbackState;
403
+ let feedbackResult = draft ? new Models.Feedback(draft) : undefined;
404
+ try {
405
+ if (!draft) {
406
+ throw new ChatError('Session feedback is missing.', {
407
+ recoverStrategy: false
408
+ });
409
+ }
410
+ if (typeof draft.messageId !== 'undefined') {
411
+ throw new ChatError('Session feedback should not contain messageId.', {
412
+ recoverStrategy: false
413
+ });
414
+ }
415
+ await this.startSession();
416
+ const feedback = new Models.Feedback({
417
+ ...draft,
418
+ sessionId: this.session.id
419
+ });
420
+ feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);
421
+ feedbackState = Models.ChatbotFeedbackState.Success;
422
+ } catch (error) {
423
+ this.setError('FailedToSendFeedback', 'Send session feedback', 'Failed to send feedback', error);
424
+ feedbackState = Models.ChatbotFeedbackState.Failure;
425
+ }
426
+ resolve({
427
+ state: feedbackState,
428
+ feedback: feedbackResult
429
+ });
430
+ }), _define_property(this, "handleMessageFeedback", async (resolve, _, draft)=>{
431
+ let feedbackState;
432
+ let feedbackResult = draft ? new Models.Feedback(draft) : undefined;
433
+ try {
434
+ if (!draft) {
435
+ throw new ChatError('Message feedback is missing.', {
436
+ recoverStrategy: false
437
+ });
438
+ }
439
+ if (!draft.messageId) {
440
+ throw new ChatError('Message feedback is missing messageId.', {
441
+ recoverStrategy: false
442
+ });
443
+ }
444
+ await this.startSession();
445
+ const feedback = new Models.Feedback({
446
+ ...draft,
447
+ sessionId: this.session.id
448
+ });
449
+ feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);
450
+ feedbackState = Models.ChatbotFeedbackState.Success;
451
+ } catch (error) {
452
+ this.setError('FailedToSendMessageFeedback', 'Send message feedback', 'Failed to send message feedback', error);
453
+ feedbackState = Models.ChatbotFeedbackState.Failure;
454
+ }
455
+ resolve({
456
+ state: feedbackState,
457
+ feedback: feedbackResult
458
+ });
459
+ });
460
+ makeObservable(this);
461
+ this.initializeAbortController();
462
+ }
463
+ }
464
+ _ts_decorate([
410
465
  inject(CHATBOT_API_CLIENT),
411
- __metadata("design:type", Object)
466
+ _ts_metadata("design:type", typeof IChatbotApiClient === "undefined" ? Object : IChatbotApiClient)
412
467
  ], ChatbotUiBackendStore.prototype, "chatbotApiClient", void 0);
413
- __decorate([
468
+ _ts_decorate([
414
469
  inject(CHATBOT_UI_STORE_TOKEN),
415
- __metadata("design:type", Object)
470
+ _ts_metadata("design:type", typeof IChatbotUiStore === "undefined" ? Object : IChatbotUiStore)
416
471
  ], ChatbotUiBackendStore.prototype, "chatUiStore", void 0);
417
- __decorate([
472
+ _ts_decorate([
418
473
  inject(Log),
419
- __metadata("design:type", Object)
474
+ _ts_metadata("design:type", typeof ILog === "undefined" ? Object : ILog)
420
475
  ], ChatbotUiBackendStore.prototype, "log", void 0);
421
- ChatbotUiBackendStore = __decorate([
476
+ ChatbotUiBackendStore = _ts_decorate([
422
477
  injectable(),
423
- __metadata("design:paramtypes", [])
478
+ _ts_metadata("design:type", Function),
479
+ _ts_metadata("design:paramtypes", [])
424
480
  ], ChatbotUiBackendStore);
425
- export { ChatbotUiBackendStore };
481
+
426
482
  //# sourceMappingURL=chatbot-ui-backend.store.js.map