chainlit 2.0.0__py3-none-any.whl → 2.0.dev0__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 +57 -56
- chainlit/action.py +10 -12
- chainlit/{auth/__init__.py → auth.py} +34 -26
- chainlit/cache.py +6 -4
- chainlit/callbacks.py +7 -52
- chainlit/chat_context.py +2 -2
- chainlit/chat_settings.py +1 -3
- chainlit/cli/__init__.py +2 -15
- chainlit/config.py +70 -41
- chainlit/context.py +9 -8
- chainlit/copilot/dist/index.js +874 -8533
- chainlit/data/__init__.py +8 -96
- chainlit/data/acl.py +2 -3
- chainlit/data/base.py +15 -1
- chainlit/data/dynamodb.py +4 -7
- chainlit/data/literalai.py +6 -4
- chainlit/data/sql_alchemy.py +9 -10
- chainlit/data/{storage_clients/azure.py → storage_clients.py} +33 -2
- chainlit/discord/__init__.py +4 -4
- chainlit/discord/app.py +1 -2
- chainlit/element.py +9 -41
- chainlit/emitter.py +21 -17
- chainlit/frontend/dist/assets/DailyMotion-b4b7af47.js +1 -0
- chainlit/frontend/dist/assets/Facebook-572972a0.js +1 -0
- chainlit/frontend/dist/assets/FilePlayer-85c69ca8.js +1 -0
- chainlit/frontend/dist/assets/Kaltura-dfc24672.js +1 -0
- chainlit/frontend/dist/assets/Mixcloud-705011f4.js +1 -0
- chainlit/frontend/dist/assets/Mux-4201a9e6.js +1 -0
- chainlit/frontend/dist/assets/Preview-23ba40a6.js +1 -0
- chainlit/frontend/dist/assets/SoundCloud-1a582d51.js +1 -0
- chainlit/frontend/dist/assets/Streamable-5017c4ba.js +1 -0
- chainlit/frontend/dist/assets/Twitch-bb2de2fa.js +1 -0
- chainlit/frontend/dist/assets/Vidyard-54e269b1.js +1 -0
- chainlit/frontend/dist/assets/Vimeo-d92c37dd.js +1 -0
- chainlit/frontend/dist/assets/Wistia-25a1363b.js +1 -0
- chainlit/frontend/dist/assets/YouTube-616e8cb7.js +1 -0
- chainlit/frontend/dist/assets/index-aaf974a9.css +1 -0
- chainlit/frontend/dist/assets/index-f5df2072.js +1027 -0
- chainlit/frontend/dist/assets/{react-plotly-BpxUS-ab.js → react-plotly-f0315f86.js} +94 -94
- chainlit/frontend/dist/index.html +3 -2
- chainlit/haystack/callbacks.py +4 -5
- chainlit/input_widget.py +4 -6
- chainlit/langchain/callbacks.py +47 -56
- chainlit/langflow/__init__.py +0 -1
- chainlit/llama_index/callbacks.py +7 -7
- chainlit/message.py +10 -8
- chainlit/mistralai/__init__.py +2 -3
- chainlit/oauth_providers.py +12 -113
- chainlit/openai/__init__.py +7 -6
- chainlit/secret.py +1 -1
- chainlit/server.py +181 -491
- chainlit/session.py +5 -7
- chainlit/slack/__init__.py +3 -3
- chainlit/slack/app.py +2 -3
- chainlit/socket.py +103 -78
- chainlit/step.py +29 -21
- chainlit/sync.py +1 -2
- chainlit/teams/__init__.py +3 -3
- chainlit/teams/app.py +0 -1
- chainlit/types.py +4 -20
- chainlit/user.py +1 -2
- chainlit/utils.py +2 -3
- chainlit/version.py +2 -3
- {chainlit-2.0.0.dist-info → chainlit-2.0.dev0.dist-info}/METADATA +39 -27
- chainlit-2.0.dev0.dist-info/RECORD +96 -0
- chainlit/auth/cookie.py +0 -123
- chainlit/auth/jwt.py +0 -37
- chainlit/data/chainlit_data_layer.py +0 -584
- chainlit/data/storage_clients/__init__.py +0 -0
- chainlit/data/storage_clients/azure_blob.py +0 -80
- chainlit/data/storage_clients/base.py +0 -22
- chainlit/data/storage_clients/gcs.py +0 -78
- chainlit/data/storage_clients/s3.py +0 -49
- chainlit/frontend/dist/assets/DailyMotion-DgRzV5GZ.js +0 -1
- chainlit/frontend/dist/assets/Dataframe-DVgwSMU2.js +0 -22
- chainlit/frontend/dist/assets/Facebook-C0vx6HWv.js +0 -1
- chainlit/frontend/dist/assets/FilePlayer-CdhzeHPP.js +0 -1
- chainlit/frontend/dist/assets/Kaltura-5iVmeUct.js +0 -1
- chainlit/frontend/dist/assets/Mixcloud-C2zi77Ex.js +0 -1
- chainlit/frontend/dist/assets/Mux-Vkebogdf.js +0 -1
- chainlit/frontend/dist/assets/Preview-DwY_sEIl.js +0 -1
- chainlit/frontend/dist/assets/SoundCloud-CREBXAWo.js +0 -1
- chainlit/frontend/dist/assets/Streamable-B5Lu25uy.js +0 -1
- chainlit/frontend/dist/assets/Twitch-y9iKCcM1.js +0 -1
- chainlit/frontend/dist/assets/Vidyard-ClYvcuEu.js +0 -1
- chainlit/frontend/dist/assets/Vimeo-D6HvM2jt.js +0 -1
- chainlit/frontend/dist/assets/Wistia-Cu4zZ2Ci.js +0 -1
- chainlit/frontend/dist/assets/YouTube-D10tR6CJ.js +0 -1
- chainlit/frontend/dist/assets/index-CI4qFOt5.js +0 -8665
- chainlit/frontend/dist/assets/index-CrrqM0nZ.css +0 -1
- chainlit/translations/nl-NL.json +0 -229
- chainlit-2.0.0.dist-info/RECORD +0 -106
- /chainlit/copilot/dist/assets/{logo_dark-IkGJ_IwC.svg → logo_dark-2a3cf740.svg} +0 -0
- /chainlit/copilot/dist/assets/{logo_light-Bb_IPh6r.svg → logo_light-b078e7bc.svg} +0 -0
- /chainlit/frontend/dist/assets/{logo_dark-IkGJ_IwC.svg → logo_dark-2a3cf740.svg} +0 -0
- /chainlit/frontend/dist/assets/{logo_light-Bb_IPh6r.svg → logo_light-b078e7bc.svg} +0 -0
- {chainlit-2.0.0.dist-info → chainlit-2.0.dev0.dist-info}/WHEEL +0 -0
- {chainlit-2.0.0.dist-info → chainlit-2.0.dev0.dist-info}/entry_points.txt +0 -0
chainlit/session.py
CHANGED
|
@@ -6,7 +6,6 @@ import uuid
|
|
|
6
6
|
from typing import TYPE_CHECKING, Any, Callable, Deque, Dict, Literal, Optional, Union
|
|
7
7
|
|
|
8
8
|
import aiofiles
|
|
9
|
-
|
|
10
9
|
from chainlit.logger import logger
|
|
11
10
|
from chainlit.types import FileReference
|
|
12
11
|
|
|
@@ -18,9 +17,9 @@ ClientType = Literal["webapp", "copilot", "teams", "slack", "discord"]
|
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class JSONEncoderIgnoreNonSerializable(json.JSONEncoder):
|
|
21
|
-
def default(self,
|
|
20
|
+
def default(self, obj):
|
|
22
21
|
try:
|
|
23
|
-
return super().default(
|
|
22
|
+
return super(JSONEncoderIgnoreNonSerializable, self).default(obj)
|
|
24
23
|
except TypeError:
|
|
25
24
|
return None
|
|
26
25
|
|
|
@@ -113,10 +112,9 @@ class BaseSession:
|
|
|
113
112
|
|
|
114
113
|
if path:
|
|
115
114
|
# Copy the file from the given path
|
|
116
|
-
async with (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
):
|
|
115
|
+
async with aiofiles.open(path, "rb") as src, aiofiles.open(
|
|
116
|
+
file_path, "wb"
|
|
117
|
+
) as dst:
|
|
120
118
|
await dst.write(await src.read())
|
|
121
119
|
elif content:
|
|
122
120
|
# Write the provided content to the file
|
chainlit/slack/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
try:
|
|
2
|
+
import slack_bolt
|
|
3
|
+
except ModuleNotFoundError:
|
|
4
4
|
raise ValueError(
|
|
5
5
|
"The slack_bolt package is required to integrate Chainlit with a Slack app. Run `pip install slack_bolt --upgrade`"
|
|
6
6
|
)
|
chainlit/slack/app.py
CHANGED
|
@@ -7,9 +7,6 @@ from functools import partial
|
|
|
7
7
|
from typing import Dict, List, Optional, Union
|
|
8
8
|
|
|
9
9
|
import httpx
|
|
10
|
-
from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler
|
|
11
|
-
from slack_bolt.async_app import AsyncApp
|
|
12
|
-
|
|
13
10
|
from chainlit.config import config
|
|
14
11
|
from chainlit.context import ChainlitContext, HTTPSession, context, context_var
|
|
15
12
|
from chainlit.data import get_data_layer
|
|
@@ -21,6 +18,8 @@ from chainlit.telemetry import trace
|
|
|
21
18
|
from chainlit.types import Feedback
|
|
22
19
|
from chainlit.user import PersistedUser, User
|
|
23
20
|
from chainlit.user_session import user_session
|
|
21
|
+
from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler
|
|
22
|
+
from slack_bolt.async_app import AsyncApp
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
class SlackEmitter(BaseChainlitEmitter):
|
chainlit/socket.py
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
3
|
import time
|
|
4
|
-
|
|
4
|
+
import uuid
|
|
5
|
+
from typing import Any, Dict, Literal
|
|
5
6
|
from urllib.parse import unquote
|
|
6
7
|
|
|
7
|
-
from
|
|
8
|
-
from typing_extensions import TypeAlias
|
|
9
|
-
|
|
8
|
+
from chainlit.action import Action
|
|
10
9
|
from chainlit.auth import get_current_user, require_login
|
|
11
10
|
from chainlit.chat_context import chat_context
|
|
12
11
|
from chainlit.config import config
|
|
13
12
|
from chainlit.context import init_ws_context
|
|
14
13
|
from chainlit.data import get_data_layer
|
|
14
|
+
from chainlit.element import Element
|
|
15
15
|
from chainlit.logger import logger
|
|
16
16
|
from chainlit.message import ErrorMessage, Message
|
|
17
17
|
from chainlit.server import sio
|
|
18
18
|
from chainlit.session import WebsocketSession
|
|
19
19
|
from chainlit.telemetry import trace_event
|
|
20
|
-
from chainlit.types import
|
|
21
|
-
|
|
20
|
+
from chainlit.types import (
|
|
21
|
+
InputAudioChunk,
|
|
22
|
+
InputAudioChunkPayload,
|
|
23
|
+
MessagePayload,
|
|
24
|
+
)
|
|
22
25
|
from chainlit.user_session import user_sessions
|
|
23
26
|
|
|
24
|
-
WSGIEnvironment: TypeAlias = dict[str, Any]
|
|
25
|
-
|
|
26
27
|
|
|
27
28
|
def restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
|
|
28
29
|
"""Restore a session from the sessionId provided by the client."""
|
|
@@ -81,44 +82,45 @@ def load_user_env(user_env):
|
|
|
81
82
|
return user_env
|
|
82
83
|
|
|
83
84
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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)
|
|
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)
|
|
118
89
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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))
|
|
96
|
+
|
|
97
|
+
except StopIteration:
|
|
98
|
+
return str(uuid.uuid5(uuid.NAMESPACE_DNS, ip))
|
|
99
|
+
|
|
100
|
+
|
|
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
|
|
122
124
|
|
|
123
125
|
# Session scoped function to emit to the client
|
|
124
126
|
def emit_fn(event, data):
|
|
@@ -128,16 +130,16 @@ async def connect(sid, environ, auth):
|
|
|
128
130
|
def emit_call_fn(event: Literal["ask", "call_fn"], data, timeout):
|
|
129
131
|
return sio.call(event, data, timeout=timeout, to=sid)
|
|
130
132
|
|
|
131
|
-
session_id =
|
|
133
|
+
session_id = environ.get("HTTP_X_CHAINLIT_SESSION_ID")
|
|
132
134
|
if restore_existing_session(sid, session_id, emit_fn, emit_call_fn):
|
|
133
135
|
return True
|
|
134
136
|
|
|
135
|
-
user_env_string =
|
|
137
|
+
user_env_string = environ.get("HTTP_USER_ENV")
|
|
136
138
|
user_env = load_user_env(user_env_string)
|
|
137
139
|
|
|
138
|
-
client_type =
|
|
140
|
+
client_type = environ.get("HTTP_X_CHAINLIT_CLIENT_TYPE")
|
|
139
141
|
http_referer = environ.get("HTTP_REFERER")
|
|
140
|
-
url_encoded_chat_profile =
|
|
142
|
+
url_encoded_chat_profile = environ.get("HTTP_X_CHAINLIT_CHAT_PROFILE")
|
|
141
143
|
chat_profile = (
|
|
142
144
|
unquote(url_encoded_chat_profile) if url_encoded_chat_profile else None
|
|
143
145
|
)
|
|
@@ -152,7 +154,7 @@ async def connect(sid, environ, auth):
|
|
|
152
154
|
user=user,
|
|
153
155
|
token=token,
|
|
154
156
|
chat_profile=chat_profile,
|
|
155
|
-
thread_id=
|
|
157
|
+
thread_id=environ.get("HTTP_X_CHAINLIT_THREAD_ID"),
|
|
156
158
|
languages=environ.get("HTTP_ACCEPT_LANGUAGE"),
|
|
157
159
|
http_referer=http_referer,
|
|
158
160
|
)
|
|
@@ -161,17 +163,17 @@ async def connect(sid, environ, auth):
|
|
|
161
163
|
return True
|
|
162
164
|
|
|
163
165
|
|
|
164
|
-
@sio.on("connection_successful")
|
|
166
|
+
@sio.on("connection_successful")
|
|
165
167
|
async def connection_successful(sid):
|
|
166
168
|
context = init_ws_context(sid)
|
|
167
169
|
|
|
170
|
+
if context.session.restored:
|
|
171
|
+
return
|
|
172
|
+
|
|
168
173
|
await context.emitter.task_end()
|
|
169
174
|
await context.emitter.clear("clear_ask")
|
|
170
175
|
await context.emitter.clear("clear_call_fn")
|
|
171
176
|
|
|
172
|
-
if context.session.restored:
|
|
173
|
-
return
|
|
174
|
-
|
|
175
177
|
if context.session.thread_id_to_resume and config.code.on_chat_resume:
|
|
176
178
|
thread = await resume_thread(context.session)
|
|
177
179
|
if thread:
|
|
@@ -194,14 +196,14 @@ async def connection_successful(sid):
|
|
|
194
196
|
context.session.current_task = task
|
|
195
197
|
|
|
196
198
|
|
|
197
|
-
@sio.on("clear_session")
|
|
199
|
+
@sio.on("clear_session")
|
|
198
200
|
async def clean_session(sid):
|
|
199
201
|
session = WebsocketSession.get(sid)
|
|
200
202
|
if session:
|
|
201
203
|
session.to_clear = True
|
|
202
204
|
|
|
203
205
|
|
|
204
|
-
@sio.on("disconnect")
|
|
206
|
+
@sio.on("disconnect")
|
|
205
207
|
async def disconnect(sid):
|
|
206
208
|
session = WebsocketSession.get(sid)
|
|
207
209
|
|
|
@@ -235,7 +237,7 @@ async def disconnect(sid):
|
|
|
235
237
|
asyncio.ensure_future(clear_on_timeout(sid))
|
|
236
238
|
|
|
237
239
|
|
|
238
|
-
@sio.on("stop")
|
|
240
|
+
@sio.on("stop")
|
|
239
241
|
async def stop(sid):
|
|
240
242
|
if session := WebsocketSession.get(sid):
|
|
241
243
|
trace_event("stop_task")
|
|
@@ -272,7 +274,7 @@ async def process_message(session: WebsocketSession, payload: MessagePayload):
|
|
|
272
274
|
await context.emitter.task_end()
|
|
273
275
|
|
|
274
276
|
|
|
275
|
-
@sio.on("edit_message")
|
|
277
|
+
@sio.on("edit_message")
|
|
276
278
|
async def edit_message(sid, payload: MessagePayload):
|
|
277
279
|
"""Handle a message sent by the User."""
|
|
278
280
|
session = WebsocketSession.require(sid)
|
|
@@ -302,7 +304,7 @@ async def edit_message(sid, payload: MessagePayload):
|
|
|
302
304
|
await context.emitter.task_end()
|
|
303
305
|
|
|
304
306
|
|
|
305
|
-
@sio.on("client_message")
|
|
307
|
+
@sio.on("client_message")
|
|
306
308
|
async def message(sid, payload: MessagePayload):
|
|
307
309
|
"""Handle a message sent by the User."""
|
|
308
310
|
session = WebsocketSession.require(sid)
|
|
@@ -311,30 +313,17 @@ async def message(sid, payload: MessagePayload):
|
|
|
311
313
|
session.current_task = task
|
|
312
314
|
|
|
313
315
|
|
|
314
|
-
@sio.on("
|
|
315
|
-
async def window_message(sid, data):
|
|
316
|
-
"""Handle a message send by the host window."""
|
|
317
|
-
session = WebsocketSession.require(sid)
|
|
318
|
-
init_ws_context(session)
|
|
319
|
-
|
|
320
|
-
if config.code.on_window_message:
|
|
321
|
-
try:
|
|
322
|
-
await config.code.on_window_message(data)
|
|
323
|
-
except asyncio.CancelledError:
|
|
324
|
-
pass
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
@sio.on("audio_start") # pyright: ignore [reportOptionalCall]
|
|
316
|
+
@sio.on("audio_start")
|
|
328
317
|
async def audio_start(sid):
|
|
329
318
|
"""Handle audio init."""
|
|
330
319
|
session = WebsocketSession.require(sid)
|
|
331
320
|
|
|
332
321
|
context = init_ws_context(session)
|
|
333
322
|
if config.code.on_audio_start:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
+
|
|
338
327
|
|
|
339
328
|
@sio.on("audio_chunk")
|
|
340
329
|
async def audio_chunk(sid, payload: InputAudioChunkPayload):
|
|
@@ -361,7 +350,7 @@ async def audio_end(sid):
|
|
|
361
350
|
|
|
362
351
|
if config.code.on_audio_end:
|
|
363
352
|
await config.code.on_audio_end()
|
|
364
|
-
|
|
353
|
+
|
|
365
354
|
except asyncio.CancelledError:
|
|
366
355
|
pass
|
|
367
356
|
except Exception as e:
|
|
@@ -373,6 +362,42 @@ async def audio_end(sid):
|
|
|
373
362
|
await context.emitter.task_end()
|
|
374
363
|
|
|
375
364
|
|
|
365
|
+
async def process_action(action: Action):
|
|
366
|
+
callback = config.code.action_callbacks.get(action.name)
|
|
367
|
+
if callback:
|
|
368
|
+
res = await callback(action)
|
|
369
|
+
return res
|
|
370
|
+
else:
|
|
371
|
+
logger.warning("No callback found for action %s", action.name)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
@sio.on("action_call")
|
|
375
|
+
async def call_action(sid, action):
|
|
376
|
+
"""Handle an action call from the UI."""
|
|
377
|
+
context = init_ws_context(sid)
|
|
378
|
+
|
|
379
|
+
action = Action(**action)
|
|
380
|
+
|
|
381
|
+
try:
|
|
382
|
+
if not context.session.has_first_interaction:
|
|
383
|
+
context.session.has_first_interaction = True
|
|
384
|
+
asyncio.create_task(context.emitter.init_thread(action.name))
|
|
385
|
+
res = await process_action(action)
|
|
386
|
+
await context.emitter.send_action_response(
|
|
387
|
+
id=action.id, status=True, response=res if isinstance(res, str) else None
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
except asyncio.CancelledError:
|
|
391
|
+
await context.emitter.send_action_response(
|
|
392
|
+
id=action.id, status=False, response="Action interrupted by the user"
|
|
393
|
+
)
|
|
394
|
+
except Exception as e:
|
|
395
|
+
logger.exception(e)
|
|
396
|
+
await context.emitter.send_action_response(
|
|
397
|
+
id=action.id, status=False, response="An error occurred"
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
|
|
376
401
|
@sio.on("chat_settings_change")
|
|
377
402
|
async def change_settings(sid, settings: Dict[str, Any]):
|
|
378
403
|
"""Handle change settings submit from the UI."""
|
chainlit/step.py
CHANGED
|
@@ -7,10 +7,6 @@ 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
|
-
|
|
14
10
|
from chainlit.config import config
|
|
15
11
|
from chainlit.context import CL_RUN_NAMES, context, local_steps
|
|
16
12
|
from chainlit.data import get_data_layer
|
|
@@ -18,6 +14,9 @@ from chainlit.element import Element
|
|
|
18
14
|
from chainlit.logger import logger
|
|
19
15
|
from chainlit.telemetry import trace_event
|
|
20
16
|
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
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
def check_add_step_in_cot(step: "Step"):
|
|
@@ -62,10 +61,11 @@ class StepDict(TypedDict, total=False):
|
|
|
62
61
|
generation: Optional[Dict]
|
|
63
62
|
showInput: Optional[Union[bool, str]]
|
|
64
63
|
language: Optional[str]
|
|
64
|
+
indent: Optional[int]
|
|
65
65
|
feedback: Optional[FeedbackDict]
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def flatten_args_kwargs(func, args, kwargs):
|
|
68
|
+
def flatten_args_kwargs(func, *args, **kwargs):
|
|
69
69
|
signature = inspect.signature(func)
|
|
70
70
|
bound_arguments = signature.bind(*args, **kwargs)
|
|
71
71
|
bound_arguments.apply_defaults()
|
|
@@ -107,8 +107,8 @@ def step(
|
|
|
107
107
|
) as step:
|
|
108
108
|
try:
|
|
109
109
|
step.input = flatten_args_kwargs(func, args, kwargs)
|
|
110
|
-
except
|
|
111
|
-
|
|
110
|
+
except:
|
|
111
|
+
pass
|
|
112
112
|
result = await func(*args, **kwargs)
|
|
113
113
|
try:
|
|
114
114
|
if result and not step.output:
|
|
@@ -134,13 +134,13 @@ def step(
|
|
|
134
134
|
) as step:
|
|
135
135
|
try:
|
|
136
136
|
step.input = flatten_args_kwargs(func, args, kwargs)
|
|
137
|
-
except
|
|
138
|
-
|
|
137
|
+
except:
|
|
138
|
+
pass
|
|
139
139
|
result = func(*args, **kwargs)
|
|
140
140
|
try:
|
|
141
141
|
if result and not step.output:
|
|
142
142
|
step.output = result
|
|
143
|
-
except
|
|
143
|
+
except:
|
|
144
144
|
step.is_error = True
|
|
145
145
|
step.output = str(e)
|
|
146
146
|
return result
|
|
@@ -317,7 +317,7 @@ class Step:
|
|
|
317
317
|
except Exception as e:
|
|
318
318
|
if self.fail_on_persist_error:
|
|
319
319
|
raise e
|
|
320
|
-
logger.error(f"Failed to persist step update: {e
|
|
320
|
+
logger.error(f"Failed to persist step update: {str(e)}")
|
|
321
321
|
|
|
322
322
|
tasks = [el.send(for_id=self.id) for el in self.elements]
|
|
323
323
|
await asyncio.gather(*tasks)
|
|
@@ -344,7 +344,7 @@ class Step:
|
|
|
344
344
|
except Exception as e:
|
|
345
345
|
if self.fail_on_persist_error:
|
|
346
346
|
raise e
|
|
347
|
-
logger.error(f"Failed to persist step deletion: {e
|
|
347
|
+
logger.error(f"Failed to persist step deletion: {str(e)}")
|
|
348
348
|
|
|
349
349
|
await context.emitter.delete_step(step_dict)
|
|
350
350
|
|
|
@@ -371,7 +371,7 @@ class Step:
|
|
|
371
371
|
except Exception as e:
|
|
372
372
|
if self.fail_on_persist_error:
|
|
373
373
|
raise e
|
|
374
|
-
logger.error(f"Failed to persist step creation: {e
|
|
374
|
+
logger.error(f"Failed to persist step creation: {str(e)}")
|
|
375
375
|
|
|
376
376
|
tasks = [el.send(for_id=self.id) for el in self.elements]
|
|
377
377
|
await asyncio.gather(*tasks)
|
|
@@ -434,6 +434,7 @@ class Step:
|
|
|
434
434
|
if not self.parent_id:
|
|
435
435
|
if parent_step:
|
|
436
436
|
self.parent_id = parent_step.id
|
|
437
|
+
context.active_steps.append(self)
|
|
437
438
|
local_steps.set(previous_steps + [self])
|
|
438
439
|
await self.send()
|
|
439
440
|
return self
|
|
@@ -445,10 +446,13 @@ class Step:
|
|
|
445
446
|
self.output = str(exc_val)
|
|
446
447
|
self.is_error = True
|
|
447
448
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
449
|
+
if self in context.active_steps:
|
|
450
|
+
context.active_steps.remove(self)
|
|
451
|
+
|
|
452
|
+
local_active_steps = local_steps.get()
|
|
453
|
+
if local_active_steps and self in local_active_steps:
|
|
454
|
+
local_active_steps.remove(self)
|
|
455
|
+
local_steps.set(local_active_steps)
|
|
452
456
|
|
|
453
457
|
await self.update()
|
|
454
458
|
|
|
@@ -461,6 +465,7 @@ class Step:
|
|
|
461
465
|
if not self.parent_id:
|
|
462
466
|
if parent_step:
|
|
463
467
|
self.parent_id = parent_step.id
|
|
468
|
+
context.active_steps.append(self)
|
|
464
469
|
local_steps.set(previous_steps + [self])
|
|
465
470
|
|
|
466
471
|
asyncio.create_task(self.send())
|
|
@@ -473,9 +478,12 @@ class Step:
|
|
|
473
478
|
self.output = str(exc_val)
|
|
474
479
|
self.is_error = True
|
|
475
480
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
481
|
+
if self in context.active_steps:
|
|
482
|
+
context.active_steps.remove(self)
|
|
483
|
+
|
|
484
|
+
local_active_steps = local_steps.get()
|
|
485
|
+
if local_active_steps and self in local_active_steps:
|
|
486
|
+
local_active_steps.remove(self)
|
|
487
|
+
local_steps.set(local_active_steps)
|
|
480
488
|
|
|
481
489
|
asyncio.create_task(self.update())
|
chainlit/sync.py
CHANGED
chainlit/teams/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
try:
|
|
2
|
+
import botbuilder
|
|
3
|
+
except ModuleNotFoundError:
|
|
4
4
|
raise ValueError(
|
|
5
5
|
"The botbuilder-core package is required to integrate Chainlit with a Slack app. Run `pip install botbuilder-core --upgrade`"
|
|
6
6
|
)
|
chainlit/teams/app.py
CHANGED
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,13 +168,11 @@ class InputAudioChunk:
|
|
|
168
168
|
elapsedTime: float
|
|
169
169
|
data: bytes
|
|
170
170
|
|
|
171
|
-
|
|
172
171
|
class OutputAudioChunk(TypedDict):
|
|
173
172
|
track: str
|
|
174
173
|
mimeType: str
|
|
175
174
|
data: bytes
|
|
176
175
|
|
|
177
|
-
|
|
178
176
|
@dataclass
|
|
179
177
|
class AskFileResponse:
|
|
180
178
|
id: str
|
|
@@ -186,16 +184,12 @@ class AskFileResponse:
|
|
|
186
184
|
|
|
187
185
|
class AskActionResponse(TypedDict):
|
|
188
186
|
name: str
|
|
189
|
-
|
|
187
|
+
value: str
|
|
190
188
|
label: str
|
|
191
|
-
|
|
189
|
+
description: str
|
|
192
190
|
forId: str
|
|
193
191
|
id: str
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
class UpdateThreadRequest(BaseModel):
|
|
197
|
-
threadId: str
|
|
198
|
-
name: str
|
|
192
|
+
collapsed: bool
|
|
199
193
|
|
|
200
194
|
|
|
201
195
|
class DeleteThreadRequest(BaseModel):
|
|
@@ -211,16 +205,6 @@ class GetThreadsRequest(BaseModel):
|
|
|
211
205
|
filter: ThreadFilter
|
|
212
206
|
|
|
213
207
|
|
|
214
|
-
class CallActionRequest(BaseModel):
|
|
215
|
-
action: Dict
|
|
216
|
-
sessionId: str
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
class ElementRequest(BaseModel):
|
|
220
|
-
element: Dict
|
|
221
|
-
sessionId: str
|
|
222
|
-
|
|
223
|
-
|
|
224
208
|
class Theme(str, Enum):
|
|
225
209
|
light = "light"
|
|
226
210
|
dark = "dark"
|
chainlit/user.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from typing import Dict, Literal, Optional, TypedDict
|
|
2
2
|
|
|
3
3
|
from dataclasses_json import DataClassJsonMixin
|
|
4
|
-
from pydantic import Field
|
|
5
|
-
from pydantic.dataclasses import dataclass
|
|
4
|
+
from pydantic.dataclasses import Field, dataclass
|
|
6
5
|
|
|
7
6
|
Provider = Literal[
|
|
8
7
|
"credentials",
|
chainlit/utils.py
CHANGED
|
@@ -6,13 +6,12 @@ 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
|
-
|
|
12
9
|
from chainlit.auth import ensure_jwt_secret
|
|
13
10
|
from chainlit.context import context
|
|
14
11
|
from chainlit.logger import logger
|
|
15
12
|
from chainlit.message import ErrorMessage
|
|
13
|
+
from fastapi import FastAPI
|
|
14
|
+
from packaging import version
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
|
chainlit/version.py
CHANGED
|
@@ -3,6 +3,5 @@ from importlib import metadata
|
|
|
3
3
|
try:
|
|
4
4
|
__version__ = metadata.version(__package__)
|
|
5
5
|
except metadata.PackageNotFoundError:
|
|
6
|
-
# Case where package metadata is not available
|
|
7
|
-
|
|
8
|
-
__version__ = "0.3.1"
|
|
6
|
+
# Case where package metadata is not available.
|
|
7
|
+
__version__ = ""
|