@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
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, expect, test } from '@jest/globals';
|
|
2
|
+
import { Models } from '../../api-client';
|
|
3
|
+
import { convertAgentFinishToBotMessage } from '../agent-stream';
|
|
4
|
+
|
|
5
|
+
describe('convertAgentFinishToBotMessage', () => {
|
|
6
|
+
test('preserves the backend BotMessage fields verbatim', () => {
|
|
7
|
+
// Real Bifurcation payload: backend sends guardFlag "BI" + isGuardrailed true.
|
|
8
|
+
const message = convertAgentFinishToBotMessage({
|
|
9
|
+
answer: 'pick one',
|
|
10
|
+
guardFlag: 'BI',
|
|
11
|
+
isGuardrailed: true,
|
|
12
|
+
sessionId: 122,
|
|
13
|
+
status: 'Bifurcation',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(message).toBeInstanceOf(Models.BotMessage);
|
|
17
|
+
expect(message.answer).toBe('pick one');
|
|
18
|
+
expect(message.guardFlag).toBe('BI');
|
|
19
|
+
expect(message.isGuardrailed).toBe(true);
|
|
20
|
+
expect(message.sessionId).toBe(122);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('ignores streaming-only metadata (status, durationMs, runId, seq)', () => {
|
|
24
|
+
const message = convertAgentFinishToBotMessage({
|
|
25
|
+
answer: 'ok',
|
|
26
|
+
guardFlag: 'N',
|
|
27
|
+
isGuardrailed: false,
|
|
28
|
+
status: 'Success',
|
|
29
|
+
durationMs: 13603,
|
|
30
|
+
runId: 'ec66a0b47d99430a99b964f7478aadd7',
|
|
31
|
+
seq: 6,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const json = message.toJSON();
|
|
35
|
+
expect(json).not.toHaveProperty('status');
|
|
36
|
+
expect(json).not.toHaveProperty('durationMs');
|
|
37
|
+
expect(json).not.toHaveProperty('runId');
|
|
38
|
+
expect(json).not.toHaveProperty('seq');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('wraps nested data into serializable instances (toJSON does not throw)', () => {
|
|
42
|
+
// Mirrors the decoded SSE JSON: nested data arrives as plain objects, not class instances.
|
|
43
|
+
const payload: any = {
|
|
44
|
+
answer: 'final',
|
|
45
|
+
guardFlag: 'BI',
|
|
46
|
+
isGuardrailed: true,
|
|
47
|
+
sessionId: 3,
|
|
48
|
+
scoredUrls: [{ url: 'https://kb/1', score: 0.9, title: 'Doc' }],
|
|
49
|
+
agentOptions: [{ agentId: 'playwright', passPhrase: 'Do it for me', caption: 'Auto' }],
|
|
50
|
+
workflowPlan: {
|
|
51
|
+
displayName: 'Refund',
|
|
52
|
+
estimatedRuntimeSec: 5,
|
|
53
|
+
steps: [{ number: 1, description: 'Look up order' }],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
const message = convertAgentFinishToBotMessage(payload);
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Regression: persisting chat state calls BotMessage.toJSON(), which iterates these and
|
|
60
|
+
* calls item.toJSON() on each — it threw "item.toJSON is not a function" for plain objects.
|
|
61
|
+
*/
|
|
62
|
+
expect(() => JSON.stringify(message)).not.toThrow();
|
|
63
|
+
expect(message.scoredUrls?.[0]).toBeInstanceOf(Models.ScoredUrl);
|
|
64
|
+
expect(message.agentOptions?.[0]).toBeInstanceOf(Models.AgentOption);
|
|
65
|
+
expect(message.workflowPlan).toBeInstanceOf(Models.WorkflowPlan);
|
|
66
|
+
expect(message.workflowPlan?.steps[0]).toBeInstanceOf(Models.WorkflowStep);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('handles a minimal payload with no nested data', () => {
|
|
70
|
+
const message = convertAgentFinishToBotMessage({
|
|
71
|
+
answer: 'x',
|
|
72
|
+
guardFlag: 'N',
|
|
73
|
+
isGuardrailed: false,
|
|
74
|
+
});
|
|
75
|
+
expect(message.scoredUrls).toBeUndefined();
|
|
76
|
+
expect(message.agentOptions).toBeUndefined();
|
|
77
|
+
expect(message.workflowPlan).toBeUndefined();
|
|
78
|
+
expect(() => JSON.stringify(message)).not.toThrow();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Models } from '../api-client';
|
|
2
|
+
|
|
3
|
+
/** Final run status reported by the backend on `run.finished`. */
|
|
4
|
+
export type AgentRunStatus =
|
|
5
|
+
| 'Success'
|
|
6
|
+
| 'Guardrailed'
|
|
7
|
+
| 'PendingApproval'
|
|
8
|
+
| 'Bifurcation'
|
|
9
|
+
| 'Error'
|
|
10
|
+
| 'Timeout';
|
|
11
|
+
|
|
12
|
+
export interface AgentPlanStep {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AgentInputOption {
|
|
19
|
+
label: string;
|
|
20
|
+
value: string;
|
|
21
|
+
style?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AgentInputRequest {
|
|
25
|
+
kind: string;
|
|
26
|
+
prompt?: string;
|
|
27
|
+
options?: AgentInputOption[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Decoded payload of the terminal `run.finished` event. The backend sends a full `BotMessage`
|
|
32
|
+
* (same field names: `answer`, `guardFlag`, `isGuardrailed`, `scoredUrls`, `agentOptions`,
|
|
33
|
+
* `workflowPlan`, `sessionId`, …) plus a little streaming-only metadata — so the mapping to the
|
|
34
|
+
* shared model is trivial (see {@link convertAgentFinishToBotMessage}).
|
|
35
|
+
*/
|
|
36
|
+
export interface AgentRunFinishedData extends Models.IBotMessage {
|
|
37
|
+
/** Final run status (streaming-only metadata, not part of the BotMessage model). */
|
|
38
|
+
status?: AgentRunStatus;
|
|
39
|
+
/** Total run duration in ms (streaming-only metadata). */
|
|
40
|
+
durationMs?: number;
|
|
41
|
+
/** Backend run identifier (streaming-only metadata). */
|
|
42
|
+
runId?: string;
|
|
43
|
+
/** Monotonic event sequence number (streaming-only metadata). */
|
|
44
|
+
seq?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Callbacks + config the consumer supplies to a streamed message. Maps the chatbot's agent events
|
|
49
|
+
* onto progress updates and exposes the generic connection lifecycle for logging / keepalive / fallback.
|
|
50
|
+
*/
|
|
51
|
+
export interface AgentStreamHandlers {
|
|
52
|
+
/** Inactivity threshold before `onInactivity` fires (defaults applied by the caller). */
|
|
53
|
+
inactivityTimeoutMs?: number;
|
|
54
|
+
onStatus?(text: string): void;
|
|
55
|
+
onText?(text: string): void;
|
|
56
|
+
onPlan?(steps: AgentPlanStep[]): void;
|
|
57
|
+
/**
|
|
58
|
+
* Marks the plan step with the given id as the active one (earlier steps become done, later
|
|
59
|
+
* ones stay pending). Driven by an explicit `activeStepId` on `plan.proposed` or a `stepId` on
|
|
60
|
+
* `status.changed` when the backend supplies it; absent that, the first step is activated on
|
|
61
|
+
* `plan.proposed`. Mid-plan advancement therefore requires backend step correlation.
|
|
62
|
+
*/
|
|
63
|
+
onStepActive?(id: string): void;
|
|
64
|
+
onInputRequested?(request: AgentInputRequest): void;
|
|
65
|
+
onInactivity?(): void;
|
|
66
|
+
onConnected?(): void;
|
|
67
|
+
onDisconnected?(): void;
|
|
68
|
+
onTimeout?(): void;
|
|
69
|
+
onCompleted?(): void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Raised when the backend emits a `run.error` event. */
|
|
73
|
+
export class AgentStreamError extends Error {
|
|
74
|
+
constructor(message?: string) {
|
|
75
|
+
super(message ?? 'Something went wrong during this step. Please try again.');
|
|
76
|
+
this.name = 'AgentStreamError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Path of the v2 streaming endpoint, appended to the configured base URL. */
|
|
81
|
+
export const AGENT_STREAM_PATH = '/api/v2/message/stream';
|
|
82
|
+
|
|
83
|
+
/** SSE event names emitted by the backend agent pipeline. */
|
|
84
|
+
export const AGENT_EVENT = {
|
|
85
|
+
RunStarted: 'run.started',
|
|
86
|
+
RunFinished: 'run.finished',
|
|
87
|
+
RunError: 'run.error',
|
|
88
|
+
StatusChanged: 'status.changed',
|
|
89
|
+
TextAppended: 'text.appended',
|
|
90
|
+
PlanProposed: 'plan.proposed',
|
|
91
|
+
InputRequested: 'input.requested',
|
|
92
|
+
} as const;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Map a terminal `run.finished` payload to the shared `BotMessage` model. The payload is already
|
|
96
|
+
* BotMessage-shaped, so `fromJS` does everything: it reads the backend's `guardFlag`/`isGuardrailed`
|
|
97
|
+
* verbatim, wraps nested data into real instances (`scoredUrls`, `agentOptions`, `workflowPlan` and
|
|
98
|
+
* its `steps`/`inputs`) so `toJSON()` can serialize it for session storage, and ignores the
|
|
99
|
+
* streaming-only metadata (`status`, `durationMs`, `runId`, `seq`).
|
|
100
|
+
*/
|
|
101
|
+
export function convertAgentFinishToBotMessage(data: AgentRunFinishedData): Models.BotMessage {
|
|
102
|
+
return Models.BotMessage.fromJS(data);
|
|
103
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ChatSseClient } from '@servicetitan/titan-chat-ui-common';
|
|
2
|
+
import { Models } from '../api-client';
|
|
3
|
+
import {
|
|
4
|
+
AGENT_EVENT,
|
|
5
|
+
AgentPlanStep,
|
|
6
|
+
AgentRunFinishedData,
|
|
7
|
+
AgentStreamError,
|
|
8
|
+
AgentStreamHandlers,
|
|
9
|
+
convertAgentFinishToBotMessage,
|
|
10
|
+
} from './agent-stream';
|
|
11
|
+
|
|
12
|
+
export interface RunAgentStreamOptions {
|
|
13
|
+
/** Fully-constructed streaming endpoint URL. */
|
|
14
|
+
url: string;
|
|
15
|
+
/** Request headers (auth, X-Client-ID, …). */
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
/** Request body, serialized as JSON by the SSE client. */
|
|
18
|
+
body: unknown;
|
|
19
|
+
/** Custom `fetch` (same as the regular API client) so auth/headers/credentials apply identically. */
|
|
20
|
+
fetch?: typeof fetch;
|
|
21
|
+
/** Progress + lifecycle callbacks (and the inactivity timeout). */
|
|
22
|
+
handlers: AgentStreamHandlers;
|
|
23
|
+
abortSignal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Shared SSE consumption used by every {@link IChatbotApiClient} adapter: opens a {@link ChatSseClient},
|
|
28
|
+
* maps the agent events onto the supplied handlers, and resolves the final {@link Models.BotMessage}
|
|
29
|
+
* from `run.finished` (or rejects on `run.error` / a fatal connection error). The only per-adapter
|
|
30
|
+
* differences — the URL, headers and body — are passed in by the caller.
|
|
31
|
+
*/
|
|
32
|
+
export function runAgentStream({
|
|
33
|
+
abortSignal,
|
|
34
|
+
body,
|
|
35
|
+
fetch,
|
|
36
|
+
handlers,
|
|
37
|
+
headers,
|
|
38
|
+
url,
|
|
39
|
+
}: RunAgentStreamOptions): Promise<Models.BotMessage> {
|
|
40
|
+
return new Promise<Models.BotMessage>((resolve, reject) => {
|
|
41
|
+
let finished: AgentRunFinishedData | undefined;
|
|
42
|
+
|
|
43
|
+
const client = new ChatSseClient({
|
|
44
|
+
url,
|
|
45
|
+
headers,
|
|
46
|
+
fetch,
|
|
47
|
+
signal: abortSignal,
|
|
48
|
+
body,
|
|
49
|
+
inactivityTimeoutMs: handlers.inactivityTimeoutMs,
|
|
50
|
+
isTerminalEvent: e =>
|
|
51
|
+
e.event === AGENT_EVENT.RunFinished || e.event === AGENT_EVENT.RunError,
|
|
52
|
+
handlers: {
|
|
53
|
+
[AGENT_EVENT.StatusChanged]: (d: { text: string; stepId?: string }) => {
|
|
54
|
+
handlers.onStatus?.(d.text);
|
|
55
|
+
if (d.stepId !== undefined) {
|
|
56
|
+
handlers.onStepActive?.(d.stepId);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
[AGENT_EVENT.TextAppended]: (d: { text: string }) => handlers.onText?.(d.text),
|
|
60
|
+
[AGENT_EVENT.PlanProposed]: (d: {
|
|
61
|
+
steps: AgentPlanStep[];
|
|
62
|
+
activeStepId?: string;
|
|
63
|
+
}) => {
|
|
64
|
+
handlers.onPlan?.(d.steps);
|
|
65
|
+
// Activate the explicitly-signalled step, else default to the first.
|
|
66
|
+
const activeId = d.activeStepId ?? d.steps?.[0]?.id;
|
|
67
|
+
if (activeId !== undefined) {
|
|
68
|
+
handlers.onStepActive?.(activeId);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
[AGENT_EVENT.InputRequested]: (d: any) =>
|
|
72
|
+
handlers.onInputRequested?.({
|
|
73
|
+
kind: d.kind,
|
|
74
|
+
prompt: d.prompt,
|
|
75
|
+
options: d.options,
|
|
76
|
+
}),
|
|
77
|
+
[AGENT_EVENT.RunFinished]: (d: AgentRunFinishedData) => {
|
|
78
|
+
finished = d;
|
|
79
|
+
},
|
|
80
|
+
[AGENT_EVENT.RunError]: (d: { message?: string }) => {
|
|
81
|
+
reject(new AgentStreamError(d.message));
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
onConnected: handlers.onConnected,
|
|
85
|
+
onDisconnected: handlers.onDisconnected,
|
|
86
|
+
onTimeout: handlers.onTimeout,
|
|
87
|
+
onInactivity: handlers.onInactivity,
|
|
88
|
+
onCompleted: handlers.onCompleted,
|
|
89
|
+
onError: reject,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
client.start().then(() => {
|
|
93
|
+
if (finished) {
|
|
94
|
+
try {
|
|
95
|
+
resolve(convertAgentFinishToBotMessage(finished));
|
|
96
|
+
} catch (err) {
|
|
97
|
+
reject(err);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
/*
|
|
102
|
+
* Stream completed without `run.finished`. A run.error / fatal onError may have
|
|
103
|
+
* already rejected (subsequent reject calls are no-ops); otherwise the server closed
|
|
104
|
+
* the connection unexpectedly — reject so the returned Promise never hangs.
|
|
105
|
+
*/
|
|
106
|
+
reject(new AgentStreamError('Stream ended without a run.finished event'));
|
|
107
|
+
}, reject);
|
|
108
|
+
});
|
|
109
|
+
}
|