chainlit 2.0.dev2__py3-none-any.whl → 2.0rc1__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 (67) hide show
  1. chainlit/__init__.py +12 -4
  2. chainlit/action.py +4 -2
  3. chainlit/{auth.py → auth/__init__.py} +20 -34
  4. chainlit/auth/cookie.py +124 -0
  5. chainlit/auth/jwt.py +37 -0
  6. chainlit/cache.py +2 -1
  7. chainlit/callbacks.py +51 -6
  8. chainlit/chat_context.py +2 -2
  9. chainlit/chat_settings.py +3 -1
  10. chainlit/cli/__init__.py +14 -1
  11. chainlit/config.py +32 -15
  12. chainlit/context.py +3 -2
  13. chainlit/copilot/dist/index.js +559 -261
  14. chainlit/data/__init__.py +27 -8
  15. chainlit/data/acl.py +3 -2
  16. chainlit/data/base.py +1 -1
  17. chainlit/data/dynamodb.py +5 -3
  18. chainlit/data/literalai.py +3 -5
  19. chainlit/data/sql_alchemy.py +6 -5
  20. chainlit/data/storage_clients/azure.py +1 -0
  21. chainlit/data/storage_clients/s3.py +1 -0
  22. chainlit/discord/app.py +2 -1
  23. chainlit/element.py +6 -5
  24. chainlit/emitter.py +19 -10
  25. chainlit/frontend/dist/assets/{DailyMotion-D1ipkdPJ.js → DailyMotion-C-_sjrtO.js} +1 -1
  26. chainlit/frontend/dist/assets/{Facebook-d4TLeTik.js → Facebook-bB34P03l.js} +1 -1
  27. chainlit/frontend/dist/assets/{FilePlayer-BcU7tttX.js → FilePlayer-BWgqGrXv.js} +1 -1
  28. chainlit/frontend/dist/assets/{Kaltura-DdaRjZrh.js → Kaltura-OY4P9Ofd.js} +1 -1
  29. chainlit/frontend/dist/assets/{Mixcloud-BaJoMsaU.js → Mixcloud-9CtT8w5Y.js} +1 -1
  30. chainlit/frontend/dist/assets/{Mux-DxPCM5d3.js → Mux-BH9A0qEi.js} +1 -1
  31. chainlit/frontend/dist/assets/{Preview-tUK_Z9pZ.js → Preview-Og00EJ05.js} +1 -1
  32. chainlit/frontend/dist/assets/{SoundCloud-K8-lFZC6.js → SoundCloud-D7resGfn.js} +1 -1
  33. chainlit/frontend/dist/assets/{Streamable-hB-AQ54w.js → Streamable-6f_6bYz1.js} +1 -1
  34. chainlit/frontend/dist/assets/{Twitch-pmuNY0J5.js → Twitch-BZJl3peM.js} +1 -1
  35. chainlit/frontend/dist/assets/{Vidyard-BSUm6trV.js → Vidyard-B7tv4b8_.js} +1 -1
  36. chainlit/frontend/dist/assets/{Vimeo-JIPn71zS.js → Vimeo-F-eA4zQI.js} +1 -1
  37. chainlit/frontend/dist/assets/{Wistia-D75KkqOG.js → Wistia-Dhxhn3IB.js} +1 -1
  38. chainlit/frontend/dist/assets/{YouTube-CPlwqNm_.js → YouTube-aFdJGjI1.js} +1 -1
  39. chainlit/frontend/dist/assets/{index-CuSbXjG5.js → index-Ba33_hdJ.js} +122 -122
  40. chainlit/frontend/dist/assets/{react-plotly-DALmanjC.js → react-plotly-DoUJXMgz.js} +1 -1
  41. chainlit/frontend/dist/index.html +1 -1
  42. chainlit/haystack/callbacks.py +5 -4
  43. chainlit/input_widget.py +6 -4
  44. chainlit/langchain/callbacks.py +56 -47
  45. chainlit/langflow/__init__.py +1 -0
  46. chainlit/llama_index/callbacks.py +7 -7
  47. chainlit/message.py +6 -5
  48. chainlit/mistralai/__init__.py +3 -2
  49. chainlit/oauth_providers.py +70 -3
  50. chainlit/openai/__init__.py +3 -2
  51. chainlit/secret.py +1 -1
  52. chainlit/server.py +232 -156
  53. chainlit/session.py +7 -5
  54. chainlit/slack/app.py +3 -2
  55. chainlit/socket.py +88 -63
  56. chainlit/step.py +11 -10
  57. chainlit/sync.py +2 -1
  58. chainlit/teams/app.py +1 -0
  59. chainlit/translations/nl-NL.json +229 -0
  60. chainlit/types.py +3 -1
  61. chainlit/user.py +2 -1
  62. chainlit/utils.py +3 -2
  63. {chainlit-2.0.dev2.dist-info → chainlit-2.0rc1.dist-info}/METADATA +3 -3
  64. chainlit-2.0rc1.dist-info/RECORD +102 -0
  65. chainlit-2.0.dev2.dist-info/RECORD +0 -99
  66. {chainlit-2.0.dev2.dist-info → chainlit-2.0rc1.dist-info}/WHEEL +0 -0
  67. {chainlit-2.0.dev2.dist-info → chainlit-2.0rc1.dist-info}/entry_points.txt +0 -0
