@servicetitan/titan-chatbot-api 8.0.0 → 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 (117) hide show
  1. package/CHANGELOG.md +12 -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 +1 -0
  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.map +1 -1
  9. package/dist/api-client/index.d.ts +0 -1
  10. package/dist/api-client/index.d.ts.map +1 -1
  11. package/dist/api-client/index.js +0 -2
  12. package/dist/api-client/index.js.map +1 -1
  13. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.d.ts +2 -0
  14. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.d.ts.map +1 -0
  15. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.js +240 -0
  16. package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.js.map +1 -0
  17. package/dist/api-client/titan-chat/chatbot-api-client.d.ts +11 -0
  18. package/dist/api-client/titan-chat/chatbot-api-client.d.ts.map +1 -1
  19. package/dist/api-client/titan-chat/chatbot-api-client.js +29 -0
  20. package/dist/api-client/titan-chat/chatbot-api-client.js.map +1 -1
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/models/__tests__/chatbot-customizations.test.d.ts +2 -0
  26. package/dist/models/__tests__/chatbot-customizations.test.d.ts.map +1 -0
  27. package/dist/models/__tests__/chatbot-customizations.test.js +36 -0
  28. package/dist/models/__tests__/chatbot-customizations.test.js.map +1 -0
  29. package/dist/models/chatbot-customizations.d.ts +17 -0
  30. package/dist/models/chatbot-customizations.d.ts.map +1 -1
  31. package/dist/models/chatbot-customizations.js +6 -1
  32. package/dist/models/chatbot-customizations.js.map +1 -1
  33. package/dist/models/index.d.ts +1 -1
  34. package/dist/models/index.d.ts.map +1 -1
  35. package/dist/models/index.js +1 -1
  36. package/dist/models/index.js.map +1 -1
  37. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.d.ts +2 -0
  38. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.d.ts.map +1 -0
  39. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.js +107 -0
  40. package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.js.map +1 -0
  41. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.d.ts +2 -0
  42. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.d.ts.map +1 -0
  43. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.js +312 -0
  44. package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.js.map +1 -0
  45. package/dist/stores/chatbot-ui-backend.store.d.ts +26 -2
  46. package/dist/stores/chatbot-ui-backend.store.d.ts.map +1 -1
  47. package/dist/stores/chatbot-ui-backend.store.js +129 -4
  48. package/dist/stores/chatbot-ui-backend.store.js.map +1 -1
  49. package/dist/streaming/__tests__/agent-stream.test.d.ts +2 -0
  50. package/dist/streaming/__tests__/agent-stream.test.d.ts.map +1 -0
  51. package/dist/streaming/__tests__/agent-stream.test.js +92 -0
  52. package/dist/streaming/__tests__/agent-stream.test.js.map +1 -0
  53. package/dist/streaming/agent-stream.d.ts +83 -0
  54. package/dist/streaming/agent-stream.d.ts.map +1 -0
  55. package/dist/streaming/agent-stream.js +28 -0
  56. package/dist/streaming/agent-stream.js.map +1 -0
  57. package/dist/streaming/index.d.ts +3 -0
  58. package/dist/streaming/index.d.ts.map +1 -0
  59. package/dist/streaming/index.js +4 -0
  60. package/dist/streaming/index.js.map +1 -0
  61. package/dist/streaming/run-agent-stream.d.ts +23 -0
  62. package/dist/streaming/run-agent-stream.d.ts.map +1 -0
  63. package/dist/streaming/run-agent-stream.js +83 -0
  64. package/dist/streaming/run-agent-stream.js.map +1 -0
  65. package/package.json +6 -3
  66. package/src/api-client/__mocks__/chatbot-api-client.mock.ts +1 -0
  67. package/src/api-client/base/chatbot-api-client.ts +11 -0
  68. package/src/api-client/index.ts +0 -1
  69. package/src/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.ts +208 -0
  70. package/src/api-client/titan-chat/chatbot-api-client.ts +46 -0
  71. package/src/index.ts +6 -1
  72. package/src/models/__tests__/chatbot-customizations.test.ts +26 -0
  73. package/src/models/chatbot-customizations.ts +20 -0
  74. package/src/models/index.ts +1 -1
  75. package/src/stores/__tests__/chatbot-ui-backend.store.observability.test.ts +105 -0
  76. package/src/stores/__tests__/chatbot-ui-backend.store.streaming.test.ts +261 -0
  77. package/src/stores/chatbot-ui-backend.store.ts +179 -4
  78. package/src/streaming/__tests__/agent-stream.test.ts +80 -0
  79. package/src/streaming/agent-stream.ts +103 -0
  80. package/src/streaming/index.ts +2 -0
  81. package/src/streaming/run-agent-stream.ts +109 -0
  82. package/tsconfig.tsbuildinfo +1 -1
  83. package/dist/api-client/help-center/__tests__/converter-from-models.test.d.ts +0 -2
  84. package/dist/api-client/help-center/__tests__/converter-from-models.test.d.ts.map +0 -1
  85. package/dist/api-client/help-center/__tests__/converter-from-models.test.js +0 -67
  86. package/dist/api-client/help-center/__tests__/converter-from-models.test.js.map +0 -1
  87. package/dist/api-client/help-center/__tests__/converter-to-models.test.d.ts +0 -2
  88. package/dist/api-client/help-center/__tests__/converter-to-models.test.d.ts.map +0 -1
  89. package/dist/api-client/help-center/__tests__/converter-to-models.test.js +0 -83
  90. package/dist/api-client/help-center/__tests__/converter-to-models.test.js.map +0 -1
  91. package/dist/api-client/help-center/chatbot-api-client.d.ts +0 -32
  92. package/dist/api-client/help-center/chatbot-api-client.d.ts.map +0 -1
  93. package/dist/api-client/help-center/chatbot-api-client.js +0 -101
  94. package/dist/api-client/help-center/chatbot-api-client.js.map +0 -1
  95. package/dist/api-client/help-center/converter-from-models.d.ts +0 -13
  96. package/dist/api-client/help-center/converter-from-models.d.ts.map +0 -1
  97. package/dist/api-client/help-center/converter-from-models.js +0 -117
  98. package/dist/api-client/help-center/converter-from-models.js.map +0 -1
  99. package/dist/api-client/help-center/converter-to-models.d.ts +0 -13
  100. package/dist/api-client/help-center/converter-to-models.d.ts.map +0 -1
  101. package/dist/api-client/help-center/converter-to-models.js +0 -101
  102. package/dist/api-client/help-center/converter-to-models.js.map +0 -1
  103. package/dist/api-client/help-center/index.d.ts +0 -3
  104. package/dist/api-client/help-center/index.d.ts.map +0 -1
  105. package/dist/api-client/help-center/index.js +0 -3
  106. package/dist/api-client/help-center/index.js.map +0 -1
  107. package/dist/api-client/help-center/native-client.d.ts +0 -1268
  108. package/dist/api-client/help-center/native-client.d.ts.map +0 -1
  109. package/dist/api-client/help-center/native-client.js +0 -4550
  110. package/dist/api-client/help-center/native-client.js.map +0 -1
  111. package/src/api-client/help-center/__tests__/converter-from-models.test.ts +0 -41
  112. package/src/api-client/help-center/__tests__/converter-to-models.test.ts +0 -89
  113. package/src/api-client/help-center/chatbot-api-client.ts +0 -122
  114. package/src/api-client/help-center/converter-from-models.ts +0 -133
  115. package/src/api-client/help-center/converter-to-models.ts +0 -127
  116. package/src/api-client/help-center/index.ts +0 -2
  117. package/src/api-client/help-center/native-client.ts +0 -5727
@@ -1,11 +1,15 @@
1
1
  import { ILog } from '@servicetitan/log-service';
2
- import { ChatError, ChatMessageModelText, ChatUiEventListener, IChatUiBackendStore } from '@servicetitan/titan-chat-ui-common';
2
+ import { ChatError, ChatMessageModelText, ChatUiEventListener, IChatUiBackendStore, StreamingProgressModel } from '@servicetitan/titan-chat-ui-common';
3
3
  import { IChatbotApiClient, Models } from '../api-client';
4
4
  import { IChatbotUiStore } from './chatbot-ui.store';
5
5
  import { InitializeStore } from './initialize.store';
6
6
  export declare const CHATBOT_UI_BACKEND_STORE_TOKEN: import("@servicetitan/react-ioc").SymbolToken<IChatbotUiBackendStore>;
