chainlit 2.7.0__py3-none-any.whl → 2.7.1__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.

Files changed (85) hide show
  1. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/METADATA +1 -1
  2. chainlit-2.7.1.dist-info/RECORD +4 -0
  3. chainlit/__init__.py +0 -207
  4. chainlit/__main__.py +0 -4
  5. chainlit/_utils.py +0 -8
  6. chainlit/action.py +0 -33
  7. chainlit/auth/__init__.py +0 -95
  8. chainlit/auth/cookie.py +0 -197
  9. chainlit/auth/jwt.py +0 -42
  10. chainlit/cache.py +0 -45
  11. chainlit/callbacks.py +0 -433
  12. chainlit/chat_context.py +0 -64
  13. chainlit/chat_settings.py +0 -34
  14. chainlit/cli/__init__.py +0 -235
  15. chainlit/config.py +0 -621
  16. chainlit/context.py +0 -112
  17. chainlit/data/__init__.py +0 -111
  18. chainlit/data/acl.py +0 -19
  19. chainlit/data/base.py +0 -107
  20. chainlit/data/chainlit_data_layer.py +0 -687
  21. chainlit/data/dynamodb.py +0 -616
  22. chainlit/data/literalai.py +0 -501
  23. chainlit/data/sql_alchemy.py +0 -741
  24. chainlit/data/storage_clients/__init__.py +0 -0
  25. chainlit/data/storage_clients/azure.py +0 -84
  26. chainlit/data/storage_clients/azure_blob.py +0 -94
  27. chainlit/data/storage_clients/base.py +0 -28
  28. chainlit/data/storage_clients/gcs.py +0 -101
  29. chainlit/data/storage_clients/s3.py +0 -88
  30. chainlit/data/utils.py +0 -29
  31. chainlit/discord/__init__.py +0 -6
  32. chainlit/discord/app.py +0 -364
  33. chainlit/element.py +0 -454
  34. chainlit/emitter.py +0 -450
  35. chainlit/hello.py +0 -12
  36. chainlit/input_widget.py +0 -182
  37. chainlit/langchain/__init__.py +0 -6
  38. chainlit/langchain/callbacks.py +0 -682
  39. chainlit/langflow/__init__.py +0 -25
  40. chainlit/llama_index/__init__.py +0 -6
  41. chainlit/llama_index/callbacks.py +0 -206
  42. chainlit/logger.py +0 -16
  43. chainlit/markdown.py +0 -57
  44. chainlit/mcp.py +0 -99
  45. chainlit/message.py +0 -619
  46. chainlit/mistralai/__init__.py +0 -50
  47. chainlit/oauth_providers.py +0 -835
  48. chainlit/openai/__init__.py +0 -53
  49. chainlit/py.typed +0 -0
  50. chainlit/secret.py +0 -9
  51. chainlit/semantic_kernel/__init__.py +0 -111
  52. chainlit/server.py +0 -1616
  53. chainlit/session.py +0 -304
  54. chainlit/sidebar.py +0 -55
  55. chainlit/slack/__init__.py +0 -6
  56. chainlit/slack/app.py +0 -427
  57. chainlit/socket.py +0 -381
  58. chainlit/step.py +0 -490
  59. chainlit/sync.py +0 -43
  60. chainlit/teams/__init__.py +0 -6
  61. chainlit/teams/app.py +0 -348
  62. chainlit/translations/bn.json +0 -214
  63. chainlit/translations/el-GR.json +0 -214
  64. chainlit/translations/en-US.json +0 -214
  65. chainlit/translations/fr-FR.json +0 -214
  66. chainlit/translations/gu.json +0 -214
  67. chainlit/translations/he-IL.json +0 -214
  68. chainlit/translations/hi.json +0 -214
  69. chainlit/translations/ja.json +0 -214
  70. chainlit/translations/kn.json +0 -214
  71. chainlit/translations/ml.json +0 -214
  72. chainlit/translations/mr.json +0 -214
  73. chainlit/translations/nl.json +0 -214
  74. chainlit/translations/ta.json +0 -214
  75. chainlit/translations/te.json +0 -214
  76. chainlit/translations/zh-CN.json +0 -214
  77. chainlit/translations.py +0 -60
  78. chainlit/types.py +0 -334
  79. chainlit/user.py +0 -43
  80. chainlit/user_session.py +0 -153
  81. chainlit/utils.py +0 -173
  82. chainlit/version.py +0 -8
  83. chainlit-2.7.0.dist-info/RECORD +0 -84
  84. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/WHEEL +0 -0
  85. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/entry_points.txt +0 -0