chainlit/socket.py CHANGED
@@ -1,29 +1,29 @@
1
1
  import asyncio
2
2
  import json
3
3
  import time
4
- import uuid
5
- from typing import Any, Dict, Literal
4
+ from typing import Any, Dict, Literal, Optional, Tuple, Union
6
5
  from urllib.parse import unquote
7
6
 
7
+ from starlette.requests import cookie_parser
8
+ from typing_extensions import TypeAlias
9
+
8
10
  from chainlit.action import Action
9
11
  from chainlit.auth import get_current_user, require_login
10
12
  from chainlit.chat_context import chat_context
11
13
  from chainlit.config import config
12
14
  from chainlit.context import init_ws_context
13
15
  from chainlit.data import get_data_layer
14
- from chainlit.element import Element
15
16
  from chainlit.logger import logger
16
17
  from chainlit.message import ErrorMessage, Message
17
18
  from chainlit.server import sio
18
19
  from chainlit.session import WebsocketSession
19
20
  from chainlit.telemetry import trace_event
20
- from chainlit.types import (
21
- InputAudioChunk,
22
- InputAudioChunkPayload,
23
- MessagePayload,
24
- )
21
+ from chainlit.types import InputAudioChunk, InputAudioChunkPayload, MessagePayload
22
+ from chainlit.user import PersistedUser, User
25
23
  from chainlit.user_session import user_sessions
26
24
 
25
+ WSGIEnvironment: TypeAlias = dict[str, Any]
26
+
27
27
 
28
28
  def restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
29
29
  """Restore a session from the sessionId provided by the client."""
@@ -82,45 +82,57 @@ def load_user_env(user_env):
82
82
  return user_env
83
83
 
84
84
 
85
- def build_anon_user_identifier(environ):
86
- scope = environ.get("asgi.scope", {})
87
- client_ip, _ = scope.get("client")
88
- ip = environ.get("HTTP_X_FORWARDED_FOR", client_ip)
85
+ def _get_token_from_auth(auth: dict) -> Optional[str]:
86
+ # Not using cookie auth, return token.
87
+ token = auth.get("token")
88
+ if token:
89
+ return token.split(" ")[1]
89
90
 
90
- try:
91
- headers = scope.get("headers", {})
92
- user_agent = next(
93
- (v.decode("utf-8") for k, v in headers if k.decode("utf-8") == "user-agent")
94
- )
95
- return str(uuid.uuid5(uuid.NAMESPACE_DNS, user_agent + ip))
91
+ return None
96
92
 
97
- except StopIteration:
98
- return str(uuid.uuid5(uuid.NAMESPACE_DNS, ip))
99
93
 
94
+ def _get_token_from_cookie(environ: WSGIEnvironment) -> Optional[str]:
95
+ if cookie_header := environ.get("HTTP_COOKIE", None):
96
+ cookies = cookie_parser(cookie_header)
97
+ return cookies.get("access_token", None)
100
98
 
