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/slack/app.py DELETED
@@ -1,427 +0,0 @@
1
- import asyncio
2
- import os
3
- import re
4
- import uuid
5
- from functools import partial
6
- from typing import Dict, List, Optional, Union
7
-
8
- import httpx
9
- from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler
10
- from slack_bolt.adapter.socket_mode.async_handler import AsyncSocketModeHandler
11
- from slack_bolt.async_app import AsyncApp
12
-
13
- from chainlit.config import config
14
- from chainlit.context import ChainlitContext, HTTPSession, context, context_var
15
- from chainlit.data import get_data_layer
16
- from chainlit.element import Element, ElementDict
17
- from chainlit.emitter import BaseChainlitEmitter
18
- from chainlit.logger import logger
19
- from chainlit.message import Message, StepDict
20
- from chainlit.types import Feedback
21
- from chainlit.user import PersistedUser, User
22
- from chainlit.user_session import user_session
23
-
24
-
25
- class SlackEmitter(BaseChainlitEmitter):
26
- def __init__(
27
- self,
28
- session: HTTPSession,
29
- app: AsyncApp,
30
- channel_id: str,
31
- say,
32
- thread_ts: Optional[str] = None,
33
- ):
34
- super().__init__(session)
35
- self.app = app
36
- self.channel_id = channel_id
37
- self.say = say
38
- self.thread_ts = thread_ts
39
-
40
- async def send_element(self, element_dict: ElementDict):
41
- if element_dict.get("display") != "inline":
42
- return
43
-
44
- persisted_file = self.session.files.get(element_dict.get("chainlitKey") or "")
45
- file: Optional[Union[bytes, str]] = None
46
-
47
- if persisted_file:
48
- file = str(persisted_file["path"])
49
- elif file_url := element_dict.get("url"):
50
- async with httpx.AsyncClient() as client:
51
- response = await client.get(file_url)
52
- if response.status_code == 200:
53
- file = response.content
54
-
55
- if not file:
56
- return
57
-
58
- await self.app.client.files_upload_v2(
59
- channel=self.channel_id,
60
- thread_ts=self.thread_ts,
61
- file=file,
62
- title=element_dict.get("name"),
63
- )
64
-
65
- async def send_step(self, step_dict: StepDict):
66
- step_type = step_dict.get("type")
67
- is_assistant_message = step_type == "assistant_message"
68
- is_empty_output = not step_dict.get("output")
69
-
70
- if is_empty_output or not is_assistant_message:
71
- return
72
-
73
- enable_feedback = get_data_layer()
74
- blocks: List[Dict] = [
75
- {
76
- "type": "section",
77
- "text": {"type": "mrkdwn", "text": step_dict["output"]},
78
- }
79
- ]
80
- if enable_feedback:
81
- current_run = context.current_run
82
- scorable_id = current_run.id if current_run else step_dict.get("id")
83
- blocks.append(
84
- {
85
- "type": "actions",
86
- "elements": [
87
- {
88
- "action_id": "thumbdown",
89
- "type": "button",
90
- "text": {
91
- "type": "plain_text",
92
- "emoji": True,
93
- "text": ":thumbsdown:",
94
- },
95
- "value": scorable_id,
96
- },
97
- {
98
- "action_id": "thumbup",
99
- "type": "button",
100
- "text": {
101
- "type": "plain_text",
102
- "emoji": True,
103
- "text": ":thumbsup:",
104
- },
105
- "value": scorable_id,
106
- },
107
- ],
108
- }
109
- )
110
- await self.say(
111
- text=step_dict["output"], blocks=blocks, thread_ts=self.thread_ts
112
- )
113
-
114
- async def update_step(self, step_dict: StepDict):
115
- is_assistant_message = step_dict["type"] == "assistant_message"
116
-
117
- if not is_assistant_message:
118
- return
119
-
120
- await self.send_step(step_dict)
121
-
122
-
123
- slack_app = AsyncApp(
124
- token=os.environ.get("SLACK_BOT_TOKEN"),
125
- signing_secret=os.environ.get("SLACK_SIGNING_SECRET"),
126
- )
127
-
128
-
129
- async def start_socket_mode():
130
- """
131
- Initializes and starts the Slack app in Socket Mode asynchronously.
132
-
133
- Uses the SLACK_WEBSOCKET_TOKEN from environment variables to authenticate.
134
- """
135
- handler = AsyncSocketModeHandler(slack_app, os.environ.get("SLACK_WEBSOCKET_TOKEN"))
136
- await handler.start_async()
137
-
138
-
139
- def init_slack_context(
140
- session: HTTPSession,
141
- slack_channel_id: str,
142
- event,
143
- say,
144
- thread_ts: Optional[str] = None,
145
- ) -> ChainlitContext:
146
- emitter = SlackEmitter(
147
- session=session,
148
- app=slack_app,
149
- channel_id=slack_channel_id,
150
- say=say,
151
- thread_ts=thread_ts,
152
- )
153
- context = ChainlitContext(session=session, emitter=emitter)
154
- context_var.set(context)
155
- user_session.set("slack_event", event)
156
- user_session.set(
157
- "fetch_slack_message_history",
158
- partial(
159
- fetch_message_history, channel_id=slack_channel_id, thread_ts=thread_ts
160
- ),
161
- )
162
- return context
163
-
164
-
165
- slack_app_handler = AsyncSlackRequestHandler(slack_app)
166
-
167
- users_by_slack_id: Dict[str, Union[User, PersistedUser]] = {}
168
-
169
- USER_PREFIX = "slack_"
170
-
171
-
172
- def clean_content(message: str):
173
- cleaned_text = re.sub(r"<@[\w]+>", "", message).strip()
174
- return cleaned_text
175
-
176
-
177
- async def get_user(slack_user_id: str):
178
- if slack_user_id in users_by_slack_id:
179
- return users_by_slack_id[slack_user_id]
180
-
181
- slack_user = await slack_app.client.users_info(user=slack_user_id)
182
- slack_user_profile = slack_user["user"]["profile"]
183
-
184
- user_identifier = slack_user_profile.get("email") or slack_user_id
185
- user = User(identifier=USER_PREFIX + user_identifier, metadata=slack_user_profile)
186
-
187
- users_by_slack_id[slack_user_id] = user
188
-
189
- if data_layer := get_data_layer():
190
- try:
191
- persisted_user = await data_layer.create_user(user)
192
- if persisted_user:
193
- users_by_slack_id[slack_user_id] = persisted_user
194
- except Exception as e:
195
- logger.error(f"Error creating user: {e}")
196
-
197
- return users_by_slack_id[slack_user_id]
198
-
199
-
200
- async def fetch_message_history(
201
- channel_id: str, thread_ts: Optional[str] = None, limit=30
202
- ):
203
- if not thread_ts:
204
- result = await slack_app.client.conversations_history(
205
- channel=channel_id, limit=limit
206
- )
207
- else:
208
- result = await slack_app.client.conversations_replies(
209
- channel=channel_id, ts=thread_ts, limit=limit
210
- )
211
- if result["ok"]:
212
- messages = result["messages"]
213
- return messages
214
- else:
215
- raise Exception(f"Failed to fetch messages: {result['error']}")
216
-
217
-
218
- async def download_slack_file(url, token):
219
- headers = {"Authorization": f"Bearer {token}"}
220
- async with httpx.AsyncClient() as client:
221
- response = await client.get(url, headers=headers)
222
- if response.status_code == 200:
223
- return response.content
224
- else:
225
- return None
226
-
227
-
228
- async def download_slack_files(session: HTTPSession, files, token):
229
- download_coros = [
230
- download_slack_file(file.get("url_private"), token) for file in files
231
- ]
232
- file_bytes_list = await asyncio.gather(*download_coros)
233
- file_refs = []
234
- for idx, file_bytes in enumerate(file_bytes_list):
235
- if file_bytes:
236
- name = files[idx].get("name")
237
- mime_type = files[idx].get("mimetype")
238
- file_ref = await session.persist_file(
239
- name=name, mime=mime_type, content=file_bytes
240
- )
241
- file_refs.append(file_ref)
242
-
243
- files_dicts = [
244
- session.files[file["id"]] for file in file_refs if file["id"] in session.files
245
- ]
246
-
247
- elements = [
248
- Element.from_dict(
249
- {
250
- "id": file["id"],
251
- "name": file["name"],
252
- "path": str(file["path"]),
253
- "chainlitKey": file["id"],
254
- "display": "inline",
255
- "type": Element.infer_type_from_mime(file["type"]),
256
- }
257
- )
258
- for file in files_dicts
259
- ]
260
-
261
- return elements
262
-
263
-
264
- async def add_reaction_if_enabled(event, emoji: str = "eyes"):
265
- if config.features.slack.reaction_on_message_received:
266
- try:
267
- await slack_app.client.reactions_add(
268
- channel=event["channel"], timestamp=event["ts"], name=emoji
269
- )
270
- except Exception as e:
271
- logger.warning(f"Failed to add reaction: {e}")
272
-
273
-
274
- async def process_slack_message(
275
- event,
276
- say,
277
- thread_id: str,
278
- thread_name: Optional[str] = None,
279
- bind_thread_to_user=False,
280
- thread_ts: Optional[str] = None,
281
- ):
282
- await add_reaction_if_enabled(event)
283
-
284
- user = await get_user(event["user"])
285
-
286
- channel_id = event["channel"]
287
-
288
- text = event.get("text")
289
- slack_files = event.get("files", [])
290
-
291
- session_id = str(uuid.uuid4())
292
- session = HTTPSession(
293
- id=session_id,
294
- thread_id=thread_id,
295
- user=user,
296
- client_type="slack",
297
- )
298
-
299
- ctx = init_slack_context(
300
- session=session,
301
- slack_channel_id=channel_id,
302
- event=event,
303
- say=say,
304
- thread_ts=thread_ts,
305
- )
306
-
307
- file_elements = await download_slack_files(
308
- session, slack_files, slack_app.client.token
309
- )
310
-
311
- if on_chat_start := config.code.on_chat_start:
312
- await on_chat_start()
313
-
314
- msg = Message(
315
- content=clean_content(text),
316
- elements=file_elements,
317
- type="user_message",
318
- author=user.metadata.get("real_name"),
319
- )
320
-
321
- await msg.send()
322
-
323
- if on_message := config.code.on_message:
324
- await on_message(msg)
325
-
326
- if on_chat_end := config.code.on_chat_end:
327
- await on_chat_end()
328
-
329
- if data_layer := get_data_layer():
330
- user_id = None
331
- if isinstance(user, PersistedUser):
332
- user_id = user.id if bind_thread_to_user else None
333
-
334
- try:
335
- await data_layer.update_thread(
336
- thread_id=thread_id,
337
- name=thread_name or msg.content,
338
- metadata=ctx.session.to_persistable(),
339
- user_id=user_id,
340
- )
341
- except Exception as e:
342
- logger.error(f"Error updating thread: {e}")
343
-
344
- await ctx.session.delete()
345
-
346
-
347
- @slack_app.event("app_home_opened")
348
- async def handle_app_home_opened(event, say):
349
- pass
350
-
351
-
352
- @slack_app.event("app_mention")
353
- async def handle_app_mentions(event, say):
354
- thread_ts = event.get("thread_ts", event["ts"])
355
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts))
356
-
357
- await process_slack_message(event, say, thread_id=thread_id, thread_ts=thread_ts)
358
-
359
-
360
- @slack_app.event("message")
361
- async def handle_message(message, say):
362
- thread_ts = message.get("thread_ts", message["ts"])
363
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts))
364
-
365
- await process_slack_message(
366
- event=message,
367
- say=say,
368
- thread_id=thread_id,
369
- bind_thread_to_user=True,
370
- thread_ts=thread_ts,
371
- )
372
-
373
-
374
- @slack_app.block_action("thumbdown")
375
- async def thumb_down(ack, context, body):
376
- await ack()
377
- step_id = body["actions"][0]["value"]
378
- thread_ts = body["message"]["thread_ts"]
379
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts))
380
-
381
- if data_layer := get_data_layer():
382
- feedback = Feedback(forId=step_id, value=0, threadId=thread_id)
383
- await data_layer.upsert_feedback(feedback)
384
-
385
- text = body["message"]["text"]
386
- blocks = body["message"]["blocks"]
387
- updated_blocks = [block for block in blocks if block["type"] != "actions"]
388
- updated_blocks.append(
389
- {
390
- "type": "section",
391
- "text": {"type": "mrkdwn", "text": ":thumbsdown: Feedback received."},
392
- }
393
- )
394
- await context.client.chat_update(
395
- channel=body["channel"]["id"],
396
- ts=body["container"]["message_ts"],
397
- text=text,
398
- blocks=updated_blocks,
399
- )
400
-
401
-
402
- @slack_app.block_action("thumbup")
403
- async def thumb_up(ack, context, body):
404
- await ack()
405
- step_id = body["actions"][0]["value"]
406
- thread_ts = body["message"]["thread_ts"]
407
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts))
408
-
409
- if data_layer := get_data_layer():
410
- feedback = Feedback(forId=step_id, value=1, threadId=thread_id)
411
- await data_layer.upsert_feedback(feedback)
412
-
413
- text = body["message"]["text"]
414
- blocks = body["message"]["blocks"]
415
- updated_blocks = [block for block in blocks if block["type"] != "actions"]
416
- updated_blocks.append(
417
- {
418
- "type": "section",
419
- "text": {"type": "mrkdwn", "text": ":thumbsup: Feedback received."},
420
- }
421
- )
422
- await context.client.chat_update(
423
- channel=body["channel"]["id"],
424
- ts=body["container"]["message_ts"],
425
- text=text,
426
- blocks=updated_blocks,
427
- )