chainlit/socket.py DELETED
@@ -1,381 +0,0 @@
1
- import asyncio
2
- import json
3
- from typing import Any, Dict, Literal, Optional, Tuple, Union
4
- from urllib.parse import unquote
5
-
6
- from starlette.requests import cookie_parser
7
- from typing_extensions import TypeAlias
8
-
9
- from chainlit.auth import (
10
- get_current_user,
11
- get_token_from_cookies,
12
- require_login,
13
- )
14
- from chainlit.chat_context import chat_context
15
- from chainlit.config import config
16
- from chainlit.context import init_ws_context
17
- from chainlit.data import get_data_layer
18
- from chainlit.logger import logger
19
- from chainlit.message import ErrorMessage, Message
20
- from chainlit.server import sio
21
- from chainlit.session import WebsocketSession
22
- from chainlit.types import InputAudioChunk, InputAudioChunkPayload, MessagePayload
23
- from chainlit.user import PersistedUser, User
24
- from chainlit.user_session import user_sessions
25
-
26
- WSGIEnvironment: TypeAlias = dict[str, Any]
27
-
28
-
29
- def restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
30
- """Restore a session from the sessionId provided by the client."""
31
- if session := WebsocketSession.get_by_id(session_id):
32
- session.restore(new_socket_id=sid)
33
- session.emit = emit_fn
34
- session.emit_call = emit_call_fn
35
- return True
36
- return False
37
-
38
-
39
- async def persist_user_session(thread_id: str, metadata: Dict):
40
- if data_layer := get_data_layer():
41
- await data_layer.update_thread(thread_id=thread_id, metadata=metadata)
42
-
43
-
44
- async def resume_thread(session: WebsocketSession):
45
- data_layer = get_data_layer()
46
- if not data_layer or not session.user or not session.thread_id_to_resume:
47
- return
48
- thread = await data_layer.get_thread(thread_id=session.thread_id_to_resume)
49
- if not thread:
50
- return
51
-
52
- author = thread.get("userIdentifier")
53
- user_is_author = author == session.user.identifier
54
-
55
- if user_is_author:
56
- metadata = thread.get("metadata") or {}
57
- if isinstance(metadata, str):
58
- metadata = json.loads(metadata)
59
- user_sessions[session.id] = metadata.copy()
60
- if chat_profile := metadata.get("chat_profile"):
61
- session.chat_profile = chat_profile
62
- if chat_settings := metadata.get("chat_settings"):
63
- session.chat_settings = chat_settings
64
-
65
- return thread
66
-
67
-
68
- def load_user_env(user_env):
69
- if user_env:
70
- user_env_dict = json.loads(user_env)
71
- # Check user env
72
- if config.project.user_env:
73
- if not user_env_dict:
74
- raise ConnectionRefusedError("Missing user environment variables")
75
- # Check if requested user environment variables are provided
76
- for key in config.project.user_env:
77
- if key not in user_env_dict:
78
- raise ConnectionRefusedError(
79
- "Missing user environment variable: " + key
80
- )
81
- return user_env_dict
82
-
83
-
84
- def _get_token_from_cookie(environ: WSGIEnvironment) -> Optional[str]:
85
- if cookie_header := environ.get("HTTP_COOKIE", None):
86
- cookies = cookie_parser(cookie_header)
87
- return get_token_from_cookies(cookies)
88
-
89
- return None
90
-
91
-
92
- def _get_token(environ: WSGIEnvironment, auth: dict) -> Optional[str]:
93
- """Take WSGI environ, return access token."""
94
- return _get_token_from_cookie(environ)
95
-
96
-
97
- async def _authenticate_connection(
98
- environ,
99
- auth,
100
- ) -> Union[Tuple[Union[User, PersistedUser], str], Tuple[None, None]]:
101
- if token := _get_token(environ, auth):
102
- user = await get_current_user(token=token)
103
- if user:
104
- return user, token
105
-
106
- return None, None
107
-
108
-
109
- @sio.on("connect") # pyright: ignore [reportOptionalCall]
110
- async def connect(sid, environ, auth):
111
- user = token = None
112
-
113
- if require_login():
114
- try:
115
- user, token = await _authenticate_connection(environ, auth)
116
- except Exception as e:
117
- logger.exception("Exception authenticating connection: %s", e)
118
-
119
- if not user:
120
- logger.error("Authentication failed in websocket connect.")
121
- raise ConnectionRefusedError("authentication failed")
122
-
123
- # Session scoped function to emit to the client
124
- def emit_fn(event, data):
125
- return sio.emit(event, data, to=sid)
126
-
127
- # Session scoped function to emit to the client and wait for a response
128
- def emit_call_fn(event: Literal["ask", "call_fn"], data, timeout):
129
- return sio.call(event, data, timeout=timeout, to=sid)
130
-
131
- session_id = auth.get("sessionId")
132
- if restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
133
- return True
134
-
135
- user_env_string = auth.get("userEnv")
136
- user_env = load_user_env(user_env_string)
137
-
138
- client_type = auth.get("clientType")
139
- url_encoded_chat_profile = auth.get("chatProfile")
140
- chat_profile = (
141
- unquote(url_encoded_chat_profile) if url_encoded_chat_profile else None
142
- )
143
-
144
- WebsocketSession(
145
- id=session_id,
146
- socket_id=sid,
147
- emit=emit_fn,
148
- emit_call=emit_call_fn,
149
- client_type=client_type,
150
- user_env=user_env,
151
- user=user,
152
- token=token,
153
- chat_profile=chat_profile,
154
- thread_id=auth.get("threadId"),
155
- environ=environ,
156
- )
157
-
158
- return True
159
-
160
-
161
- @sio.on("connection_successful") # pyright: ignore [reportOptionalCall]
162
- async def connection_successful(sid):
163
- context = init_ws_context(sid)
164
-
165
- await context.emitter.task_end()
166
- await context.emitter.clear("clear_ask")
167
- await context.emitter.clear("clear_call_fn")
168
-
169
- if context.session.restored:
170
- return
171
-
172
- if context.session.thread_id_to_resume and config.code.on_chat_resume:
173
- thread = await resume_thread(context.session)
174
- if thread:
175
- context.session.has_first_interaction = True
176
- await context.emitter.emit(
177
- "first_interaction",
178
- {"interaction": "resume", "thread_id": thread.get("id")},
179
- )
180
- await config.code.on_chat_resume(thread)
181
-
182
- for step in thread.get("steps", []):
183
- if "message" in step["type"]:
184
- chat_context.add(Message.from_dict(step))
185
-
186
- await context.emitter.resume_thread(thread)
187
- return
188
- else:
189
- await context.emitter.send_resume_thread_error("Thread not found.")
190
-
191
- if config.code.on_chat_start:
192
- task = asyncio.create_task(config.code.on_chat_start())
193
- context.session.current_task = task
194
-
195
-
196
- @sio.on("clear_session") # pyright: ignore [reportOptionalCall]
197
- async def clean_session(sid):
198
- session = WebsocketSession.get(sid)
199
- if session:
200
- session.to_clear = True
201
-
202
-
203
- @sio.on("disconnect") # pyright: ignore [reportOptionalCall]
204
- async def disconnect(sid):
205
- session = WebsocketSession.get(sid)
206
-
207
- if not session:
208
- return
209
-
210
- init_ws_context(session)
211
-
212
- if config.code.on_chat_end:
213
- await config.code.on_chat_end()
214
-
215
- if session.thread_id and session.has_first_interaction:
216
- await persist_user_session(session.thread_id, session.to_persistable())
217
-
218
- async def clear(_sid):
219
- if session := WebsocketSession.get(_sid):
220
- # Clean up the user session
221
- if session.id in user_sessions:
222
- user_sessions.pop(session.id)
223
- # Clean up the session
224
- await session.delete()
225
-
226
- if session.to_clear:
227
- await clear(sid)
228
- else:
229
-
230
- async def clear_on_timeout(_sid):
231
- await asyncio.sleep(config.project.session_timeout)
232
- await clear(_sid)
233
-
234
- asyncio.ensure_future(clear_on_timeout(sid))
235
-
236
-
237
- @sio.on("stop") # pyright: ignore [reportOptionalCall]
238
- async def stop(sid):
239
- if session := WebsocketSession.get(sid):
240
- init_ws_context(session)
241
- await Message(content="Task manually stopped.").send()
242
-
243
- if session.current_task:
244
- session.current_task.cancel()
245
-
246
- if config.code.on_stop:
247
- await config.code.on_stop()
248
-
249
-
250
- async def process_message(session: WebsocketSession, payload: MessagePayload):
251
- """Process a message from the user."""
252
- try:
253
- context = init_ws_context(session)
254
- await context.emitter.task_start()
255
- message = await context.emitter.process_message(payload)
256
-
257
- if config.code.on_message:
258
- await asyncio.sleep(0.001)
259
- await config.code.on_message(message)
260
- except asyncio.CancelledError:
261
- pass
262
- except Exception as e:
263
- logger.exception(e)
264
- await ErrorMessage(
265
- author="Error", content=str(e) or e.__class__.__name__
266
- ).send()
267
- finally:
268
- await context.emitter.task_end()
269
-
270
-
271
- @sio.on("edit_message") # pyright: ignore [reportOptionalCall]
272
- async def edit_message(sid, payload: MessagePayload):
273
- """Handle a message sent by the User."""
274
- session = WebsocketSession.require(sid)
275
- context = init_ws_context(session)
276
-
277
- messages = chat_context.get()
278
-
279
- orig_message = None
280
-
281
- for message in messages:
282
- if orig_message:
283
- await message.remove()
284
-
285
- if message.id == payload["message"]["id"]:
286
- message.content = payload["message"]["output"]
287
- await message.update()
288
- orig_message = message
289
-
290
- await context.emitter.task_start()
291
-
292
- if config.code.on_message:
293
- try:
294
- await config.code.on_message(orig_message)
295
- except asyncio.CancelledError:
296
- pass
297
- finally:
298
- await context.emitter.task_end()
299
-
300
-
301
- @sio.on("client_message") # pyright: ignore [reportOptionalCall]
302
- async def message(sid, payload: MessagePayload):
303
- """Handle a message sent by the User."""
304
- session = WebsocketSession.require(sid)
305
-
306
- task = asyncio.create_task(process_message(session, payload))
307
- session.current_task = task
308
-
309
-
310
- @sio.on("window_message") # pyright: ignore [reportOptionalCall]
311
- async def window_message(sid, data):
312
- """Handle a message send by the host window."""
313
- session = WebsocketSession.require(sid)
314
- init_ws_context(session)
315
-
316
- if config.code.on_window_message:
317
- try:
318
- await config.code.on_window_message(data)
319
- except asyncio.CancelledError:
320
- pass
321
-
322
-
323
- @sio.on("audio_start") # pyright: ignore [reportOptionalCall]
324
- async def audio_start(sid):
325
- """Handle audio init."""
326
- session = WebsocketSession.require(sid)
327
-
328
- context = init_ws_context(session)
329
- if config.features.audio.enabled:
330
- connected = bool(await config.code.on_audio_start())
331
- connection_state = "on" if connected else "off"
332
- await context.emitter.update_audio_connection(connection_state)
333
-
334
-
335
- @sio.on("audio_chunk")
336
- async def audio_chunk(sid, payload: InputAudioChunkPayload):
337
- """Handle an audio chunk sent by the user."""
338
- session = WebsocketSession.require(sid)
339
-
340
- init_ws_context(session)
341
-
342
- if config.features.audio.enabled:
343
- asyncio.create_task(config.code.on_audio_chunk(InputAudioChunk(**payload)))
344
-
345
-
346
- @sio.on("audio_end")
347
- async def audio_end(sid):
348
- """Handle the end of the audio stream."""
349
- session = WebsocketSession.require(sid)
350
- try:
351
- context = init_ws_context(session)
352
- await context.emitter.task_start()
353
-
354
- if not session.has_first_interaction:
355
- session.has_first_interaction = True
356
- asyncio.create_task(context.emitter.init_thread("audio"))
357
-
358
- if config.features.audio.enabled:
359
- await config.code.on_audio_end()
360
-
361
- except asyncio.CancelledError:
362
- pass
363
- except Exception as e:
364
- logger.exception(e)
365
- await ErrorMessage(
366
- author="Error", content=str(e) or e.__class__.__name__
367
- ).send()
368
- finally:
369
- await context.emitter.task_end()
370
-
371
-
372
- @sio.on("chat_settings_change")
373
- async def change_settings(sid, settings: Dict[str, Any]):
374
- """Handle change settings submit from the UI."""
375
- context = init_ws_context(sid)
376
-
377
- for key, value in settings.items():
378
- context.session.chat_settings[key] = value
379
-
380
- if config.code.on_settings_update:
381
- await config.code.on_settings_update(settings)