101
- @sio.on("connect")
102
- async def connect(sid, environ):
103
- if (
104
- not config.code.on_chat_start
105
- and not config.code.on_message
106
- and not config.code.on_audio_chunk
107
- ):
108
- logger.warning(
109
- "You need to configure at least one of on_chat_start, on_message or on_audio_chunk callback"
110
- )
111
- return False
112
- user = None
113
- token = None
114
- login_required = require_login()
115
- try:
116
- # Check if the authentication is required
117
- if login_required:
118
- authorization_header = environ.get("HTTP_AUTHORIZATION")
119
- token = authorization_header.split(" ")[1] if authorization_header else None
120
- user = await get_current_user(token=token)
121
- except Exception:
122
- logger.info("Authentication failed")
123
- return False
99
+ return None
100
+
101
+
102
+ def _get_token(environ: WSGIEnvironment, auth: dict) -> Optional[str]:
103
+ """Take WSGI environ, return access token."""
104
+
105
+ if not config.project.cookie_auth:
106
+ return _get_token_from_auth(auth)
107
+
108
+ return _get_token_from_cookie(environ)
109
+
110
+
111
+ async def _authenticate_connection(
112
+ environ,
113
+ auth,
114
+ ) -> Union[Tuple[Union[User, PersistedUser], str], Tuple[None, None]]:
115
+ if token := _get_token(environ, auth):
116
+ user = await get_current_user(token=token)
117
+ if user:
118
+ return user, token
119
+
120
+ return None, None
121
+
122
+
123
+ @sio.on("connect") # pyright: ignore [reportOptionalCall]
124
+ async def connect(sid, environ, auth):
125
+ user = token = None
126
+
127
+ if require_login():
128
+ try:
129
+ user, token = await _authenticate_connection(environ, auth)
130
+ except Exception as e:
131
+ logger.exception("Exception authenticating connection: %s", e)
132
+
133
+ if not user:
134
+ logger.error("Authentication failed in websocket connect.")
135
+ raise ConnectionRefusedError("authentication failed")
124
136
 
125
137
  # Session scoped function to emit to the client
126
138
  def emit_fn(event, data):
@@ -130,16 +142,16 @@ async def connect(sid, environ):
130
142
  def emit_call_fn(event: Literal["ask", "call_fn"], data, timeout):
131
143
  return sio.call(event, data, timeout=timeout, to=sid)
132
144
 
133
- session_id = environ.get("HTTP_X_CHAINLIT_SESSION_ID")
145
+ session_id = auth.get("sessionId")
134
146
  if restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
135
147
  return True
136
148
 
137
- user_env_string = environ.get("HTTP_USER_ENV")
149
+ user_env_string = auth.get("userEnv")
138
150
  user_env = load_user_env(user_env_string)
139
151
 
140
- client_type = environ.get("HTTP_X_CHAINLIT_CLIENT_TYPE")
152
+ client_type = auth.get("clientType")
141
153
  http_referer = environ.get("HTTP_REFERER")
142
- url_encoded_chat_profile = environ.get("HTTP_X_CHAINLIT_CHAT_PROFILE")
154
+ url_encoded_chat_profile = auth.get("chatProfile")
143
155
  chat_profile = (
144
156
  unquote(url_encoded_chat_profile) if url_encoded_chat_profile else None
145
157
  )
@@ -154,7 +166,7 @@ async def connect(sid, environ):
154
166
  user=user,
155
167
  token=token,
156
168
  chat_profile=chat_profile,
157
- thread_id=environ.get("HTTP_X_CHAINLIT_THREAD_ID"),
169
+ thread_id=auth.get("threadId"),
158
170
  languages=environ.get("HTTP_ACCEPT_LANGUAGE"),
159
171
  http_referer=http_referer,
160
172
  )
@@ -163,17 +175,17 @@ async def connect(sid, environ):
163
175
  return True
164
176
 
165
177
 
166
- @sio.on("connection_successful")
178
+ @sio.on("connection_successful") # pyright: ignore [reportOptionalCall]
167
179
  async def connection_successful(sid):
168
180
  context = init_ws_context(sid)
169
181
 
170
- if context.session.restored:
171
- return
172
-
173
182
  await context.emitter.task_end()
174
183
  await context.emitter.clear("clear_ask")
175
184
  await context.emitter.clear("clear_call_fn")
176
185
 
