@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.
- package/CHANGELOG.md +12 -0
- package/dist/api-client/__mocks__/chatbot-api-client.mock.d.ts +1 -0
- package/dist/api-client/__mocks__/chatbot-api-client.mock.d.ts.map +1 -1
- package/dist/api-client/__mocks__/chatbot-api-client.mock.js +1 -0
- package/dist/api-client/__mocks__/chatbot-api-client.mock.js.map +1 -1
- package/dist/api-client/base/chatbot-api-client.d.ts +7 -0
- package/dist/api-client/base/chatbot-api-client.d.ts.map +1 -1
- package/dist/api-client/base/chatbot-api-client.js.map +1 -1
- package/dist/api-client/index.d.ts +0 -1
- package/dist/api-client/index.d.ts.map +1 -1
- package/dist/api-client/index.js +0 -2
- package/dist/api-client/index.js.map +1 -1
- package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.d.ts +2 -0
- package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.d.ts.map +1 -0
- package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.js +240 -0
- package/dist/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.js.map +1 -0
- package/dist/api-client/titan-chat/chatbot-api-client.d.ts +11 -0
- package/dist/api-client/titan-chat/chatbot-api-client.d.ts.map +1 -1
- package/dist/api-client/titan-chat/chatbot-api-client.js +29 -0
- package/dist/api-client/titan-chat/chatbot-api-client.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/models/__tests__/chatbot-customizations.test.d.ts +2 -0
- package/dist/models/__tests__/chatbot-customizations.test.d.ts.map +1 -0
- package/dist/models/__tests__/chatbot-customizations.test.js +36 -0
- package/dist/models/__tests__/chatbot-customizations.test.js.map +1 -0
- package/dist/models/chatbot-customizations.d.ts +17 -0
- package/dist/models/chatbot-customizations.d.ts.map +1 -1
- package/dist/models/chatbot-customizations.js +6 -1
- package/dist/models/chatbot-customizations.js.map +1 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +1 -1
- package/dist/models/index.js.map +1 -1
- package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.d.ts +2 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.d.ts.map +1 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.js +107 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.observability.test.js.map +1 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.d.ts +2 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.d.ts.map +1 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.js +312 -0
- package/dist/stores/__tests__/chatbot-ui-backend.store.streaming.test.js.map +1 -0
- package/dist/stores/chatbot-ui-backend.store.d.ts +26 -2
- package/dist/stores/chatbot-ui-backend.store.d.ts.map +1 -1
- package/dist/stores/chatbot-ui-backend.store.js +129 -4
- package/dist/stores/chatbot-ui-backend.store.js.map +1 -1
- package/dist/streaming/__tests__/agent-stream.test.d.ts +2 -0
- package/dist/streaming/__tests__/agent-stream.test.d.ts.map +1 -0
- package/dist/streaming/__tests__/agent-stream.test.js +92 -0
- package/dist/streaming/__tests__/agent-stream.test.js.map +1 -0
- package/dist/streaming/agent-stream.d.ts +83 -0
- package/dist/streaming/agent-stream.d.ts.map +1 -0
- package/dist/streaming/agent-stream.js +28 -0
- package/dist/streaming/agent-stream.js.map +1 -0
- package/dist/streaming/index.d.ts +3 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +4 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming/run-agent-stream.d.ts +23 -0
- package/dist/streaming/run-agent-stream.d.ts.map +1 -0
- package/dist/streaming/run-agent-stream.js +83 -0
- package/dist/streaming/run-agent-stream.js.map +1 -0
- package/package.json +6 -3
- package/src/api-client/__mocks__/chatbot-api-client.mock.ts +1 -0
- package/src/api-client/base/chatbot-api-client.ts +11 -0
- package/src/api-client/index.ts +0 -1
- package/src/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.ts +208 -0
- package/src/api-client/titan-chat/chatbot-api-client.ts +46 -0
- package/src/index.ts +6 -1
- package/src/models/__tests__/chatbot-customizations.test.ts +26 -0
- package/src/models/chatbot-customizations.ts +20 -0
- package/src/models/index.ts +1 -1
- package/src/stores/__tests__/chatbot-ui-backend.store.observability.test.ts +105 -0
- package/src/stores/__tests__/chatbot-ui-backend.store.streaming.test.ts +261 -0
- package/src/stores/chatbot-ui-backend.store.ts +179 -4
- package/src/streaming/__tests__/agent-stream.test.ts +80 -0
- package/src/streaming/agent-stream.ts +103 -0
- package/src/streaming/index.ts +2 -0
- package/src/streaming/run-agent-stream.ts +109 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/api-client/help-center/__tests__/converter-from-models.test.d.ts +0 -2
- package/dist/api-client/help-center/__tests__/converter-from-models.test.d.ts.map +0 -1
- package/dist/api-client/help-center/__tests__/converter-from-models.test.js +0 -67
- package/dist/api-client/help-center/__tests__/converter-from-models.test.js.map +0 -1
- package/dist/api-client/help-center/__tests__/converter-to-models.test.d.ts +0 -2
- package/dist/api-client/help-center/__tests__/converter-to-models.test.d.ts.map +0 -1
- package/dist/api-client/help-center/__tests__/converter-to-models.test.js +0 -83
- package/dist/api-client/help-center/__tests__/converter-to-models.test.js.map +0 -1
- package/dist/api-client/help-center/chatbot-api-client.d.ts +0 -32
- package/dist/api-client/help-center/chatbot-api-client.d.ts.map +0 -1
- package/dist/api-client/help-center/chatbot-api-client.js +0 -101
- package/dist/api-client/help-center/chatbot-api-client.js.map +0 -1
- package/dist/api-client/help-center/converter-from-models.d.ts +0 -13
- package/dist/api-client/help-center/converter-from-models.d.ts.map +0 -1
- package/dist/api-client/help-center/converter-from-models.js +0 -117
- package/dist/api-client/help-center/converter-from-models.js.map +0 -1
- package/dist/api-client/help-center/converter-to-models.d.ts +0 -13
- package/dist/api-client/help-center/converter-to-models.d.ts.map +0 -1
- package/dist/api-client/help-center/converter-to-models.js +0 -101
- package/dist/api-client/help-center/converter-to-models.js.map +0 -1
- package/dist/api-client/help-center/index.d.ts +0 -3
- package/dist/api-client/help-center/index.d.ts.map +0 -1
- package/dist/api-client/help-center/index.js +0 -3
- package/dist/api-client/help-center/index.js.map +0 -1
- package/dist/api-client/help-center/native-client.d.ts +0 -1268
- package/dist/api-client/help-center/native-client.d.ts.map +0 -1
- package/dist/api-client/help-center/native-client.js +0 -4550
- package/dist/api-client/help-center/native-client.js.map +0 -1
- package/src/api-client/help-center/__tests__/converter-from-models.test.ts +0 -41
- package/src/api-client/help-center/__tests__/converter-to-models.test.ts +0 -89
- package/src/api-client/help-center/chatbot-api-client.ts +0 -122
- package/src/api-client/help-center/converter-from-models.ts +0 -133
- package/src/api-client/help-center/converter-to-models.ts +0 -127
- package/src/api-client/help-center/index.ts +0 -2
- package/src/api-client/help-center/native-client.ts +0 -5727
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# v9.0.0 (Mon Jun 08 2026)
|
|
2
|
+
|
|
3
|
+
#### 💥 Breaking Change
|
|
4
|
+
|
|
5
|
+
- SPA-8507: Agent Progress Streaming — Frontend Streaming UX [#91](https://github.com/servicetitan/titan-chatbot-client/pull/91) ([@AlexYarmolchuk](https://github.com/AlexYarmolchuk))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- Alexandr Yarmolchuk ([@AlexYarmolchuk](https://github.com/AlexYarmolchuk))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# v8.0.0 (Wed Jun 03 2026)
|
|
2
14
|
|
|
3
15
|
#### 💥 Breaking Change
|
|
@@ -8,5 +8,6 @@ export declare class ChatbotApiClientMock implements IChatbotApiClient {
|
|
|
8
8
|
patchSession: jest.Mock<any, any, any>;
|
|
9
9
|
deleteSession: jest.Mock<any, any, any>;
|
|
10
10
|
getTranscripts: jest.Mock<any, any, any>;
|
|
11
|
+
streamMessage: jest.Mock<any, any, any>;
|
|
11
12
|
}
|
|
12
13
|
//# sourceMappingURL=chatbot-api-client.mock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatbot-api-client.mock.d.ts","sourceRoot":"","sources":["../../../src/api-client/__mocks__/chatbot-api-client.mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AAEvC,qBAAa,oBAAqB,YAAW,iBAAiB;IAC1D,YAAY,2BAAa;IACzB,WAAW,2BAAa;IACxB,iBAAiB,2BAAa;IAC9B,UAAU,2BAAa;IACvB,WAAW,2BAAa;IACxB,YAAY,2BAAa;IACzB,aAAa,2BAAa;IAC1B,cAAc,2BAAa;
|
|
1
|
+
{"version":3,"file":"chatbot-api-client.mock.d.ts","sourceRoot":"","sources":["../../../src/api-client/__mocks__/chatbot-api-client.mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AAEvC,qBAAa,oBAAqB,YAAW,iBAAiB;IAC1D,YAAY,2BAAa;IACzB,WAAW,2BAAa;IACxB,iBAAiB,2BAAa;IAC9B,UAAU,2BAAa;IACvB,WAAW,2BAAa;IACxB,YAAY,2BAAa;IACzB,aAAa,2BAAa;IAC1B,cAAc,2BAAa;IAC3B,aAAa,2BAAa;CAC7B"}
|
|
@@ -21,6 +21,7 @@ export class ChatbotApiClientMock {
|
|
|
21
21
|
_define_property(this, "patchSession", jest.fn());
|
|
22
22
|
_define_property(this, "deleteSession", jest.fn());
|
|
23
23
|
_define_property(this, "getTranscripts", jest.fn());
|
|
24
|
+
_define_property(this, "streamMessage", jest.fn());
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/api-client/__mocks__/chatbot-api-client.mock.ts"],"sourcesContent":["import { IChatbotApiClient } from '..';\n\nexport class ChatbotApiClientMock implements IChatbotApiClient {\n postFeedback = jest.fn();\n postMessage = jest.fn();\n postFollowUpEmail = jest.fn();\n getOptions = jest.fn();\n postSession = jest.fn();\n patchSession = jest.fn();\n deleteSession = jest.fn();\n getTranscripts = jest.fn();\n}\n"],"names":["ChatbotApiClientMock","postFeedback","jest","fn","postMessage","postFollowUpEmail","getOptions","postSession","patchSession","deleteSession","getTranscripts"],"mappings":";;;;;;;;;;;;;AAEA,OAAO,MAAMA;;QACTC,uBAAAA,gBAAeC,KAAKC,EAAE;QACtBC,uBAAAA,eAAcF,KAAKC,EAAE;QACrBE,uBAAAA,qBAAoBH,KAAKC,EAAE;QAC3BG,uBAAAA,cAAaJ,KAAKC,EAAE;QACpBI,uBAAAA,eAAcL,KAAKC,EAAE;QACrBK,uBAAAA,gBAAeN,KAAKC,EAAE;QACtBM,uBAAAA,iBAAgBP,KAAKC,EAAE;QACvBO,uBAAAA,kBAAiBR,KAAKC,EAAE;;
|
|
1
|
+
{"version":3,"sources":["../../../src/api-client/__mocks__/chatbot-api-client.mock.ts"],"sourcesContent":["import { IChatbotApiClient } from '..';\n\nexport class ChatbotApiClientMock implements IChatbotApiClient {\n postFeedback = jest.fn();\n postMessage = jest.fn();\n postFollowUpEmail = jest.fn();\n getOptions = jest.fn();\n postSession = jest.fn();\n patchSession = jest.fn();\n deleteSession = jest.fn();\n getTranscripts = jest.fn();\n streamMessage = jest.fn();\n}\n"],"names":["ChatbotApiClientMock","postFeedback","jest","fn","postMessage","postFollowUpEmail","getOptions","postSession","patchSession","deleteSession","getTranscripts","streamMessage"],"mappings":";;;;;;;;;;;;;AAEA,OAAO,MAAMA;;QACTC,uBAAAA,gBAAeC,KAAKC,EAAE;QACtBC,uBAAAA,eAAcF,KAAKC,EAAE;QACrBE,uBAAAA,qBAAoBH,KAAKC,EAAE;QAC3BG,uBAAAA,cAAaJ,KAAKC,EAAE;QACpBI,uBAAAA,eAAcL,KAAKC,EAAE;QACrBK,uBAAAA,gBAAeN,KAAKC,EAAE;QACtBM,uBAAAA,iBAAgBP,KAAKC,EAAE;QACvBO,uBAAAA,kBAAiBR,KAAKC,EAAE;QACxBQ,uBAAAA,iBAAgBT,KAAKC,EAAE;;AAC3B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Models } from '..';
|
|
2
|
+
import { AgentStreamHandlers } from '../../streaming';
|
|
2
3
|
/**
|
|
3
4
|
* Token for injecting the chatbot client settings for proper initialization of the client.
|
|
4
5
|
*/
|
|
@@ -17,6 +18,12 @@ export interface IChatbotClientSettings {
|
|
|
17
18
|
export interface IChatbotApiClient {
|
|
18
19
|
postFeedback(body: Models.IFeedback, abortSignal?: AbortSignal): Promise<Models.Feedback>;
|
|
19
20
|
postMessage(body: Models.IUserMessage, abortSignal?: AbortSignal): Promise<Models.BotMessage>;
|
|
21
|
+
/**
|
|
22
|
+
* Streaming variant of {@link postMessage}: consumes the SSE agent-progress stream, forwarding
|
|
23
|
+
* progress events to `handlers`, and resolves with the final {@link Models.BotMessage}.
|
|
24
|
+
* Optional — clients that do not support streaming omit it, and consumers fall back to {@link postMessage}.
|
|
25
|
+
*/
|
|
26
|
+
streamMessage?(body: Models.IUserMessage, handlers: AgentStreamHandlers, abortSignal?: AbortSignal): Promise<Models.BotMessage>;
|
|
20
27
|
postFollowUpEmail(body: Models.IUserMessage, abortSignal?: AbortSignal): Promise<Models.BotMessage>;
|
|
21
28
|
getOptions(abortSignal?: AbortSignal): Promise<Models.FrontendModel>;
|
|
22
29
|
postSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatbot-api-client.d.ts","sourceRoot":"","sources":["../../../src/api-client/base/chatbot-api-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"chatbot-api-client.d.ts","sourceRoot":"","sources":["../../../src/api-client/base/chatbot-api-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,uBAAuB,uEAC8B,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,kBAAkB,kEAAuD,CAAC;AAEvF,KAAK,WAAW,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;AACtD,KAAK,4BAA4B,CAAC,CAAC,SAAS,WAAW,IAAI,MAAM,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;AACpG,KAAK,qBAAqB,CAAC,CAAC,SAAS,WAAW,IAAI,UAAU,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC,CAAC;AAChG,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,WAAW,IAChD,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC;AAC/F,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,IACjD,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC;AAEpG,MAAM,WAAW,sBAAsB;CAAG;AAE1C,MAAM,WAAW,iBAAiB;IAC9B,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1F,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9F;;;;OAIG;IACH,aAAa,CAAC,CACV,IAAI,EAAE,MAAM,CAAC,YAAY,EACzB,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,CAAC,EAAE,WAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,iBAAiB,CACb,IAAI,EAAE,MAAM,CAAC,YAAY,EACzB,WAAW,CAAC,EAAE,WAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,UAAU,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACrE,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvF,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxF,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzF,cAAc,CACV,KAAK,CAAC,EAAE,IAAI,EACZ,GAAG,CAAC,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;CAC7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/api-client/base/chatbot-api-client.ts"],"sourcesContent":["import { symbolToken } from '@servicetitan/react-ioc';\nimport { Models } from '..';\n\n/**\n * Token for injecting the chatbot client settings for proper initialization of the client.\n */\nexport const CHATBOT_CLIENT_SETTINGS =\n symbolToken<IChatbotClientSettings>('CHATBOT_CLIENT_SETTINGS');\n\n/**\n * Token for injecting the chatbot API client.\n */\nexport const CHATBOT_API_CLIENT = symbolToken<IChatbotApiClient>('CHATBOT_API_CLIENT');\n\ntype Constructor = abstract new (...args: any) => any;\ntype ConstructorParametersFactory<T extends Constructor> = () => Required<ConstructorParameters<T>>;\ntype ParametersFromFactory<T extends Constructor> = ReturnType<ConstructorParametersFactory<T>>;\nexport type FirstParameterType<T extends Constructor> =\n ParametersFromFactory<T> extends [infer P1, ...any[]] ? Exclude<P1, undefined> : undefined;\nexport type SecondParameterType<T extends Constructor> =\n ParametersFromFactory<T> extends [any, infer P2, ...any[]] ? Exclude<P2, undefined> : undefined;\n\nexport interface IChatbotClientSettings {}\n\nexport interface IChatbotApiClient {\n postFeedback(body: Models.IFeedback, abortSignal?: AbortSignal): Promise<Models.Feedback>;\n postMessage(body: Models.IUserMessage, abortSignal?: AbortSignal): Promise<Models.BotMessage>;\n postFollowUpEmail(\n body: Models.IUserMessage,\n abortSignal?: AbortSignal\n ): Promise<Models.BotMessage>;\n getOptions(abortSignal?: AbortSignal): Promise<Models.FrontendModel>;\n postSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;\n patchSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;\n deleteSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;\n getTranscripts(\n start?: Date,\n end?: Date,\n signal?: AbortSignal\n ): Promise<Models.ExportHistoryMessage[]>;\n}\n"],"names":["symbolToken","CHATBOT_CLIENT_SETTINGS","CHATBOT_API_CLIENT"],"mappings":"AAAA,SAASA,WAAW,QAAQ,0BAA0B;
|
|
1
|
+
{"version":3,"sources":["../../../src/api-client/base/chatbot-api-client.ts"],"sourcesContent":["import { symbolToken } from '@servicetitan/react-ioc';\nimport { Models } from '..';\nimport { AgentStreamHandlers } from '../../streaming';\n\n/**\n * Token for injecting the chatbot client settings for proper initialization of the client.\n */\nexport const CHATBOT_CLIENT_SETTINGS =\n symbolToken<IChatbotClientSettings>('CHATBOT_CLIENT_SETTINGS');\n\n/**\n * Token for injecting the chatbot API client.\n */\nexport const CHATBOT_API_CLIENT = symbolToken<IChatbotApiClient>('CHATBOT_API_CLIENT');\n\ntype Constructor = abstract new (...args: any) => any;\ntype ConstructorParametersFactory<T extends Constructor> = () => Required<ConstructorParameters<T>>;\ntype ParametersFromFactory<T extends Constructor> = ReturnType<ConstructorParametersFactory<T>>;\nexport type FirstParameterType<T extends Constructor> =\n ParametersFromFactory<T> extends [infer P1, ...any[]] ? Exclude<P1, undefined> : undefined;\nexport type SecondParameterType<T extends Constructor> =\n ParametersFromFactory<T> extends [any, infer P2, ...any[]] ? Exclude<P2, undefined> : undefined;\n\nexport interface IChatbotClientSettings {}\n\nexport interface IChatbotApiClient {\n postFeedback(body: Models.IFeedback, abortSignal?: AbortSignal): Promise<Models.Feedback>;\n postMessage(body: Models.IUserMessage, abortSignal?: AbortSignal): Promise<Models.BotMessage>;\n /**\n * Streaming variant of {@link postMessage}: consumes the SSE agent-progress stream, forwarding\n * progress events to `handlers`, and resolves with the final {@link Models.BotMessage}.\n * Optional — clients that do not support streaming omit it, and consumers fall back to {@link postMessage}.\n */\n streamMessage?(\n body: Models.IUserMessage,\n handlers: AgentStreamHandlers,\n abortSignal?: AbortSignal\n ): Promise<Models.BotMessage>;\n postFollowUpEmail(\n body: Models.IUserMessage,\n abortSignal?: AbortSignal\n ): Promise<Models.BotMessage>;\n getOptions(abortSignal?: AbortSignal): Promise<Models.FrontendModel>;\n postSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;\n patchSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;\n deleteSession(body: Models.ISession, abortSignal?: AbortSignal): Promise<Models.Session>;\n getTranscripts(\n start?: Date,\n end?: Date,\n signal?: AbortSignal\n ): Promise<Models.ExportHistoryMessage[]>;\n}\n"],"names":["symbolToken","CHATBOT_CLIENT_SETTINGS","CHATBOT_API_CLIENT"],"mappings":"AAAA,SAASA,WAAW,QAAQ,0BAA0B;AAItD;;CAEC,GACD,OAAO,MAAMC,0BACTD,YAAoC,2BAA2B;AAEnE;;CAEC,GACD,OAAO,MAAME,qBAAqBF,YAA+B,sBAAsB"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export * as ApiClientTitanChat from './titan-chat';
|
|
2
|
-
export * as ApiClientHelpCenter from './help-center';
|
|
3
2
|
export * as Models from './models';
|
|
4
3
|
export * as ModelsMocks from './models/__mocks__/models.mock';
|
|
5
4
|
export * as ClientMocks from './__mocks__/chatbot-api-client.mock';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,kBAAkB,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,kBAAkB,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,WAAW,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,WAAW,MAAM,qCAAqC,CAAC;AACnE,OAAO,KAAK,WAAW,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/api-client/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as _ApiClientTitanChat from './titan-chat';
|
|
2
2
|
export { _ApiClientTitanChat as ApiClientTitanChat };
|
|
3
|
-
import * as _ApiClientHelpCenter from './help-center';
|
|
4
|
-
export { _ApiClientHelpCenter as ApiClientHelpCenter };
|
|
5
3
|
import * as _Models from './models';
|
|
6
4
|
export { _Models as Models };
|
|
7
5
|
import * as _ModelsMocks from './models/__mocks__/models.mock';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/api-client/index.ts"],"sourcesContent":["export * as ApiClientTitanChat from './titan-chat';\nexport * as
|
|
1
|
+
{"version":3,"sources":["../../src/api-client/index.ts"],"sourcesContent":["export * as ApiClientTitanChat from './titan-chat';\nexport * as Models from './models';\nexport * as ModelsMocks from './models/__mocks__/models.mock';\nexport * as ClientMocks from './__mocks__/chatbot-api-client.mock';\nexport * as ModelsUtils from './utils/model-utils';\nexport type { IChatbotClientSettings, IChatbotApiClient } from './base/chatbot-api-client';\nexport { CHATBOT_CLIENT_SETTINGS, CHATBOT_API_CLIENT } from './base/chatbot-api-client';\n"],"names":["ApiClientTitanChat","Models","ModelsMocks","ClientMocks","ModelsUtils","CHATBOT_CLIENT_SETTINGS","CHATBOT_API_CLIENT"],"mappings":"AAAA,qCAAoC,eAAe;AAAnD,SAAO,uBAAKA,kBAAkB,GAAqB;AACnD,yBAAwB,WAAW;AAAnC,SAAO,WAAKC,MAAM,GAAiB;AACnC,8BAA6B,iCAAiC;AAA9D,SAAO,gBAAKC,WAAW,GAAuC;AAC9D,8BAA6B,sCAAsC;AAAnE,SAAO,gBAAKC,WAAW,GAA4C;AACnE,8BAA6B,sBAAsB;AAAnD,SAAO,gBAAKC,WAAW,GAA4B;AAEnD,SAASC,uBAAuB,EAAEC,kBAAkB,QAAQ,4BAA4B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatbot-api-client-stream.test.d.ts","sourceRoot":"","sources":["../../../../src/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, jest, test } from '@jest/globals';
|
|
2
|
+
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
|
3
|
+
import { Models } from '../..';
|
|
4
|
+
import { ChatbotApiClient } from '../chatbot-api-client';
|
|
5
|
+
jest.mock('@microsoft/fetch-event-source');
|
|
6
|
+
const fetchEventSourceMock = fetchEventSource;
|
|
7
|
+
const okResponse = ()=>({
|
|
8
|
+
ok: true,
|
|
9
|
+
status: 200,
|
|
10
|
+
headers: {
|
|
11
|
+
get: ()=>'text/event-stream'
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
const evt = (event, data)=>({
|
|
15
|
+
id: '',
|
|
16
|
+
event,
|
|
17
|
+
data: JSON.stringify(data)
|
|
18
|
+
});
|
|
19
|
+
/** Mock that opens, exposes init, and stays pending until the client aborts. */ function captureOpen() {
|
|
20
|
+
const capture = {
|
|
21
|
+
opened: undefined
|
|
22
|
+
};
|
|
23
|
+
capture.opened = new Promise((markOpened)=>{
|
|
24
|
+
fetchEventSourceMock.mockImplementation((_url, init)=>{
|
|
25
|
+
var _init_onopen;
|
|
26
|
+
capture.init = init;
|
|
27
|
+
markOpened();
|
|
28
|
+
return Promise.resolve((_init_onopen = init.onopen) === null || _init_onopen === void 0 ? void 0 : _init_onopen.call(init, okResponse())).then(()=>new Promise((resolve)=>{
|
|
29
|
+
const s = init.signal;
|
|
30
|
+
if (s === null || s === void 0 ? void 0 : s.aborted) {
|
|
31
|
+
resolve();
|
|
32
|
+
} else {
|
|
33
|
+
s === null || s === void 0 ? void 0 : s.addEventListener('abort', ()=>resolve(), {
|
|
34
|
+
once: true
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
return capture;
|
|
41
|
+
}
|
|
42
|
+
/** The same custom fetch the regular API client would use (injects auth, etc.). */ const customFetch = (_url, _init)=>Promise.resolve(new Response());
|
|
43
|
+
const settings = {
|
|
44
|
+
version: '2',
|
|
45
|
+
clientId: 'help-center',
|
|
46
|
+
constructorParametersFactory: ()=>({
|
|
47
|
+
baseUrl: 'https://api.test/base',
|
|
48
|
+
httpClient: {
|
|
49
|
+
fetch: customFetch
|
|
50
|
+
}
|
|
51
|
+
}),
|
|
52
|
+
streamHeadersFactory: ()=>({
|
|
53
|
+
Authorization: 'Bearer t'
|
|
54
|
+
})
|
|
55
|
+
};
|
|
56
|
+
describe('ChatbotApiClient (titan-chat).streamMessage', ()=>{
|
|
57
|
+
beforeEach(()=>{
|
|
58
|
+
fetchEventSourceMock.mockReset();
|
|
59
|
+
});
|
|
60
|
+
test('opens the versioned stream endpoint with X-Client-ID + extra headers and the message body', async ()=>{
|
|
61
|
+
const capture = captureOpen();
|
|
62
|
+
const client = new ChatbotApiClient(settings);
|
|
63
|
+
const promise = client.streamMessage(new Models.UserMessage({
|
|
64
|
+
sessionId: 9,
|
|
65
|
+
question: 'hi',
|
|
66
|
+
experience: Models.Experience.MultiTurn
|
|
67
|
+
}), {});
|
|
68
|
+
await capture.opened;
|
|
69
|
+
expect(String(fetchEventSourceMock.mock.calls[0][0])).toBe('https://api.test/base/api/v2/message/stream');
|
|
70
|
+
expect(capture.init.method).toBe('POST');
|
|
71
|
+
expect(capture.init.headers).toMatchObject({
|
|
72
|
+
'X-Client-ID': 'help-center',
|
|
73
|
+
'Authorization': 'Bearer t',
|
|
74
|
+
'Accept': 'text/event-stream'
|
|
75
|
+
});
|
|
76
|
+
const sent = JSON.parse(capture.init.body);
|
|
77
|
+
expect(sent.question).toBe('hi');
|
|
78
|
+
expect(sent.sessionId).toBe(9);
|
|
79
|
+
capture.init.onmessage(evt('run.finished', {
|
|
80
|
+
seq: 1,
|
|
81
|
+
status: 'Success',
|
|
82
|
+
answer: 'done'
|
|
83
|
+
}));
|
|
84
|
+
await promise;
|
|
85
|
+
});
|
|
86
|
+
test('forwards the configured httpClient.fetch so SSE uses the same request config as the API', async ()=>{
|
|
87
|
+
const capture = captureOpen();
|
|
88
|
+
const client = new ChatbotApiClient(settings);
|
|
89
|
+
const promise = client.streamMessage(new Models.UserMessage({
|
|
90
|
+
question: 'q',
|
|
91
|
+
experience: Models.Experience.MultiTurn
|
|
92
|
+
}), {});
|
|
93
|
+
await capture.opened;
|
|
94
|
+
// fetchEventSource receives the same fetch the regular client uses → auth/headers apply identically.
|
|
95
|
+
expect(capture.init.fetch).toBe(customFetch);
|
|
96
|
+
capture.init.onmessage(evt('run.finished', {
|
|
97
|
+
seq: 1,
|
|
98
|
+
status: 'Success',
|
|
99
|
+
answer: 'done'
|
|
100
|
+
}));
|
|
101
|
+
await promise;
|
|
102
|
+
});
|
|
103
|
+
test('maps agent events and resolves a BotMessage from run.finished', async ()=>{
|
|
104
|
+
const capture = captureOpen();
|
|
105
|
+
const handlers = {
|
|
106
|
+
onStatus: jest.fn(),
|
|
107
|
+
onText: jest.fn()
|
|
108
|
+
};
|
|
109
|
+
const client = new ChatbotApiClient(settings);
|
|
110
|
+
const promise = client.streamMessage(new Models.UserMessage({
|
|
111
|
+
question: 'q',
|
|
112
|
+
experience: Models.Experience.MultiTurn
|
|
113
|
+
}), handlers);
|
|
114
|
+
await capture.opened;
|
|
115
|
+
capture.init.onmessage(evt('status.changed', {
|
|
116
|
+
seq: 1,
|
|
117
|
+
text: 'Thinking…'
|
|
118
|
+
}));
|
|
119
|
+
capture.init.onmessage(evt('text.appended', {
|
|
120
|
+
seq: 2,
|
|
121
|
+
text: '✓ done step'
|
|
122
|
+
}));
|
|
123
|
+
capture.init.onmessage(evt('run.finished', {
|
|
124
|
+
seq: 3,
|
|
125
|
+
status: 'Success',
|
|
126
|
+
answer: 'final',
|
|
127
|
+
sessionId: 5
|
|
128
|
+
}));
|
|
129
|
+
const bot = await promise;
|
|
130
|
+
expect(handlers.onStatus).toHaveBeenCalledWith('Thinking…');
|
|
131
|
+
expect(handlers.onText).toHaveBeenCalledWith('✓ done step');
|
|
132
|
+
expect(bot).toBeInstanceOf(Models.BotMessage);
|
|
133
|
+
expect(bot.answer).toBe('final');
|
|
134
|
+
expect(bot.sessionId).toBe(5);
|
|
135
|
+
});
|
|
136
|
+
test('plan.proposed forwards steps and activates the first step by default', async ()=>{
|
|
137
|
+
const capture = captureOpen();
|
|
138
|
+
const handlers = {
|
|
139
|
+
onPlan: jest.fn(),
|
|
140
|
+
onStepActive: jest.fn()
|
|
141
|
+
};
|
|
142
|
+
const client = new ChatbotApiClient(settings);
|
|
143
|
+
const promise = client.streamMessage(new Models.UserMessage({
|
|
144
|
+
question: 'q',
|
|
145
|
+
experience: Models.Experience.MultiTurn
|
|
146
|
+
}), handlers);
|
|
147
|
+
await capture.opened;
|
|
148
|
+
capture.init.onmessage(evt('plan.proposed', {
|
|
149
|
+
seq: 1,
|
|
150
|
+
steps: [
|
|
151
|
+
{
|
|
152
|
+
id: 'a',
|
|
153
|
+
title: 'Look up'
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: 'b',
|
|
157
|
+
title: 'Answer'
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}));
|
|
161
|
+
capture.init.onmessage(evt('run.finished', {
|
|
162
|
+
seq: 2,
|
|
163
|
+
status: 'Success',
|
|
164
|
+
answer: 'x'
|
|
165
|
+
}));
|
|
166
|
+
await promise;
|
|
167
|
+
expect(handlers.onPlan).toHaveBeenCalledWith([
|
|
168
|
+
{
|
|
169
|
+
id: 'a',
|
|
170
|
+
title: 'Look up'
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: 'b',
|
|
174
|
+
title: 'Answer'
|
|
175
|
+
}
|
|
176
|
+
]);
|
|
177
|
+
expect(handlers.onStepActive).toHaveBeenCalledWith('a');
|
|
178
|
+
});
|
|
179
|
+
test('plan.proposed honors an explicit activeStepId', async ()=>{
|
|
180
|
+
const capture = captureOpen();
|
|
181
|
+
const handlers = {
|
|
182
|
+
onStepActive: jest.fn()
|
|
183
|
+
};
|
|
184
|
+
const client = new ChatbotApiClient(settings);
|
|
185
|
+
const promise = client.streamMessage(new Models.UserMessage({
|
|
186
|
+
question: 'q',
|
|
187
|
+
experience: Models.Experience.MultiTurn
|
|
188
|
+
}), handlers);
|
|
189
|
+
await capture.opened;
|
|
190
|
+
capture.init.onmessage(evt('plan.proposed', {
|
|
191
|
+
seq: 1,
|
|
192
|
+
activeStepId: 'b',
|
|
193
|
+
steps: [
|
|
194
|
+
{
|
|
195
|
+
id: 'a',
|
|
196
|
+
title: 'Look up'
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: 'b',
|
|
200
|
+
title: 'Answer'
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
}));
|
|
204
|
+
capture.init.onmessage(evt('run.finished', {
|
|
205
|
+
seq: 2,
|
|
206
|
+
status: 'Success',
|
|
207
|
+
answer: 'x'
|
|
208
|
+
}));
|
|
209
|
+
await promise;
|
|
210
|
+
expect(handlers.onStepActive).toHaveBeenCalledWith('b');
|
|
211
|
+
});
|
|
212
|
+
test('status.changed advances the active step when it carries a stepId', async ()=>{
|
|
213
|
+
const capture = captureOpen();
|
|
214
|
+
const handlers = {
|
|
215
|
+
onStatus: jest.fn(),
|
|
216
|
+
onStepActive: jest.fn()
|
|
217
|
+
};
|
|
218
|
+
const client = new ChatbotApiClient(settings);
|
|
219
|
+
const promise = client.streamMessage(new Models.UserMessage({
|
|
220
|
+
question: 'q',
|
|
221
|
+
experience: Models.Experience.MultiTurn
|
|
222
|
+
}), handlers);
|
|
223
|
+
await capture.opened;
|
|
224
|
+
capture.init.onmessage(evt('status.changed', {
|
|
225
|
+
seq: 1,
|
|
226
|
+
text: 'Searching…',
|
|
227
|
+
stepId: 'b'
|
|
228
|
+
}));
|
|
229
|
+
capture.init.onmessage(evt('run.finished', {
|
|
230
|
+
seq: 2,
|
|
231
|
+
status: 'Success',
|
|
232
|
+
answer: 'x'
|
|
233
|
+
}));
|
|
234
|
+
await promise;
|
|
235
|
+
expect(handlers.onStatus).toHaveBeenCalledWith('Searching…');
|
|
236
|
+
expect(handlers.onStepActive).toHaveBeenCalledWith('b');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=chatbot-api-client-stream.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/api-client/titan-chat/__tests__/chatbot-api-client-stream.test.ts"],"sourcesContent":["import { beforeEach, describe, expect, jest, test } from '@jest/globals';\nimport { type EventSourceMessage, fetchEventSource } from '@microsoft/fetch-event-source';\nimport { Models } from '../..';\nimport type { AgentStreamHandlers } from '../../../streaming';\nimport { ChatbotApiClient, IChatbotClientSettingsTitanChat } from '../chatbot-api-client';\n\njest.mock('@microsoft/fetch-event-source');\n\nconst fetchEventSourceMock = fetchEventSource as jest.MockedFunction<typeof fetchEventSource>;\n\nconst okResponse = () =>\n ({ ok: true, status: 200, headers: { get: () => 'text/event-stream' } }) as unknown as Response;\nconst evt = (event: string, data: unknown): EventSourceMessage => ({\n id: '',\n event,\n data: JSON.stringify(data),\n});\n\n/** Mock that opens, exposes init, and stays pending until the client aborts. */\nfunction captureOpen() {\n const capture: { init?: any; opened: Promise<void> } = { opened: undefined as any };\n capture.opened = new Promise<void>(markOpened => {\n fetchEventSourceMock.mockImplementation((_url, init) => {\n capture.init = init;\n markOpened();\n return Promise.resolve(init.onopen?.(okResponse())).then(\n () =>\n new Promise<void>(resolve => {\n const s: AbortSignal | null | undefined = init.signal;\n if (s?.aborted) {\n resolve();\n } else {\n s?.addEventListener('abort', () => resolve(), { once: true });\n }\n })\n );\n });\n });\n return capture;\n}\n\n/** The same custom fetch the regular API client would use (injects auth, etc.). */\nconst customFetch = ((_url: any, _init?: any) => Promise.resolve(new Response())) as typeof fetch;\n\nconst settings: IChatbotClientSettingsTitanChat = {\n version: '2',\n clientId: 'help-center',\n constructorParametersFactory: () => ({\n baseUrl: 'https://api.test/base',\n httpClient: { fetch: customFetch },\n }),\n streamHeadersFactory: () => ({ Authorization: 'Bearer t' }),\n};\n\ndescribe('ChatbotApiClient (titan-chat).streamMessage', () => {\n beforeEach(() => {\n fetchEventSourceMock.mockReset();\n });\n\n test('opens the versioned stream endpoint with X-Client-ID + extra headers and the message body', async () => {\n const capture = captureOpen();\n const client = new ChatbotApiClient(settings);\n\n const promise = client.streamMessage(\n new Models.UserMessage({\n sessionId: 9,\n question: 'hi',\n experience: Models.Experience.MultiTurn,\n }),\n {}\n );\n await capture.opened;\n\n expect(String((fetchEventSourceMock.mock.calls[0] as any[])[0])).toBe(\n 'https://api.test/base/api/v2/message/stream'\n );\n expect(capture.init.method).toBe('POST');\n expect(capture.init.headers).toMatchObject({\n 'X-Client-ID': 'help-center',\n 'Authorization': 'Bearer t',\n 'Accept': 'text/event-stream',\n });\n const sent = JSON.parse(capture.init.body);\n expect(sent.question).toBe('hi');\n expect(sent.sessionId).toBe(9);\n\n capture.init.onmessage(evt('run.finished', { seq: 1, status: 'Success', answer: 'done' }));\n await promise;\n });\n\n test('forwards the configured httpClient.fetch so SSE uses the same request config as the API', async () => {\n const capture = captureOpen();\n const client = new ChatbotApiClient(settings);\n\n const promise = client.streamMessage(\n new Models.UserMessage({ question: 'q', experience: Models.Experience.MultiTurn }),\n {}\n );\n await capture.opened;\n\n // fetchEventSource receives the same fetch the regular client uses → auth/headers apply identically.\n expect(capture.init.fetch).toBe(customFetch);\n\n capture.init.onmessage(evt('run.finished', { seq: 1, status: 'Success', answer: 'done' }));\n await promise;\n });\n\n test('maps agent events and resolves a BotMessage from run.finished', async () => {\n const capture = captureOpen();\n const handlers: AgentStreamHandlers = { onStatus: jest.fn(), onText: jest.fn() };\n const client = new ChatbotApiClient(settings);\n\n const promise = client.streamMessage(\n new Models.UserMessage({ question: 'q', experience: Models.Experience.MultiTurn }),\n handlers\n );\n await capture.opened;\n\n capture.init.onmessage(evt('status.changed', { seq: 1, text: 'Thinking…' }));\n capture.init.onmessage(evt('text.appended', { seq: 2, text: '✓ done step' }));\n capture.init.onmessage(\n evt('run.finished', { seq: 3, status: 'Success', answer: 'final', sessionId: 5 })\n );\n\n const bot = await promise;\n expect(handlers.onStatus).toHaveBeenCalledWith('Thinking…');\n expect(handlers.onText).toHaveBeenCalledWith('✓ done step');\n expect(bot).toBeInstanceOf(Models.BotMessage);\n expect(bot.answer).toBe('final');\n expect(bot.sessionId).toBe(5);\n });\n\n test('plan.proposed forwards steps and activates the first step by default', async () => {\n const capture = captureOpen();\n const handlers: AgentStreamHandlers = { onPlan: jest.fn(), onStepActive: jest.fn() };\n const client = new ChatbotApiClient(settings);\n\n const promise = client.streamMessage(\n new Models.UserMessage({ question: 'q', experience: Models.Experience.MultiTurn }),\n handlers\n );\n await capture.opened;\n\n capture.init.onmessage(\n evt('plan.proposed', {\n seq: 1,\n steps: [\n { id: 'a', title: 'Look up' },\n { id: 'b', title: 'Answer' },\n ],\n })\n );\n capture.init.onmessage(evt('run.finished', { seq: 2, status: 'Success', answer: 'x' }));\n\n await promise;\n expect(handlers.onPlan).toHaveBeenCalledWith([\n { id: 'a', title: 'Look up' },\n { id: 'b', title: 'Answer' },\n ]);\n expect(handlers.onStepActive).toHaveBeenCalledWith('a');\n });\n\n test('plan.proposed honors an explicit activeStepId', async () => {\n const capture = captureOpen();\n const handlers: AgentStreamHandlers = { onStepActive: jest.fn() };\n const client = new ChatbotApiClient(settings);\n\n const promise = client.streamMessage(\n new Models.UserMessage({ question: 'q', experience: Models.Experience.MultiTurn }),\n handlers\n );\n await capture.opened;\n\n capture.init.onmessage(\n evt('plan.proposed', {\n seq: 1,\n activeStepId: 'b',\n steps: [\n { id: 'a', title: 'Look up' },\n { id: 'b', title: 'Answer' },\n ],\n })\n );\n capture.init.onmessage(evt('run.finished', { seq: 2, status: 'Success', answer: 'x' }));\n\n await promise;\n expect(handlers.onStepActive).toHaveBeenCalledWith('b');\n });\n\n test('status.changed advances the active step when it carries a stepId', async () => {\n const capture = captureOpen();\n const handlers: AgentStreamHandlers = { onStatus: jest.fn(), onStepActive: jest.fn() };\n const client = new ChatbotApiClient(settings);\n\n const promise = client.streamMessage(\n new Models.UserMessage({ question: 'q', experience: Models.Experience.MultiTurn }),\n handlers\n );\n await capture.opened;\n\n capture.init.onmessage(evt('status.changed', { seq: 1, text: 'Searching…', stepId: 'b' }));\n capture.init.onmessage(evt('run.finished', { seq: 2, status: 'Success', answer: 'x' }));\n\n await promise;\n expect(handlers.onStatus).toHaveBeenCalledWith('Searching…');\n expect(handlers.onStepActive).toHaveBeenCalledWith('b');\n });\n});\n"],"names":["beforeEach","describe","expect","jest","test","fetchEventSource","Models","ChatbotApiClient","mock","fetchEventSourceMock","okResponse","ok","status","headers","get","evt","event","data","id","JSON","stringify","captureOpen","capture","opened","undefined","Promise","markOpened","mockImplementation","_url","init","resolve","onopen","then","s","signal","aborted","addEventListener","once","customFetch","_init","Response","settings","version","clientId","constructorParametersFactory","baseUrl","httpClient","fetch","streamHeadersFactory","Authorization","mockReset","client","promise","streamMessage","UserMessage","sessionId","question","experience","Experience","MultiTurn","String","calls","toBe","method","toMatchObject","sent","parse","body","onmessage","seq","answer","handlers","onStatus","fn","onText","text","bot","toHaveBeenCalledWith","toBeInstanceOf","BotMessage","onPlan","onStepActive","steps","title","activeStepId","stepId"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Models } from '..';
|
|
2
|
+
import { AgentStreamHandlers } from '../../streaming';
|
|
2
3
|
import { FirstParameterType, IChatbotApiClient, IChatbotClientSettings, SecondParameterType } from '../base/chatbot-api-client';
|
|
3
4
|
import { Client } from './native-client';
|
|
4
5
|
/**
|
|
@@ -12,6 +13,11 @@ export interface IChatbotClientSettingsTitanChat extends IChatbotClientSettings
|
|
|
12
13
|
};
|
|
13
14
|
version: string;
|
|
14
15
|
clientId: string;
|
|
16
|
+
/**
|
|
17
|
+
* Extra headers for the SSE streaming request. `X-Client-ID` is always sent (from `clientId`);
|
|
18
|
+
* use this for anything the fetch http client would otherwise add (e.g. Authorization). Optional.
|
|
19
|
+
*/
|
|
20
|
+
streamHeadersFactory?: () => Record<string, string>;
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
17
23
|
* Client adapter adopts the generated titan chatbot client to the generic IChatbotApiClient interface.
|
|
@@ -20,11 +26,16 @@ export interface IChatbotClientSettingsTitanChat extends IChatbotClientSettings
|
|
|
20
26
|
export declare class ChatbotApiClient implements IChatbotApiClient {
|
|
21
27
|
private readonly chatbotApiClientSettings;
|
|
22
28
|
private readonly client;
|
|
29
|
+
/** Same base URL the generated `Client` uses, so streaming URLs are built identically. */
|
|
30
|
+
private readonly baseUrl;
|
|
31
|
+
/** Same `fetch` the generated `Client` uses, so the SSE request gets identical auth/headers. */
|
|
32
|
+
private readonly httpFetch?;
|
|
23
33
|
get version(): string;
|
|
24
34
|
get clientId(): string;
|
|
25
35
|
constructor(chatbotApiClientSettings: IChatbotClientSettingsTitanChat);
|
|
26
36
|
postFeedback(body: Models.Feedback, abortSignal?: AbortSignal): Promise<Models.Feedback>;
|
|
27
37
|
postMessage(body: Models.UserMessage, abortSignal?: AbortSignal): Promise<Models.BotMessage>;
|
|
38
|
+
streamMessage(body: Models.IUserMessage, handlers: AgentStreamHandlers, abortSignal?: AbortSignal): Promise<Models.BotMessage>;
|
|
28
39
|
postFollowUpEmail(body: Models.UserMessage, abortSignal?: AbortSignal): Promise<Models.BotMessage>;
|
|
29
40
|
getOptions(abortSignal?: AbortSignal): Promise<Models.FrontendModel>;
|
|
30
41
|
postSession(body: Models.Session, abortSignal?: AbortSignal): Promise<Models.Session>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatbot-api-client.d.ts","sourceRoot":"","sources":["../../../src/api-client/titan-chat/chatbot-api-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAEH,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACtB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"chatbot-api-client.d.ts","sourceRoot":"","sources":["../../../src/api-client/titan-chat/chatbot-api-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAkB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAEH,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACtB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC;;;GAGG;AACH,MAAM,WAAW,+BAAgC,SAAQ,sBAAsB;IAC3E,4BAA4B,EAAE,MAAM;QAChC,OAAO,CAAC,EAAE,kBAAkB,CAAC,OAAO,MAAM,CAAC,CAAC;QAC5C,UAAU,CAAC,EAAE,mBAAmB,CAAC,OAAO,MAAM,CAAC,CAAC;KACnD,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvD;AAED;;;GAGG;AACH,qBACa,gBAAiB,YAAW,iBAAiB;IAiBlD,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IAhB7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAe;IAE1C,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;gBAIoB,wBAAwB,EAAE,+BAA+B;IAc9E,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW;IAI7D,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,WAAW;IAI/D,aAAa,CACT,IAAI,EAAE,MAAM,CAAC,YAAY,EACzB,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,CAAC,EAAE,WAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;IAsB7B,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,WAAW;IAIrE,UAAU,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;IAI9D,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW;IAIjE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW;IAI5D,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW;IAI7D,cAAc,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW;CAGhE"}
|
|
@@ -26,9 +26,11 @@ function _ts_param(paramIndex, decorator) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
import { inject, injectable } from '@servicetitan/react-ioc';
|
|
29
|
+
import { runAgentStream } from '../../streaming';
|
|
29
30
|
import { CHATBOT_CLIENT_SETTINGS } from '../base/chatbot-api-client';
|
|
30
31
|
// eslint-disable-next-line no-restricted-imports
|
|
31
32
|
import { Client } from './native-client';
|
|
33
|
+
/** Streaming endpoint template, mirroring the generated client's `/api/v{version}/message`. */ const AGENT_STREAM_PATH_TEMPLATE = '/api/v{version}/message/stream';
|
|
32
34
|
export class ChatbotApiClient {
|
|
33
35
|
get version() {
|
|
34
36
|
return this.chatbotApiClientSettings.version;
|
|
@@ -42,6 +44,25 @@ export class ChatbotApiClient {
|
|
|
42
44
|
postMessage(body, abortSignal) {
|
|
43
45
|
return this.client.message(this.version, this.clientId, body, abortSignal);
|
|
44
46
|
}
|
|
47
|
+
streamMessage(body, handlers, abortSignal) {
|
|
48
|
+
var _ref;
|
|
49
|
+
var _this_chatbotApiClientSettings_streamHeadersFactory, _this_chatbotApiClientSettings;
|
|
50
|
+
/*
|
|
51
|
+
* Build the URL exactly as the generated Client does for `/api/v{version}/message`:
|
|
52
|
+
* substitute {version}, then strip a dangling query separator.
|
|
53
|
+
*/ const url = (this.baseUrl + AGENT_STREAM_PATH_TEMPLATE).replace('{version}', encodeURIComponent('' + this.version)).replace(/[?&]$/, '');
|
|
54
|
+
return runAgentStream({
|
|
55
|
+
url,
|
|
56
|
+
fetch: this.httpFetch,
|
|
57
|
+
headers: {
|
|
58
|
+
'X-Client-ID': this.clientId,
|
|
59
|
+
...(_ref = (_this_chatbotApiClientSettings_streamHeadersFactory = (_this_chatbotApiClientSettings = this.chatbotApiClientSettings).streamHeadersFactory) === null || _this_chatbotApiClientSettings_streamHeadersFactory === void 0 ? void 0 : _this_chatbotApiClientSettings_streamHeadersFactory.call(_this_chatbotApiClientSettings)) !== null && _ref !== void 0 ? _ref : {}
|
|
60
|
+
},
|
|
61
|
+
body,
|
|
62
|
+
handlers,
|
|
63
|
+
abortSignal
|
|
64
|
+
});
|
|
65
|
+
}
|
|
45
66
|
postFollowUpEmail(body, abortSignal) {
|
|
46
67
|
return this.client.followUpEmail(this.version, this.clientId, body, abortSignal);
|
|
47
68
|
}
|
|
@@ -63,9 +84,17 @@ export class ChatbotApiClient {
|
|
|
63
84
|
constructor(chatbotApiClientSettings){
|
|
64
85
|
_define_property(this, "chatbotApiClientSettings", void 0);
|
|
65
86
|
_define_property(this, "client", void 0);
|
|
87
|
+
/** Same base URL the generated `Client` uses, so streaming URLs are built identically. */ _define_property(this, "baseUrl", void 0);
|
|
88
|
+
/** Same `fetch` the generated `Client` uses, so the SSE request gets identical auth/headers. */ _define_property(this, "httpFetch", void 0);
|
|
66
89
|
this.chatbotApiClientSettings = chatbotApiClientSettings;
|
|
67
90
|
const { baseUrl, httpClient } = this.chatbotApiClientSettings.constructorParametersFactory();
|
|
68
91
|
this.client = new Client(baseUrl, httpClient);
|
|
92
|
+
// Mirror the generated client's `this.baseUrl = baseUrl ?? ""`.
|
|
93
|
+
this.baseUrl = baseUrl !== null && baseUrl !== void 0 ? baseUrl : '';
|
|
94
|
+
/*
|
|
95
|
+
* Reuse the same fetch the generated client uses, so the SSE request goes through the
|
|
96
|
+
* consumer's request configuration (auth token, X-HC-Instance, credentials, …).
|
|
97
|
+
*/ this.httpFetch = httpClient === null || httpClient === void 0 ? void 0 : httpClient.fetch;
|
|
69
98
|
}
|
|
70
99
|
}
|
|
71
100
|
ChatbotApiClient = _ts_decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/api-client/titan-chat/chatbot-api-client.ts"],"sourcesContent":["import { inject, injectable } from '@servicetitan/react-ioc';\nimport { Models } from '..';\nimport {\n CHATBOT_CLIENT_SETTINGS,\n FirstParameterType,\n IChatbotApiClient,\n IChatbotClientSettings,\n SecondParameterType,\n} from '../base/chatbot-api-client';\n// eslint-disable-next-line no-restricted-imports\nimport { Client } from './native-client';\n\n/**\n * Settings for the chatbot client, which includes a factory for constructor parameters, and additional settings\n * like version and clientId which are used in the API calls.\n */\nexport interface IChatbotClientSettingsTitanChat extends IChatbotClientSettings {\n constructorParametersFactory: () => {\n baseUrl?: FirstParameterType<typeof Client>;\n httpClient?: SecondParameterType<typeof Client>;\n };\n version: string;\n clientId: string;\n}\n\n/**\n * Client adapter adopts the generated titan chatbot client to the generic IChatbotApiClient interface.\n * Contains client-specific methods for interacting with the titan chatbot API.\n */\n@injectable()\nexport class ChatbotApiClient implements IChatbotApiClient {\n private readonly client: Client;\n\n get version(): string {\n return this.chatbotApiClientSettings.version;\n }\n\n get clientId(): string {\n return this.chatbotApiClientSettings.clientId;\n }\n\n constructor(\n @inject(CHATBOT_CLIENT_SETTINGS)\n private readonly chatbotApiClientSettings: IChatbotClientSettingsTitanChat\n ) {\n const { baseUrl, httpClient } =\n this.chatbotApiClientSettings.constructorParametersFactory();\n this.client = new Client(baseUrl, httpClient);\n }\n\n postFeedback(body: Models.Feedback, abortSignal?: AbortSignal) {\n return this.client.feedback(this.version, this.clientId, body, abortSignal);\n }\n\n postMessage(body: Models.UserMessage, abortSignal?: AbortSignal) {\n return this.client.message(this.version, this.clientId, body, abortSignal);\n }\n\n postFollowUpEmail(body: Models.UserMessage, abortSignal?: AbortSignal) {\n return this.client.followUpEmail(this.version, this.clientId, body, abortSignal);\n }\n\n getOptions(abortSignal?: AbortSignal): Promise<Models.FrontendModel> {\n return this.client.options(this.version, this.clientId, abortSignal);\n }\n\n async postSession(body: Models.Session, abortSignal?: AbortSignal) {\n return this.client.sessionPOST(this.version, this.clientId, body, abortSignal);\n }\n\n patchSession(body: Models.Session, abortSignal?: AbortSignal) {\n return this.client.sessionPATCH(this.version, this.clientId, body, abortSignal);\n }\n\n deleteSession(body: Models.Session, abortSignal?: AbortSignal) {\n return this.client.sessionDELETE(this.version, this.clientId, body, abortSignal);\n }\n\n getTranscripts(start?: Date, end?: Date, signal?: AbortSignal) {\n return this.client.transcripts(start, end, this.version, this.clientId, signal);\n }\n}\n"],"names":["inject","injectable","CHATBOT_CLIENT_SETTINGS","Client","ChatbotApiClient","version","chatbotApiClientSettings","clientId","postFeedback","body","abortSignal","client","feedback","postMessage","message","postFollowUpEmail","followUpEmail","getOptions","options","postSession","sessionPOST","patchSession","sessionPATCH","deleteSession","sessionDELETE","getTranscripts","start","end","signal","transcripts","
|
|
1
|
+
{"version":3,"sources":["../../../src/api-client/titan-chat/chatbot-api-client.ts"],"sourcesContent":["import { inject, injectable } from '@servicetitan/react-ioc';\nimport { Models } from '..';\nimport { AgentStreamHandlers, runAgentStream } from '../../streaming';\nimport {\n CHATBOT_CLIENT_SETTINGS,\n FirstParameterType,\n IChatbotApiClient,\n IChatbotClientSettings,\n SecondParameterType,\n} from '../base/chatbot-api-client';\n// eslint-disable-next-line no-restricted-imports\nimport { Client } from './native-client';\n\n/** Streaming endpoint template, mirroring the generated client's `/api/v{version}/message`. */\nconst AGENT_STREAM_PATH_TEMPLATE = '/api/v{version}/message/stream';\n\n/**\n * Settings for the chatbot client, which includes a factory for constructor parameters, and additional settings\n * like version and clientId which are used in the API calls.\n */\nexport interface IChatbotClientSettingsTitanChat extends IChatbotClientSettings {\n constructorParametersFactory: () => {\n baseUrl?: FirstParameterType<typeof Client>;\n httpClient?: SecondParameterType<typeof Client>;\n };\n version: string;\n clientId: string;\n /**\n * Extra headers for the SSE streaming request. `X-Client-ID` is always sent (from `clientId`);\n * use this for anything the fetch http client would otherwise add (e.g. Authorization). Optional.\n */\n streamHeadersFactory?: () => Record<string, string>;\n}\n\n/**\n * Client adapter adopts the generated titan chatbot client to the generic IChatbotApiClient interface.\n * Contains client-specific methods for interacting with the titan chatbot API.\n */\n@injectable()\nexport class ChatbotApiClient implements IChatbotApiClient {\n private readonly client: Client;\n /** Same base URL the generated `Client` uses, so streaming URLs are built identically. */\n private readonly baseUrl: string;\n /** Same `fetch` the generated `Client` uses, so the SSE request gets identical auth/headers. */\n private readonly httpFetch?: typeof fetch;\n\n get version(): string {\n return this.chatbotApiClientSettings.version;\n }\n\n get clientId(): string {\n return this.chatbotApiClientSettings.clientId;\n }\n\n constructor(\n @inject(CHATBOT_CLIENT_SETTINGS)\n private readonly chatbotApiClientSettings: IChatbotClientSettingsTitanChat\n ) {\n const { baseUrl, httpClient } =\n this.chatbotApiClientSettings.constructorParametersFactory();\n this.client = new Client(baseUrl, httpClient);\n // Mirror the generated client's `this.baseUrl = baseUrl ?? \"\"`.\n this.baseUrl = baseUrl ?? '';\n /*\n * Reuse the same fetch the generated client uses, so the SSE request goes through the\n * consumer's request configuration (auth token, X-HC-Instance, credentials, …).\n */\n this.httpFetch = httpClient?.fetch as typeof fetch | undefined;\n }\n\n postFeedback(body: Models.Feedback, abortSignal?: AbortSignal) {\n return this.client.feedback(this.version, this.clientId, body, abortSignal);\n }\n\n postMessage(body: Models.UserMessage, abortSignal?: AbortSignal) {\n return this.client.message(this.version, this.clientId, body, abortSignal);\n }\n\n streamMessage(\n body: Models.IUserMessage,\n handlers: AgentStreamHandlers,\n abortSignal?: AbortSignal\n ): Promise<Models.BotMessage> {\n /*\n * Build the URL exactly as the generated Client does for `/api/v{version}/message`:\n * substitute {version}, then strip a dangling query separator.\n */\n const url = (this.baseUrl + AGENT_STREAM_PATH_TEMPLATE)\n .replace('{version}', encodeURIComponent('' + this.version))\n .replace(/[?&]$/, '');\n\n return runAgentStream({\n url,\n fetch: this.httpFetch,\n headers: {\n 'X-Client-ID': this.clientId,\n ...(this.chatbotApiClientSettings.streamHeadersFactory?.() ?? {}),\n },\n body,\n handlers,\n abortSignal,\n });\n }\n\n postFollowUpEmail(body: Models.UserMessage, abortSignal?: AbortSignal) {\n return this.client.followUpEmail(this.version, this.clientId, body, abortSignal);\n }\n\n getOptions(abortSignal?: AbortSignal): Promise<Models.FrontendModel> {\n return this.client.options(this.version, this.clientId, abortSignal);\n }\n\n async postSession(body: Models.Session, abortSignal?: AbortSignal) {\n return this.client.sessionPOST(this.version, this.clientId, body, abortSignal);\n }\n\n patchSession(body: Models.Session, abortSignal?: AbortSignal) {\n return this.client.sessionPATCH(this.version, this.clientId, body, abortSignal);\n }\n\n deleteSession(body: Models.Session, abortSignal?: AbortSignal) {\n return this.client.sessionDELETE(this.version, this.clientId, body, abortSignal);\n }\n\n getTranscripts(start?: Date, end?: Date, signal?: AbortSignal) {\n return this.client.transcripts(start, end, this.version, this.clientId, signal);\n }\n}\n"],"names":["inject","injectable","runAgentStream","CHATBOT_CLIENT_SETTINGS","Client","AGENT_STREAM_PATH_TEMPLATE","ChatbotApiClient","version","chatbotApiClientSettings","clientId","postFeedback","body","abortSignal","client","feedback","postMessage","message","streamMessage","handlers","url","baseUrl","replace","encodeURIComponent","fetch","httpFetch","headers","streamHeadersFactory","postFollowUpEmail","followUpEmail","getOptions","options","postSession","sessionPOST","patchSession","sessionPATCH","deleteSession","sessionDELETE","getTranscripts","start","end","signal","transcripts","httpClient","constructorParametersFactory"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export * from './api-client';
|
|
2
2
|
export * from './stores';
|
|
3
|
+
export * from './streaming';
|
|
3
4
|
export type * from './models';
|
|
5
|
+
export { isChatbotStreamingEnabled, DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS, } from './models/chatbot-customizations';
|
|
4
6
|
export * from './hooks/use-customization-chatbot';
|
|
5
|
-
export * as NativeClientHC from './api-client/help-center/native-client';
|
|
6
7
|
export * as NativeClientTC from './api-client/titan-chat/native-client';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,mBAAmB,UAAU,CAAC;AAE9B,OAAO,EACH,yBAAyB,EACzB,uCAAuC,GAC1C,MAAM,iCAAiC,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,OAAO,KAAK,cAAc,MAAM,uCAAuC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-restricted-imports */ export * from './api-client';
|
|
2
2
|
export * from './stores';
|
|
3
|
+
export * from './streaming';
|
|
4
|
+
// Runtime helpers from models (the `export type *` above is type-only).
|
|
5
|
+
export { isChatbotStreamingEnabled, DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS } from './models/chatbot-customizations';
|
|
3
6
|
export * from './hooks/use-customization-chatbot';
|
|
4
|
-
import * as _NativeClientHC from './api-client/help-center/native-client';
|
|
5
|
-
export { _NativeClientHC as NativeClientHC };
|
|
6
7
|
import * as _NativeClientTC from './api-client/titan-chat/native-client';
|
|
7
8
|
export { _NativeClientTC as NativeClientTC };
|
|
8
9
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable no-restricted-imports */\nexport * from './api-client';\nexport * from './stores';\nexport type * from './models';\nexport
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable no-restricted-imports */\nexport * from './api-client';\nexport * from './stores';\nexport * from './streaming';\nexport type * from './models';\n// Runtime helpers from models (the `export type *` above is type-only).\nexport {\n isChatbotStreamingEnabled,\n DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS,\n} from './models/chatbot-customizations';\nexport * from './hooks/use-customization-chatbot';\nexport * as NativeClientTC from './api-client/titan-chat/native-client';\n"],"names":["isChatbotStreamingEnabled","DEFAULT_STREAMING_INACTIVITY_TIMEOUT_MS","NativeClientTC"],"mappings":"AAAA,wCAAwC,GACxC,cAAc,eAAe;AAC7B,cAAc,WAAW;AACzB,cAAc,cAAc;AAE5B,wEAAwE;AACxE,SACIA,yBAAyB,EACzBC,uCAAuC,QACpC,kCAAkC;AACzC,cAAc,oCAAoC;AAClD,iCAAgC,wCAAwC;AAAxE,SAAO,mBAAKC,cAAc,GAA8C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatbot-customizations.test.d.ts","sourceRoot":"","sources":["../../../src/models/__tests__/chatbot-customizations.test.ts"],"names":[],"mappings":""}
|