7
7
  export interface IChatbotUiBackendStore extends IChatUiBackendStore {
8
8
  session?: Models.ISession;
9
+ /** Live progress for the in-flight streamed run. */
10
+ streamingProgress: StreamingProgressModel;
11
+ /** Count of streaming → non-streaming fallbacks. */
12
+ streamingFallbackCount: number;
9
13
  initialize: () => void;
10
14
  saveCurrentState: () => void;
11
15
  deleteFromSessionStorage: () => void;
@@ -16,6 +20,10 @@ export interface IChatbotUiBackendStore extends IChatUiBackendStore {
16
20
  export declare class ChatbotUiBackendStore extends InitializeStore implements IChatbotUiBackendStore {
17
21
  session?: Models.ISession;
18
22
  abortController: AbortController;
23
+ /** Live progress for the in-flight streamed run (status line, activity log, steps, keepalive). */
24
+ readonly streamingProgress: StreamingProgressModel;
25
+ /** Count of streaming → non-streaming fallbacks, tracked separately for regression detection. */
26
+ streamingFallbackCount: number;
19
27
  protected readonly chatbotApiClient: IChatbotApiClient;
20
28
  protected readonly chatUiStore: IChatbotUiStore;
21
29
  private log;
@@ -53,10 +61,26 @@ export declare class ChatbotUiBackendStore extends InitializeStore implements IC
53
61
  protected reset(): void;
54
62
  protected destroy(): Promise<void>;
55
63
  protected processBotAnswer(answer: Models.IBotMessage): void;
64
+ /**
65
+ * Routes a send to the SSE streaming path when enabled (and supported by the client),
66
+ * otherwise to the existing non-streaming path. Default is non-streaming.
67
+ */
68
+ protected routeSend(messageModel: ChatMessageModelText, selections?: Models.Selections, timeoutMs?: number): Promise<void>;
56
69
  protected sendMessage(messageModel: ChatMessageModelText, selections?: Models.Selections, timeoutMs?: number): Promise<void>;
70
+ /**
71
+ * Streaming send-path: consumes the SSE agent-progress stream, rendering live progress and
72
+ * resolving the final answer on `run.finished`. Applies an inactivity-only timeout (no hard
73
+ * request timeout). Falls back transparently to {@link sendMessage} when the stream is
74
+ * unreachable at connect time — propagating the original per-message `timeoutMs` so the
75
+ * fallback behaves identically to the non-streaming path; surfaces a step error if the
76
+ * connection fails after connecting.
77
+ */
78
+ protected sendMessageStreaming(messageModel: ChatMessageModelText, selections?: Models.Selections, timeoutMs?: number): Promise<void>;
79
+ /** Logs a streaming connection lifecycle phase (connected, disconnected, timed_out, completed, fallback). */
80
+ protected logStreaming(phase: string): void;
57
81
  protected setSession(session?: Models.ISession): void;
58
82
  protected startSession(sessionData?: Models.ISession['data'], forceRecreate?: boolean): Promise<Models.ISession | undefined>;
59
- protected api<K extends keyof IChatbotApiClient, Args extends Parameters<IChatbotApiClient[K]>, Result extends ReturnType<IChatbotApiClient[K]>>(methodName: K, ...args: Args): Promise<Awaited<Result>>;
83
+ protected api<K extends keyof IChatbotApiClient, Args extends Parameters<NonNullable<IChatbotApiClient[K]>>, Result extends ReturnType<NonNullable<IChatbotApiClient[K]>>>(methodName: K, ...args: Args): Promise<Awaited<Result>>;
60
84
  protected withSaveState<T>(action: () => T): T;
61
85
  protected setChatError(code: string, error: ChatError): void;
62
86
  protected setError(code: string, title: string, message: string, error: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"chatbot-ui-backend.store.d.ts","sourceRoot":"","sources":["../../src/stores/chatbot-ui-backend.store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chatbot-ui-backend.store.d.ts","sourceRoot":"","sources":["../../src/stores/chatbot-ui-backend.store.ts"],"names":[],"mappings":"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"}
@@ -22,14 +22,18 @@ function _ts_metadata(k, v) {
22
22
  }
23
23
  import { ILog, Log } from '@servicetitan/log-service';
24
24
  import { inject, injectable, symbolToken } from '@servicetitan/react-ioc';
25
- import { ChatError, ChatMessageState, ChatRunState, ChatUiEvent } from '@servicetitan/titan-chat-ui-common';
25
+ import { ChatError, ChatMessageState, ChatRunState, ChatUiEvent, StreamingProgressModel } from '@servicetitan/titan-chat-ui-common';
26
26
  import axios from 'axios';
27
27
  import { makeObservable, runInAction } from 'mobx';
28
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';
29
31
  import { withTimeout } from '../utils/axios-utils';
30
32
  import { CHATBOT_UI_STORE_TOKEN, ChatbotUiEvent, IChatbotUiStore } from './chatbot-ui.store';
31
33
  import { InitializeStore } from './initialize.store';
32
34
  const DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS = 31000; // 31 seconds
35
+ const STREAMING_KEEPALIVE_TEXT = 'Still working on it…';
36
+ const STREAMING_STEP_ERROR = 'Something went wrong during this step. Please try again.';
33
37
  const isAbortedError = (error)=>axios.isCancel(error) || (error === null || error === void 0 ? void 0 : error.name) === 'AbortError';
34
38
  export const CHATBOT_UI_BACKEND_STORE_TOKEN = symbolToken('CHATBOT_UI_BACKEND_STORE_TOKEN');
35
39
  export class ChatbotUiBackendStore extends InitializeStore {
@@ -122,6 +126,15 @@ export class ChatbotUiBackendStore extends InitializeStore {
122
126
  processBotAnswer(answer) {
123
127
  this.chatUiStore.addMessage(true, answer.answer, answer);
124
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
+ }
125
138
  async sendMessage(messageModel, selections, timeoutMs) {
126
139
  const question = messageModel.message;
127
140
  const perRequestController = new AbortController();
@@ -168,6 +181,118 @@ export class ChatbotUiBackendStore extends InitializeStore {
168
181
  this.chatUiStore.setAgentTyping(false);
169
182
  }
170
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{
285
+ this.abortController.signal.removeEventListener('abort', forwardStoreAbort);
286
+ this.chatUiStore.setAgentTyping(false);
287
+ }
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
+ }
171
296
  setSession(session) {
172
297
  this.session = session;
173
298
  }
@@ -244,7 +369,7 @@ export class ChatbotUiBackendStore extends InitializeStore {
244
369
  });
245
370
  }
246
371
  constructor(){
247
- super(), _define_property(this, "session", void 0), _define_property(this, "abortController", void 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)=>{
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)=>{
248
373
  await this.run();
249
374
  resolve();
250
375
  }), _define_property(this, "handleDestroy", async (resolve)=>{
@@ -256,7 +381,7 @@ export class ChatbotUiBackendStore extends InitializeStore {
256
381
  await this.run();
257
382
  resolve();
258
383
  }), _define_property(this, "handleMessageSend", async (resolve, _, messageModel, selections, timeoutMs)=>{
259
- await this.sendMessage(messageModel, selections, timeoutMs);
384
+ await this.routeSend(messageModel, selections, timeoutMs);
260
385
  resolve();
261
386
  }), _define_property(this, "handleMessageSendRetry", async (resolve, _, messageModel)=>{
262
387
  var _messageModel_data, _messageModel_data1;
@@ -266,7 +391,7 @@ export class ChatbotUiBackendStore extends InitializeStore {
266
391
  }
267
392
  const selections = (_messageModel_data = messageModel.data) === null || _messageModel_data === void 0 ? void 0 : _messageModel_data.selections;
268
393
  const timeoutMs = (_messageModel_data1 = messageModel.data) === null || _messageModel_data1 === void 0 ? void 0 : _messageModel_data1.timeoutMs;
269
- await this.sendMessage(messageModel, selections, timeoutMs);
394
+ await this.routeSend(messageModel, selections, timeoutMs);
270
395
  resolve();
271
396
  }), _define_property(this, "handleSessionStart", async (resolve, _, sessionData, forceRecreate)=>{
272
397
  const session = await this.startSession(sessionData, forceRecreate);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/stores/chatbot-ui-backend.store.ts"],"sourcesContent":["import { ILog, Log } from '@servicetitan/log-service';\nimport { inject, injectable, symbolToken } from '@servicetitan/react-ioc';\nimport {\n ChatError,\n ChatMessageModelBase,\n ChatMessageModelText,\n ChatMessageState,\n ChatRunState,\n ChatUiEvent,\n ChatUiEventListener,\n IChatUiBackendStore,\n} from '@servicetitan/titan-chat-ui-common';\nimport axios from 'axios';\nimport { makeObservable, runInAction } from 'mobx';\nimport { CHATBOT_API_CLIENT, IChatbotApiClient, Models, ModelsUtils } from '../api-client';\nimport { withTimeout } from '../utils/axios-utils';\nimport { CHATBOT_UI_STORE_TOKEN, ChatbotUiEvent, IChatbotUiStore } from './chatbot-ui.store';\nimport { InitializeStore } from './initialize.store';\n\nconst DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS = 31000; // 31 seconds\n\nconst isAbortedError = (error: unknown): boolean =>\n axios.isCancel(error) || (error as { name?: string } | null)?.name === 'AbortError';\n\nexport const CHATBOT_UI_BACKEND_STORE_TOKEN = symbolToken<IChatbotUiBackendStore>(\n 'CHATBOT_UI_BACKEND_STORE_TOKEN'\n);\n\nexport interface IChatbotUiBackendStore extends IChatUiBackendStore {\n session?: Models.ISession;\n initialize: () => void;\n saveCurrentState: () => void;\n deleteFromSessionStorage: () => void;\n restoreChatSession: () => void;\n getSessionData: () => Promise<Models.ISession['data'] | undefined>;\n restartTimers: () => void;\n}\n\n@injectable()\nexport class ChatbotUiBackendStore extends InitializeStore implements IChatbotUiBackendStore {\n session?: Models.ISession;\n abortController!: AbortController;\n @inject(CHATBOT_API_CLIENT) protected readonly chatbotApiClient!: IChatbotApiClient;\n @inject(CHATBOT_UI_STORE_TOKEN) protected readonly chatUiStore!: IChatbotUiStore;\n\n @inject(Log) private log!: ILog;\n private sessionPromise?: Promise<Models.ISession>;\n\n protected get logService(): ILog {\n return this.log;\n }\n\n protected get customizations() {\n return this.chatUiStore.customizations;\n }\n\n constructor() {\n super();\n makeObservable(this);\n this.initializeAbortController();\n }\n\n subscribe(): void {\n this.unsubscribe();\n this.chatUiStore.on(ChatUiEvent.eventRun, this.handleRun);\n this.chatUiStore.on(ChatUiEvent.eventDestroy, this.handleDestroy);\n this.chatUiStore.on(ChatUiEvent.eventRestart, this.handleRestart);\n this.chatUiStore.on(ChatUiEvent.eventMessageSend, this.handleMessageSend);\n this.chatUiStore.on(ChatUiEvent.eventMessageSendRetry, this.handleMessageSendRetry);\n this.chatUiStore.on(ChatbotUiEvent.eventChatbotSessionStart, this.handleSessionStart);\n this.chatUiStore.on(ChatbotUiEvent.eventChatbotSessionFeedback, this.handleSessionFeedback);\n this.chatUiStore.on(ChatbotUiEvent.eventChatbotMessageFeedback, this.handleMessageFeedback);\n }\n unsubscribe(): void {\n this.chatUiStore.off(ChatUiEvent.eventRun, this.handleRun);\n this.chatUiStore.off(ChatUiEvent.eventDestroy, this.handleDestroy);\n this.chatUiStore.off(ChatUiEvent.eventRestart, this.handleRestart);\n this.chatUiStore.off(ChatUiEvent.eventMessageSend, this.handleMessageSend);\n this.chatUiStore.off(ChatUiEvent.eventMessageSendRetry, this.handleMessageSendRetry);\n this.chatUiStore.off(ChatbotUiEvent.eventChatbotSessionStart, this.handleSessionStart);\n this.chatUiStore.off(\n ChatbotUiEvent.eventChatbotSessionFeedback,\n this.handleSessionFeedback\n );\n this.chatUiStore.off(\n ChatbotUiEvent.eventChatbotMessageFeedback,\n this.handleMessageFeedback\n );\n }\n\n handleRun: ChatUiEventListener = async resolve => {\n await this.run();\n resolve();\n };\n\n handleDestroy: ChatUiEventListener = async resolve => {\n await this.destroy();\n resolve();\n };\n\n handleRestart: ChatUiEventListener = async resolve => {\n await this.destroy();\n this.deleteFromSessionStorage();\n await this.run();\n resolve();\n };\n\n handleMessageSend: ChatUiEventListener = async (\n resolve,\n _,\n messageModel: ChatMessageModelText,\n selections: Models.Selections | undefined,\n timeoutMs?: number\n ) => {\n await this.sendMessage(messageModel, selections, timeoutMs);\n resolve();\n };\n\n handleMessageSendRetry: ChatUiEventListener = async (\n resolve,\n _,\n messageModel: ChatMessageModelBase\n ) => {\n if (messageModel.type !== 'message') {\n resolve();\n return;\n }\n const selections = messageModel.data?.selections as Models.Selections | undefined;\n const timeoutMs = messageModel.data?.timeoutMs as number | undefined;\n await this.sendMessage(messageModel as ChatMessageModelText, selections, timeoutMs);\n resolve();\n };\n\n handleSessionStart: ChatUiEventListener<{\n session?: Models.ISession;\n }> = async (resolve, _, sessionData?: Models.ISession['data'], forceRecreate?: boolean) => {\n const session = await this.startSession(sessionData, forceRecreate);\n resolve({\n session,\n });\n };\n\n handleSessionFeedback: ChatUiEventListener<{\n state: Models.ChatbotFeedbackState;\n feedback?: Models.Feedback;\n }> = async (resolve, _, draft?: Models.IFeedback) => {\n let feedbackState: Models.ChatbotFeedbackState;\n let feedbackResult: Models.Feedback | undefined = draft\n ? new Models.Feedback(draft)\n : undefined;\n try {\n if (!draft) {\n throw new ChatError('Session feedback is missing.', {\n recoverStrategy: false,\n });\n }\n if (typeof draft.messageId !== 'undefined') {\n throw new ChatError('Session feedback should not contain messageId.', {\n recoverStrategy: false,\n });\n }\n await this.startSession();\n const feedback = new Models.Feedback({ ...draft, sessionId: this.session!.id! });\n feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);\n feedbackState = Models.ChatbotFeedbackState.Success;\n } catch (error: unknown) {\n this.setError(\n 'FailedToSendFeedback',\n 'Send session feedback',\n 'Failed to send feedback',\n error\n );\n feedbackState = Models.ChatbotFeedbackState.Failure;\n }\n resolve({\n state: feedbackState,\n feedback: feedbackResult,\n });\n };\n\n handleMessageFeedback: ChatUiEventListener<{\n state: Models.ChatbotFeedbackState;\n feedback?: Models.Feedback;\n }> = async (resolve, _, draft?: Models.IFeedback) => {\n let feedbackState: Models.ChatbotFeedbackState;\n let feedbackResult: Models.Feedback | undefined = draft\n ? new Models.Feedback(draft)\n : undefined;\n try {\n if (!draft) {\n throw new ChatError('Message feedback is missing.', {\n recoverStrategy: false,\n });\n }\n if (!draft.messageId) {\n throw new ChatError('Message feedback is missing messageId.', {\n recoverStrategy: false,\n });\n }\n await this.startSession();\n const feedback = new Models.Feedback({ ...draft, sessionId: this.session!.id! });\n feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);\n feedbackState = Models.ChatbotFeedbackState.Success;\n } catch (error: unknown) {\n this.setError(\n 'FailedToSendMessageFeedback',\n 'Send message feedback',\n 'Failed to send message feedback',\n error\n );\n feedbackState = Models.ChatbotFeedbackState.Failure;\n }\n resolve({\n state: feedbackState,\n feedback: feedbackResult,\n });\n };\n\n async getSessionData(): Promise<Models.ISession['data'] | undefined> {\n return Promise.resolve(undefined);\n }\n\n restoreChatSession() {}\n\n saveCurrentState() {}\n\n deleteFromSessionStorage() {}\n\n restartTimers() {}\n\n protected ensureWelcomeMessage() {\n if (this.chatUiStore.messages.length) {\n return;\n }\n this.withSaveState(() => {\n this.chatUiStore.addMessageWelcome(\n `Hi there! I’m ${this.chatUiStore.agent.name}, an AI chatbot powered by Titan Intelligence. ` +\n 'I’m here to answer your questions about using ServiceTitan. ' +\n 'You can ask me things like \"How to merge duplicate customers?\". ' +\n 'Do you have a question for me?'\n );\n });\n }\n\n protected logError(code: string, message: string, error: any) {\n if (isAbortedError(error)) {\n return;\n }\n this.logService.error({\n error,\n message,\n category: 'TitanChatbot',\n code: `TitanChatbot_${code}`,\n });\n }\n\n protected override async initializeInternal() {\n await super.initializeInternal();\n const options = await this.chatbotApiClient.getOptions();\n runInAction(() => {\n this.chatUiStore.filterStore.initFilters(options, {\n isDefaultSelected: this.customizations?.filters?.isDefaultSelected,\n });\n });\n }\n\n protected async run() {\n this.chatUiStore.setStatus(ChatRunState.Initializing);\n try {\n await this.initialize();\n this.restoreChatSession();\n this.ensureWelcomeMessage();\n this.restartTimers();\n this.chatUiStore.setStatus(ChatRunState.Started);\n } catch (error: unknown) {\n this.setError(\n 'FailedToInitialize',\n 'Initialization Error',\n 'Unable to start the chatbot service. Please check your connection and refresh the page.',\n error\n );\n }\n }\n\n protected reset() {\n this.setSession(undefined);\n }\n\n protected async destroy() {\n if (this.session) {\n const session = await this.api('deleteSession', this.session);\n this.setSession(session);\n }\n this.reset();\n this.chatUiStore.reset();\n }\n\n protected processBotAnswer(answer: Models.IBotMessage) {\n this.chatUiStore.addMessage(true, answer.answer, answer);\n }\n\n protected async sendMessage(\n messageModel: ChatMessageModelText,\n selections?: Models.Selections,\n timeoutMs?: number\n ) {\n const question = messageModel.message;\n const perRequestController = new AbortController();\n const forwardStoreAbort = () =>\n perRequestController.abort(this.abortController.signal.reason);\n this.abortController.signal.addEventListener('abort', forwardStoreAbort, { once: true });\n try {\n await this.startSession();\n this.chatUiStore.setAgentTyping(true);\n const answer = await withTimeout(\n this.api(\n 'postMessage',\n new Models.UserMessage({\n sessionId: this.session!.id!,\n question,\n experience: Models.Experience.MultiTurn,\n selections,\n }),\n perRequestController.signal\n ),\n timeoutMs ??\n this.customizations?.timeouts?.chatbotRequestTimeoutMs ??\n DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS,\n perRequestController\n );\n this.withSaveState(() => {\n // Set message state to Delivered and preserve selections and bot answer id to the user question (to have a link between question and answer)\n this.chatUiStore.setMessageState(messageModel, ChatMessageState.Delivered, {\n answerId: answer.id,\n selections,\n });\n this.processBotAnswer(answer);\n this.chatUiStore.resetError(ChatRunState.Started);\n });\n } catch (error: unknown) {\n this.withSaveState(() => {\n this.chatUiStore.setMessageState(messageModel, ChatMessageState.Failed, {\n selections,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n });\n });\n if (error instanceof ChatError) {\n this.setChatError('FailedToSendMessage', error);\n } else {\n this.setError(\n 'FailedToSendMessage',\n 'Send message',\n 'Failed to send message',\n error\n );\n }\n } finally {\n this.abortController.signal.removeEventListener('abort', forwardStoreAbort);\n this.chatUiStore.setAgentTyping(false);\n }\n }\n\n protected setSession(session?: Models.ISession) {\n this.session = session;\n }\n\n protected async startSession(sessionData?: Models.ISession['data'], forceRecreate = false) {\n if (forceRecreate) {\n this.reset();\n this.sessionPromise = undefined;\n }\n if (this.session) {\n return this.session;\n }\n if (!this.sessionPromise) {\n this.sessionPromise = (async () => {\n let data = await this.getSessionData();\n if (sessionData) {\n data = { ...data, ...sessionData };\n }\n return this.api(\n 'postSession',\n ModelsUtils.createNewSessionModel({ data }),\n this.abortController.signal\n );\n })();\n const session = await this.sessionPromise;\n this.setSession(session);\n this.withSaveState(() => {\n this.chatUiStore.resetError(ChatRunState.Started);\n });\n }\n try {\n await this.sessionPromise;\n } finally {\n this.sessionPromise = undefined;\n }\n return this.session;\n }\n\n protected async api<\n K extends keyof IChatbotApiClient,\n Args extends Parameters<IChatbotApiClient[K]>,\n Result extends ReturnType<IChatbotApiClient[K]>,\n >(methodName: K, ...args: Args): Promise<Awaited<Result>> {\n const method = this.chatbotApiClient[methodName];\n if (method) {\n try {\n return (method as (...args: Args) => Result).call(\n this.chatbotApiClient,\n ...args\n ) as Promise<Awaited<Result>>;\n } finally {\n this.restartTimers();\n }\n }\n throw new Error(`Method '${methodName}' not found in the API.`);\n }\n\n protected withSaveState<T>(action: () => T): T {\n const result = action();\n this.saveCurrentState();\n return result;\n }\n\n protected setChatError(code: string, error: ChatError) {\n this.logError(code, error.message, error);\n this.withSaveState(() => {\n this.chatUiStore.setChatError(error);\n });\n }\n\n protected setError(code: string, title: string, message: string, error: any) {\n if (isAbortedError(error)) {\n return;\n }\n this.logError(code, message, error);\n this.withSaveState(() => {\n this.chatUiStore.setError(message, error?.message ?? error);\n });\n }\n\n protected initializeAbortController(): void {\n this.abortController = new AbortController();\n this.abortController.signal.addEventListener('abort', () => {\n this.initializeAbortController();\n });\n }\n}\n"],"names":["ILog","Log","inject","injectable","symbolToken","ChatError","ChatMessageState","ChatRunState","ChatUiEvent","axios","makeObservable","runInAction","CHATBOT_API_CLIENT","IChatbotApiClient","Models","ModelsUtils","withTimeout","CHATBOT_UI_STORE_TOKEN","ChatbotUiEvent","IChatbotUiStore","InitializeStore","DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS","isAbortedError","error","isCancel","name","CHATBOT_UI_BACKEND_STORE_TOKEN","ChatbotUiBackendStore","logService","log","customizations","chatUiStore","subscribe","unsubscribe","on","eventRun","handleRun","eventDestroy","handleDestroy","eventRestart","handleRestart","eventMessageSend","handleMessageSend","eventMessageSendRetry","handleMessageSendRetry","eventChatbotSessionStart","handleSessionStart","eventChatbotSessionFeedback","handleSessionFeedback","eventChatbotMessageFeedback","handleMessageFeedback","off","getSessionData","Promise","resolve","undefined","restoreChatSession","saveCurrentState","deleteFromSessionStorage","restartTimers","ensureWelcomeMessage","messages","length","withSaveState","addMessageWelcome","agent","logError","code","message","category","initializeInternal","options","chatbotApiClient","getOptions","filterStore","initFilters","isDefaultSelected","filters","run","setStatus","Initializing","initialize","Started","setError","reset","setSession","destroy","session","api","processBotAnswer","answer","addMessage","sendMessage","messageModel","selections","timeoutMs","question","perRequestController","AbortController","forwardStoreAbort","abort","abortController","signal","reason","addEventListener","once","startSession","setAgentTyping","UserMessage","sessionId","id","experience","Experience","MultiTurn","timeouts","chatbotRequestTimeoutMs","setMessageState","Delivered","answerId","resetError","Failed","setChatError","removeEventListener","sessionData","forceRecreate","sessionPromise","data","createNewSessionModel","methodName","args","method","call","Error","action","result","title","initializeAbortController","_","type","draft","feedbackState","feedbackResult","Feedback","recoverStrategy","messageId","feedback","ChatbotFeedbackState","Success","Failure","state"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/stores/chatbot-ui-backend.store.ts"],"sourcesContent":["import { ILog, Log } from '@servicetitan/log-service';\nimport { inject, injectable, symbolToken } from '@servicetitan/react-ioc';\nimport {\n ChatError,\n ChatMessageModelBase,\n ChatMessageModelText,\n ChatMessageState,\n ChatRunState,\n ChatUiEvent,\n ChatUiEventListener,\n IChatUiBackendStore,\n StreamingProgressModel,\n} from '@servicetitan/titan-chat-ui-common';\nimport axios from 'axios';\nimport { makeObservable, runInAction } from 'mobx';\nimport { CHATBOT_API_CLIENT, IChatbotApiClient, Models, ModelsUtils } from '../api-client';\nimport {\n DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS,\n isChatbotStreamingEnabled,\n} from '../models/chatbot-customizations';\nimport { AgentStreamError, AgentStreamHandlers } from '../streaming';\nimport { withTimeout } from '../utils/axios-utils';\nimport { CHATBOT_UI_STORE_TOKEN, ChatbotUiEvent, IChatbotUiStore } from './chatbot-ui.store';\nimport { InitializeStore } from './initialize.store';\n\nconst DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS = 31000; // 31 seconds\n\nconst STREAMING_KEEPALIVE_TEXT = 'Still working on it…';\nconst STREAMING_STEP_ERROR = 'Something went wrong during this step. Please try again.';\n\nconst isAbortedError = (error: unknown): boolean =>\n axios.isCancel(error) || (error as { name?: string } | null)?.name === 'AbortError';\n\nexport const CHATBOT_UI_BACKEND_STORE_TOKEN = symbolToken<IChatbotUiBackendStore>(\n 'CHATBOT_UI_BACKEND_STORE_TOKEN'\n);\n\nexport interface IChatbotUiBackendStore extends IChatUiBackendStore {\n session?: Models.ISession;\n /** Live progress for the in-flight streamed run. */\n streamingProgress: StreamingProgressModel;\n /** Count of streaming → non-streaming fallbacks. */\n streamingFallbackCount: number;\n initialize: () => void;\n saveCurrentState: () => void;\n deleteFromSessionStorage: () => void;\n restoreChatSession: () => void;\n getSessionData: () => Promise<Models.ISession['data'] | undefined>;\n restartTimers: () => void;\n}\n\n@injectable()\nexport class ChatbotUiBackendStore extends InitializeStore implements IChatbotUiBackendStore {\n session?: Models.ISession;\n abortController!: AbortController;\n\n /** Live progress for the in-flight streamed run (status line, activity log, steps, keepalive). */\n readonly streamingProgress = new StreamingProgressModel();\n /** Count of streaming → non-streaming fallbacks, tracked separately for regression detection. */\n streamingFallbackCount = 0;\n\n @inject(CHATBOT_API_CLIENT) protected readonly chatbotApiClient!: IChatbotApiClient;\n @inject(CHATBOT_UI_STORE_TOKEN) protected readonly chatUiStore!: IChatbotUiStore;\n\n @inject(Log) private log!: ILog;\n private sessionPromise?: Promise<Models.ISession>;\n\n protected get logService(): ILog {\n return this.log;\n }\n\n protected get customizations() {\n return this.chatUiStore.customizations;\n }\n\n constructor() {\n super();\n makeObservable(this);\n this.initializeAbortController();\n }\n\n subscribe(): void {\n this.unsubscribe();\n this.chatUiStore.on(ChatUiEvent.eventRun, this.handleRun);\n this.chatUiStore.on(ChatUiEvent.eventDestroy, this.handleDestroy);\n this.chatUiStore.on(ChatUiEvent.eventRestart, this.handleRestart);\n this.chatUiStore.on(ChatUiEvent.eventMessageSend, this.handleMessageSend);\n this.chatUiStore.on(ChatUiEvent.eventMessageSendRetry, this.handleMessageSendRetry);\n this.chatUiStore.on(ChatbotUiEvent.eventChatbotSessionStart, this.handleSessionStart);\n this.chatUiStore.on(ChatbotUiEvent.eventChatbotSessionFeedback, this.handleSessionFeedback);\n this.chatUiStore.on(ChatbotUiEvent.eventChatbotMessageFeedback, this.handleMessageFeedback);\n }\n unsubscribe(): void {\n this.chatUiStore.off(ChatUiEvent.eventRun, this.handleRun);\n this.chatUiStore.off(ChatUiEvent.eventDestroy, this.handleDestroy);\n this.chatUiStore.off(ChatUiEvent.eventRestart, this.handleRestart);\n this.chatUiStore.off(ChatUiEvent.eventMessageSend, this.handleMessageSend);\n this.chatUiStore.off(ChatUiEvent.eventMessageSendRetry, this.handleMessageSendRetry);\n this.chatUiStore.off(ChatbotUiEvent.eventChatbotSessionStart, this.handleSessionStart);\n this.chatUiStore.off(\n ChatbotUiEvent.eventChatbotSessionFeedback,\n this.handleSessionFeedback\n );\n this.chatUiStore.off(\n ChatbotUiEvent.eventChatbotMessageFeedback,\n this.handleMessageFeedback\n );\n }\n\n handleRun: ChatUiEventListener = async resolve => {\n await this.run();\n resolve();\n };\n\n handleDestroy: ChatUiEventListener = async resolve => {\n await this.destroy();\n resolve();\n };\n\n handleRestart: ChatUiEventListener = async resolve => {\n await this.destroy();\n this.deleteFromSessionStorage();\n await this.run();\n resolve();\n };\n\n handleMessageSend: ChatUiEventListener = async (\n resolve,\n _,\n messageModel: ChatMessageModelText,\n selections: Models.Selections | undefined,\n timeoutMs?: number\n ) => {\n await this.routeSend(messageModel, selections, timeoutMs);\n resolve();\n };\n\n handleMessageSendRetry: ChatUiEventListener = async (\n resolve,\n _,\n messageModel: ChatMessageModelBase\n ) => {\n if (messageModel.type !== 'message') {\n resolve();\n return;\n }\n const selections = messageModel.data?.selections as Models.Selections | undefined;\n const timeoutMs = messageModel.data?.timeoutMs as number | undefined;\n await this.routeSend(messageModel as ChatMessageModelText, selections, timeoutMs);\n resolve();\n };\n\n handleSessionStart: ChatUiEventListener<{\n session?: Models.ISession;\n }> = async (resolve, _, sessionData?: Models.ISession['data'], forceRecreate?: boolean) => {\n const session = await this.startSession(sessionData, forceRecreate);\n resolve({\n session,\n });\n };\n\n handleSessionFeedback: ChatUiEventListener<{\n state: Models.ChatbotFeedbackState;\n feedback?: Models.Feedback;\n }> = async (resolve, _, draft?: Models.IFeedback) => {\n let feedbackState: Models.ChatbotFeedbackState;\n let feedbackResult: Models.Feedback | undefined = draft\n ? new Models.Feedback(draft)\n : undefined;\n try {\n if (!draft) {\n throw new ChatError('Session feedback is missing.', {\n recoverStrategy: false,\n });\n }\n if (typeof draft.messageId !== 'undefined') {\n throw new ChatError('Session feedback should not contain messageId.', {\n recoverStrategy: false,\n });\n }\n await this.startSession();\n const feedback = new Models.Feedback({ ...draft, sessionId: this.session!.id! });\n feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);\n feedbackState = Models.ChatbotFeedbackState.Success;\n } catch (error: unknown) {\n this.setError(\n 'FailedToSendFeedback',\n 'Send session feedback',\n 'Failed to send feedback',\n error\n );\n feedbackState = Models.ChatbotFeedbackState.Failure;\n }\n resolve({\n state: feedbackState,\n feedback: feedbackResult,\n });\n };\n\n handleMessageFeedback: ChatUiEventListener<{\n state: Models.ChatbotFeedbackState;\n feedback?: Models.Feedback;\n }> = async (resolve, _, draft?: Models.IFeedback) => {\n let feedbackState: Models.ChatbotFeedbackState;\n let feedbackResult: Models.Feedback | undefined = draft\n ? new Models.Feedback(draft)\n : undefined;\n try {\n if (!draft) {\n throw new ChatError('Message feedback is missing.', {\n recoverStrategy: false,\n });\n }\n if (!draft.messageId) {\n throw new ChatError('Message feedback is missing messageId.', {\n recoverStrategy: false,\n });\n }\n await this.startSession();\n const feedback = new Models.Feedback({ ...draft, sessionId: this.session!.id! });\n feedbackResult = await this.api('postFeedback', feedback, this.abortController.signal);\n feedbackState = Models.ChatbotFeedbackState.Success;\n } catch (error: unknown) {\n this.setError(\n 'FailedToSendMessageFeedback',\n 'Send message feedback',\n 'Failed to send message feedback',\n error\n );\n feedbackState = Models.ChatbotFeedbackState.Failure;\n }\n resolve({\n state: feedbackState,\n feedback: feedbackResult,\n });\n };\n\n async getSessionData(): Promise<Models.ISession['data'] | undefined> {\n return Promise.resolve(undefined);\n }\n\n restoreChatSession() {}\n\n saveCurrentState() {}\n\n deleteFromSessionStorage() {}\n\n restartTimers() {}\n\n protected ensureWelcomeMessage() {\n if (this.chatUiStore.messages.length) {\n return;\n }\n this.withSaveState(() => {\n this.chatUiStore.addMessageWelcome(\n `Hi there! I’m ${this.chatUiStore.agent.name}, an AI chatbot powered by Titan Intelligence. ` +\n 'I’m here to answer your questions about using ServiceTitan. ' +\n 'You can ask me things like \"How to merge duplicate customers?\". ' +\n 'Do you have a question for me?'\n );\n });\n }\n\n protected logError(code: string, message: string, error: any) {\n if (isAbortedError(error)) {\n return;\n }\n this.logService.error({\n error,\n message,\n category: 'TitanChatbot',\n code: `TitanChatbot_${code}`,\n });\n }\n\n protected override async initializeInternal() {\n await super.initializeInternal();\n const options = await this.chatbotApiClient.getOptions();\n runInAction(() => {\n this.chatUiStore.filterStore.initFilters(options, {\n isDefaultSelected: this.customizations?.filters?.isDefaultSelected,\n });\n });\n }\n\n protected async run() {\n this.chatUiStore.setStatus(ChatRunState.Initializing);\n try {\n await this.initialize();\n this.restoreChatSession();\n this.ensureWelcomeMessage();\n this.restartTimers();\n this.chatUiStore.setStatus(ChatRunState.Started);\n } catch (error: unknown) {\n this.setError(\n 'FailedToInitialize',\n 'Initialization Error',\n 'Unable to start the chatbot service. Please check your connection and refresh the page.',\n error\n );\n }\n }\n\n protected reset() {\n this.setSession(undefined);\n }\n\n protected async destroy() {\n if (this.session) {\n const session = await this.api('deleteSession', this.session);\n this.setSession(session);\n }\n this.reset();\n this.chatUiStore.reset();\n }\n\n protected processBotAnswer(answer: Models.IBotMessage) {\n this.chatUiStore.addMessage(true, answer.answer, answer);\n }\n\n /**\n * Routes a send to the SSE streaming path when enabled (and supported by the client),\n * otherwise to the existing non-streaming path. Default is non-streaming.\n */\n protected routeSend(\n messageModel: ChatMessageModelText,\n selections?: Models.Selections,\n timeoutMs?: number\n ): Promise<void> {\n if (isChatbotStreamingEnabled(this.customizations) && this.chatbotApiClient.streamMessage) {\n return this.sendMessageStreaming(messageModel, selections, timeoutMs);\n }\n return this.sendMessage(messageModel, selections, timeoutMs);\n }\n\n protected async sendMessage(\n messageModel: ChatMessageModelText,\n selections?: Models.Selections,\n timeoutMs?: number\n ) {\n const question = messageModel.message;\n const perRequestController = new AbortController();\n const forwardStoreAbort = () =>\n perRequestController.abort(this.abortController.signal.reason);\n this.abortController.signal.addEventListener('abort', forwardStoreAbort, { once: true });\n try {\n await this.startSession();\n this.chatUiStore.setAgentTyping(true);\n const answer = await withTimeout(\n this.api(\n 'postMessage',\n new Models.UserMessage({\n sessionId: this.session!.id!,\n question,\n experience: Models.Experience.MultiTurn,\n selections,\n }),\n perRequestController.signal\n ),\n timeoutMs ??\n this.customizations?.timeouts?.chatbotRequestTimeoutMs ??\n DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS,\n perRequestController\n );\n this.withSaveState(() => {\n // Set message state to Delivered and preserve selections and bot answer id to the user question (to have a link between question and answer)\n this.chatUiStore.setMessageState(messageModel, ChatMessageState.Delivered, {\n answerId: answer.id,\n selections,\n });\n this.processBotAnswer(answer);\n this.chatUiStore.resetError(ChatRunState.Started);\n });\n } catch (error: unknown) {\n this.withSaveState(() => {\n this.chatUiStore.setMessageState(messageModel, ChatMessageState.Failed, {\n selections,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n });\n });\n if (error instanceof ChatError) {\n this.setChatError('FailedToSendMessage', error);\n } else {\n this.setError(\n 'FailedToSendMessage',\n 'Send message',\n 'Failed to send message',\n error\n );\n }\n } finally {\n this.abortController.signal.removeEventListener('abort', forwardStoreAbort);\n this.chatUiStore.setAgentTyping(false);\n }\n }\n\n /**\n * Streaming send-path: consumes the SSE agent-progress stream, rendering live progress and\n * resolving the final answer on `run.finished`. Applies an inactivity-only timeout (no hard\n * request timeout). Falls back transparently to {@link sendMessage} when the stream is\n * unreachable at connect time — propagating the original per-message `timeoutMs` so the\n * fallback behaves identically to the non-streaming path; surfaces a step error if the\n * connection fails after connecting.\n */\n protected async sendMessageStreaming(\n messageModel: ChatMessageModelText,\n selections?: Models.Selections,\n timeoutMs?: number\n ) {\n const question = messageModel.message;\n const perRequestController = new AbortController();\n const forwardStoreAbort = () =>\n perRequestController.abort(this.abortController.signal.reason);\n this.abortController.signal.addEventListener('abort', forwardStoreAbort, { once: true });\n\n let connected = false;\n try {\n await this.startSession();\n this.chatUiStore.setAgentTyping(true);\n runInAction(() => this.streamingProgress.reset());\n\n const inactivityTimeoutMs =\n this.customizations?.streaming?.inactivityTimeoutMs ??\n DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS;\n\n // Apply a progress mutation, then scroll so the newest event stays in view.\n const updateProgress = (mutate: () => void) => {\n runInAction(mutate);\n this.chatUiStore.triggerScroll();\n };\n\n const handlers: AgentStreamHandlers = {\n inactivityTimeoutMs,\n onStatus: text =>\n updateProgress(() => {\n this.streamingProgress.clearKeepalive();\n this.streamingProgress.setStatus(text);\n }),\n onText: text =>\n updateProgress(() => {\n this.streamingProgress.clearKeepalive();\n this.streamingProgress.appendLog(text);\n }),\n onPlan: steps =>\n updateProgress(() => {\n this.streamingProgress.clearKeepalive();\n this.streamingProgress.setSteps(steps);\n }),\n onStepActive: id =>\n updateProgress(() => {\n this.streamingProgress.clearKeepalive();\n this.streamingProgress.setActiveStep(id);\n }),\n onInactivity: () =>\n updateProgress(() =>\n this.streamingProgress.setKeepalive(STREAMING_KEEPALIVE_TEXT)\n ),\n onConnected: () => {\n connected = true;\n this.logStreaming('connected');\n },\n onDisconnected: () => this.logStreaming('disconnected'),\n onTimeout: () => this.logStreaming('timed_out'),\n onCompleted: () => this.logStreaming('completed'),\n };\n\n const answer = await this.api(\n 'streamMessage',\n new Models.UserMessage({\n sessionId: this.session!.id!,\n question,\n experience: Models.Experience.MultiTurn,\n selections,\n }),\n handlers,\n perRequestController.signal\n );\n\n this.withSaveState(() => {\n this.chatUiStore.setMessageState(messageModel, ChatMessageState.Delivered, {\n answerId: answer.id,\n selections,\n });\n this.processBotAnswer(answer);\n this.chatUiStore.resetError(ChatRunState.Started);\n });\n /*\n * Mark every plan step done and clear the transient keepalive; the rendered trail is\n * faded by the UI once the final answer is shown. The next streamed send resets the model.\n */\n runInAction(() => {\n this.streamingProgress.completeAllSteps();\n this.streamingProgress.clearKeepalive();\n });\n } catch (error: unknown) {\n if (isAbortedError(error)) {\n return;\n }\n\n // Never connected → the endpoint was unreachable at connect time: fall back silently.\n if (!connected) {\n this.streamingFallbackCount += 1;\n this.logStreaming('fallback');\n runInAction(() => this.streamingProgress.reset());\n await this.sendMessage(messageModel, selections, timeoutMs);\n return;\n }\n\n // Connected then failed: surface the step error (the agent's message if provided).\n this.withSaveState(() => {\n this.chatUiStore.setMessageState(messageModel, ChatMessageState.Failed, {\n selections,\n });\n });\n runInAction(() => this.streamingProgress.reset());\n const message =\n error instanceof AgentStreamError ? error.message : STREAMING_STEP_ERROR;\n if (error instanceof ChatError) {\n this.setChatError('FailedToSendMessage', error);\n } else {\n this.setError('FailedToSendMessage', 'Send message', message, error);\n }\n } finally {\n this.abortController.signal.removeEventListener('abort', forwardStoreAbort);\n this.chatUiStore.setAgentTyping(false);\n }\n }\n\n /** Logs a streaming connection lifecycle phase (connected, disconnected, timed_out, completed, fallback). */\n protected logStreaming(phase: string): void {\n this.logService.info({\n message: `Streaming ${phase}`,\n category: 'TitanChatbot',\n code: `TitanChatbot_Streaming_${phase}`,\n });\n }\n\n protected setSession(session?: Models.ISession) {\n this.session = session;\n }\n\n protected async startSession(sessionData?: Models.ISession['data'], forceRecreate = false) {\n if (forceRecreate) {\n this.reset();\n this.sessionPromise = undefined;\n }\n if (this.session) {\n return this.session;\n }\n if (!this.sessionPromise) {\n this.sessionPromise = (async () => {\n let data = await this.getSessionData();\n if (sessionData) {\n data = { ...data, ...sessionData };\n }\n return this.api(\n 'postSession',\n ModelsUtils.createNewSessionModel({ data }),\n this.abortController.signal\n );\n })();\n const session = await this.sessionPromise;\n this.setSession(session);\n this.withSaveState(() => {\n this.chatUiStore.resetError(ChatRunState.Started);\n });\n }\n try {\n await this.sessionPromise;\n } finally {\n this.sessionPromise = undefined;\n }\n return this.session;\n }\n\n protected async api<\n K extends keyof IChatbotApiClient,\n Args extends Parameters<NonNullable<IChatbotApiClient[K]>>,\n Result extends ReturnType<NonNullable<IChatbotApiClient[K]>>,\n >(methodName: K, ...args: Args): Promise<Awaited<Result>> {\n const method = this.chatbotApiClient[methodName];\n if (method) {\n try {\n return (method as (...args: Args) => Result).call(\n this.chatbotApiClient,\n ...args\n ) as Promise<Awaited<Result>>;\n } finally {\n this.restartTimers();\n }\n }\n throw new Error(`Method '${methodName}' not found in the API.`);\n }\n\n protected withSaveState<T>(action: () => T): T {\n const result = action();\n this.saveCurrentState();\n return result;\n }\n\n protected setChatError(code: string, error: ChatError) {\n this.logError(code, error.message, error);\n this.withSaveState(() => {\n this.chatUiStore.setChatError(error);\n });\n }\n\n protected setError(code: string, title: string, message: string, error: any) {\n if (isAbortedError(error)) {\n return;\n }\n this.logError(code, message, error);\n this.withSaveState(() => {\n this.chatUiStore.setError(message, error?.message ?? error);\n });\n }\n\n protected initializeAbortController(): void {\n this.abortController = new AbortController();\n this.abortController.signal.addEventListener('abort', () => {\n this.initializeAbortController();\n });\n }\n}\n"],"names":["ILog","Log","inject","injectable","symbolToken","ChatError","ChatMessageState","ChatRunState","ChatUiEvent","StreamingProgressModel","axios","makeObservable","runInAction","CHATBOT_API_CLIENT","IChatbotApiClient","Models","ModelsUtils","DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS","isChatbotStreamingEnabled","AgentStreamError","withTimeout","CHATBOT_UI_STORE_TOKEN","ChatbotUiEvent","IChatbotUiStore","InitializeStore","DEFAULT_CHATBOT_ASK_BOT_TIMEOUT_MS","STREAMING_KEEPALIVE_TEXT","STREAMING_STEP_ERROR","isAbortedError","error","isCancel","name","CHATBOT_UI_BACKEND_STORE_TOKEN","ChatbotUiBackendStore","logService","log","customizations","chatUiStore","subscribe","unsubscribe","on","eventRun","handleRun","eventDestroy","handleDestroy","eventRestart","handleRestart","eventMessageSend","handleMessageSend","eventMessageSendRetry","handleMessageSendRetry","eventChatbotSessionStart","handleSessionStart","eventChatbotSessionFeedback","handleSessionFeedback","eventChatbotMessageFeedback","handleMessageFeedback","off","getSessionData","Promise","resolve","undefined","restoreChatSession","saveCurrentState","deleteFromSessionStorage","restartTimers","ensureWelcomeMessage","messages","length","withSaveState","addMessageWelcome","agent","logError","code","message","category","initializeInternal","options","chatbotApiClient","getOptions","filterStore","initFilters","isDefaultSelected","filters","run","setStatus","Initializing","initialize","Started","setError","reset","setSession","destroy","session","api","processBotAnswer","answer","addMessage","routeSend","messageModel","selections","timeoutMs","streamMessage","sendMessageStreaming","sendMessage","question","perRequestController","AbortController","forwardStoreAbort","abort","abortController","signal","reason","addEventListener","once","startSession","setAgentTyping","UserMessage","sessionId","id","experience","Experience","MultiTurn","timeouts","chatbotRequestTimeoutMs","setMessageState","Delivered","answerId","resetError","Failed","setChatError","removeEventListener","connected","streamingProgress","inactivityTimeoutMs","streaming","updateProgress","mutate","triggerScroll","handlers","onStatus","text","clearKeepalive","onText","appendLog","onPlan","steps","setSteps","onStepActive","setActiveStep","onInactivity","setKeepalive","onConnected","logStreaming","onDisconnected","onTimeout","onCompleted","completeAllSteps","streamingFallbackCount","phase","info","sessionData","forceRecreate","sessionPromise","data","createNewSessionModel","methodName","args","method","call","Error","action","result","title","initializeAbortController","_","type","draft","feedbackState","feedbackResult","Feedback","recoverStrategy","messageId","feedback","ChatbotFeedbackState","Success","Failure","state"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-stream.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-stream.test.d.ts","sourceRoot":"","sources":["../../../src/streaming/__tests__/agent-stream.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ import { describe, expect, test } from '@jest/globals';
2
+ import { Models } from '../../api-client';
3
+ import { convertAgentFinishToBotMessage } from '../agent-stream';
4
+ describe('convertAgentFinishToBotMessage', ()=>{
5
+ test('preserves the backend BotMessage fields verbatim', ()=>{
6
+ // Real Bifurcation payload: backend sends guardFlag "BI" + isGuardrailed true.
7
+ const message = convertAgentFinishToBotMessage({
8
+ answer: 'pick one',
9
+ guardFlag: 'BI',
10
+ isGuardrailed: true,
11
+ sessionId: 122,
12
+ status: 'Bifurcation'
13
+ });
14
+ expect(message).toBeInstanceOf(Models.BotMessage);
15
+ expect(message.answer).toBe('pick one');
16
+ expect(message.guardFlag).toBe('BI');
17
+ expect(message.isGuardrailed).toBe(true);
18
+ expect(message.sessionId).toBe(122);
19
+ });
20
+ test('ignores streaming-only metadata (status, durationMs, runId, seq)', ()=>{
21
+ const message = convertAgentFinishToBotMessage({
22
+ answer: 'ok',
23
+ guardFlag: 'N',
24
+ isGuardrailed: false,
25
+ status: 'Success',
26
+ durationMs: 13603,
27
+ runId: 'ec66a0b47d99430a99b964f7478aadd7',
28
+ seq: 6
29
+ });
30
+ const json = message.toJSON();
31
+ expect(json).not.toHaveProperty('status');
32
+ expect(json).not.toHaveProperty('durationMs');
33
+ expect(json).not.toHaveProperty('runId');
34
+ expect(json).not.toHaveProperty('seq');
35
+ });
36
+ test('wraps nested data into serializable instances (toJSON does not throw)', ()=>{
37
+ var _message_scoredUrls, _message_agentOptions, _message_workflowPlan;
38
+ // Mirrors the decoded SSE JSON: nested data arrives as plain objects, not class instances.
39
+ const payload = {
40
+ answer: 'final',
41
+ guardFlag: 'BI',
42
+ isGuardrailed: true,
43
+ sessionId: 3,
44
+ scoredUrls: [
45
+ {
46
+ url: 'https://kb/1',
47
+ score: 0.9,
48
+ title: 'Doc'
49
+ }
50
+ ],
51
+ agentOptions: [
52
+ {
53
+ agentId: 'playwright',
54
+ passPhrase: 'Do it for me',
55
+ caption: 'Auto'
56
+ }
57
+ ],
58
+ workflowPlan: {
59
+ displayName: 'Refund',
60
+ estimatedRuntimeSec: 5,
61
+ steps: [
62
+ {
63
+ number: 1,
64
+ description: 'Look up order'
65
+ }
66
+ ]
67
+ }
68
+ };
69
+ const message = convertAgentFinishToBotMessage(payload);
70
+ /*
71
+ * Regression: persisting chat state calls BotMessage.toJSON(), which iterates these and
72
+ * calls item.toJSON() on each — it threw "item.toJSON is not a function" for plain objects.
73
+ */ expect(()=>JSON.stringify(message)).not.toThrow();
74
+ expect((_message_scoredUrls = message.scoredUrls) === null || _message_scoredUrls === void 0 ? void 0 : _message_scoredUrls[0]).toBeInstanceOf(Models.ScoredUrl);
75
+ expect((_message_agentOptions = message.agentOptions) === null || _message_agentOptions === void 0 ? void 0 : _message_agentOptions[0]).toBeInstanceOf(Models.AgentOption);
76
+ expect(message.workflowPlan).toBeInstanceOf(Models.WorkflowPlan);
77
+ expect((_message_workflowPlan = message.workflowPlan) === null || _message_workflowPlan === void 0 ? void 0 : _message_workflowPlan.steps[0]).toBeInstanceOf(Models.WorkflowStep);
78
+ });
79
+ test('handles a minimal payload with no nested data', ()=>{
80
+ const message = convertAgentFinishToBotMessage({
81
+ answer: 'x',
82
+ guardFlag: 'N',
83
+ isGuardrailed: false
84
+ });
85
+ expect(message.scoredUrls).toBeUndefined();
86
+ expect(message.agentOptions).toBeUndefined();
87
+ expect(message.workflowPlan).toBeUndefined();
88
+ expect(()=>JSON.stringify(message)).not.toThrow();
89
+ });
90
+ });
91
+
92
+ //# sourceMappingURL=agent-stream.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/streaming/__tests__/agent-stream.test.ts"],"sourcesContent":["import { describe, expect, test } from '@jest/globals';\nimport { Models } from '../../api-client';\nimport { convertAgentFinishToBotMessage } from '../agent-stream';\n\ndescribe('convertAgentFinishToBotMessage', () => {\n test('preserves the backend BotMessage fields verbatim', () => {\n // Real Bifurcation payload: backend sends guardFlag \"BI\" + isGuardrailed true.\n const message = convertAgentFinishToBotMessage({\n answer: 'pick one',\n guardFlag: 'BI',\n isGuardrailed: true,\n sessionId: 122,\n status: 'Bifurcation',\n });\n\n expect(message).toBeInstanceOf(Models.BotMessage);\n expect(message.answer).toBe('pick one');\n expect(message.guardFlag).toBe('BI');\n expect(message.isGuardrailed).toBe(true);\n expect(message.sessionId).toBe(122);\n });\n\n test('ignores streaming-only metadata (status, durationMs, runId, seq)', () => {\n const message = convertAgentFinishToBotMessage({\n answer: 'ok',\n guardFlag: 'N',\n isGuardrailed: false,\n status: 'Success',\n durationMs: 13603,\n runId: 'ec66a0b47d99430a99b964f7478aadd7',\n seq: 6,\n });\n\n const json = message.toJSON();\n expect(json).not.toHaveProperty('status');\n expect(json).not.toHaveProperty('durationMs');\n expect(json).not.toHaveProperty('runId');\n expect(json).not.toHaveProperty('seq');\n });\n\n test('wraps nested data into serializable instances (toJSON does not throw)', () => {\n // Mirrors the decoded SSE JSON: nested data arrives as plain objects, not class instances.\n const payload: any = {\n answer: 'final',\n guardFlag: 'BI',\n isGuardrailed: true,\n sessionId: 3,\n scoredUrls: [{ url: 'https://kb/1', score: 0.9, title: 'Doc' }],\n agentOptions: [{ agentId: 'playwright', passPhrase: 'Do it for me', caption: 'Auto' }],\n workflowPlan: {\n displayName: 'Refund',\n estimatedRuntimeSec: 5,\n steps: [{ number: 1, description: 'Look up order' }],\n },\n };\n const message = convertAgentFinishToBotMessage(payload);\n\n /*\n * Regression: persisting chat state calls BotMessage.toJSON(), which iterates these and\n * calls item.toJSON() on each — it threw \"item.toJSON is not a function\" for plain objects.\n */\n expect(() => JSON.stringify(message)).not.toThrow();\n expect(message.scoredUrls?.[0]).toBeInstanceOf(Models.ScoredUrl);\n expect(message.agentOptions?.[0]).toBeInstanceOf(Models.AgentOption);\n expect(message.workflowPlan).toBeInstanceOf(Models.WorkflowPlan);\n expect(message.workflowPlan?.steps[0]).toBeInstanceOf(Models.WorkflowStep);\n });\n\n test('handles a minimal payload with no nested data', () => {\n const message = convertAgentFinishToBotMessage({\n answer: 'x',\n guardFlag: 'N',\n isGuardrailed: false,\n });\n expect(message.scoredUrls).toBeUndefined();\n expect(message.agentOptions).toBeUndefined();\n expect(message.workflowPlan).toBeUndefined();\n expect(() => JSON.stringify(message)).not.toThrow();\n });\n});\n"],"names":["describe","expect","test","Models","convertAgentFinishToBotMessage","message","answer","guardFlag","isGuardrailed","sessionId","status","toBeInstanceOf","BotMessage","toBe","durationMs","runId","seq","json","toJSON","not","toHaveProperty","payload","scoredUrls","url","score","title","agentOptions","agentId","passPhrase","caption","workflowPlan","displayName","estimatedRuntimeSec","steps","number","description","JSON","stringify","toThrow","ScoredUrl","AgentOption","WorkflowPlan","WorkflowStep","toBeUndefined"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,IAAI,QAAQ,gBAAgB;AACvD,SAASC,MAAM,QAAQ,mBAAmB;AAC1C,SAASC,8BAA8B,QAAQ,kBAAkB;AAEjEJ,SAAS,kCAAkC;IACvCE,KAAK,oDAAoD;QACrD,+EAA+E;QAC/E,MAAMG,UAAUD,+BAA+B;YAC3CE,QAAQ;YACRC,WAAW;YACXC,eAAe;YACfC,WAAW;YACXC,QAAQ;QACZ;QAEAT,OAAOI,SAASM,cAAc,CAACR,OAAOS,UAAU;QAChDX,OAAOI,QAAQC,MAAM,EAAEO,IAAI,CAAC;QAC5BZ,OAAOI,QAAQE,SAAS,EAAEM,IAAI,CAAC;QAC/BZ,OAAOI,QAAQG,aAAa,EAAEK,IAAI,CAAC;QACnCZ,OAAOI,QAAQI,SAAS,EAAEI,IAAI,CAAC;IACnC;IAEAX,KAAK,oEAAoE;QACrE,MAAMG,UAAUD,+BAA+B;YAC3CE,QAAQ;YACRC,WAAW;YACXC,eAAe;YACfE,QAAQ;YACRI,YAAY;YACZC,OAAO;YACPC,KAAK;QACT;QAEA,MAAMC,OAAOZ,QAAQa,MAAM;QAC3BjB,OAAOgB,MAAME,GAAG,CAACC,cAAc,CAAC;QAChCnB,OAAOgB,MAAME,GAAG,CAACC,cAAc,CAAC;QAChCnB,OAAOgB,MAAME,GAAG,CAACC,cAAc,CAAC;QAChCnB,OAAOgB,MAAME,GAAG,CAACC,cAAc,CAAC;IACpC;IAEAlB,KAAK,yEAAyE;YAsBnEG,qBACAA,uBAEAA;QAxBP,2FAA2F;QAC3F,MAAMgB,UAAe;YACjBf,QAAQ;YACRC,WAAW;YACXC,eAAe;YACfC,WAAW;YACXa,YAAY;gBAAC;oBAAEC,KAAK;oBAAgBC,OAAO;oBAAKC,OAAO;gBAAM;aAAE;YAC/DC,cAAc;gBAAC;oBAAEC,SAAS;oBAAcC,YAAY;oBAAgBC,SAAS;gBAAO;aAAE;YACtFC,cAAc;gBACVC,aAAa;gBACbC,qBAAqB;gBACrBC,OAAO;oBAAC;wBAAEC,QAAQ;wBAAGC,aAAa;oBAAgB;iBAAE;YACxD;QACJ;QACA,MAAM9B,UAAUD,+BAA+BiB;QAE/C;;;SAGC,GACDpB,OAAO,IAAMmC,KAAKC,SAAS,CAAChC,UAAUc,GAAG,CAACmB,OAAO;QACjDrC,QAAOI,sBAAAA,QAAQiB,UAAU,cAAlBjB,0CAAAA,mBAAoB,CAAC,EAAE,EAAEM,cAAc,CAACR,OAAOoC,SAAS;QAC/DtC,QAAOI,wBAAAA,QAAQqB,YAAY,cAApBrB,4CAAAA,qBAAsB,CAAC,EAAE,EAAEM,cAAc,CAACR,OAAOqC,WAAW;QACnEvC,OAAOI,QAAQyB,YAAY,EAAEnB,cAAc,CAACR,OAAOsC,YAAY;QAC/DxC,QAAOI,wBAAAA,QAAQyB,YAAY,cAApBzB,4CAAAA,sBAAsB4B,KAAK,CAAC,EAAE,EAAEtB,cAAc,CAACR,OAAOuC,YAAY;IAC7E;IAEAxC,KAAK,iDAAiD;QAClD,MAAMG,UAAUD,+BAA+B;YAC3CE,QAAQ;YACRC,WAAW;YACXC,eAAe;QACnB;QACAP,OAAOI,QAAQiB,UAAU,EAAEqB,aAAa;QACxC1C,OAAOI,QAAQqB,YAAY,EAAEiB,aAAa;QAC1C1C,OAAOI,QAAQyB,YAAY,EAAEa,aAAa;QAC1C1C,OAAO,IAAMmC,KAAKC,SAAS,CAAChC,UAAUc,GAAG,CAACmB,OAAO;IACrD;AACJ"}
@@ -0,0 +1,83 @@
1
+ import { Models } from '../api-client';
2
+ /** Final run status reported by the backend on `run.finished`. */
3
+ export type AgentRunStatus = 'Success' | 'Guardrailed' | 'PendingApproval' | 'Bifurcation' | 'Error' | 'Timeout';
4
+ export interface AgentPlanStep {
5
+ id: string;
6
+ title: string;
7
+ description?: string;
8
+ }
9
+ export interface AgentInputOption {
10
+ label: string;
11
+ value: string;
12
+ style?: string;
13
+ }
14
+ export interface AgentInputRequest {
15
+ kind: string;
16
+ prompt?: string;
17
+ options?: AgentInputOption[];
18
+ }
19
+ /**
20
+ * Decoded payload of the terminal `run.finished` event. The backend sends a full `BotMessage`
21
+ * (same field names: `answer`, `guardFlag`, `isGuardrailed`, `scoredUrls`, `agentOptions`,
22
+ * `workflowPlan`, `sessionId`, …) plus a little streaming-only metadata — so the mapping to the
23
+ * shared model is trivial (see {@link convertAgentFinishToBotMessage}).
24
+ */
25
+ export interface AgentRunFinishedData extends Models.IBotMessage {
26
+ /** Final run status (streaming-only metadata, not part of the BotMessage model). */
27
+ status?: AgentRunStatus;
28
+ /** Total run duration in ms (streaming-only metadata). */
29
+ durationMs?: number;
30
+ /** Backend run identifier (streaming-only metadata). */
31
+ runId?: string;
32
+ /** Monotonic event sequence number (streaming-only metadata). */
33
+ seq?: number;
34
+ }
35
+ /**
36
+ * Callbacks + config the consumer supplies to a streamed message. Maps the chatbot's agent events
37
+ * onto progress updates and exposes the generic connection lifecycle for logging / keepalive / fallback.
38
+ */
39
+ export interface AgentStreamHandlers {
40
+ /** Inactivity threshold before `onInactivity` fires (defaults applied by the caller). */
41
+ inactivityTimeoutMs?: number;
42
+ onStatus?(text: string): void;
43
+ onText?(text: string): void;
44
+ onPlan?(steps: AgentPlanStep[]): void;
45
+ /**
46
+ * Marks the plan step with the given id as the active one (earlier steps become done, later
47
+ * ones stay pending). Driven by an explicit `activeStepId` on `plan.proposed` or a `stepId` on
48
+ * `status.changed` when the backend supplies it; absent that, the first step is activated on
49
+ * `plan.proposed`. Mid-plan advancement therefore requires backend step correlation.
50
+ */
51
+ onStepActive?(id: string): void;
52
+ onInputRequested?(request: AgentInputRequest): void;
53
+ onInactivity?(): void;
54
+ onConnected?(): void;
55
+ onDisconnected?(): void;
56
+ onTimeout?(): void;
57
+ onCompleted?(): void;
58
+ }
59
+ /** Raised when the backend emits a `run.error` event. */
60
+ export declare class AgentStreamError extends Error {
61
+ constructor(message?: string);
62
+ }
63
+ /** Path of the v2 streaming endpoint, appended to the configured base URL. */
64
+ export declare const AGENT_STREAM_PATH = "/api/v2/message/stream";
65
+ /** SSE event names emitted by the backend agent pipeline. */
66
+ export declare const AGENT_EVENT: {
67
+ readonly RunStarted: "run.started";
68
+ readonly RunFinished: "run.finished";
69
+ readonly RunError: "run.error";
70
+ readonly StatusChanged: "status.changed";
71
+ readonly TextAppended: "text.appended";
72
+ readonly PlanProposed: "plan.proposed";
73
+ readonly InputRequested: "input.requested";
74
+ };
75
+ /**
76
+ * Map a terminal `run.finished` payload to the shared `BotMessage` model. The payload is already
77
+ * BotMessage-shaped, so `fromJS` does everything: it reads the backend's `guardFlag`/`isGuardrailed`
78
+ * verbatim, wraps nested data into real instances (`scoredUrls`, `agentOptions`, `workflowPlan` and
79
+ * its `steps`/`inputs`) so `toJSON()` can serialize it for session storage, and ignores the
80
+ * streaming-only metadata (`status`, `durationMs`, `runId`, `seq`).
81
+ */
82
+ export declare function convertAgentFinishToBotMessage(data: AgentRunFinishedData): Models.BotMessage;
83
+ //# sourceMappingURL=agent-stream.d.ts.map