186
+ if context.session.restored:
187
+ return
188
+
177
189
  if context.session.thread_id_to_resume and config.code.on_chat_resume:
178
190
  thread = await resume_thread(context.session)
179
191
  if thread:
@@ -196,14 +208,14 @@ async def connection_successful(sid):
196
208
  context.session.current_task = task
197
209
 
198
210
 
199
- @sio.on("clear_session")
211
+ @sio.on("clear_session") # pyright: ignore [reportOptionalCall]
200
212
  async def clean_session(sid):
201
213
  session = WebsocketSession.get(sid)
202
214
  if session:
203
215
  session.to_clear = True
204
216
 
205
217
 
206
- @sio.on("disconnect")
218
+ @sio.on("disconnect") # pyright: ignore [reportOptionalCall]
207
219
  async def disconnect(sid):
208
220
  session = WebsocketSession.get(sid)
209
221
 
@@ -237,7 +249,7 @@ async def disconnect(sid):
237
249
  asyncio.ensure_future(clear_on_timeout(sid))
238
250
 
239
251
 
240
- @sio.on("stop")
252
+ @sio.on("stop") # pyright: ignore [reportOptionalCall]
241
253
  async def stop(sid):
242
254
  if session := WebsocketSession.get(sid):
243
255
  trace_event("stop_task")
@@ -274,7 +286,7 @@ async def process_message(session: WebsocketSession, payload: MessagePayload):
274
286
  await context.emitter.task_end()
275
287
 
276
288
 
277
- @sio.on("edit_message")
289
+ @sio.on("edit_message") # pyright: ignore [reportOptionalCall]
278
290
  async def edit_message(sid, payload: MessagePayload):
279
291
  """Handle a message sent by the User."""
280
292
  session = WebsocketSession.require(sid)
@@ -304,7 +316,7 @@ async def edit_message(sid, payload: MessagePayload):
304
316
  await context.emitter.task_end()
305
317
 
306
318
 
307
- @sio.on("client_message")
319
+ @sio.on("client_message") # pyright: ignore [reportOptionalCall]
308
320
  async def message(sid, payload: MessagePayload):
309
321
  """Handle a message sent by the User."""
310
322
  session = WebsocketSession.require(sid)
@@ -313,17 +325,30 @@ async def message(sid, payload: MessagePayload):
313
325
  session.current_task = task
314
326
 
315
327
 
316
- @sio.on("audio_start")
328
+ @sio.on("window_message") # pyright: ignore [reportOptionalCall]
329
+ async def window_message(sid, data):
330
+ """Handle a message send by the host window."""
331
+ session = WebsocketSession.require(sid)
332
+ init_ws_context(session)
333
+
334
+ if config.code.on_window_message:
335
+ try:
336
+ await config.code.on_window_message(data)
337
+ except asyncio.CancelledError:
338
+ pass
339
+
340
+
341
+ @sio.on("audio_start") # pyright: ignore [reportOptionalCall]
317
342
  async def audio_start(sid):
318
343
  """Handle audio init."""
319
344
  session = WebsocketSession.require(sid)
320
345
 
321
346
  context = init_ws_context(session)
322
347
  if config.code.on_audio_start:
323
- connected = bool(await config.code.on_audio_start())
324
- connection_state = "on" if connected else "off"
325
- await context.emitter.update_audio_connection(connection_state)
326
-
348
+ connected = bool(await config.code.on_audio_start())
349
+ connection_state = "on" if connected else "off"
350
+ await context.emitter.update_audio_connection(connection_state)
351
+
327
352
 
328
353
  @sio.on("audio_chunk")
329
354
  async def audio_chunk(sid, payload: InputAudioChunkPayload):
@@ -350,7 +375,7 @@ async def audio_end(sid):
350
375
 
351
376
  if config.code.on_audio_end:
352
377
  await config.code.on_audio_end()
353
-
378
+
354
379
  except asyncio.CancelledError:
355
380
  pass
356
381
  except Exception as e:
chainlit/step.py CHANGED
@@ -7,6 +7,10 @@ from copy import deepcopy
7
7
  from functools import wraps
8
8
  from typing import Callable, Dict, List, Optional, TypedDict, Union
9
9
 
