@aikaara/chat-sdk 0.1.4 → 0.3.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/README.md +435 -0
- package/dist/AikaaraChatClient-Cqbcd1jb.mjs +11538 -0
- package/dist/AikaaraChatClient-kAu65hX-.cjs +8 -0
- package/dist/cdn/aikaara-chat.iife.js +118 -18
- package/dist/headless.cjs +1 -1
- package/dist/headless.d.ts +523 -5
- package/dist/headless.mjs +142 -9
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +541 -5
- package/dist/index.mjs +36 -28
- package/dist/ui.cjs +111 -18
- package/dist/ui.d.ts +498 -3
- package/dist/ui.mjs +322 -88
- package/package.json +4 -1
- package/dist/headless-BhsiNVQj.mjs +0 -551
- package/dist/headless-CrgIWcf7.cjs +0 -1
package/dist/headless.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./AikaaraChatClient-kAu65hX-.cjs");class g extends s.EventEmitter{registration=null;pendingEdits=[];constructor(t){super(),this.setupListeners(t)}registerForm(t){this.registration=t;const e=this.pendingEdits.filter(i=>i.entity_type===t.entityType&&String(i.entity_id)===String(t.entityId));if(e.length>0){for(const i of e)t.onFieldUpdate(i.fields),this.emit("edit:applied",{entityType:i.entity_type,entityId:i.entity_id,fields:i.fields});this.pendingEdits=this.pendingEdits.filter(i=>!(i.entity_type===t.entityType&&String(i.entity_id)===String(t.entityId)))}}unregisterForm(t,e){this.registration?.entityType===t&&String(this.registration?.entityId)===String(e)&&(this.registration=null)}get currentForm(){return this.registration}pushFieldUpdates(t,e,i){this.registration&&this.registration.entityType===t&&String(this.registration.entityId)===String(e)?(this.registration.onFieldUpdate(i),this.emit("edit:applied",{entityType:t,entityId:e,fields:i})):(this.pendingEdits.push({action:"edit_entity",entity_type:t,entity_id:e,fields:i}),this.emit("edit:pending",{entityType:t,entityId:e,fields:i}))}async requestSave(){if(!this.registration)return{success:!1,error:"No form registered"};try{return await this.registration.onSave(),this.emit("save:success",{entityType:this.registration.entityType,entityId:this.registration.entityId}),{success:!0}}catch(t){const e=t instanceof Error?t.message:"Save failed";return this.emit("save:error",{entityType:this.registration.entityType,entityId:this.registration.entityId,error:e}),{success:!1,error:e}}}async requestTest(t){if(!this.registration?.onTest)return{success:!1,error:"Current form does not support testing"};try{return await this.registration.onTest(t),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Test failed"}}}setupListeners(t){t.on("action:edit_entity",e=>{this.pushFieldUpdates(e.entity_type,e.entity_id,e.fields)}),t.on("action:save_entity",e=>{this.requestSave()}),t.on("action:test_tool",e=>{this.emit("test:triggered",{toolId:e.tool_id,parameters:e.parameters}),this.requestTest(e.parameters)})}}function m(n){return{async upload(t,e){const i=new FormData,p=n.fieldName??"file";i.append(p,t,t.name);const o=typeof n.extraFields=="function"?n.extraFields(e):n.extraFields;if(o)for(const[u,y]of Object.entries(o))i.append(u,y);i.append("conversationId",e.conversationId),i.append("userId",e.userId),e.projectId&&i.append("projectId",e.projectId);const c=typeof n.headers=="function"?await n.headers():n.headers??{},a=await fetch(n.endpoint,{method:n.method??"POST",body:i,headers:c,credentials:n.credentials});if(!a.ok)throw new Error(`Upload failed: ${a.status} ${a.statusText}`);const d=await a.json().catch(()=>({}));if(n.parseResponse)return n.parseResponse(d,e);const r=d,l=r.url??r.fileUrl??r.publicUrl,h=r.fileName??r.name??t.name;if(!l)throw new Error('Upload response missing "url" / "fileUrl" / "publicUrl"');return{url:l,fileName:h,cloudFileId:typeof r.cloudFileId=="string"?r.cloudFileId:void 0,relativePath:typeof r.path=="string"?r.path:void 0,contentType:typeof r.contentType=="string"?r.contentType:void 0,byteSize:typeof r.byteSize=="number"?r.byteSize:void 0,meta:r}}}}exports.ActionCableClient=s.ActionCableClient;exports.AikaaraChatClient=s.AikaaraChatClient;exports.ApiClient=s.ApiClient;exports.ChannelSubscription=s.ChannelSubscription;exports.ConnectionManager=s.ConnectionManager;exports.ConversationManager=s.ConversationManager;exports.EventEmitter=s.EventEmitter;exports.MessageStore=s.MessageStore;exports.TiledeskTransport=s.TiledeskTransport;exports.extractTiledeskFileEnvelope=s.extractTiledeskFileEnvelope;exports.inferTiledeskRole=s.inferTiledeskRole;exports.isTiledeskSelfEcho=s.isTiledeskSelfEcho;exports.parseTiledeskTemplate=s.parseTiledeskTemplate;exports.FormBridge=g;exports.createFetchUploadAdapter=m;
|
package/dist/headless.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare interface ActionCableMessage {
|
|
|
22
22
|
message?: unknown;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export declare type AgentAction = EditEntityAction | SaveEntityAction | TestToolAction | NavigateAction;
|
|
26
|
+
|
|
25
27
|
export declare interface AgentEvent {
|
|
26
28
|
type: AgentEventType;
|
|
27
29
|
[key: string]: unknown;
|
|
@@ -31,39 +33,108 @@ export declare type AgentEventType = 'status' | 'error' | 'agent_start' | 'agent
|
|
|
31
33
|
|
|
32
34
|
export declare class AikaaraChatClient extends EventEmitter<ChatEvents> {
|
|
33
35
|
private connection;
|
|
36
|
+
private tiledesk;
|
|
34
37
|
private api;
|
|
35
38
|
private messageStore;
|
|
36
39
|
private conversationManager;
|
|
37
40
|
private subscription;
|
|
38
41
|
private config;
|
|
39
|
-
|
|
42
|
+
private mode;
|
|
43
|
+
private uploadAdapter;
|
|
44
|
+
private tiledeskUnsubs;
|
|
45
|
+
constructor(config: ChatClientConfig, opts?: {
|
|
46
|
+
uploadAdapter?: UploadAdapter;
|
|
47
|
+
});
|
|
48
|
+
private usesAikaara;
|
|
49
|
+
private usesTiledesk;
|
|
50
|
+
private initTiledeskTransport;
|
|
40
51
|
connect(): Promise<void>;
|
|
41
52
|
sendMessage(content: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Upload a file via the configured UploadAdapter (client-side: file goes
|
|
55
|
+
* to the tenant's own backend, never through Aikaara). Then publish the
|
|
56
|
+
* Tiledesk file-message envelope so hooks_controller picks it up.
|
|
57
|
+
*/
|
|
58
|
+
sendFile(file: File | Blob, opts?: {
|
|
59
|
+
caption?: string;
|
|
60
|
+
}): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Trigger Tiledesk's CHAT_INITIATED event — required to kick off a bot flow
|
|
63
|
+
* for newly-created Tiledesk request groups.
|
|
64
|
+
*/
|
|
65
|
+
initiateTiledeskChat(extraAttributes?: Record<string, unknown>): void;
|
|
66
|
+
/** Mark a Tiledesk message as read (publishes status=300 update). */
|
|
67
|
+
markTiledeskRead(messageId: string): void;
|
|
68
|
+
setUploadAdapter(adapter: UploadAdapter): void;
|
|
42
69
|
sendUserEvent(eventKey: string, value?: object, source?: string): Promise<void>;
|
|
43
70
|
loadHistory(): Promise<Message[]>;
|
|
44
71
|
get messages(): Message[];
|
|
45
72
|
get conversationId(): string | null;
|
|
46
73
|
get isConnected(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Update the agent's context with information about the host app's current state.
|
|
76
|
+
* Call this on route changes so the agent knows what page/entity the user is viewing.
|
|
77
|
+
*
|
|
78
|
+
* The context is stored in conversation metadata and interpolated into the system prompt.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* // On route change
|
|
83
|
+
* client.setContext({
|
|
84
|
+
* currentPage: '/products/42',
|
|
85
|
+
* entityType: 'product',
|
|
86
|
+
* entityId: '42',
|
|
87
|
+
* availableRoutes: { products: '/products', orders: '/orders' },
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
setContext(context: AppContext): Promise<void>;
|
|
47
92
|
disconnect(): Promise<void>;
|
|
93
|
+
private handleTiledeskMessage;
|
|
94
|
+
private handleTiledeskStatusUpdate;
|
|
95
|
+
/**
|
|
96
|
+
* Parse structured action results from tool execution output.
|
|
97
|
+
* When the agent calls tools like `edit_current_entity`, `save_current_entity`,
|
|
98
|
+
* `navigate_to`, or `test_tool_by_id`, the result contains an action payload
|
|
99
|
+
* that the SDK emits as a typed event for the host app to handle.
|
|
100
|
+
*/
|
|
101
|
+
private parseActionResult;
|
|
48
102
|
private handleBroadcast;
|
|
49
103
|
}
|
|
50
104
|
|
|
51
105
|
export declare class ApiClient {
|
|
52
106
|
private baseUrl;
|
|
53
107
|
private apiKey?;
|
|
108
|
+
private authToken?;
|
|
54
109
|
private userToken;
|
|
55
|
-
constructor(baseUrl: string, userToken: string, apiKey?: string);
|
|
110
|
+
constructor(baseUrl: string, userToken: string, apiKey?: string, authToken?: string);
|
|
56
111
|
createConversation(params: {
|
|
57
112
|
systemPromptId?: number;
|
|
58
113
|
channel?: string;
|
|
59
114
|
title?: string;
|
|
60
115
|
extUid?: string;
|
|
61
116
|
}): Promise<CreateConversationResponse>;
|
|
117
|
+
updateContext(conversationId: string, context: Record<string, unknown>): Promise<void>;
|
|
62
118
|
getMessages(conversationId: string): Promise<Message[]>;
|
|
63
119
|
private mapMessage;
|
|
64
120
|
private request;
|
|
65
121
|
}
|
|
66
122
|
|
|
123
|
+
export declare interface AppContext {
|
|
124
|
+
/** Current page/route path in the host app (e.g., '/products/42') */
|
|
125
|
+
currentPage: string;
|
|
126
|
+
/** Entity type on the current page (e.g., 'product', 'agent') */
|
|
127
|
+
entityType?: string;
|
|
128
|
+
/** Entity ID on the current page */
|
|
129
|
+
entityId?: string | number;
|
|
130
|
+
/** Project/workspace ID if applicable */
|
|
131
|
+
projectId?: string | number;
|
|
132
|
+
/** Routes the agent can navigate to — map of label → path */
|
|
133
|
+
availableRoutes?: Record<string, string>;
|
|
134
|
+
/** Additional context for the agent (e.g., form field names, entity schema) */
|
|
135
|
+
custom?: Record<string, unknown>;
|
|
136
|
+
}
|
|
137
|
+
|
|
67
138
|
export declare class ChannelSubscription {
|
|
68
139
|
readonly identifier: string;
|
|
69
140
|
private callbacks;
|
|
@@ -82,15 +153,35 @@ export declare class ChannelSubscription {
|
|
|
82
153
|
|
|
83
154
|
export declare interface ChatClientConfig extends ConnectionConfig {
|
|
84
155
|
apiKey?: string;
|
|
156
|
+
authToken?: string;
|
|
85
157
|
extUid?: string;
|
|
86
158
|
conversationId?: string;
|
|
87
159
|
systemPromptId?: number;
|
|
88
|
-
channel?: 'widget' | 'api';
|
|
160
|
+
channel?: 'widget' | 'api' | 'sidekick';
|
|
161
|
+
/**
|
|
162
|
+
* Transport selection.
|
|
163
|
+
* - `aikaara` (default): ActionCable to Aikaara Rails (AI streaming).
|
|
164
|
+
* - `tiledesk`: MQTT direct to a self-hosted Tiledesk + chat21 stack.
|
|
165
|
+
* - `dual`: both — Aikaara cable for AI, Tiledesk MQTT for live-agent + file events.
|
|
166
|
+
*/
|
|
167
|
+
transport?: TransportMode;
|
|
168
|
+
/**
|
|
169
|
+
* Tiledesk-side identity. Required when `transport` is `tiledesk` or `dual`.
|
|
170
|
+
* `userId` here is the Tiledesk user `_id` and is also used as the SDK conversation
|
|
171
|
+
* subject — Aikaara conversations bound to this user via ext_uid mapping.
|
|
172
|
+
*/
|
|
173
|
+
tiledeskIdentity?: {
|
|
174
|
+
userId: string;
|
|
175
|
+
userName?: string;
|
|
176
|
+
departmentId?: string;
|
|
177
|
+
senderFullname?: string;
|
|
178
|
+
};
|
|
89
179
|
onMessage?: (message: Message) => void;
|
|
90
180
|
onStatusChange?: (status: string) => void;
|
|
91
181
|
onError?: (error: Error) => void;
|
|
92
182
|
onStreamUpdate?: (delta: string, fullContent: string) => void;
|
|
93
183
|
onConnectionStateChange?: (state: ConnectionState) => void;
|
|
184
|
+
onTemplateMessage?: (template: TemplateMessageEvent) => void;
|
|
94
185
|
}
|
|
95
186
|
|
|
96
187
|
export declare interface ChatEvents {
|
|
@@ -116,12 +207,26 @@ export declare interface ChatEvents {
|
|
|
116
207
|
'typing:stop': void;
|
|
117
208
|
'error': Error;
|
|
118
209
|
'status': string;
|
|
210
|
+
'action:edit_entity': EditEntityAction;
|
|
211
|
+
'action:save_entity': SaveEntityAction;
|
|
212
|
+
'action:test_tool': TestToolAction;
|
|
213
|
+
'action:navigate': NavigateAction;
|
|
214
|
+
'tool:start': {
|
|
215
|
+
toolName: string;
|
|
216
|
+
args: Record<string, unknown>;
|
|
217
|
+
};
|
|
218
|
+
'tool:end': {
|
|
219
|
+
toolName: string;
|
|
220
|
+
result: unknown;
|
|
221
|
+
isError: boolean;
|
|
222
|
+
};
|
|
119
223
|
}
|
|
120
224
|
|
|
121
225
|
export declare interface ConnectionConfig {
|
|
122
226
|
baseUrl: string;
|
|
123
227
|
wsUrl?: string;
|
|
124
228
|
userToken: string;
|
|
229
|
+
tiledesk?: TiledeskTransportConfig;
|
|
125
230
|
reconnect?: boolean;
|
|
126
231
|
maxReconnectAttempts?: number;
|
|
127
232
|
reconnectInterval?: number;
|
|
@@ -164,6 +269,15 @@ declare interface CreateConversationResponse {
|
|
|
164
269
|
status: string;
|
|
165
270
|
}
|
|
166
271
|
|
|
272
|
+
export declare function createFetchUploadAdapter(config: FetchUploadAdapterConfig): UploadAdapter;
|
|
273
|
+
|
|
274
|
+
export declare interface EditEntityAction {
|
|
275
|
+
action: 'edit_entity';
|
|
276
|
+
entity_type: string;
|
|
277
|
+
entity_id: string | number;
|
|
278
|
+
fields: FieldUpdate[];
|
|
279
|
+
}
|
|
280
|
+
|
|
167
281
|
export declare class EventEmitter<Events extends Record<string, any>> {
|
|
168
282
|
private handlers;
|
|
169
283
|
on<K extends keyof Events & string>(event: K, handler: (data: Events[K]) => void): () => void;
|
|
@@ -172,10 +286,153 @@ export declare class EventEmitter<Events extends Record<string, any>> {
|
|
|
172
286
|
removeAllListeners(): void;
|
|
173
287
|
}
|
|
174
288
|
|
|
289
|
+
export declare function extractTiledeskFileEnvelope(message: TiledeskMessage): TiledeskFileEnvelope | null;
|
|
290
|
+
|
|
291
|
+
export declare interface FetchUploadAdapterConfig {
|
|
292
|
+
endpoint: string;
|
|
293
|
+
method?: 'POST' | 'PUT';
|
|
294
|
+
fieldName?: string;
|
|
295
|
+
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
296
|
+
credentials?: RequestCredentials;
|
|
297
|
+
extraFields?: Record<string, string> | ((ctx: UploadAdapterContext) => Record<string, string>);
|
|
298
|
+
parseResponse?: (raw: unknown, ctx: UploadAdapterContext) => UploadAdapterResult;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export declare interface FieldUpdate {
|
|
302
|
+
field: string;
|
|
303
|
+
value: unknown;
|
|
304
|
+
previousValue?: unknown;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export declare class FormBridge extends EventEmitter<FormBridgeEvents> {
|
|
308
|
+
private registration;
|
|
309
|
+
private pendingEdits;
|
|
310
|
+
constructor(client: AikaaraChatClient);
|
|
311
|
+
/**
|
|
312
|
+
* Register a form to receive AI-driven edits.
|
|
313
|
+
* Only one form can be registered at a time (the active page).
|
|
314
|
+
*/
|
|
315
|
+
registerForm(reg: FormRegistration): void;
|
|
316
|
+
/**
|
|
317
|
+
* Unregister the form (call on unmount).
|
|
318
|
+
*/
|
|
319
|
+
unregisterForm(entityType: string, entityId: string | number): void;
|
|
320
|
+
/**
|
|
321
|
+
* Get the current form registration (if any).
|
|
322
|
+
*/
|
|
323
|
+
get currentForm(): FormRegistration | null;
|
|
324
|
+
/**
|
|
325
|
+
* Manually push field updates (for custom tool handling).
|
|
326
|
+
*/
|
|
327
|
+
pushFieldUpdates(entityType: string, entityId: string | number, fields: FieldUpdate[]): void;
|
|
328
|
+
/**
|
|
329
|
+
* Request the current form to save.
|
|
330
|
+
*/
|
|
331
|
+
requestSave(): Promise<{
|
|
332
|
+
success: boolean;
|
|
333
|
+
error?: string;
|
|
334
|
+
}>;
|
|
335
|
+
/**
|
|
336
|
+
* Request the current form to run a test.
|
|
337
|
+
*/
|
|
338
|
+
requestTest(params?: Record<string, unknown>): Promise<{
|
|
339
|
+
success: boolean;
|
|
340
|
+
error?: string;
|
|
341
|
+
}>;
|
|
342
|
+
private setupListeners;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* FormBridge — Enables AI agents to visually edit forms in the host application.
|
|
347
|
+
*
|
|
348
|
+
* This bridges the gap between AI tool results and UI form state. When the agent
|
|
349
|
+
* calls tools like `edit_current_entity`, the FormBridge receives the action and
|
|
350
|
+
* pushes field updates to the registered form.
|
|
351
|
+
*
|
|
352
|
+
* ## Usage (any framework)
|
|
353
|
+
*
|
|
354
|
+
* ```typescript
|
|
355
|
+
* import { AikaaraChatClient, FormBridge } from '@aikaara/chat-sdk/headless';
|
|
356
|
+
*
|
|
357
|
+
* const client = new AikaaraChatClient({ baseUrl, userToken, authToken });
|
|
358
|
+
* const bridge = new FormBridge(client);
|
|
359
|
+
*
|
|
360
|
+
* // Register a form (call when your form mounts)
|
|
361
|
+
* bridge.registerForm({
|
|
362
|
+
* entityType: 'product',
|
|
363
|
+
* entityId: 42,
|
|
364
|
+
* onFieldUpdate: (fields) => {
|
|
365
|
+
* for (const { field, value } of fields) {
|
|
366
|
+
* formState[field] = value; // update your form framework
|
|
367
|
+
* }
|
|
368
|
+
* },
|
|
369
|
+
* onSave: async () => await api.saveProduct(42, formState),
|
|
370
|
+
* getCurrentValues: () => ({ ...formState }),
|
|
371
|
+
* });
|
|
372
|
+
*
|
|
373
|
+
* // Unregister when form unmounts
|
|
374
|
+
* bridge.unregisterForm('product', 42);
|
|
375
|
+
* ```
|
|
376
|
+
*
|
|
377
|
+
* ## React hook (provided by dashboard, but easy to replicate)
|
|
378
|
+
*
|
|
379
|
+
* ```tsx
|
|
380
|
+
* function useFormBridge(bridge, { entityType, entityId, onFieldUpdate, onSave }) {
|
|
381
|
+
* useEffect(() => {
|
|
382
|
+
* bridge.registerForm({ entityType, entityId, onFieldUpdate, onSave, getCurrentValues });
|
|
383
|
+
* return () => bridge.unregisterForm(entityType, entityId);
|
|
384
|
+
* }, [entityType, entityId]);
|
|
385
|
+
* }
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
export declare interface FormBridgeEvents {
|
|
389
|
+
'edit:applied': {
|
|
390
|
+
entityType: string;
|
|
391
|
+
entityId: string | number;
|
|
392
|
+
fields: FieldUpdate[];
|
|
393
|
+
};
|
|
394
|
+
'edit:pending': {
|
|
395
|
+
entityType: string;
|
|
396
|
+
entityId: string | number;
|
|
397
|
+
fields: FieldUpdate[];
|
|
398
|
+
};
|
|
399
|
+
'save:success': {
|
|
400
|
+
entityType: string;
|
|
401
|
+
entityId: string | number;
|
|
402
|
+
};
|
|
403
|
+
'save:error': {
|
|
404
|
+
entityType: string;
|
|
405
|
+
entityId: string | number;
|
|
406
|
+
error: string;
|
|
407
|
+
};
|
|
408
|
+
'test:triggered': {
|
|
409
|
+
toolId: number;
|
|
410
|
+
parameters: Record<string, unknown>;
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export declare interface FormRegistration {
|
|
415
|
+
entityType: string;
|
|
416
|
+
entityId: string | number;
|
|
417
|
+
onFieldUpdate: (fields: FieldUpdate[]) => void;
|
|
418
|
+
onSave: () => Promise<void>;
|
|
419
|
+
onTest?: (params?: Record<string, unknown>) => Promise<void>;
|
|
420
|
+
getCurrentValues: () => Record<string, unknown>;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export declare function inferTiledeskRole(message: TiledeskMessage, cfg: TiledeskRoleConfig): TiledeskRole;
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Self-echo detector — Tiledesk fans the user's outgoing publish back
|
|
427
|
+
* as a `clientadded` event on the same connection. UI must dedupe against
|
|
428
|
+
* the optimistic local message rather than rendering twice.
|
|
429
|
+
*/
|
|
430
|
+
export declare function isTiledeskSelfEcho(message: TiledeskMessage, userId: string): boolean;
|
|
431
|
+
|
|
175
432
|
export declare interface Message {
|
|
176
433
|
id: string;
|
|
177
434
|
conversationId: string;
|
|
178
|
-
role: 'user' | 'assistant' | 'system' | 'tool';
|
|
435
|
+
role: 'user' | 'assistant' | 'system' | 'tool' | 'agent';
|
|
179
436
|
content: string;
|
|
180
437
|
toolCalls?: ToolCall[];
|
|
181
438
|
toolCallResults?: ToolCallResult;
|
|
@@ -183,7 +440,19 @@ export declare interface Message {
|
|
|
183
440
|
tokensOutput?: number;
|
|
184
441
|
metadata?: Record<string, unknown>;
|
|
185
442
|
createdAt: string;
|
|
186
|
-
status?: 'sending' | 'sent' | 'streaming' | 'complete' | 'error';
|
|
443
|
+
status?: 'sending' | 'sent' | 'delivered' | 'read' | 'streaming' | 'complete' | 'error';
|
|
444
|
+
externalId?: string;
|
|
445
|
+
template?: {
|
|
446
|
+
contentType?: string;
|
|
447
|
+
templateId?: string;
|
|
448
|
+
payload?: unknown;
|
|
449
|
+
};
|
|
450
|
+
attachments?: Array<{
|
|
451
|
+
fileName: string;
|
|
452
|
+
fileUrl: string;
|
|
453
|
+
cloudFileId?: string;
|
|
454
|
+
contentType?: string;
|
|
455
|
+
}>;
|
|
187
456
|
}
|
|
188
457
|
|
|
189
458
|
export declare class MessageStore {
|
|
@@ -191,6 +460,22 @@ export declare class MessageStore {
|
|
|
191
460
|
private optimisticCounter;
|
|
192
461
|
get messages(): Message[];
|
|
193
462
|
addOptimistic(role: 'user', content: string, conversationId: string): Message;
|
|
463
|
+
/**
|
|
464
|
+
* Reconcile a remote message against an outstanding optimistic message.
|
|
465
|
+
* Tiledesk fans the user's outgoing publish back as an inbound clientadded —
|
|
466
|
+
* dedupe by exact content + recency window so the optimistic bubble keeps
|
|
467
|
+
* its position and we don't render duplicates.
|
|
468
|
+
*/
|
|
469
|
+
reconcileOptimistic(remote: Message, recencyMs?: number): Message | null;
|
|
470
|
+
/**
|
|
471
|
+
* Append a remote-originated message (e.g. from Tiledesk MQTT). If a matching
|
|
472
|
+
* optimistic message exists it is reconciled in place; otherwise appended.
|
|
473
|
+
*/
|
|
474
|
+
upsertRemoteMessage(remote: Message): {
|
|
475
|
+
message: Message;
|
|
476
|
+
deduped: boolean;
|
|
477
|
+
};
|
|
478
|
+
updateMessageStatus(externalId: string, status: Message['status']): Message | undefined;
|
|
194
479
|
confirmOptimistic(tempId: string): void;
|
|
195
480
|
addStreamingMessage(conversationId: string): Message;
|
|
196
481
|
updateStreaming(content: string): void;
|
|
@@ -205,8 +490,211 @@ export declare class MessageStore {
|
|
|
205
490
|
clear(): void;
|
|
206
491
|
}
|
|
207
492
|
|
|
493
|
+
export declare interface NavigateAction {
|
|
494
|
+
navigate_to: string;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
export declare function parseTiledeskTemplate(message: TiledeskMessage): TiledeskParsedTemplate;
|
|
498
|
+
|
|
499
|
+
export declare interface SaveEntityAction {
|
|
500
|
+
action: 'save_entity';
|
|
501
|
+
}
|
|
502
|
+
|
|
208
503
|
declare type SubscriptionCallback = (data: unknown) => void;
|
|
209
504
|
|
|
505
|
+
declare interface TemplateMessageEvent {
|
|
506
|
+
messageId: string;
|
|
507
|
+
conversationId: string;
|
|
508
|
+
role: 'user' | 'assistant' | 'system' | 'agent';
|
|
509
|
+
contentType?: string;
|
|
510
|
+
templateId?: string;
|
|
511
|
+
payload?: unknown;
|
|
512
|
+
innerMessage?: string;
|
|
513
|
+
raw: unknown;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export declare interface TestToolAction {
|
|
517
|
+
action: 'test_tool';
|
|
518
|
+
tool_id: number;
|
|
519
|
+
parameters: Record<string, unknown>;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export declare interface TiledeskFileEnvelope {
|
|
523
|
+
fileName?: string;
|
|
524
|
+
fileUrl?: string;
|
|
525
|
+
cloudFileId?: string;
|
|
526
|
+
templateId?: string;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export declare interface TiledeskFileMessageInput {
|
|
530
|
+
fileName: string;
|
|
531
|
+
fileUrl: string;
|
|
532
|
+
cloudFileId?: string;
|
|
533
|
+
templateId?: string;
|
|
534
|
+
headerImgSrc?: string;
|
|
535
|
+
type?: 'link' | 'image';
|
|
536
|
+
isDeepLink?: boolean;
|
|
537
|
+
description?: string;
|
|
538
|
+
attributes?: Record<string, unknown>;
|
|
539
|
+
metadata?: Record<string, unknown>;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export declare interface TiledeskFileTemplateConfig {
|
|
543
|
+
templateId: string;
|
|
544
|
+
headerImgSrc?: string;
|
|
545
|
+
type?: 'link' | 'image';
|
|
546
|
+
isDeepLink?: boolean;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
export declare interface TiledeskMessage {
|
|
550
|
+
text?: string;
|
|
551
|
+
type?: string;
|
|
552
|
+
sender?: string;
|
|
553
|
+
senderFullname?: string;
|
|
554
|
+
sender_fullname?: string;
|
|
555
|
+
recipient?: string;
|
|
556
|
+
recipient_fullname?: string;
|
|
557
|
+
channel_type?: string;
|
|
558
|
+
timestamp?: number;
|
|
559
|
+
app_id?: string;
|
|
560
|
+
message_id?: string;
|
|
561
|
+
status?: number;
|
|
562
|
+
attributes?: Record<string, unknown>;
|
|
563
|
+
metadata?: Record<string, unknown>;
|
|
564
|
+
[key: string]: unknown;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export declare interface TiledeskMessageContext {
|
|
568
|
+
topic: string;
|
|
569
|
+
conversationId?: string;
|
|
570
|
+
messageId?: string;
|
|
571
|
+
kind: 'clientadded' | 'update' | 'unknown';
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export declare interface TiledeskMessageDefaults {
|
|
575
|
+
channelType?: string;
|
|
576
|
+
channel?: string;
|
|
577
|
+
requestChannel?: string;
|
|
578
|
+
platform?: string;
|
|
579
|
+
medium?: string;
|
|
580
|
+
departmentId?: string;
|
|
581
|
+
attributes?: Record<string, unknown>;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
export declare interface TiledeskParsedTemplate {
|
|
585
|
+
contentType?: string;
|
|
586
|
+
templateId?: string;
|
|
587
|
+
payload?: unknown;
|
|
588
|
+
innerMessage?: string;
|
|
589
|
+
raw: TiledeskMessage;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
export declare type TiledeskRole = 'user' | 'assistant' | 'system' | 'agent';
|
|
593
|
+
|
|
594
|
+
export declare interface TiledeskRoleConfig {
|
|
595
|
+
userId: string;
|
|
596
|
+
systemSenders?: string[];
|
|
597
|
+
botSenderPrefix?: string;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export declare interface TiledeskStatusUpdate {
|
|
601
|
+
conversationId: string;
|
|
602
|
+
messageId: string;
|
|
603
|
+
status: number;
|
|
604
|
+
raw: Record<string, unknown>;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export declare interface TiledeskTopicTemplates {
|
|
608
|
+
inbound?: string;
|
|
609
|
+
inboundUpdate?: string;
|
|
610
|
+
outbound?: string;
|
|
611
|
+
presence?: string;
|
|
612
|
+
wildcardSubscribe?: string;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export declare class TiledeskTransport {
|
|
616
|
+
private client;
|
|
617
|
+
private config;
|
|
618
|
+
private currentToken;
|
|
619
|
+
private clientId;
|
|
620
|
+
private appId;
|
|
621
|
+
private topics;
|
|
622
|
+
private messageHandlers;
|
|
623
|
+
private stateHandlers;
|
|
624
|
+
private statusUpdateHandlers;
|
|
625
|
+
private subscribedTopics;
|
|
626
|
+
private reconnectAttempt;
|
|
627
|
+
private maxReconnectAttempts;
|
|
628
|
+
private reconnectMaxDelayMs;
|
|
629
|
+
private disposed;
|
|
630
|
+
private reconnectTimer;
|
|
631
|
+
private inboundRegex;
|
|
632
|
+
private inboundUpdateRegex;
|
|
633
|
+
constructor(config: TiledeskTransportConfig);
|
|
634
|
+
connect(): Promise<void>;
|
|
635
|
+
subscribeWildcard(): void;
|
|
636
|
+
subscribeToConversation(conversationId: string): void;
|
|
637
|
+
unsubscribeFromConversation(conversationId: string): void;
|
|
638
|
+
publishMessage(conversationId: string, text: string, overrides?: Partial<TiledeskMessage>): void;
|
|
639
|
+
publishFileMessage(conversationId: string, file: TiledeskFileMessageInput): void;
|
|
640
|
+
publishRaw(conversationId: string, message: TiledeskMessage): void;
|
|
641
|
+
/**
|
|
642
|
+
* Send a read receipt for a message. Tiledesk widgets publish
|
|
643
|
+
* `{"status":300}` to apps/{appId}/users/{userId}/messages/{convId}/{msgId}/update.
|
|
644
|
+
*/
|
|
645
|
+
publishReadReceipt(conversationId: string, messageId: string, status?: number): void;
|
|
646
|
+
/**
|
|
647
|
+
* Trigger conversation kickoff. Tiledesk bot routing waits for the
|
|
648
|
+
* widget to publish a CHAT_INITIATED event before the bot replies.
|
|
649
|
+
*/
|
|
650
|
+
publishChatInitiated(conversationId: string, extraAttributes?: Record<string, unknown>): void;
|
|
651
|
+
onMessage(handler: TransportMessageHandler): () => void;
|
|
652
|
+
onStateChange(handler: TransportStateHandler): () => void;
|
|
653
|
+
onStatusUpdate(handler: TransportStatusUpdateHandler): () => void;
|
|
654
|
+
disconnect(): void;
|
|
655
|
+
get isConnected(): boolean;
|
|
656
|
+
private scheduleReconnect;
|
|
657
|
+
private notifyStateChange;
|
|
658
|
+
private dispatchInbound;
|
|
659
|
+
private buildOutgoingEnvelope;
|
|
660
|
+
private publishEnvelope;
|
|
661
|
+
private renderInboundTopic;
|
|
662
|
+
private renderOutboundTopic;
|
|
663
|
+
private renderPresenceTopic;
|
|
664
|
+
private renderTemplate;
|
|
665
|
+
private buildTopicRegex;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
export declare interface TiledeskTransportConfig {
|
|
669
|
+
mqttEndpoint: string;
|
|
670
|
+
jwtToken: string;
|
|
671
|
+
userId: string;
|
|
672
|
+
userName?: string;
|
|
673
|
+
projectId: string;
|
|
674
|
+
appId?: string;
|
|
675
|
+
clientId?: string;
|
|
676
|
+
protocolVersion?: 3 | 4 | 5;
|
|
677
|
+
protocolId?: 'MQIsdp' | 'MQTT';
|
|
678
|
+
mqttUsername?: string;
|
|
679
|
+
connectTimeoutMs?: number;
|
|
680
|
+
keepAliveSec?: number;
|
|
681
|
+
maxReconnectAttempts?: number;
|
|
682
|
+
reconnectMaxDelayMs?: number;
|
|
683
|
+
tokenProvider?: () => Promise<string>;
|
|
684
|
+
wildcardSubscribe?: boolean;
|
|
685
|
+
subscribeQos?: 0 | 1 | 2;
|
|
686
|
+
publishQos?: 0 | 1 | 2;
|
|
687
|
+
publishRetain?: boolean;
|
|
688
|
+
enablePresence?: boolean;
|
|
689
|
+
presencePayloadConnected?: Record<string, unknown>;
|
|
690
|
+
presencePayloadDisconnected?: Record<string, unknown>;
|
|
691
|
+
topicTemplates?: TiledeskTopicTemplates;
|
|
692
|
+
messageDefaults?: TiledeskMessageDefaults;
|
|
693
|
+
fileTemplate?: TiledeskFileTemplateConfig;
|
|
694
|
+
recipientFullnameResolver?: (conversationId: string) => string | undefined;
|
|
695
|
+
senderFullname?: string;
|
|
696
|
+
}
|
|
697
|
+
|
|
210
698
|
export declare interface ToolCall {
|
|
211
699
|
id: string;
|
|
212
700
|
type: 'function';
|
|
@@ -221,6 +709,35 @@ export declare interface ToolCallResult {
|
|
|
221
709
|
content: string;
|
|
222
710
|
}
|
|
223
711
|
|
|
712
|
+
export declare type TransportMessageHandler = (message: TiledeskMessage, ctx: TiledeskMessageContext) => void;
|
|
713
|
+
|
|
714
|
+
declare type TransportMode = 'aikaara' | 'tiledesk' | 'dual';
|
|
715
|
+
|
|
716
|
+
export declare type TransportStateHandler = (connected: boolean) => void;
|
|
717
|
+
|
|
718
|
+
export declare type TransportStatusUpdateHandler = (update: TiledeskStatusUpdate) => void;
|
|
719
|
+
|
|
720
|
+
export declare interface UploadAdapter {
|
|
721
|
+
upload(file: File | Blob, ctx: UploadAdapterContext): Promise<UploadAdapterResult>;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
export declare interface UploadAdapterContext {
|
|
725
|
+
conversationId: string;
|
|
726
|
+
userId: string;
|
|
727
|
+
projectId?: string;
|
|
728
|
+
appId?: string;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
export declare interface UploadAdapterResult {
|
|
732
|
+
url: string;
|
|
733
|
+
fileName: string;
|
|
734
|
+
cloudFileId?: string;
|
|
735
|
+
relativePath?: string;
|
|
736
|
+
contentType?: string;
|
|
737
|
+
byteSize?: number;
|
|
738
|
+
meta?: Record<string, unknown>;
|
|
739
|
+
}
|
|
740
|
+
|
|
224
741
|
export declare interface WidgetConfig extends ChatClientConfig {
|
|
225
742
|
position?: 'bottom-right' | 'bottom-left';
|
|
226
743
|
offset?: {
|
|
@@ -243,6 +760,7 @@ export declare interface WidgetConfig extends ChatClientConfig {
|
|
|
243
760
|
showBubble?: boolean;
|
|
244
761
|
bubbleText?: string;
|
|
245
762
|
bubbleIcon?: string;
|
|
763
|
+
uploadAdapter?: UploadAdapter;
|
|
246
764
|
}
|
|
247
765
|
|
|
248
766
|
export { }
|