@onedeskpro/chatbot-core 0.1.0 → 0.2.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/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,20 @@ 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
+ /** Server id of the last `message:receive` push rendered as an agent bubble. */
61
+ private lastPushId;
44
62
  /**
45
63
  * Bumped by every init() and by destroy(). An async init compares the token it
46
64
  * started with against this before touching anything, so a superseded run — a
@@ -55,11 +73,40 @@ export declare class ChatbotCore {
55
73
  * everything — not just the transitions that have a dedicated event.
56
74
  */
57
75
  private setState;
76
+ private applyMode;
77
+ /** Derive ticket existence from status restore / socket pushes. */
78
+ private syncHasActiveTicket;
79
+ private syncWidgetMode;
58
80
  init(options: ChatbotInitOptions): Promise<void>;
59
- /** Returns null on failure — a network blip must not block the user from trying. */
60
- private fetchConfig;
81
+ /**
82
+ * Maps `/sdk/config` failures: missing Connected Channels becomes `no-agent`,
83
+ * other 403s show the API message, and 401/network stay as `state.error`.
84
+ */
85
+ private handleConfigError;
86
+ private resolveVisitorGate;
87
+ private enterChat;
88
+ private connectSdkSocket;
89
+ private disconnectSdkSocket;
90
+ /** Restore episode mode after identify / verify — never hydrates messages. */
91
+ private restoreTicketStatus;
92
+ private handleTicketStatus;
93
+ /**
94
+ * Live human (agent) pushes from `/sdk` `message:receive`.
95
+ *
96
+ * Choice: ignore while `mode === 'ai'`. Website outbound (including AI
97
+ * replies) is fanned out to the visitor room; AI text already arrives via
98
+ * `POST /sdk/chat` REST and would double-render as an `agent` bubble. Accept
99
+ * pushes in `waiting` / `human` / `closed` (late agent messages after close).
100
+ * Also dedupe against the last bubble: an `ai` bubble by content, an `agent`
101
+ * bubble by server id, so an agent can send the same text twice.
102
+ */
103
+ private handleMessageReceive;
104
+ submitIdentify(payload: IdentifyRequest): Promise<void>;
105
+ /**
106
+ * Escalate the open AI ticket to Unassigned. No-op unless the widget is in `ai` mode.
107
+ */
108
+ requestHuman(): Promise<void>;
61
109
  sendMessage(text: string): Promise<void>;
62
- private loadHistory;
63
110
  on<K extends keyof ChatbotEventMap>(event: K, listener: Listener<K>): () => void;
64
111
  resetSession(): void;
65
112
  open(): void;