10
+ from literalai import BaseGeneration
11
+ from literalai.helper import utc_now
12
+ from literalai.observability.step import StepType, TrueStepType
13
+
10
14
  from chainlit.config import config
11
15
  from chainlit.context import CL_RUN_NAMES, context, local_steps
12
16
  from chainlit.data import get_data_layer
@@ -14,9 +18,6 @@ from chainlit.element import Element
14
18
  from chainlit.logger import logger
15
19
  from chainlit.telemetry import trace_event
16
20
  from chainlit.types import FeedbackDict
17
- from literalai import BaseGeneration
18
- from literalai.helper import utc_now
19
- from literalai.observability.step import StepType, TrueStepType
20
21
 
21
22
 
22
23
  def check_add_step_in_cot(step: "Step"):
@@ -107,8 +108,8 @@ def step(
107
108
  ) as step:
108
109
  try:
109
110
  step.input = flatten_args_kwargs(func, args, kwargs)
110
- except:
111
- pass
111
+ except Exception as e:
112
+ logger.exception(e)
112
113
  result = await func(*args, **kwargs)
113
114
  try:
114
115
  if result and not step.output:
@@ -134,8 +135,8 @@ def step(
134
135
  ) as step:
135
136
  try:
136
137
  step.input = flatten_args_kwargs(func, args, kwargs)
137
- except:
138
- pass
138
+ except Exception as e:
139
+ logger.exception(e)
139
140
  result = func(*args, **kwargs)
140
141
  try:
141
142
  if result and not step.output:
@@ -317,7 +318,7 @@ class Step:
317
318
  except Exception as e:
318
319
  if self.fail_on_persist_error:
319
320
  raise e
320
- logger.error(f"Failed to persist step update: {str(e)}")
321
+ logger.error(f"Failed to persist step update: {e!s}")
321
322
 
322
323
  tasks = [el.send(for_id=self.id) for el in self.elements]
323
324
  await asyncio.gather(*tasks)
@@ -344,7 +345,7 @@ class Step:
344
345
  except Exception as e:
345
346
  if self.fail_on_persist_error:
346
347
  raise e
347
- logger.error(f"Failed to persist step deletion: {str(e)}")
348
+ logger.error(f"Failed to persist step deletion: {e!s}")
348
349
 
349
350
  await context.emitter.delete_step(step_dict)
350
351
 
@@ -371,7 +372,7 @@ class Step:
371
372
  except Exception as e:
372
373
  if self.fail_on_persist_error:
373
374
  raise e
374
- logger.error(f"Failed to persist step creation: {str(e)}")
375
+ logger.error(f"Failed to persist step creation: {e!s}")
375
376
 
376
377
  tasks = [el.send(for_id=self.id) for el in self.elements]
377
378
  await asyncio.gather(*tasks)
chainlit/sync.py CHANGED
@@ -10,9 +10,10 @@ import asyncio
10
10
  import threading
11
11
 
12
12
  from asyncer import asyncify
13
- from chainlit.context import context_var
14
13
  from syncer import sync
15
14
 
15
+ from chainlit.context import context_var
16
+
16
17
  make_async = asyncify
17
18
 
18
19
  T_Retval = TypeVar("T_Retval")
chainlit/teams/app.py CHANGED
@@ -28,6 +28,7 @@ from botbuilder.schema import (
28
28
  ChannelAccount,
29
29
  HeroCard,
30
30
  )
31
+
31
32
  from chainlit.config import config
32
33
  from chainlit.context import ChainlitContext, HTTPSession, context, context_var
33
34
  from chainlit.data import get_data_layer
