@elia-assistant/chatui 1.0.26 → 2.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/README.md +111 -17
- package/dist/App.d.ts +0 -1
- package/dist/chat-store.js +141 -139
- package/dist/chatui.iife.js +30 -31
- package/dist/chunks/{middleware-Brf3TxqP.js → middleware-BG8DEvI8.js} +28 -23
- package/dist/chunks/{settingsStore-JRogtJV3.js → settingsStore-DzpdfGcd.js} +41 -40
- package/dist/createChat.d.ts +17 -0
- package/dist/i18n.d.ts +8 -2
- package/dist/iife.d.ts +2 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +3664 -2257
- package/dist/lib/storage.d.ts +7 -3
- package/dist/store/StoreContext.d.ts +32 -0
- package/dist/store/chatStore.d.ts +8 -3
- package/dist/store/settingsStore.d.ts +10 -3
- package/dist/store.js +2 -2
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunks/i18n-DS9aLar5.js +0 -1321
package/README.md
CHANGED
|
@@ -15,20 +15,74 @@ Ships as a pre-built ESM bundle and a CDN-ready IIFE bundle. Config-compatible w
|
|
|
15
15
|
npm install @elia-assistant/chatui
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
```
|
|
19
|
-
// src/
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
18
|
+
```tsx
|
|
19
|
+
// src/ChatWidget.tsx
|
|
20
|
+
import { useEffect, useRef } from 'react'
|
|
21
|
+
import { createChat, type ChatInstance } from '@elia-assistant/chatui'
|
|
22
|
+
|
|
23
|
+
export function ChatWidget() {
|
|
24
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
25
|
+
const instanceRef = useRef<ChatInstance | null>(null)
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!containerRef.current || instanceRef.current) return
|
|
29
|
+
instanceRef.current = createChat({
|
|
30
|
+
target: containerRef.current,
|
|
31
|
+
webhookUrl: 'https://your-n8n.example.com/webhook/abc',
|
|
32
|
+
mode: 'window',
|
|
33
|
+
})
|
|
34
|
+
return () => {
|
|
35
|
+
// Deferred so StrictMode's double-invoke doesn't unmount mid-render.
|
|
36
|
+
const instance = instanceRef.current
|
|
37
|
+
instanceRef.current = null
|
|
38
|
+
setTimeout(() => instance?.unmount(), 0)
|
|
39
|
+
}
|
|
40
|
+
}, [])
|
|
41
|
+
|
|
42
|
+
return <div ref={containerRef} style={{ height: '100%' }} />
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`createChat()` mounts into a shadow root, so the widget's CSS is fully isolated from your app's.
|
|
47
|
+
|
|
48
|
+
The host's `vite.config.ts` needs `optimizeDeps.exclude: ['@elia-assistant/chatui']` so Vite doesn't re-bundle the already-bundled package. See [example.html](./example.html) for the full integration guide.
|
|
22
49
|
|
|
23
|
-
|
|
50
|
+
#### Raw component tree (no shadow root)
|
|
51
|
+
|
|
52
|
+
If you need the widget inside your own React tree rather than a shadow root, render `<App />` directly. It reads its stores and translations from context, so you must build them and supply both providers:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { I18nextProvider } from 'react-i18next'
|
|
56
|
+
import {
|
|
57
|
+
App,
|
|
58
|
+
StoreProvider,
|
|
59
|
+
createChatI18n,
|
|
60
|
+
createSettingsStore,
|
|
61
|
+
createChatStore,
|
|
62
|
+
} from '@elia-assistant/chatui'
|
|
63
|
+
|
|
64
|
+
// Create these once, outside the component - not on every render.
|
|
65
|
+
const i18n = createChatI18n()
|
|
66
|
+
const settingsStore = createSettingsStore(i18n)
|
|
67
|
+
const chatStore = createChatStore()
|
|
68
|
+
|
|
69
|
+
settingsStore.getState().setConfig({
|
|
24
70
|
webhookUrl: 'https://your-n8n.example.com/webhook/abc',
|
|
25
71
|
mode: 'window',
|
|
26
72
|
})
|
|
27
73
|
|
|
28
|
-
|
|
74
|
+
export function ChatWidget() {
|
|
75
|
+
return (
|
|
76
|
+
<I18nextProvider i18n={i18n}>
|
|
77
|
+
<StoreProvider settingsStore={settingsStore} chatStore={chatStore}>
|
|
78
|
+
<App />
|
|
79
|
+
</StoreProvider>
|
|
80
|
+
</I18nextProvider>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
29
83
|
```
|
|
30
84
|
|
|
31
|
-
|
|
85
|
+
Without both providers `<App />` throws `useSettingsStore must be used within a <StoreProvider>`. Note that this path does not inject the widget's CSS for you - prefer `createChat()` unless you specifically need to avoid the shadow root.
|
|
32
86
|
|
|
33
87
|
### Plain HTML (CDN, no bundler)
|
|
34
88
|
|
|
@@ -56,9 +110,24 @@ const instance = createChat({
|
|
|
56
110
|
webhookUrl: '...',
|
|
57
111
|
mode: 'window',
|
|
58
112
|
})
|
|
59
|
-
|
|
113
|
+
|
|
114
|
+
instance.setConfig({ botName: 'Support' }) // patch config without remounting
|
|
115
|
+
instance.setTheme('cosmos')
|
|
116
|
+
instance.setLanguage('sk')
|
|
117
|
+
instance.unmount() // remove
|
|
60
118
|
```
|
|
61
119
|
|
|
120
|
+
### Multiple widgets on one page
|
|
121
|
+
|
|
122
|
+
Every `createChat()` call gets its own config, theme, language and conversation state, so two widgets never fight over each other's settings. They do share `localStorage`, though - pass `storageNamespace` to keep their persisted state apart:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
createChat({ target: '#support', webhookUrl: '...' })
|
|
126
|
+
createChat({ target: '#demo', webhookUrl: '...', storageNamespace: 'demo' })
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Omit `storageNamespace` for the single-widget case and the default storage keys are used, so existing installs keep their saved settings and history.
|
|
130
|
+
|
|
62
131
|
---
|
|
63
132
|
|
|
64
133
|
## Features
|
|
@@ -74,10 +143,11 @@ const instance = createChat({
|
|
|
74
143
|
- **CTA popup** — timed speech-bubble with optional Web Audio notification, window mode only
|
|
75
144
|
- **Conversation history** — optional sidebar with persistent multi-session history
|
|
76
145
|
- **Per-language content** — initial messages, bot name, CTA text, welcome subtitle, tab titles, all configurable per language
|
|
77
|
-
- **Multilingual UI** — English and Slovak bundled; extend via `
|
|
146
|
+
- **Multilingual UI** — English and Slovak bundled; extend via `instance.i18n.addResourceBundle` at runtime
|
|
78
147
|
- **Markdown rendering** — bot messages render full GFM via `react-markdown`
|
|
79
148
|
- **Configurable "Powered by" footer** — change the link text/URL or hide it entirely
|
|
80
149
|
- **Persistent settings** — config + theme + language survive page reloads (`localStorage`)
|
|
150
|
+
- **Multi-instance safe** — every `createChat()` call is fully isolated; `storageNamespace` separates their persisted state too
|
|
81
151
|
- **Lockable UI** — `hideSettings: true` removes the gear, theme picker, and settings modal (default for npm consumers)
|
|
82
152
|
- **Export config** — generate ready-to-paste host code from the settings modal
|
|
83
153
|
|
|
@@ -85,7 +155,7 @@ const instance = createChat({
|
|
|
85
155
|
|
|
86
156
|
## Configuration
|
|
87
157
|
|
|
88
|
-
All options live on `ChatConfig`.
|
|
158
|
+
All options live on `ChatConfig`. Pass them to `createChat()`, or patch them later via `instance.setConfig()`.
|
|
89
159
|
|
|
90
160
|
### Required
|
|
91
161
|
|
|
@@ -160,7 +230,7 @@ A tab is shown only if its block has `feedUrl` or `items`. If neither tab is con
|
|
|
160
230
|
| `initialMessages` | `string[]` | Global fallback initial bot messages |
|
|
161
231
|
| `i18n[lang]` | `LangOverride` | Per-language content overrides |
|
|
162
232
|
|
|
163
|
-
To set the initial UI language,
|
|
233
|
+
To set the initial UI language, pass `language: 'sk'` to `createChat()` (or call `instance.setLanguage('sk')` later). On a fresh browser, the default falls back to `navigator.language` then `'en'`.
|
|
164
234
|
|
|
165
235
|
`LangOverride` fields: `initialMessages`, `ctaText`, `botName`, `welcomeSubtitle`, `tabs.{notifications,help,chat}.title`.
|
|
166
236
|
|
|
@@ -262,19 +332,22 @@ The FAQ tab includes a search box that filters by case-insensitive substring acr
|
|
|
262
332
|
Bundled languages: `en`, `sk` (split into `dist/chunks/translation-*.js`, lazy-loaded).
|
|
263
333
|
To add another without rebuilding chatui, register the bundle yourself:
|
|
264
334
|
|
|
335
|
+
Each instance owns a private i18next instance, exposed as `instance.i18n`. Register the bundle there - a bundle added to the global `i18next` singleton will not reach the widget:
|
|
336
|
+
|
|
265
337
|
```ts
|
|
266
|
-
|
|
267
|
-
import { useSettingsStore } from '@elia-assistant/chatui/store'
|
|
338
|
+
const instance = createChat({ target: '#chat', webhookUrl: '...' })
|
|
268
339
|
|
|
269
|
-
i18n
|
|
340
|
+
instance.i18n?.addResourceBundle('fr', 'translation', {
|
|
270
341
|
welcome: { subtitle: 'Commencez une conversation.' },
|
|
271
342
|
input: { placeholder: 'Tapez un message...' },
|
|
272
343
|
// ...full keys: see node_modules/@elia-assistant/chatui/dist/chunks/translation-*.js
|
|
273
344
|
})
|
|
274
345
|
|
|
275
|
-
|
|
346
|
+
instance.setLanguage('fr')
|
|
276
347
|
```
|
|
277
348
|
|
|
349
|
+
`instance.i18n` is `undefined` only when `createChat()` was called before `DOMContentLoaded` and the widget has not mounted yet.
|
|
350
|
+
|
|
278
351
|
Then any per-language overrides live under `config.i18n.fr`.
|
|
279
352
|
|
|
280
353
|
---
|
|
@@ -284,13 +357,14 @@ Then any per-language overrides live under `config.i18n.fr`.
|
|
|
284
357
|
Hidden by default for npm consumers — configuration is expected to live in code. Flip `hideSettings: false` to expose the gear, theme picker, and settings modal (handy for admin dashboards, internal tools, live demos):
|
|
285
358
|
|
|
286
359
|
```ts
|
|
287
|
-
|
|
360
|
+
createChat({
|
|
361
|
+
target: '#chat',
|
|
288
362
|
webhookUrl: '...',
|
|
289
363
|
hideSettings: false,
|
|
290
364
|
})
|
|
291
365
|
```
|
|
292
366
|
|
|
293
|
-
The settings modal includes an **Export config** button that generates the exact `setConfig()` call for pasting into a host project.
|
|
367
|
+
The settings modal includes an **Export config** button that generates the exact `instance.setConfig()` call for pasting into a host project.
|
|
294
368
|
|
|
295
369
|
The chatui repo's own `npm run dev` unlocks the UI automatically.
|
|
296
370
|
|
|
@@ -339,6 +413,26 @@ React 19 is a peer dependency for the ESM bundle. The IIFE bundle includes React
|
|
|
339
413
|
|
|
340
414
|
---
|
|
341
415
|
|
|
416
|
+
## Migrating from 1.x
|
|
417
|
+
|
|
418
|
+
2.0 removed the module-level global stores. Each `createChat()` call now owns its config, theme, language and conversation state, which is what makes multiple widgets on one page possible. `createChat()` itself is unchanged, so **CDN / `Chatui.createChat()` integrations need no changes** - and the default `localStorage` keys are unchanged, so saved settings and chat history carry over.
|
|
419
|
+
|
|
420
|
+
What did change:
|
|
421
|
+
|
|
422
|
+
| 1.x | 2.0 |
|
|
423
|
+
|---|---|
|
|
424
|
+
| `import { useSettingsStore } from '@elia-assistant/chatui/store'` | removed - use the `createChat()` instance |
|
|
425
|
+
| `useSettingsStore.getState().setConfig({...})` | `instance.setConfig({...})`, or pass the options to `createChat()` |
|
|
426
|
+
| `useSettingsStore.getState().setTheme(id)` | `instance.setTheme(id)` |
|
|
427
|
+
| `useSettingsStore.getState().setLanguage(lang)` | `instance.setLanguage(lang)` |
|
|
428
|
+
| `useChatStore` from `@elia-assistant/chatui/chat-store` | removed - no global chat store exists |
|
|
429
|
+
| `i18next.addResourceBundle(...)` on the global singleton | `instance.i18n?.addResourceBundle(...)` |
|
|
430
|
+
| `<App />` rendered directly | still supported, but must be wrapped in `<I18nextProvider>` + `<StoreProvider>` (see [Install](#raw-component-tree-no-shadow-root)) |
|
|
431
|
+
|
|
432
|
+
The `./store` and `./chat-store` subpath exports now expose only the `createSettingsStore` / `createChatStore` factories and their state types. Importing `useSettingsStore` from them fails at import time rather than silently returning something without `.getState()`.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
342
436
|
## License
|
|
343
437
|
|
|
344
438
|
MIT - see [LICENSE](./LICENSE). Built by [Igor Demovic](https://github.com/idemovic).
|
package/dist/App.d.ts
CHANGED
package/dist/chat-store.js
CHANGED
|
@@ -1,149 +1,151 @@
|
|
|
1
|
-
import { n as e, t } from "./chunks/middleware-
|
|
1
|
+
import { n as e, r as t, t as n } from "./chunks/middleware-BG8DEvI8.js";
|
|
2
2
|
//#region src/store/chatStore.ts
|
|
3
|
-
function
|
|
3
|
+
function r() {
|
|
4
4
|
return Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
...e.messages,
|
|
24
|
-
[t]: []
|
|
25
|
-
}
|
|
26
|
-
})), t;
|
|
27
|
-
},
|
|
28
|
-
setToken(t, n, r) {
|
|
29
|
-
e((e) => ({ tokens: {
|
|
30
|
-
...e.tokens,
|
|
31
|
-
[t]: {
|
|
32
|
-
token: n,
|
|
33
|
-
expiresAt: r
|
|
34
|
-
}
|
|
35
|
-
} }));
|
|
36
|
-
},
|
|
37
|
-
setActiveSession(t) {
|
|
38
|
-
e({ activeSessionId: t });
|
|
39
|
-
},
|
|
40
|
-
addMessage(t, n) {
|
|
41
|
-
e((e) => {
|
|
42
|
-
let r = e.messages[t] ?? [];
|
|
43
|
-
if (r.some((e) => e.id === n.id)) return {};
|
|
44
|
-
let i = [...r, n];
|
|
45
|
-
return {
|
|
46
|
-
sessions: e.sessions.map((e) => e.id !== t || e.title !== "New conversation" || n.role !== "user" ? e : {
|
|
47
|
-
...e,
|
|
48
|
-
title: n.content.slice(0, 50)
|
|
49
|
-
}),
|
|
6
|
+
function i(i) {
|
|
7
|
+
return e()(n((e, t) => ({
|
|
8
|
+
sessions: [],
|
|
9
|
+
activeSessionId: null,
|
|
10
|
+
messages: {},
|
|
11
|
+
isStreaming: !1,
|
|
12
|
+
awaitingAgentReply: {},
|
|
13
|
+
tokens: {},
|
|
14
|
+
createSession() {
|
|
15
|
+
let t = r(), n = {
|
|
16
|
+
id: t,
|
|
17
|
+
title: "New conversation",
|
|
18
|
+
createdAt: Date.now()
|
|
19
|
+
};
|
|
20
|
+
return e((e) => ({
|
|
21
|
+
sessions: [n, ...e.sessions],
|
|
22
|
+
activeSessionId: t,
|
|
50
23
|
messages: {
|
|
51
24
|
...e.messages,
|
|
52
|
-
[t]:
|
|
25
|
+
[t]: []
|
|
53
26
|
}
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (!i) return {};
|
|
97
|
-
let a = !1, o = i.map((e) => e.id !== n || e.status === r ? e : (a = !0, {
|
|
98
|
-
...e,
|
|
99
|
-
status: r
|
|
100
|
-
}));
|
|
101
|
-
return a ? { messages: {
|
|
102
|
-
...e.messages,
|
|
103
|
-
[t]: o
|
|
104
|
-
} } : {};
|
|
105
|
-
});
|
|
106
|
-
},
|
|
107
|
-
deleteSession(t) {
|
|
108
|
-
e((e) => {
|
|
109
|
-
let n = e.sessions.filter((e) => e.id !== t), r = { ...e.messages };
|
|
110
|
-
delete r[t];
|
|
111
|
-
let i = { ...e.awaitingAgentReply };
|
|
112
|
-
return delete i[t], {
|
|
113
|
-
sessions: n,
|
|
114
|
-
messages: r,
|
|
115
|
-
awaitingAgentReply: i,
|
|
116
|
-
activeSessionId: e.activeSessionId === t ? n[0]?.id ?? null : e.activeSessionId
|
|
117
|
-
};
|
|
118
|
-
});
|
|
119
|
-
},
|
|
120
|
-
renameSession(t, n) {
|
|
121
|
-
e((e) => ({ sessions: e.sessions.map((e) => e.id === t ? {
|
|
122
|
-
...e,
|
|
123
|
-
title: n
|
|
124
|
-
} : e) }));
|
|
125
|
-
},
|
|
126
|
-
clearMessages(n) {
|
|
127
|
-
e((e) => {
|
|
128
|
-
let t = { ...e.awaitingAgentReply };
|
|
129
|
-
return delete t[n], {
|
|
130
|
-
messages: {
|
|
27
|
+
})), t;
|
|
28
|
+
},
|
|
29
|
+
setToken(t, n, r) {
|
|
30
|
+
e((e) => ({ tokens: {
|
|
31
|
+
...e.tokens,
|
|
32
|
+
[t]: {
|
|
33
|
+
token: n,
|
|
34
|
+
expiresAt: r
|
|
35
|
+
}
|
|
36
|
+
} }));
|
|
37
|
+
},
|
|
38
|
+
setActiveSession(t) {
|
|
39
|
+
e({ activeSessionId: t });
|
|
40
|
+
},
|
|
41
|
+
addMessage(t, n) {
|
|
42
|
+
e((e) => {
|
|
43
|
+
let r = e.messages[t] ?? [];
|
|
44
|
+
if (r.some((e) => e.id === n.id)) return {};
|
|
45
|
+
let i = [...r, n];
|
|
46
|
+
return {
|
|
47
|
+
sessions: e.sessions.map((e) => e.id !== t || e.title !== "New conversation" || n.role !== "user" ? e : {
|
|
48
|
+
...e,
|
|
49
|
+
title: n.content.slice(0, 50)
|
|
50
|
+
}),
|
|
51
|
+
messages: {
|
|
52
|
+
...e.messages,
|
|
53
|
+
[t]: i
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
appendToLastBot(t, n) {
|
|
59
|
+
e((e) => {
|
|
60
|
+
let r = e.messages[t] ?? [];
|
|
61
|
+
if (r.length === 0) return {};
|
|
62
|
+
let i = r[r.length - 1];
|
|
63
|
+
if (i.role !== "bot") return {};
|
|
64
|
+
let a = [...r.slice(0, -1), {
|
|
65
|
+
...i,
|
|
66
|
+
content: i.content + n
|
|
67
|
+
}];
|
|
68
|
+
return { messages: {
|
|
131
69
|
...e.messages,
|
|
132
|
-
[
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
})
|
|
70
|
+
[t]: a
|
|
71
|
+
} };
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
removeLastBotIfEmpty(t) {
|
|
75
|
+
e((e) => {
|
|
76
|
+
let n = e.messages[t] ?? [];
|
|
77
|
+
if (n.length === 0) return {};
|
|
78
|
+
let r = n[n.length - 1];
|
|
79
|
+
return r.role !== "bot" || r.content !== "" ? {} : { messages: {
|
|
80
|
+
...e.messages,
|
|
81
|
+
[t]: n.slice(0, -1)
|
|
82
|
+
} };
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
setStreaming(t) {
|
|
86
|
+
e({ isStreaming: t });
|
|
87
|
+
},
|
|
88
|
+
setAwaitingAgentReply(t, n) {
|
|
89
|
+
e((e) => {
|
|
90
|
+
let r = { ...e.awaitingAgentReply };
|
|
91
|
+
return n ? r[t] = !0 : delete r[t], { awaitingAgentReply: r };
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
updateMessageStatus(t, n, r) {
|
|
95
|
+
e((e) => {
|
|
96
|
+
let i = e.messages[t];
|
|
97
|
+
if (!i) return {};
|
|
98
|
+
let a = !1, o = i.map((e) => e.id !== n || e.status === r ? e : (a = !0, {
|
|
99
|
+
...e,
|
|
100
|
+
status: r
|
|
101
|
+
}));
|
|
102
|
+
return a ? { messages: {
|
|
103
|
+
...e.messages,
|
|
104
|
+
[t]: o
|
|
105
|
+
} } : {};
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
deleteSession(t) {
|
|
109
|
+
e((e) => {
|
|
110
|
+
let n = e.sessions.filter((e) => e.id !== t), r = { ...e.messages };
|
|
111
|
+
delete r[t];
|
|
112
|
+
let i = { ...e.awaitingAgentReply };
|
|
113
|
+
return delete i[t], {
|
|
114
|
+
sessions: n,
|
|
115
|
+
messages: r,
|
|
116
|
+
awaitingAgentReply: i,
|
|
117
|
+
activeSessionId: e.activeSessionId === t ? n[0]?.id ?? null : e.activeSessionId
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
renameSession(t, n) {
|
|
122
|
+
e((e) => ({ sessions: e.sessions.map((e) => e.id === t ? {
|
|
123
|
+
...e,
|
|
124
|
+
title: n
|
|
125
|
+
} : e) }));
|
|
126
|
+
},
|
|
127
|
+
clearMessages(n) {
|
|
128
|
+
e((e) => {
|
|
129
|
+
let t = { ...e.awaitingAgentReply };
|
|
130
|
+
return delete t[n], {
|
|
131
|
+
messages: {
|
|
132
|
+
...e.messages,
|
|
133
|
+
[n]: []
|
|
134
|
+
},
|
|
135
|
+
awaitingAgentReply: t
|
|
136
|
+
};
|
|
137
|
+
}), t().renameSession(n, "New conversation");
|
|
138
|
+
}
|
|
139
|
+
}), {
|
|
140
|
+
name: t("chatui-chat", i),
|
|
141
|
+
partialize: (e) => ({
|
|
142
|
+
sessions: e.sessions,
|
|
143
|
+
activeSessionId: e.activeSessionId,
|
|
144
|
+
messages: e.messages
|
|
145
|
+
})
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
146
148
|
//#endregion
|
|
147
|
-
export {
|
|
149
|
+
export { i as createChatStore };
|
|
148
150
|
|
|
149
151
|
//# sourceMappingURL=chat-store.js.map
|