@@ -87,6 +134,8 @@ export declare interface ChatbotRequestError extends Error {
87
134
 
88
135
  export { ChatbotState }
89
136
 
137
+ export { ChatbotTicketMode }
138
+
90
139
  export { ChatMessage }
91
140
 
92
141
  export { ChatRequest }
@@ -106,6 +155,12 @@ export declare class EventEmitter {
106
155
  removeAllListeners(): void;
107
156
  }
108
157
 
158
+ export { IdentifyRequest }
159
+
160
+ export { IdentifyResponseData }
161
+
162
+ export declare function isChatbotRequestError(error: unknown): error is ChatbotRequestError;
163
+
109
164
  declare type Listener<K extends keyof ChatbotEventMap> = ChatbotEventMap[K] extends void ? () => void : (payload: ChatbotEventMap[K]) => void;
110
165
 
111
166
  declare type Listener_2<T> = T extends void ? () => void : (payload: T) => void;
@@ -115,15 +170,53 @@ export declare const OnedeskProChatbot: {
115
170
  getInstance(): ChatbotCore | null;
116
171
  };
117
172
 
173
+ /**
174
+ * Strip any path/query/hash from an API base URL so Socket.IO connects to the
175
+ * server origin + `/sdk` namespace (not `/v1/sdk` if the REST client uses a path prefix).
176
+ */
177
+ export declare function resolveSdkSocketUrl(baseUrl: string): string;
178
+
118
179
  export { SdkConfigResponse }
119
180
 
181
+ /**
182
+ * Visitor Socket.IO helper for the dedicated `/sdk` namespace.
183
+ * Auth is handshake-only (`apiKey` + `visitorToken`); no BetterAuth session.
184
+ */
185
+ export declare class SdkSocket {
186
+ private socket;
187
+ get connected(): boolean;
188
+ connect(opts: SdkSocketConnectOptions): void;
189
+ disconnect(): void;
190
+ }
191
+
192
+ export declare interface SdkSocketConnectOptions {
193
+ /** API base URL (may include a path prefix); origin is used for the `/sdk` namespace. */
194
+ baseUrl: string;
195
+ apiKey: string;
196
+ visitorToken: string;
197
+ onTicketStatus?: (payload: TicketStatusData) => void;
198
+ /** Raw inbox-shaped payload from `message:receive` (mapped in ChatbotCore later). */
199
+ onMessageReceive?: (payload: unknown) => void;
200
+ /**
201
+ * Fired on socket.io `connect` after the first successful connection
202
+ * (i.e. reconnect). Callers should re-fetch ticket status — no history backfill.
203
+ */
204
+ onReconnect?: () => void;
205
+ onConnectError?: (error: Error) => void;
206
+ }
207
+
120
208
  export declare class SessionManager {
121
- private sessionId;
122
- init(providedSessionId?: string): string;
209
+ private token;
210
+ private storageKey;
211
+ /** Scope the token to an agent so multiple widgets on one origin stay isolated. */
212
+ setScope(agentId: string | null | undefined): void;
123
213
  get(): string | null;
124
- reset(): string;
125
- private persist;
126
- private generateId;
214
+ set(token: string): void;
215
+ clear(): void;
127
216
  }
128
217
 
218
+ export { TicketStatusData }
219
+
220
+ export { VisitorVerifyResponse }
221
+
129
222
  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,20 @@ 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
+ /** Server id of the last `message:receive` push rendered as an agent bubble. */
61
+ private lastPushId;
44
62
  /**
45
63
  * Bumped by every init() and by destroy(). An async init compares the token it
46
64
  * started with against this before touching anything, so a superseded run — a
@@ -55,11 +73,40 @@ export declare class ChatbotCore {
55
73
  * everything — not just the transitions that have a dedicated event.
56
74
  */
57
75
  private setState;
76
+ private applyMode;
77
+ /** Derive ticket existence from status restore / socket pushes. */
78
+ private syncHasActiveTicket;
79
+ private syncWidgetMode;
58
80
  init(options: ChatbotInitOptions): Promise<void>;
59
- /** Returns null on failure — a network blip must not block the user from trying. */
60
- private fetchConfig;
81
+ /**
82
+ * Maps `/sdk/config` failures: missing Connected Channels becomes `no-agent`,
83
+ * other 403s show the API message, and 401/network stay as `state.error`.
84
+ */
85
+ private handleConfigError;
86
+ private resolveVisitorGate;
87
+ private enterChat;
88
+ private connectSdkSocket;
89
+ private disconnectSdkSocket;
90
+ /** Restore episode mode after identify / verify — never hydrates messages. */
91
+ private restoreTicketStatus;
92
+ private handleTicketStatus;
93
+ /**
94
+ * Live human (agent) pushes from `/sdk` `message:receive`.
95
+ *
96
+ * Choice: ignore while `mode === 'ai'`. Website outbound (including AI
97
+ * replies) is fanned out to the visitor room; AI text already arrives via
98
+ * `POST /sdk/chat` REST and would double-render as an `agent` bubble. Accept
99
+ * pushes in `waiting` / `human` / `closed` (late agent messages after close).
100
+ * Also dedupe against the last bubble: an `ai` bubble by content, an `agent`
101
+ * bubble by server id, so an agent can send the same text twice.
102
+ */
103
+ private handleMessageReceive;
104
+ submitIdentify(payload: IdentifyRequest): Promise<void>;
105
+ /**
106
+ * Escalate the open AI ticket to Unassigned. No-op unless the widget is in `ai` mode.
107
+ */
108
+ requestHuman(): Promise<void>;
61
109
  sendMessage(text: string): Promise<void>;
62
- private loadHistory;
63
110
  on<K extends keyof ChatbotEventMap>(event: K, listener: Listener<K>): () => void;
64
111
  resetSession(): void;
65
112
  open(): void;
@@ -87,6 +134,8 @@ export declare interface ChatbotRequestError extends Error {
87
134
 
88
135
  export { ChatbotState }
89
136
 
137
+ export { ChatbotTicketMode }
138
+
90
139
  export { ChatMessage }
91
140
 
92
141
  export { ChatRequest }
@@ -106,6 +155,12 @@ export declare class EventEmitter {
106
155
  removeAllListeners(): void;
107
156
  }
108
157
 
158
+ export { IdentifyRequest }
159
+
160
+ export { IdentifyResponseData }
161
+
162
+ export declare function isChatbotRequestError(error: unknown): error is ChatbotRequestError;
163
+
109
164
  declare type Listener<K extends keyof ChatbotEventMap> = ChatbotEventMap[K] extends void ? () => void : (payload: ChatbotEventMap[K]) => void;
110
165
 
111
166
  declare type Listener_2<T> = T extends void ? () => void : (payload: T) => void;
@@ -115,15 +170,53 @@ export declare const OnedeskProChatbot: {
115
170
  getInstance(): ChatbotCore | null;
116
171
  };
117
172
 
173
+ /**
174
+ * Strip any path/query/hash from an API base URL so Socket.IO connects to the
175
+ * server origin + `/sdk` namespace (not `/v1/sdk` if the REST client uses a path prefix).
176
+ */
177
+ export declare function resolveSdkSocketUrl(baseUrl: string): string;
178
+
118
179
  export { SdkConfigResponse }
119
180
 
181
+ /**
182
+ * Visitor Socket.IO helper for the dedicated `/sdk` namespace.
183
+ * Auth is handshake-only (`apiKey` + `visitorToken`); no BetterAuth session.
184
+ */
185
+ export declare class SdkSocket {
186
+ private socket;
187
+ get connected(): boolean;
188
+ connect(opts: SdkSocketConnectOptions): void;
189
+ disconnect(): void;
190
+ }
191
+
192
+ export declare interface SdkSocketConnectOptions {
193
+ /** API base URL (may include a path prefix); origin is used for the `/sdk` namespace. */
194
+ baseUrl: string;
195
+ apiKey: string;
196
+ visitorToken: string;
197
+ onTicketStatus?: (payload: TicketStatusData) => void;
198
+ /** Raw inbox-shaped payload from `message:receive` (mapped in ChatbotCore later). */
199
+ onMessageReceive?: (payload: unknown) => void;
200
+ /**
201
+ * Fired on socket.io `connect` after the first successful connection
202
+ * (i.e. reconnect). Callers should re-fetch ticket status — no history backfill.
203
+ */
204
+ onReconnect?: () => void;
205
+ onConnectError?: (error: Error) => void;
206
+ }
207
+
120
208
  export declare class SessionManager {
121
- private sessionId;
122
- init(providedSessionId?: string): string;
209
+ private token;
210
+ private storageKey;
211
+ /** Scope the token to an agent so multiple widgets on one origin stay isolated. */
212
+ setScope(agentId: string | null | undefined): void;
123
213
  get(): string | null;
124
- reset(): string;
125
- private persist;
126
- private generateId;
214
+ set(token: string): void;
215
+ clear(): void;
127
216
  }
128
217
 
218
+ export { TicketStatusData }
219
+
220
+ export { VisitorVerifyResponse }
221
+
129
222
  export { }