@@ -0,0 +1,229 @@
1
+ {
2
+ "components": {
3
+ "atoms": {
4
+ "buttons": {
5
+ "userButton": {
6
+ "menu": {
7
+ "settings": "Instellingen",
8
+ "settingsKey": "I",
9
+ "APIKeys": "API-sleutels",
10
+ "logout": "Uitloggen"
11
+ }
12
+ }
13
+ }
14
+ },
15
+ "molecules": {
16
+ "newChatButton": {
17
+ "newChat": "Nieuwe Chat"
18
+ },
19
+ "tasklist": {
20
+ "TaskList": {
21
+ "title": "\ud83d\uddd2\ufe0f Takenlijst",
22
+ "loading": "Laden...",
23
+ "error": "Er is een fout opgetreden"
24
+ }
25
+ },
26
+ "attachments": {
27
+ "cancelUpload": "Upload annuleren",
28
+ "removeAttachment": "Bijlage verwijderen"
29
+ },
30
+ "newChatDialog": {
31
+ "createNewChat": "Nieuwe chat maken?",
32
+ "clearChat": "Dit zal de huidige berichten wissen en een nieuwe chat starten.",
33
+ "cancel": "Annuleren",
34
+ "confirm": "Bevestigen"
35
+ },
36
+ "settingsModal": {
37
+ "settings": "Instellingen",
38
+ "expandMessages": "Berichten uitbreiden",
39
+ "hideChainOfThought": "Gedachtenketen verbergen",
40
+ "darkMode": "Donkere modus"
41
+ },
42
+ "detailsButton": {
43
+ "using": "Gebruikt",
44
+ "used": "Gebruikt"
45
+ },
46
+ "auth": {
47
+ "authLogin": {
48
+ "title": "Log in om toegang te krijgen tot de app.",
49
+ "form": {
50
+ "email": "E-mailadres",
51
+ "password": "Wachtwoord",
52
+ "noAccount": "Nog geen account?",
53
+ "alreadyHaveAccount": "Al een account?",
54
+ "signup": "Registreren",
55
+ "signin": "Inloggen",
56
+ "or": "OF",
57
+ "continue": "Doorgaan",
58
+ "forgotPassword": "Wachtwoord vergeten?",
59
+ "passwordMustContain": "Uw wachtwoord moet bevatten:",
60
+ "emailRequired": "e-mail is een verplicht veld",
61
+ "passwordRequired": "wachtwoord is een verplicht veld"
62
+ },
63
+ "error": {
64
+ "default": "Inloggen niet mogelijk.",
65
+ "signin": "Probeer in te loggen met een ander account.",
66
+ "oauthsignin": "Probeer in te loggen met een ander account.",
67
+ "redirect_uri_mismatch": "De omleidings-URI komt niet overeen met de oauth-appconfiguratie.",
68
+ "oauthcallbackerror": "Probeer in te loggen met een ander account.",
69
+ "oauthcreateaccount": "Probeer in te loggen met een ander account.",
70
+ "emailcreateaccount": "Probeer in te loggen met een ander account.",
71
+ "callback": "Probeer in te loggen met een ander account.",
72
+ "oauthaccountnotlinked": "Om uw identiteit te bevestigen, log in met hetzelfde account dat u oorspronkelijk gebruikte.",
73
+ "emailsignin": "De e-mail kon niet worden verzonden.",
74
+ "emailverify": "Verifieer uw e-mail, een nieuwe e-mail is verzonden.",
75
+ "credentialssignin": "Inloggen mislukt. Controleer of de verstrekte gegevens correct zijn.",
76
+ "sessionrequired": "Log in om toegang te krijgen tot deze pagina."
77
+ }
78
+ },
79
+ "authVerifyEmail": {
80
+ "almostThere": "Bijna daar! We hebben een e-mail gestuurd naar ",
81
+ "verifyEmailLink": "Klik op de link in die e-mail om uw registratie te voltooien.",
82
+ "didNotReceive": "Kun je de e-mail niet vinden?",
83
+ "resendEmail": "E-mail opnieuw verzenden",
84
+ "goBack": "Ga terug",
85
+ "emailSent": "E-mail succesvol verzonden.",
86
+ "verifyEmail": "Verifieer uw e-mailadres"
87
+ },
88
+ "providerButton": {
89
+ "continue": "Doorgaan met {{provider}}",
90
+ "signup": "Aanmelden met {{provider}}"
91
+ },
92
+ "authResetPassword": {
93
+ "newPasswordRequired": "Nieuw wachtwoord is een verplicht veld",
94
+ "passwordsMustMatch": "Wachtwoorden moeten overeenkomen",
95
+ "confirmPasswordRequired": "Bevestig wachtwoord is een verplicht veld",
96
+ "newPassword": "Nieuw wachtwoord",
97
+ "confirmPassword": "Bevestig wachtwoord",
98
+ "resetPassword": "Wachtwoord resetten"
99
+ },
100
+ "authForgotPassword": {
101
+ "email": "E-mailadres",
102
+ "emailRequired": "e-mail is een verplicht veld",
103
+ "emailSent": "Controleer het e-mailadres {{email}} voor instructies om uw wachtwoord te resetten.",
104
+ "enterEmail": "Voer uw e-mailadres in en we sturen u instructies om uw wachtwoord te resetten.",
105
+ "resendEmail": "E-mail opnieuw verzenden",
106
+ "continue": "Doorgaan",
107
+ "goBack": "Ga terug"
108
+ }
109
+ }
110
+ },
111
+ "organisms": {
112
+ "chat": {
113
+ "history": {
114
+ "index": {
115
+ "showHistory": "Geschiedenis tonen",
116
+ "lastInputs": "Laatste invoer",
117
+ "noInputs": "Zo leeg...",
118
+ "loading": "Laden..."
119
+ }
120
+ },
121
+ "inputBox": {
122
+ "input": {
123
+ "placeholder": "Typ uw bericht hier..."
124
+ },
125
+ "speechButton": {
126
+ "start": "Opname starten",
127
+ "stop": "Opname stoppen"
128
+ },
129
+ "SubmitButton": {
130
+ "sendMessage": "Bericht verzenden",
131
+ "stopTask": "Taak stoppen"
132
+ },
133
+ "UploadButton": {
134
+ "attachFiles": "Bestanden toevoegen"
135
+ },
136
+ "waterMark": {
137
+ "text": "Gebouwd met"
138
+ }
139
+ },
140
+ "Messages": {
141
+ "index": {
142
+ "running": "Bezig",
143
+ "executedSuccessfully": "succesvol uitgevoerd",
144
+ "failed": "mislukt",
145
+ "feedbackUpdated": "Feedback bijgewerkt",
146
+ "updating": "Bijwerken"
147
+ }
148
+ },
149
+ "dropScreen": {
150
+ "dropYourFilesHere": "Sleep uw bestanden hierheen"
151
+ },
152
+ "index": {
153
+ "failedToUpload": "Uploaden mislukt",
154
+ "cancelledUploadOf": "Upload geannuleerd van",
155
+ "couldNotReachServer": "Server niet bereikbaar",
156
+ "continuingChat": "Vervolg van eerdere chat"
157
+ },
158
+ "settings": {
159
+ "settingsPanel": "Instellingenpaneel",
160
+ "reset": "Resetten",
161
+ "cancel": "Annuleren",
162
+ "confirm": "Bevestigen"
163
+ }
164
+ },
165
+ "threadHistory": {
166
+ "sidebar": {
167
+ "filters": {
168
+ "FeedbackSelect": {
169
+ "feedbackAll": "Feedback: Alles",
170
+ "feedbackPositive": "Feedback: Positief",
171
+ "feedbackNegative": "Feedback: Negatief"
172
+ },
173
+ "SearchBar": {
174
+ "search": "Zoeken"
175
+ }
176
+ },
177
+ "DeleteThreadButton": {
178
+ "confirmMessage": "Dit verwijdert de thread evenals de berichten en elementen.",
179
+ "cancel": "Annuleren",
180
+ "confirm": "Bevestigen",
181
+ "deletingChat": "Chat verwijderen",
182
+ "chatDeleted": "Chat verwijderd"
183
+ },
184
+ "index": {
185
+ "pastChats": "Vorige Chats"
186
+ },
187
+ "ThreadList": {
188
+ "empty": "Leeg...",
189
+ "today": "Vandaag",
190
+ "yesterday": "Gisteren",
191
+ "previous7days": "Afgelopen 7 dagen",
192
+ "previous30days": "Afgelopen 30 dagen"
193
+ },
194
+ "TriggerButton": {
195
+ "closeSidebar": "Zijbalk sluiten",
196
+ "openSidebar": "Zijbalk openen"
197
+ }
198
+ },
199
+ "Thread": {
200
+ "backToChat": "Terug naar chat",
201
+ "chatCreatedOn": "Deze chat is aangemaakt op"
202
+ }
203
+ },
204
+ "header": {
205
+ "chat": "Chat",
206
+ "readme": "Readme"
207
+ }
208
+ }
209
+ },
210
+ "hooks": {
211
+ "useLLMProviders": {
212
+ "failedToFetchProviders": "Kan providers niet ophalen:"
213
+ }
214
+ },
215
+ "pages": {
216
+ "Design": {},
217
+ "Env": {
218
+ "savedSuccessfully": "Succesvol opgeslagen",
219
+ "requiredApiKeys": "Vereiste API-sleutels",
220
+ "requiredApiKeysInfo": "Om deze app te gebruiken, zijn de volgende API-sleutels vereist. De sleutels worden opgeslagen in de lokale opslag van uw apparaat."
221
+ },
222
+ "Page": {
223
+ "notPartOfProject": "U maakt geen deel uit van dit project."
224
+ },
225
+ "ResumeButton": {
226
+ "resumeChat": "Chat hervatten"
227
+ }
228
+ }
229
+ }
chainlit/types.py CHANGED
@@ -79,7 +79,7 @@ T = TypeVar("T", covariant=True)
79
79
  class HasFromDict(Protocol[T]):
