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/discord/app.py DELETED
@@ -1,364 +0,0 @@
1
- import asyncio
2
- import mimetypes
3
- import re
4
- import uuid
5
- from datetime import datetime
6
- from io import BytesIO
7
- from typing import TYPE_CHECKING, Dict, List, Optional, Union
8
-
9
- if TYPE_CHECKING:
10
- from discord.abc import MessageableChannel
11
-
12
- import discord
13
- import filetype
14
- import httpx
15
- from discord.ui import Button, View
16
-
17
- from chainlit.config import config
18
- from chainlit.context import ChainlitContext, HTTPSession, context, context_var
19
- from chainlit.data import get_data_layer
20
- from chainlit.element import Element, ElementDict
21
- from chainlit.emitter import BaseChainlitEmitter
22
- from chainlit.logger import logger
23
- from chainlit.message import Message, StepDict
24
- from chainlit.types import Feedback
25
- from chainlit.user import PersistedUser, User
26
- from chainlit.user_session import user_session
27
-
28
-
29
- class FeedbackView(View):
30
- def __init__(self, step_id: str):
31
- super().__init__(timeout=None)
32
- self.step_id = step_id
33
-
34
- @discord.ui.button(label="👎")
35
- async def thumbs_down(self, interaction: discord.Interaction, button: Button):
36
- if data_layer := get_data_layer():
37
- try:
38
- feedback = Feedback(forId=self.step_id, value=0)
39
- await data_layer.upsert_feedback(feedback)
40
- except Exception as e:
41
- logger.error(f"Error upserting feedback: {e}")
42
- if interaction.message:
43
- await interaction.message.edit(view=None)
44
- await interaction.message.add_reaction("👎")
45
-
46
- @discord.ui.button(label="👍")
47
- async def thumbs_up(self, interaction: discord.Interaction, button: Button):
48
- if data_layer := get_data_layer():
49
- try:
50
- feedback = Feedback(forId=self.step_id, value=1)
51
- await data_layer.upsert_feedback(feedback)
52
- except Exception as e:
53
- logger.error(f"Error upserting feedback: {e}")
54
- if interaction.message:
55
- await interaction.message.edit(view=None)
56
- await interaction.message.add_reaction("👍")
57
-
58
-
59
- class DiscordEmitter(BaseChainlitEmitter):
60
- def __init__(self, session: HTTPSession, channel: "MessageableChannel"):
61
- super().__init__(session)
62
- self.channel = channel
63
-
64
- async def send_element(self, element_dict: ElementDict):
65
- if element_dict.get("display") != "inline":
66
- return
67
-
68
- persisted_file = self.session.files.get(element_dict.get("chainlitKey") or "")
69
- file: Optional[Union[BytesIO, str]] = None
70
- mime: Optional[str] = None
71
-
72
- if persisted_file:
73
- file = str(persisted_file["path"])
74
- mime = element_dict.get("mime")
75
- elif file_url := element_dict.get("url"):
76
- async with httpx.AsyncClient() as client:
77
- response = await client.get(file_url)
78
- if response.status_code == 200:
79
- file = BytesIO(response.content)
80
- mime = filetype.guess_mime(file)
81
-
82
- if not file:
83
- return
84
-
85
- element_name: str = element_dict.get("name", "Untitled")
86
-
87
- if mime:
88
- file_extension = mimetypes.guess_extension(mime)
89
- if file_extension:
90
- element_name += file_extension
91
-
92
- file_obj = discord.File(file, filename=element_name)
93
- await self.channel.send(file=file_obj)
94
-
95
- async def send_step(self, step_dict: StepDict):
96
- if not step_dict["type"] == "assistant_message":
97
- return
98
-
99
- step_type = step_dict.get("type")
100
- is_message = step_type in [
101
- "user_message",
102
- "assistant_message",
103
- ]
104
- is_empty_output = not step_dict.get("output")
105
-
106
- if is_empty_output or not is_message:
107
- return
108
- else:
109
- enable_feedback = get_data_layer()
110
- message = await self.channel.send(step_dict["output"])
111
-
112
- if enable_feedback:
113
- current_run = context.current_run
114
- scorable_id = current_run.id if current_run else step_dict.get("id")
115
- if not scorable_id:
116
- return
117
- view = FeedbackView(scorable_id)
118
- await message.edit(view=view)
119
-
120
- async def update_step(self, step_dict: StepDict):
121
- if not step_dict["type"] == "assistant_message":
122
- return
123
-
124
- await self.send_step(step_dict)
125
-
126
-
127
- intents = discord.Intents.default()
128
- intents.message_content = True
129
-
130
- client = discord.Client(intents=intents)
131
-
132
-
133
- def init_discord_context(
134
- session: HTTPSession,
135
- channel: "MessageableChannel",
136
- message: discord.Message,
137
- ) -> ChainlitContext:
138
- emitter = DiscordEmitter(session=session, channel=channel)
139
- context = ChainlitContext(session=session, emitter=emitter)
140
- context_var.set(context)
141
- user_session.set("discord_message", message)
142
- user_session.set("discord_channel", channel)
143
- return context
144
-
145
-
146
- users_by_discord_id: Dict[int, Union[User, PersistedUser]] = {}
147
-
148
- USER_PREFIX = "discord_"
149
-
150
-
151
- async def get_user(discord_user: Union[discord.User, discord.Member]):
152
- if discord_user.id in users_by_discord_id:
153
- return users_by_discord_id[discord_user.id]
154
-
155
- metadata = {
156
- "name": discord_user.name,
157
- "id": discord_user.id,
158
- }
159
- user = User(identifier=USER_PREFIX + str(discord_user.name), metadata=metadata)
160
-
161
- users_by_discord_id[discord_user.id] = user
162
-
163
- if data_layer := get_data_layer():
164
- try:
165
- persisted_user = await data_layer.create_user(user)
166
- if persisted_user:
167
- users_by_discord_id[discord_user.id] = persisted_user
168
- except Exception as e:
169
- logger.error(f"Error creating user: {e}")
170
-
171
- return users_by_discord_id[discord_user.id]
172
-
173
-
174
- async def download_discord_file(url: str):
175
- async with httpx.AsyncClient() as client:
176
- response = await client.get(url)
177
- if response.status_code == 200:
178
- return response.content
179
- else:
180
- return None
181
-
182
-
183
- async def download_discord_files(
184
- session: HTTPSession, attachments: List[discord.Attachment]
185
- ):
186
- download_coros = [
187
- download_discord_file(attachment.url) for attachment in attachments
188
- ]
189
- file_bytes_list = await asyncio.gather(*download_coros)
190
- file_refs = []
191
- for idx, file_bytes in enumerate(file_bytes_list):
192
- if file_bytes:
193
- name = attachments[idx].filename
194
- mime_type = attachments[idx].content_type or "application/octet-stream"
195
- file_ref = await session.persist_file(
196
- name=name, mime=mime_type, content=file_bytes
197
- )
198
- file_refs.append(file_ref)
199
-
200
- files_dicts = [
201
- session.files[file["id"]] for file in file_refs if file["id"] in session.files
202
- ]
203
-
204
- elements = [
205
- Element.from_dict(
206
- {
207
- "id": file["id"],
208
- "name": file["name"],
209
- "path": str(file["path"]),
210
- "chainlitKey": file["id"],
211
- "display": "inline",
212
- "type": Element.infer_type_from_mime(file["type"]),
213
- }
214
- )
215
- for file in files_dicts
216
- ]
217
-
218
- return elements
219
-
220
-
221
- def clean_content(message: discord.Message):
222
- if not client.user:
223
- return message.content
224
-
225
- # Regex to find mentions of the bot
226
- bot_mention = f"<@!?{client.user.id}>"
227
- # Replace the bot's mention with nothing
228
- return re.sub(bot_mention, "", message.content).strip()
229
-
230
-
231
- async def process_discord_message(
232
- message: discord.Message,
233
- thread_id: str,
234
- thread_name: str,
235
- channel: "MessageableChannel",
236
- bind_thread_to_user=False,
237
- ):
238
- user = await get_user(message.author)
239
-
240
- text = clean_content(message)
241
- discord_files = message.attachments
242
-
243
- session_id = str(uuid.uuid4())
244
- session = HTTPSession(
245
- id=session_id,
246
- thread_id=thread_id,
247
- user=user,
248
- client_type="discord",
249
- )
250
-
251
- ctx = init_discord_context(
252
- session=session,
253
- channel=channel,
254
- message=message,
255
- )
256
-
257
- file_elements = await download_discord_files(session, discord_files)
258
-
259
- if on_chat_start := config.code.on_chat_start:
260
- await on_chat_start()
261
-
262
- msg = Message(
263
- content=text,
264
- elements=file_elements,
265
- type="user_message",
266
- author=user.metadata.get("name"),
267
- )
268
-
269
- await msg.send()
270
-
271
- if on_message := config.code.on_message:
272
- async with channel.typing():
273
- await on_message(msg)
274
-
275
- if on_chat_end := config.code.on_chat_end:
276
- await on_chat_end()
277
-
278
- if data_layer := get_data_layer():
279
- user_id = None
280
- if isinstance(user, PersistedUser):
281
- user_id = user.id if bind_thread_to_user else None
282
-
283
- try:
284
- await data_layer.update_thread(
285
- thread_id=thread_id,
286
- name=thread_name,
287
- metadata=ctx.session.to_persistable(),
288
- user_id=user_id,
289
- )
290
- except Exception as e:
291
- logger.error(f"Error updating thread: {e}")
292
-
293
- await ctx.session.delete()
294
-
295
-
296
- @client.event
297
- async def on_ready():
298
- logger.info(f"Logged in as {client.user}")
299
-
300
-
301
- @client.event
302
- async def on_message(message: discord.Message):
303
- if not client.user or message.author == client.user:
304
- return
305
-
306
- is_dm = isinstance(message.channel, discord.DMChannel)
307
- if not client.user.mentioned_in(message) and not is_dm:
308
- return
309
-
310
- thread_name: str = ""
311
- thread_id: str = ""
312
- bind_thread_to_user = False
313
- channel = message.channel
314
-
315
- if isinstance(message.channel, discord.Thread):
316
- thread_name = f"{message.channel.name}"
317
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, str(channel.id)))
318
- elif isinstance(message.channel, discord.ForumChannel):
319
- thread_name = f"{message.channel.name}"
320
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, str(channel.id)))
321
- elif isinstance(message.channel, discord.DMChannel):
322
- thread_id = str(
323
- uuid.uuid5(
324
- uuid.NAMESPACE_DNS,
325
- str(channel.id) + datetime.today().strftime("%Y-%m-%d"),
326
- )
327
- )
328
- thread_name = (
329
- f"{message.author} Discord DM {datetime.today().strftime('%Y-%m-%d')}"
330
- )
331
- bind_thread_to_user = True
332
- elif isinstance(message.channel, discord.GroupChannel):
333
- thread_id = str(
334
- uuid.uuid5(
335
- uuid.NAMESPACE_DNS,
336
- str(channel.id) + datetime.today().strftime("%Y-%m-%d"),
337
- )
338
- )
339
- thread_name = f"{message.channel.name}"
340
- elif isinstance(message.channel, discord.TextChannel):
341
- # Discord limits thread names to 100 characters and does not create
342
- # threads from empty messages.
343
- thread_id = str(
344
- uuid.uuid5(
345
- uuid.NAMESPACE_DNS,
346
- str(channel.id) + datetime.today().strftime("%Y-%m-%d"),
347
- )
348
- )
349
- discord_thread_name = clean_content(message)[:100] or "Untitled"
350
- channel = await message.channel.create_thread(
351
- name=discord_thread_name, message=message
352
- )
353
- thread_name = f"{channel.name}"
354
- else:
355
- logger.warning(f"Unsupported channel type: {message.channel.type}")
356
- return
357
-
358
- await process_discord_message(
359
- message=message,
360
- thread_id=thread_id,
361
- thread_name=thread_name,
362
- channel=channel,
363
- bind_thread_to_user=bind_thread_to_user,
364
- )