chainlit 1.1.404__py3-none-any.whl → 1.2.0rc0__py3-none-any.whl
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.
Potentially problematic release.
This version of chainlit might be problematic. Click here for more details.
- chainlit/__init__.py +63 -305
- chainlit/_utils.py +8 -0
- chainlit/assistant.py +16 -0
- chainlit/assistant_settings.py +35 -0
- chainlit/callbacks.py +340 -0
- chainlit/cli/__init__.py +1 -1
- chainlit/config.py +58 -28
- chainlit/copilot/dist/index.js +512 -631
- chainlit/data/__init__.py +6 -521
- chainlit/data/base.py +121 -0
- chainlit/data/dynamodb.py +5 -8
- chainlit/data/literalai.py +395 -0
- chainlit/data/sql_alchemy.py +11 -9
- chainlit/data/storage_clients.py +69 -15
- chainlit/data/utils.py +29 -0
- chainlit/element.py +1 -1
- chainlit/emitter.py +7 -0
- chainlit/frontend/dist/assets/{DailyMotion-e665b444.js → DailyMotion-aa368b7e.js} +1 -1
- chainlit/frontend/dist/assets/{Facebook-5207db92.js → Facebook-0335db46.js} +1 -1
- chainlit/frontend/dist/assets/{FilePlayer-86937d6e.js → FilePlayer-8d04256c.js} +1 -1
- chainlit/frontend/dist/assets/{Kaltura-c96622c1.js → Kaltura-67c9dd31.js} +1 -1
- chainlit/frontend/dist/assets/{Mixcloud-57ae3e32.js → Mixcloud-6bbaccf5.js} +1 -1
- chainlit/frontend/dist/assets/{Mux-20373920.js → Mux-c2bcb757.js} +1 -1
- chainlit/frontend/dist/assets/{Preview-c68c0613.js → Preview-210f3955.js} +1 -1
- chainlit/frontend/dist/assets/{SoundCloud-8a9e3eae.js → SoundCloud-a0276b84.js} +1 -1
- chainlit/frontend/dist/assets/{Streamable-1ed099af.js → Streamable-a007323d.js} +1 -1
- chainlit/frontend/dist/assets/{Twitch-6820039f.js → Twitch-e6a88aa3.js} +1 -1
- chainlit/frontend/dist/assets/{Vidyard-d39ab91d.js → Vidyard-dfb88a35.js} +1 -1
- chainlit/frontend/dist/assets/{Vimeo-017cd9a7.js → Vimeo-3baa13d9.js} +1 -1
- chainlit/frontend/dist/assets/{Wistia-a509d9f2.js → Wistia-e52f7bef.js} +1 -1
- chainlit/frontend/dist/assets/{YouTube-42dfd82f.js → YouTube-1715f22b.js} +1 -1
- chainlit/frontend/dist/assets/index-bfdd8585.js +729 -0
- chainlit/frontend/dist/assets/react-plotly-55648373.js +3484 -0
- chainlit/frontend/dist/index.html +1 -1
- chainlit/input_widget.py +22 -0
- chainlit/langchain/callbacks.py +6 -1
- chainlit/llama_index/callbacks.py +20 -4
- chainlit/markdown.py +15 -9
- chainlit/message.py +0 -1
- chainlit/server.py +113 -37
- chainlit/session.py +27 -4
- chainlit/socket.py +50 -1
- chainlit/translations/bn.json +231 -0
- chainlit/translations/en-US.json +6 -0
- chainlit/translations/fr-FR.json +236 -0
- chainlit/translations/gu.json +231 -0
- chainlit/translations/he-IL.json +231 -0
- chainlit/translations/hi.json +231 -0
- chainlit/translations/kn.json +231 -0
- chainlit/translations/ml.json +231 -0
- chainlit/translations/mr.json +231 -0
- chainlit/translations/ta.json +231 -0
- chainlit/translations/te.json +231 -0
- chainlit/types.py +1 -1
- chainlit/user_session.py +4 -0
- chainlit/utils.py +1 -1
- {chainlit-1.1.404.dist-info → chainlit-1.2.0rc0.dist-info}/METADATA +10 -10
- chainlit-1.2.0rc0.dist-info/RECORD +99 -0
- chainlit/frontend/dist/assets/index-30df9b2b.js +0 -730
- chainlit/frontend/dist/assets/react-plotly-5bb34118.js +0 -3602
- chainlit-1.1.404.dist-info/RECORD +0 -82
- {chainlit-1.1.404.dist-info → chainlit-1.2.0rc0.dist-info}/WHEEL +0 -0
- {chainlit-1.1.404.dist-info → chainlit-1.2.0rc0.dist-info}/entry_points.txt +0 -0
chainlit/callbacks.py
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import inspect
|
|
3
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from chainlit.action import Action
|
|
6
|
+
from chainlit.assistant import Assistant
|
|
7
|
+
from chainlit.assistant_settings import AssistantSettings
|
|
8
|
+
from chainlit.config import config
|
|
9
|
+
from chainlit.message import Message
|
|
10
|
+
from chainlit.oauth_providers import get_configured_oauth_providers
|
|
11
|
+
from chainlit.step import Step, step
|
|
12
|
+
from chainlit.telemetry import trace
|
|
13
|
+
from chainlit.types import ChatProfile, Starter, ThreadDict
|
|
14
|
+
from chainlit.user import User
|
|
15
|
+
from chainlit.utils import wrap_user_function
|
|
16
|
+
from fastapi import Request, Response
|
|
17
|
+
from starlette.datastructures import Headers
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def experimental(func):
|
|
21
|
+
@functools.wraps(func)
|
|
22
|
+
def wrapper(*args, **kwargs):
|
|
23
|
+
print(f"\033[1;33mexperimental feature: {func.__name__}\033[0m")
|
|
24
|
+
return func(*args, **kwargs)
|
|
25
|
+
|
|
26
|
+
return wrapper
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@trace
|
|
30
|
+
def password_auth_callback(
|
|
31
|
+
func: Callable[[str, str], Awaitable[Optional[User]]]
|
|
32
|
+
) -> Callable:
|
|
33
|
+
"""
|
|
34
|
+
Framework agnostic decorator to authenticate the user.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
func (Callable[[str, str], Awaitable[Optional[User]]]): The authentication callback to execute. Takes the email and password as parameters.
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
@cl.password_auth_callback
|
|
41
|
+
async def password_auth_callback(username: str, password: str) -> Optional[User]:
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Callable[[str, str], Awaitable[Optional[User]]]: The decorated authentication callback.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
config.code.password_auth_callback = wrap_user_function(func)
|
|
48
|
+
return func
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@trace
|
|
52
|
+
def header_auth_callback(
|
|
53
|
+
func: Callable[[Headers], Awaitable[Optional[User]]]
|
|
54
|
+
) -> Callable:
|
|
55
|
+
"""
|
|
56
|
+
Framework agnostic decorator to authenticate the user via a header
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
func (Callable[[Headers], Awaitable[Optional[User]]]): The authentication callback to execute.
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
@cl.header_auth_callback
|
|
63
|
+
async def header_auth_callback(headers: Headers) -> Optional[User]:
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Callable[[Headers], Awaitable[Optional[User]]]: The decorated authentication callback.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
config.code.header_auth_callback = wrap_user_function(func)
|
|
70
|
+
return func
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@trace
|
|
74
|
+
def oauth_callback(
|
|
75
|
+
func: Callable[
|
|
76
|
+
[str, str, Dict[str, str], User, Optional[str]], Awaitable[Optional[User]]
|
|
77
|
+
],
|
|
78
|
+
) -> Callable:
|
|
79
|
+
"""
|
|
80
|
+
Framework agnostic decorator to authenticate the user via oauth
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
func (Callable[[str, str, Dict[str, str], User, Optional[str]], Awaitable[Optional[User]]]): The authentication callback to execute.
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
@cl.oauth_callback
|
|
87
|
+
async def oauth_callback(provider_id: str, token: str, raw_user_data: Dict[str, str], default_app_user: User, id_token: Optional[str]) -> Optional[User]:
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Callable[[str, str, Dict[str, str], User, Optional[str]], Awaitable[Optional[User]]]: The decorated authentication callback.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
if len(get_configured_oauth_providers()) == 0:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
"You must set the environment variable for at least one oauth provider to use oauth authentication."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
config.code.oauth_callback = wrap_user_function(func)
|
|
99
|
+
return func
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@trace
|
|
103
|
+
def on_logout(func: Callable[[Request, Response], Any]) -> Callable:
|
|
104
|
+
"""
|
|
105
|
+
Function called when the user logs out.
|
|
106
|
+
Takes the FastAPI request and response as parameters.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
config.code.on_logout = wrap_user_function(func)
|
|
110
|
+
return func
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@trace
|
|
114
|
+
def on_message(func: Callable) -> Callable:
|
|
115
|
+
"""
|
|
116
|
+
Framework agnostic decorator to react to messages coming from the UI.
|
|
117
|
+
The decorated function is called every time a new message is received.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
func (Callable[[Message], Any]): The function to be called when a new message is received. Takes a cl.Message.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Callable[[str], Any]: The decorated on_message function.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
async def with_parent_id(message: Message):
|
|
127
|
+
async with Step(name="on_message", type="run", parent_id=message.id) as s:
|
|
128
|
+
s.input = message.content
|
|
129
|
+
if len(inspect.signature(func).parameters) > 0:
|
|
130
|
+
await func(message)
|
|
131
|
+
else:
|
|
132
|
+
await func()
|
|
133
|
+
|
|
134
|
+
config.code.on_message = wrap_user_function(with_parent_id)
|
|
135
|
+
return func
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@trace
|
|
139
|
+
def on_chat_start(func: Callable) -> Callable:
|
|
140
|
+
"""
|
|
141
|
+
Hook to react to the user websocket connection event.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
func (Callable[], Any]): The connection hook to execute.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Callable[], Any]: The decorated hook.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
config.code.on_chat_start = wrap_user_function(
|
|
151
|
+
step(func, name="on_chat_start", type="run"), with_task=True
|
|
152
|
+
)
|
|
153
|
+
return func
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@trace
|
|
157
|
+
def on_chat_resume(func: Callable[[ThreadDict], Any]) -> Callable:
|
|
158
|
+
"""
|
|
159
|
+
Hook to react to resume websocket connection event.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
func (Callable[], Any]): The connection hook to execute.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Callable[], Any]: The decorated hook.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
config.code.on_chat_resume = wrap_user_function(func, with_task=True)
|
|
169
|
+
return func
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@trace
|
|
173
|
+
def set_chat_profiles(
|
|
174
|
+
func: Callable[[Optional["User"]], Awaitable[List["ChatProfile"]]],
|
|
175
|
+
) -> Callable:
|
|
176
|
+
"""
|
|
177
|
+
Programmatic declaration of the available chat profiles (can depend on the User from the session if authentication is setup).
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
func (Callable[[Optional["User"]], Awaitable[List["ChatProfile"]]]): The function declaring the chat profiles.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Callable[[Optional["User"]], Awaitable[List["ChatProfile"]]]: The decorated function.
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
config.code.set_chat_profiles = wrap_user_function(func)
|
|
187
|
+
return func
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@trace
|
|
191
|
+
def set_starters(
|
|
192
|
+
func: Callable[[Optional["User"]], Awaitable[List["Starter"]]]
|
|
193
|
+
) -> Callable:
|
|
194
|
+
"""
|
|
195
|
+
Programmatic declaration of the available starter (can depend on the User from the session if authentication is setup).
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
func (Callable[[Optional["User"]], Awaitable[List["Starter"]]]): The function declaring the starters.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Callable[[Optional["User"]], Awaitable[List["Starter"]]]: The decorated function.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
config.code.set_starters = wrap_user_function(func)
|
|
205
|
+
return func
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@trace
|
|
209
|
+
def on_chat_end(func: Callable) -> Callable:
|
|
210
|
+
"""
|
|
211
|
+
Hook to react to the user websocket disconnect event.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
func (Callable[], Any]): The disconnect hook to execute.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
Callable[], Any]: The decorated hook.
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
config.code.on_chat_end = wrap_user_function(func, with_task=True)
|
|
221
|
+
return func
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@trace
|
|
225
|
+
def on_audio_chunk(func: Callable) -> Callable:
|
|
226
|
+
"""
|
|
227
|
+
Hook to react to the audio chunks being sent.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
chunk (AudioChunk): The audio chunk being sent.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Callable[], Any]: The decorated hook.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
config.code.on_audio_chunk = wrap_user_function(func, with_task=False)
|
|
237
|
+
return func
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@trace
|
|
241
|
+
def on_audio_end(func: Callable) -> Callable:
|
|
242
|
+
"""
|
|
243
|
+
Hook to react to the audio stream ending. This is called after the last audio chunk is sent.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
elements ([List[Element]): The files that were uploaded before starting the audio stream (if any).
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Callable[], Any]: The decorated hook.
|
|
250
|
+
"""
|
|
251
|
+
|
|
252
|
+
config.code.on_audio_end = wrap_user_function(
|
|
253
|
+
step(func, name="on_audio_end", type="run"), with_task=True
|
|
254
|
+
)
|
|
255
|
+
return func
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@trace
|
|
259
|
+
def author_rename(
|
|
260
|
+
func: Callable[[str], Awaitable[str]]
|
|
261
|
+
) -> Callable[[str], Awaitable[str]]:
|
|
262
|
+
"""
|
|
263
|
+
Useful to rename the author of message to display more friendly author names in the UI.
|
|
264
|
+
Args:
|
|
265
|
+
func (Callable[[str], Awaitable[str]]): The function to be called to rename an author. Takes the original author name as parameter.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Callable[[Any, str], Awaitable[Any]]: The decorated function.
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
config.code.author_rename = wrap_user_function(func)
|
|
272
|
+
return func
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@trace
|
|
276
|
+
def on_stop(func: Callable) -> Callable:
|
|
277
|
+
"""
|
|
278
|
+
Hook to react to the user stopping a thread.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
func (Callable[[], Any]): The stop hook to execute.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Callable[[], Any]: The decorated stop hook.
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
config.code.on_stop = wrap_user_function(func)
|
|
288
|
+
return func
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def action_callback(name: str) -> Callable:
|
|
292
|
+
"""
|
|
293
|
+
Callback to call when an action is clicked in the UI.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
func (Callable[[Action], Any]): The action callback to execute. First parameter is the action.
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
def decorator(func: Callable[[Action], Any]):
|
|
300
|
+
config.code.action_callbacks[name] = wrap_user_function(func, with_task=True)
|
|
301
|
+
return func
|
|
302
|
+
|
|
303
|
+
return decorator
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def on_settings_update(
|
|
307
|
+
func: Callable[[Dict[str, Any]], Any],
|
|
308
|
+
) -> Callable[[Dict[str, Any]], Any]:
|
|
309
|
+
"""
|
|
310
|
+
Hook to react to the user changing any settings.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
func (Callable[], Any]): The hook to execute after settings were changed.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Callable[], Any]: The decorated hook.
|
|
317
|
+
"""
|
|
318
|
+
|
|
319
|
+
config.code.on_settings_update = wrap_user_function(func, with_task=True)
|
|
320
|
+
return func
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# Experimental
|
|
324
|
+
@trace
|
|
325
|
+
@experimental
|
|
326
|
+
def on_create_assistant(
|
|
327
|
+
func: Callable[[Optional[User], AssistantSettings], Any]
|
|
328
|
+
) -> Callable[[Optional[User], AssistantSettings], Any]:
|
|
329
|
+
config.code.on_create_assistant = wrap_user_function(func)
|
|
330
|
+
return func
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
# Experimental
|
|
334
|
+
@trace
|
|
335
|
+
@experimental
|
|
336
|
+
def on_list_assistants(
|
|
337
|
+
func: Callable[[Optional[User]], List[Assistant]]
|
|
338
|
+
) -> Callable[[Optional[User]], List[Assistant]]:
|
|
339
|
+
config.code.on_list_assistants = wrap_user_function(func)
|
|
340
|
+
return func
|
chainlit/cli/__init__.py
CHANGED
|
@@ -183,7 +183,7 @@ def chainlit_run(
|
|
|
183
183
|
no_cache = True
|
|
184
184
|
# This is required to have OpenAI LLM providers available for the CI run
|
|
185
185
|
os.environ["OPENAI_API_KEY"] = "sk-FAKE-OPENAI-API-KEY"
|
|
186
|
-
# This is required for
|
|
186
|
+
# This is required for authentication tests
|
|
187
187
|
os.environ["CHAINLIT_AUTH_SECRET"] = "SUPER_SECRET"
|
|
188
188
|
else:
|
|
189
189
|
trace_event("chainlit run")
|
chainlit/config.py
CHANGED
|
@@ -4,7 +4,17 @@ import site
|
|
|
4
4
|
import sys
|
|
5
5
|
from importlib import util
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import (
|
|
8
|
+
TYPE_CHECKING,
|
|
9
|
+
Any,
|
|
10
|
+
Awaitable,
|
|
11
|
+
Callable,
|
|
12
|
+
Dict,
|
|
13
|
+
List,
|
|
14
|
+
Literal,
|
|
15
|
+
Optional,
|
|
16
|
+
Union,
|
|
17
|
+
)
|
|
8
18
|
|
|
9
19
|
import tomli
|
|
10
20
|
from chainlit.logger import logger
|
|
@@ -14,15 +24,17 @@ from dataclasses_json import DataClassJsonMixin
|
|
|
14
24
|
from pydantic.dataclasses import Field, dataclass
|
|
15
25
|
from starlette.datastructures import Headers
|
|
16
26
|
|
|
27
|
+
from ._utils import is_path_inside
|
|
28
|
+
|
|
17
29
|
if TYPE_CHECKING:
|
|
18
30
|
from chainlit.action import Action
|
|
31
|
+
from chainlit.assistant import Assistant
|
|
19
32
|
from chainlit.element import ElementBased
|
|
20
33
|
from chainlit.message import Message
|
|
21
34
|
from chainlit.types import AudioChunk, ChatProfile, Starter, ThreadDict
|
|
22
35
|
from chainlit.user import User
|
|
23
36
|
from fastapi import Request, Response
|
|
24
37
|
|
|
25
|
-
|
|
26
38
|
BACKEND_ROOT = os.path.dirname(__file__)
|
|
27
39
|
PACKAGE_ROOT = os.path.dirname(os.path.dirname(BACKEND_ROOT))
|
|
28
40
|
TRANSLATIONS_DIR = os.path.join(BACKEND_ROOT, "translations")
|
|
@@ -270,10 +282,14 @@ class CodeSettings:
|
|
|
270
282
|
# Module object loaded from the module_name
|
|
271
283
|
module: Any = None
|
|
272
284
|
# Bunch of callbacks defined by the developer
|
|
273
|
-
password_auth_callback: Optional[
|
|
274
|
-
|
|
285
|
+
password_auth_callback: Optional[
|
|
286
|
+
Callable[[str, str], Awaitable[Optional["User"]]]
|
|
287
|
+
] = None
|
|
288
|
+
header_auth_callback: Optional[Callable[[Headers], Awaitable[Optional["User"]]]] = (
|
|
289
|
+
None
|
|
290
|
+
)
|
|
275
291
|
oauth_callback: Optional[
|
|
276
|
-
Callable[[str, str, Dict[str, str], "User"], Optional["User"]]
|
|
292
|
+
Callable[[str, str, Dict[str, str], "User"], Awaitable[Optional["User"]]]
|
|
277
293
|
] = None
|
|
278
294
|
on_logout: Optional[Callable[["Request", "Response"], Any]] = None
|
|
279
295
|
on_stop: Optional[Callable[[], Any]] = None
|
|
@@ -284,12 +300,18 @@ class CodeSettings:
|
|
|
284
300
|
on_audio_chunk: Optional[Callable[["AudioChunk"], Any]] = None
|
|
285
301
|
on_audio_end: Optional[Callable[[List["ElementBased"]], Any]] = None
|
|
286
302
|
|
|
287
|
-
author_rename: Optional[Callable[[str], str]] = None
|
|
303
|
+
author_rename: Optional[Callable[[str], Awaitable[str]]] = None
|
|
288
304
|
on_settings_update: Optional[Callable[[Dict[str, Any]], Any]] = None
|
|
289
|
-
set_chat_profiles: Optional[
|
|
305
|
+
set_chat_profiles: Optional[
|
|
306
|
+
Callable[[Optional["User"]], Awaitable[List["ChatProfile"]]]
|
|
307
|
+
] = None
|
|
308
|
+
set_starters: Optional[Callable[[Optional["User"]], Awaitable[List["Starter"]]]] = (
|
|
290
309
|
None
|
|
291
310
|
)
|
|
292
|
-
|
|
311
|
+
|
|
312
|
+
# assistant-related callback function
|
|
313
|
+
on_create_assistant: Optional[Callable[[Optional["User"], Any], Any]] = None
|
|
314
|
+
on_list_assistants: Optional[Callable[[Optional["User"]], List["Assistant"]]] = None
|
|
293
315
|
|
|
294
316
|
|
|
295
317
|
@dataclass()
|
|
@@ -327,33 +349,41 @@ class ChainlitConfig:
|
|
|
327
349
|
# fallback to root language (ex: `de` when `de-DE` is not found)
|
|
328
350
|
parent_language = language.split("-")[0]
|
|
329
351
|
|
|
330
|
-
|
|
331
|
-
config_translation_dir, f"{language}.json"
|
|
332
|
-
)
|
|
333
|
-
translation_lib_parent_language_file_path = os.path.join(
|
|
334
|
-
config_translation_dir, f"{parent_language}.json"
|
|
335
|
-
)
|
|
336
|
-
default_translation_lib_file_path = os.path.join(
|
|
337
|
-
config_translation_dir, f"{default_language}.json"
|
|
338
|
-
)
|
|
352
|
+
translation_dir = Path(config_translation_dir)
|
|
339
353
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
354
|
+
translation_lib_file_path = translation_dir / f"{language}.json"
|
|
355
|
+
translation_lib_parent_language_file_path = (
|
|
356
|
+
translation_dir / f"{parent_language}.json"
|
|
357
|
+
)
|
|
358
|
+
default_translation_lib_file_path = translation_dir / f"{default_language}.json"
|
|
359
|
+
|
|
360
|
+
if (
|
|
361
|
+
is_path_inside(translation_lib_file_path, translation_dir)
|
|
362
|
+
and translation_lib_file_path.is_file()
|
|
363
|
+
):
|
|
364
|
+
translation = json.loads(
|
|
365
|
+
translation_lib_file_path.read_text(encoding="utf-8")
|
|
366
|
+
)
|
|
367
|
+
elif (
|
|
368
|
+
is_path_inside(translation_lib_parent_language_file_path, translation_dir)
|
|
369
|
+
and translation_lib_parent_language_file_path.is_file()
|
|
370
|
+
):
|
|
344
371
|
logger.warning(
|
|
345
372
|
f"Translation file for {language} not found. Using parent translation {parent_language}."
|
|
346
373
|
)
|
|
347
|
-
|
|
348
|
-
translation_lib_parent_language_file_path
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
|
|
374
|
+
translation = json.loads(
|
|
375
|
+
translation_lib_parent_language_file_path.read_text(encoding="utf-8")
|
|
376
|
+
)
|
|
377
|
+
elif (
|
|
378
|
+
is_path_inside(default_translation_lib_file_path, translation_dir)
|
|
379
|
+
and default_translation_lib_file_path.is_file()
|
|
380
|
+
):
|
|
352
381
|
logger.warning(
|
|
353
382
|
f"Translation file for {language} not found. Using default translation {default_language}."
|
|
354
383
|
)
|
|
355
|
-
|
|
356
|
-
|
|
384
|
+
translation = json.loads(
|
|
385
|
+
default_translation_lib_file_path.read_text(encoding="utf-8")
|
|
386
|
+
)
|
|
357
387
|
|
|
358
388
|
return translation
|
|
359
389
|
|