@onedeskpro/chatbot-core 0.1.0 → 0.2.1

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/dist/index.d.cts CHANGED
@@ -4,10 +4,15 @@ import { ChatbotBlockReason } from '@onedeskpro/chatbot-types';
4
4
  import { ChatbotEventMap } from '@onedeskpro/chatbot-types';
5
5
  import { ChatbotInitOptions } from '@onedeskpro/chatbot-types';
6
6
  import { ChatbotState } from '@onedeskpro/chatbot-types';
7
+ import { ChatbotTicketMode } from '@onedeskpro/chatbot-types';
7
8
  import { ChatMessage } from '@onedeskpro/chatbot-types';
8
9
  import { ChatRequest } from '@onedeskpro/chatbot-types';
9
10
  import { ChatResponseData } from '@onedeskpro/chatbot-types';
11
+ import { IdentifyRequest } from '@onedeskpro/chatbot-types';
12
+ import { IdentifyResponseData } from '@onedeskpro/chatbot-types';
10
13
  import { SdkConfigResponse } from '@onedeskpro/chatbot-types';
14
+ import { TicketStatusData } from '@onedeskpro/chatbot-types';
15
+ import { VisitorVerifyResponse } from '@onedeskpro/chatbot-types';
11
16
 
12
17
  export declare class ApiClient {
13
18
  private baseUrl;
@@ -16,9 +21,12 @@ export declare class ApiClient {
16
21
  constructor(options: ApiClientOptions);
17
22
  private fail;
18
23
  private request;
24
+ identify(payload: IdentifyRequest): Promise<IdentifyResponseData>;
25
+ verifyVisitor(visitorToken: string): Promise<VisitorVerifyResponse>;
19
26
  sendMessage(payload: ChatRequest): Promise<ChatResponseData>;
20
- fetchHistory(sessionId: string): Promise<ChatMessage[]>;
21
27
  fetchConfig(): Promise<SdkConfigResponse>;
28
+ requestHuman(visitorToken: string): Promise<TicketStatusData>;
29
+ fetchTicketStatus(visitorToken: string): Promise<TicketStatusData>;
22
30
  }
23
31
 
24
32
  declare interface ApiClientOptions {
@@ -37,10 +45,22 @@ export { ChatbotBlockReason }
37
45
  export declare class ChatbotCore {
38
46
  private apiClient;
39
47
  private emitter;
40
- private session;
48
+ private visitorTokens;
41
49
  private widget;
50
+ private sdkSocket;
42
51
  private options;
43
52
  private callerSetName;
53
+ /**
54
+ * True once this session has an open (or recently closed) ticket episode —
55
+ * from ticket-status `conversationId`, a non-ai mode, or a successful chat
56
+ * round-trip. Gates the request-human control so visitors cannot escalate
57
+ * before a ticket exists.
58
+ */
59
+ private hasActiveTicket;
60
+ /** Pending readiness re-check while the server is unreachable. */
61
+ private retryTimer;
62
+ /** Server id of the last `message:receive` push rendered as an agent bubble. */
63
+ private lastPushId;
44
64
  /**
45
65
  * Bumped by every init() and by destroy(). An async init compares the token it
46
66
  * started with against this before touching anything, so a superseded run — a
@@ -55,11 +75,51 @@ export declare class ChatbotCore {
55
75
  * everything — not just the transitions that have a dedicated event.
56
76
  */
57
77
  private setState;
78
+ private applyMode;
79
+ /** Derive ticket existence from status restore / socket pushes. */
80
+ private syncHasActiveTicket;
81
+ private syncWidgetMode;
58
82
  init(options: ChatbotInitOptions): Promise<void>;
59
- /** Returns null on failure — a network blip must not block the user from trying. */
60
- private fetchConfig;
83
+ /**
84
+ * Asks `/sdk/config` whether the server is up and the agent can reply, and
85
+ * shows the widget only when both hold. An unreachable server is retried on
86
+ * READINESS_RETRY_DELAYS_MS; a configuration problem is final for this page.
87
+ * `ready` fires once the outcome is settled either way.
88
+ */
89
+ private checkReadiness;
90
+ /** Creates the widget hidden; checkReadiness reveals it once every check passed. */
91
+ private mountWidget;
92
+ private clearRetry;
93
+ /**
94
+ * Maps `/sdk/config` rejections other than an unreachable server: missing
95
+ * Connected Channels becomes `no-agent`; anything else (an invalid key, a
96
+ * disallowed origin) is recorded as `state.error`.
97
+ */
98
+ private handleConfigError;
99
+ private resolveVisitorGate;
100
+ private enterChat;
101
+ private connectSdkSocket;
102
+ private disconnectSdkSocket;
103
+ /** Restore episode mode after identify / verify — never hydrates messages. */
104
+ private restoreTicketStatus;
105
+ private handleTicketStatus;
106
+ /**
107
+ * Live human (agent) pushes from `/sdk` `message:receive`.
108
+ *
109
+ * Choice: ignore while `mode === 'ai'`. Website outbound (including AI
110
+ * replies) is fanned out to the visitor room; AI text already arrives via
111
+ * `POST /sdk/chat` REST and would double-render as an `agent` bubble. Accept
112
+ * pushes in `waiting` / `human` / `closed` (late agent messages after close).
113
+ * Also dedupe against the last bubble: an `ai` bubble by content, an `agent`
114
+ * bubble by server id, so an agent can send the same text twice.
115
+ */
116
+ private handleMessageReceive;
117
+ submitIdentify(payload: IdentifyRequest): Promise<void>;
118
+ /**
119
+ * Escalate the open AI ticket to Unassigned. No-op unless the widget is in `ai` mode.
120
+ */
121
+ requestHuman(): Promise<void>;
61
122
  sendMessage(text: string): Promise<void>;
62
- private loadHistory;
63
123
  on<K extends keyof ChatbotEventMap>(event: K, listener: Listener<K>): () => void;
64
124
  resetSession(): void;
65
125
  open(): void;
@@ -87,6 +147,8 @@ export declare interface ChatbotRequestError extends Error {
87
147
 
88
148
  export { ChatbotState }
89
149
 
150
+ export { ChatbotTicketMode }
151
+
90
152
  export { ChatMessage }
91
153
 
92
154
  export { ChatRequest }
@@ -106,6 +168,12 @@ export declare class EventEmitter {
106
168
  removeAllListeners(): void;
107
169
  }
108
170
 
171
+ export { IdentifyRequest }
172
+
173
+ export { IdentifyResponseData }
174
+
175
+ export declare function isChatbotRequestError(error: unknown): error is ChatbotRequestError;
176
+
109
177
  declare type Listener<K extends keyof ChatbotEventMap> = ChatbotEventMap[K] extends void ? () => void : (payload: ChatbotEventMap[K]) => void;
110
178
 
111
179
  declare type Listener_2<T> = T extends void ? () => void : (payload: T) => void;
@@ -115,15 +183,53 @@ export declare const OnedeskProChatbot: {
115
183
  getInstance(): ChatbotCore | null;
116
184
  };
117
185
 
186
+ /**
187
+ * Strip any path/query/hash from an API base URL so Socket.IO connects to the
188
+ * server origin + `/sdk` namespace (not `/v1/sdk` if the REST client uses a path prefix).
189
+ */
190
+ export declare function resolveSdkSocketUrl(baseUrl: string): string;
191
+
118
192
  export { SdkConfigResponse }
119
193
 
194
+ /**
195
+ * Visitor Socket.IO helper for the dedicated `/sdk` namespace.
196
+ * Auth is handshake-only (`apiKey` + `visitorToken`); no BetterAuth session.
197
+ */
198
+ export declare class SdkSocket {
199
+ private socket;
200
+ get connected(): boolean;
201
+ connect(opts: SdkSocketConnectOptions): void;
202
+ disconnect(): void;
203
+ }
204
+
205
+ export declare interface SdkSocketConnectOptions {
206
+ /** API base URL (may include a path prefix); origin is used for the `/sdk` namespace. */
207
+ baseUrl: string;
208
+ apiKey: string;
209
+ visitorToken: string;
210
+ onTicketStatus?: (payload: TicketStatusData) => void;
211
+ /** Raw inbox-shaped payload from `message:receive` (mapped in ChatbotCore later). */
212
+ onMessageReceive?: (payload: unknown) => void;
213
+ /**
214
+ * Fired on socket.io `connect` after the first successful connection
215
+ * (i.e. reconnect). Callers should re-fetch ticket status — no history backfill.
216
+ */
217
+ onReconnect?: () => void;
218
+ onConnectError?: (error: Error) => void;
219
+ }
220
+
120
221
  export declare class SessionManager {
121
- private sessionId;
122
- init(providedSessionId?: string): string;
222
+ private token;
223
+ private storageKey;
224
+ /** Scope the token to an agent so multiple widgets on one origin stay isolated. */
225
+ setScope(agentId: string | null | undefined): void;
123
226
  get(): string | null;
124
- reset(): string;
125
- private persist;
126
- private generateId;
227
+ set(token: string): void;
228
+ clear(): void;
127
229
  }
128
230
 
231
+ export { TicketStatusData }
232
+
233
+ export { VisitorVerifyResponse }
234
+
129
235
  export { }
package/dist/index.d.ts CHANGED
@@ -4,10 +4,15 @@ import { ChatbotBlockReason } from '@onedeskpro/chatbot-types';
4
4
  import { ChatbotEventMap } from '@onedeskpro/chatbot-types';
5
5
  import { ChatbotInitOptions } from '@onedeskpro/chatbot-types';
6
6
  import { ChatbotState } from '@onedeskpro/chatbot-types';
7
+ import { ChatbotTicketMode } from '@onedeskpro/chatbot-types';
7
8
  import { ChatMessage } from '@onedeskpro/chatbot-types';
8
9
  import { ChatRequest } from '@onedeskpro/chatbot-types';
9
10
  import { ChatResponseData } from '@onedeskpro/chatbot-types';
11
+ import { IdentifyRequest } from '@onedeskpro/chatbot-types';
12
+ import { IdentifyResponseData } from '@onedeskpro/chatbot-types';
10
13
  import { SdkConfigResponse } from '@onedeskpro/chatbot-types';
14
+ import { TicketStatusData } from '@onedeskpro/chatbot-types';
15
+ import { VisitorVerifyResponse } from '@onedeskpro/chatbot-types';
11
16
 
12
17
  export declare class ApiClient {
13
18
  private baseUrl;
@@ -16,9 +21,12 @@ export declare class ApiClient {
16
21
  constructor(options: ApiClientOptions);
17
22
  private fail;
18
23
  private request;
24
+ identify(payload: IdentifyRequest): Promise<IdentifyResponseData>;
25
+ verifyVisitor(visitorToken: string): Promise<VisitorVerifyResponse>;
19
26
  sendMessage(payload: ChatRequest): Promise<ChatResponseData>;
20
- fetchHistory(sessionId: string): Promise<ChatMessage[]>;
21
27
  fetchConfig(): Promise<SdkConfigResponse>;
28
+ requestHuman(visitorToken: string): Promise<TicketStatusData>;
29
+ fetchTicketStatus(visitorToken: string): Promise<TicketStatusData>;
22
30
  }
23
31
 
24
32
  declare interface ApiClientOptions {
@@ -37,10 +45,22 @@ export { ChatbotBlockReason }
37
45
  export declare class ChatbotCore {
38
46
  private apiClient;
39
47
  private emitter;
40
- private session;
48
+ private visitorTokens;
41
49
  private widget;
50
+ private sdkSocket;
42
51
  private options;
43
52
  private callerSetName;
53
+ /**
54
+ * True once this session has an open (or recently closed) ticket episode —
55
+ * from ticket-status `conversationId`, a non-ai mode, or a successful chat
56
+ * round-trip. Gates the request-human control so visitors cannot escalate
57
+ * before a ticket exists.
58
+ */
59
+ private hasActiveTicket;
60
+ /** Pending readiness re-check while the server is unreachable. */
61
+ private retryTimer;
62
+ /** Server id of the last `message:receive` push rendered as an agent bubble. */
63
+ private lastPushId;
44
64
  /**
45
65
  * Bumped by every init() and by destroy(). An async init compares the token it
46
66
  * started with against this before touching anything, so a superseded run — a
@@ -55,11 +75,51 @@ export declare class ChatbotCore {
55
75
  * everything — not just the transitions that have a dedicated event.
56
76
  */
57
77
  private setState;
78
+ private applyMode;
79
+ /** Derive ticket existence from status restore / socket pushes. */
80
+ private syncHasActiveTicket;
81
+ private syncWidgetMode;
58
82
  init(options: ChatbotInitOptions): Promise<void>;
59
- /** Returns null on failure — a network blip must not block the user from trying. */
60
- private fetchConfig;
83
+ /**
84
+ * Asks `/sdk/config` whether the server is up and the agent can reply, and
85
+ * shows the widget only when both hold. An unreachable server is retried on
86
+ * READINESS_RETRY_DELAYS_MS; a configuration problem is final for this page.
87
+ * `ready` fires once the outcome is settled either way.
88
+ */
89
+ private checkReadiness;
90
+ /** Creates the widget hidden; checkReadiness reveals it once every check passed. */
91
+ private mountWidget;
92
+ private clearRetry;
93
+ /**
94
+ * Maps `/sdk/config` rejections other than an unreachable server: missing
95
+ * Connected Channels becomes `no-agent`; anything else (an invalid key, a
96
+ * disallowed origin) is recorded as `state.error`.
97
+ */
98
+ private handleConfigError;
99
+ private resolveVisitorGate;
100
+ private enterChat;
101
+ private connectSdkSocket;
102
+ private disconnectSdkSocket;
103
+ /** Restore episode mode after identify / verify — never hydrates messages. */
104
+ private restoreTicketStatus;
105
+ private handleTicketStatus;
106
+ /**
107
+ * Live human (agent) pushes from `/sdk` `message:receive`.
108
+ *
109
+ * Choice: ignore while `mode === 'ai'`. Website outbound (including AI
110
+ * replies) is fanned out to the visitor room; AI text already arrives via
111
+ * `POST /sdk/chat` REST and would double-render as an `agent` bubble. Accept
112
+ * pushes in `waiting` / `human` / `closed` (late agent messages after close).
113
+ * Also dedupe against the last bubble: an `ai` bubble by content, an `agent`
114
+ * bubble by server id, so an agent can send the same text twice.
115
+ */
116
+ private handleMessageReceive;
117
+ submitIdentify(payload: IdentifyRequest): Promise<void>;
118
+ /**
119
+ * Escalate the open AI ticket to Unassigned. No-op unless the widget is in `ai` mode.
120
+ */
121
+ requestHuman(): Promise<void>;
61
122
  sendMessage(text: string): Promise<void>;
62
- private loadHistory;
63
123
  on<K extends keyof ChatbotEventMap>(event: K, listener: Listener<K>): () => void;
64
124
  resetSession(): void;
65
125
  open(): void;
@@ -87,6 +147,8 @@ export declare interface ChatbotRequestError extends Error {
87
147
 
88
148
  export { ChatbotState }
89
149
 
150
+ export { ChatbotTicketMode }
151
+
90
152
  export { ChatMessage }
91
153
 
92
154
  export { ChatRequest }
@@ -106,6 +168,12 @@ export declare class EventEmitter {
106
168
  removeAllListeners(): void;
107
169
  }
108
170
 
171
+ export { IdentifyRequest }
172
+
173
+ export { IdentifyResponseData }
174
+
175
+ export declare function isChatbotRequestError(error: unknown): error is ChatbotRequestError;
176
+
109
177
  declare type Listener<K extends keyof ChatbotEventMap> = ChatbotEventMap[K] extends void ? () => void : (payload: ChatbotEventMap[K]) => void;
110
178
 
111
179
  declare type Listener_2<T> = T extends void ? () => void : (payload: T) => void;
@@ -115,15 +183,53 @@ export declare const OnedeskProChatbot: {
115
183
  getInstance(): ChatbotCore | null;
116
184
  };
117
185
 
186
+ /**
187
+ * Strip any path/query/hash from an API base URL so Socket.IO connects to the
188
+ * server origin + `/sdk` namespace (not `/v1/sdk` if the REST client uses a path prefix).
189
+ */
190
+ export declare function resolveSdkSocketUrl(baseUrl: string): string;
191
+
118
192
  export { SdkConfigResponse }
119
193
 
194
+ /**
195
+ * Visitor Socket.IO helper for the dedicated `/sdk` namespace.
196
+ * Auth is handshake-only (`apiKey` + `visitorToken`); no BetterAuth session.
197
+ */
198
+ export declare class SdkSocket {
199
+ private socket;
200
+ get connected(): boolean;
201
+ connect(opts: SdkSocketConnectOptions): void;
202
+ disconnect(): void;
203
+ }
204
+
205
+ export declare interface SdkSocketConnectOptions {
206
+ /** API base URL (may include a path prefix); origin is used for the `/sdk` namespace. */
207
+ baseUrl: string;
208
+ apiKey: string;
209
+ visitorToken: string;
210
+ onTicketStatus?: (payload: TicketStatusData) => void;
211
+ /** Raw inbox-shaped payload from `message:receive` (mapped in ChatbotCore later). */
212
+ onMessageReceive?: (payload: unknown) => void;
213
+ /**
214
+ * Fired on socket.io `connect` after the first successful connection
215
+ * (i.e. reconnect). Callers should re-fetch ticket status — no history backfill.
216
+ */
217
+ onReconnect?: () => void;
218
+ onConnectError?: (error: Error) => void;
219
+ }
220
+
120
221
  export declare class SessionManager {
121
- private sessionId;
122
- init(providedSessionId?: string): string;
222
+ private token;
223
+ private storageKey;
224
+ /** Scope the token to an agent so multiple widgets on one origin stay isolated. */
225
+ setScope(agentId: string | null | undefined): void;
123
226
  get(): string | null;
124
- reset(): string;
125
- private persist;
126
- private generateId;
227
+ set(token: string): void;
228
+ clear(): void;
127
229
  }
128
230
 
231
+ export { TicketStatusData }
232
+
233
+ export { VisitorVerifyResponse }
234
+
129
235
  export { }