80
80
  @classmethod
81
81
  def from_dict(cls, obj_dict: Any) -> T:
82
- raise NotImplementedError()
82
+ raise NotImplementedError
83
83
 
84
84
 
85
85
  @dataclass
@@ -168,11 +168,13 @@ class InputAudioChunk:
168
168
  elapsedTime: float
169
169
  data: bytes
170
170
 
171
+
171
172
  class OutputAudioChunk(TypedDict):
172
173
  track: str
173
174
  mimeType: str
174
175
  data: bytes
175
176
 
177
+
176
178
  @dataclass
177
179
  class AskFileResponse:
178
180
  id: str
chainlit/user.py CHANGED
@@ -1,7 +1,8 @@
1
1
  from typing import Dict, Literal, Optional, TypedDict
2
2
 
3
3
  from dataclasses_json import DataClassJsonMixin
4
- from pydantic.dataclasses import Field, dataclass
4
+ from pydantic import Field
5
+ from pydantic.dataclasses import dataclass
5
6
 
6
7
  Provider = Literal[
7
8
  "credentials",
chainlit/utils.py CHANGED
@@ -6,12 +6,13 @@ from asyncio import CancelledError
6
6
  from typing import Callable
7
7
 
8
8
  import click
9
+ from fastapi import FastAPI
10
+ from packaging import version
11
+
9
12
  from chainlit.auth import ensure_jwt_secret
10
13
  from chainlit.context import context
11
14
  from chainlit.logger import logger
12
15
  from chainlit.message import ErrorMessage
13
- from fastapi import FastAPI
14
- from packaging import version
15
16
 
16
17
 
17
18
  def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: chainlit
3
- Version: 2.0.dev2
3
+ Version: 2.0rc1
4
4
  Summary: Build Conversational AI.
5
5
  Home-page: https://chainlit.io/
6
6
  License: Apache-2.0
@@ -24,7 +24,7 @@ Requires-Dist: aiofiles (>=23.1.0,<24.0.0)
24
24
  Requires-Dist: asyncer (>=0.0.7,<0.0.8)
25
25
  Requires-Dist: click (>=8.1.3,<9.0.0)
26
26
  Requires-Dist: dataclasses_json (>=0.6.7,<0.7.0)
27
- Requires-Dist: fastapi (>=0.110.1,<0.113)
27
+ Requires-Dist: fastapi (>=0.115.3,<0.116)
28
28
  Requires-Dist: filetype (>=1.2.0,<2.0.0)
29
29
  Requires-Dist: httpx (>=0.23.0)
30
30
  Requires-Dist: lazify (>=0.4.0,<0.5.0)
@@ -37,7 +37,7 @@ Requires-Dist: pyjwt (>=2.8.0,<3.0.0)
37
37
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
38
38
  Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
39
39
  Requires-Dist: python-socketio (>=5.11.0,<6.0.0)
40
- Requires-Dist: starlette (>=0.37.2,<0.38.0)
40
+ Requires-Dist: starlette (>=0.41.2,<0.42.0)
41
41
  Requires-Dist: syncer (>=2.0.3,<3.0.0)
42
42
  Requires-Dist: tomli (>=2.0.1,<3.0.0)
43
43
  Requires-Dist: uptrace (>=1.22.0,<2.0.0)