chainlit 1.1.306__py3-none-any.whl → 1.1.400__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 (44) hide show
  1. chainlit/__init__.py +16 -3
  2. chainlit/config.py +4 -4
  3. chainlit/context.py +9 -0
  4. chainlit/copilot/dist/index.js +132 -129
  5. chainlit/data/__init__.py +8 -12
  6. chainlit/data/sql_alchemy.py +0 -4
  7. chainlit/discord/app.py +42 -20
  8. chainlit/emitter.py +5 -9
  9. chainlit/frontend/dist/assets/{DailyMotion-4ebdfef1.js → DailyMotion-e2c926d0.js} +1 -1
  10. chainlit/frontend/dist/assets/{Facebook-40982be3.js → Facebook-88f80aba.js} +1 -1
  11. chainlit/frontend/dist/assets/{FilePlayer-5b3a4ad0.js → FilePlayer-febd1b0d.js} +1 -1
  12. chainlit/frontend/dist/assets/{Kaltura-6c5cb748.js → Kaltura-606fe0bd.js} +1 -1
  13. chainlit/frontend/dist/assets/{Mixcloud-7a304880.js → Mixcloud-b3db090a.js} +1 -1
  14. chainlit/frontend/dist/assets/{Mux-1bd85c69.js → Mux-ca847a7d.js} +1 -1
  15. chainlit/frontend/dist/assets/{Preview-e91eb05e.js → Preview-7a3747b5.js} +1 -1
  16. chainlit/frontend/dist/assets/{SoundCloud-2f2116b2.js → SoundCloud-0da01fb1.js} +1 -1
  17. chainlit/frontend/dist/assets/{Streamable-b92c07ce.js → Streamable-4a6ab048.js} +1 -1
  18. chainlit/frontend/dist/assets/{Twitch-58a2eb9a.js → Twitch-3e260619.js} +1 -1
  19. chainlit/frontend/dist/assets/{Vidyard-ad5bffa0.js → Vidyard-73692980.js} +1 -1
  20. chainlit/frontend/dist/assets/{Vimeo-8fb43e9c.js → Vimeo-6627c7a8.js} +1 -1
  21. chainlit/frontend/dist/assets/{Wistia-d03e6237.js → Wistia-27df9c66.js} +1 -1
  22. chainlit/frontend/dist/assets/{YouTube-6b7d1dae.js → YouTube-a11d419d.js} +1 -1
  23. chainlit/frontend/dist/assets/{index-4f01eb67.js → index-d66d1800.js} +104 -101
  24. chainlit/frontend/dist/assets/{react-plotly-ef3ac5f0.js → react-plotly-012ed517.js} +1 -1
  25. chainlit/frontend/dist/index.html +1 -1
  26. chainlit/haystack/callbacks.py +1 -3
  27. chainlit/langchain/callbacks.py +37 -16
  28. chainlit/llama_index/callbacks.py +0 -6
  29. chainlit/message.py +0 -16
  30. chainlit/mistralai/__init__.py +2 -5
  31. chainlit/openai/__init__.py +0 -2
  32. chainlit/server.py +2 -2
  33. chainlit/session.py +2 -12
  34. chainlit/slack/app.py +36 -27
  35. chainlit/socket.py +10 -10
  36. chainlit/step.py +37 -32
  37. chainlit/teams/app.py +23 -18
  38. chainlit/translations/zh-CN.json +229 -0
  39. chainlit/user_session.py +0 -3
  40. {chainlit-1.1.306.dist-info → chainlit-1.1.400.dist-info}/METADATA +1 -1
  41. chainlit-1.1.400.dist-info/RECORD +82 -0
  42. chainlit-1.1.306.dist-info/RECORD +0 -81
  43. {chainlit-1.1.306.dist-info → chainlit-1.1.400.dist-info}/WHEEL +0 -0
  44. {chainlit-1.1.306.dist-info → chainlit-1.1.400.dist-info}/entry_points.txt +0 -0
@@ -21,7 +21,7 @@
21
21
  <script>
22
22
  const global = globalThis;
23
23
  </script>
24
- <script type="module" crossorigin src="/assets/index-4f01eb67.js"></script>
24
+ <script type="module" crossorigin src="/assets/index-d66d1800.js"></script>
25
25
  <link rel="stylesheet" href="/assets/index-aaf974a9.css">
26
26
  </head>
27
27
  <body>
@@ -68,9 +68,7 @@ class HaystackAgentCallbackHandler:
68
68
  self.last_tokens: List[str] = []
69
69
  self.answer_reached = False
70
70
 
71
- root_message = context.session.root_message
72
- parent_id = root_message.id if root_message else None
73
- run_step = Step(name=self.agent_name, type="run", parent_id=parent_id)
71
+ run_step = Step(name=self.agent_name, type="run")
74
72
  run_step.start = utc_now()
75
73
  run_step.input = kwargs
76
74
 
@@ -1,11 +1,8 @@
1
1
  import json
2
2
  import time
3
- from typing import Any, Dict, List, Optional, TypedDict, Union
3
+ from typing import Any, Dict, List, Optional, Tuple, TypedDict, Union
4
4
  from uuid import UUID
5
5
 
6
- from chainlit.context import context_var
7
- from chainlit.message import Message
8
- from chainlit.step import Step
9
6
  from langchain.callbacks.tracers.base import BaseTracer
10
7
  from langchain.callbacks.tracers.schemas import Run
11
8
  from langchain.schema import BaseMessage
@@ -15,6 +12,10 @@ from literalai import ChatGeneration, CompletionGeneration, GenerationMessage
15
12
  from literalai.helper import utc_now
16
13
  from literalai.step import TrueStepType
17
14
 
15
+ from chainlit.context import context_var
16
+ from chainlit.message import Message
17
+ from chainlit.step import Step
18
+
18
19
  DEFAULT_ANSWER_PREFIX_TOKENS = ["Final", "Answer", ":"]
19
20
 
20
21
 
@@ -229,7 +230,24 @@ class GenerationHelper:
229
230
  return provider, model, tools, settings
230
231
 
231
232
 
232
- DEFAULT_TO_IGNORE = ["Runnable", "<lambda>"]
233
+ def process_content(content: Any) -> Tuple[Dict, Optional[str]]:
234
+ if content is None:
235
+ return {}, None
236
+ if isinstance(content, dict):
237
+ return content, "json"
238
+ elif isinstance(content, str):
239
+ return {"content": content}, "text"
240
+ else:
241
+ return {"content": str(content)}, "text"
242
+
243
+
244
+ DEFAULT_TO_IGNORE = [
245
+ "RunnableSequence",
246
+ "RunnableParallel",
247
+ "RunnableAssign",
248
+ "RunnableLambda",
249
+ "<lambda>",
250
+ ]
233
251
  DEFAULT_TO_KEEP = ["retriever", "llm", "agent", "chain", "tool"]
234
252
 
235
253
 
@@ -267,8 +285,6 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
267
285
 
268
286
  if self.context.current_step:
269
287
  self.root_parent_id = self.context.current_step.id
270
- elif self.context.session.root_message:
271
- self.root_parent_id = self.context.session.root_message.id
272
288
  else:
273
289
  self.root_parent_id = None
274
290
 
@@ -431,9 +447,6 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
431
447
  self.ignored_runs.add(str(run.id))
432
448
  return ignore, parent_id
433
449
 
434
- def _is_annotable(self, run: Run):
435
- return run.run_type in ["retriever", "llm"]
436
-
437
450
  def _start_trace(self, run: Run) -> None:
438
451
  super()._start_trace(run)
439
452
  context_var.set(self.context)
@@ -463,17 +476,18 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
463
476
  elif run.run_type == "embedding":
464
477
  step_type = "embedding"
465
478
 
466
- disable_feedback = not self._is_annotable(run)
467
-
468
479
  step = Step(
469
480
  id=str(run.id),
470
481
  name=run.name,
471
482
  type=step_type,
472
483
  parent_id=parent_id,
473
- disable_feedback=disable_feedback,
474
484
  )
475
485
  step.start = utc_now()
476
- step.input = run.inputs
486
+ step.input, language = process_content(run.inputs)
487
+ if language is not None:
488
+ if step.metadata is None:
489
+ step.metadata = {}
490
+ step.metadata["language"] = language
477
491
 
478
492
  self.steps[str(run.id)] = step
479
493
 
@@ -497,6 +511,9 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
497
511
  generations = (run.outputs or {}).get("generations", [])
498
512
  generation = generations[0][0]
499
513
  variables = self.generation_inputs.get(str(run.parent_run_id), {})
514
+ variables = {
515
+ k: process_content(v) for k, v in variables.items() if v is not None
516
+ }
500
517
  if message := generation.get("message"):
501
518
  chat_start = self.chat_generations[str(run.id)]
502
519
  duration = time.time() - chat_start["start"]
@@ -527,7 +544,11 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
527
544
  "prompt_id"
528
545
  ]
529
546
  if custom_variables := m.additional_kwargs.get("variables"):
530
- current_step.generation.variables = custom_variables
547
+ current_step.generation.variables = {
548
+ k: process_content(v)
549
+ for k, v in custom_variables.items()
550
+ if v is not None
551
+ }
531
552
  break
532
553
 
533
554
  current_step.language = "json"
@@ -571,7 +592,7 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
571
592
  output = outputs.get(output_keys[0], outputs)
572
593
 
573
594
  if current_step:
574
- current_step.output = output
595
+ current_step.output, _ = output
575
596
  current_step.end = utc_now()
576
597
  self._run_sync(current_step.update())
577
598
 
@@ -41,11 +41,6 @@ class LlamaIndexCallbackHandler(TokenCountingHandler):
41
41
  return event_parent_id
42
42
  elif context_var.get().current_step:
43
43
  return context_var.get().current_step.id
44
- elif context_var.get().session.root_message:
45
- root_message = context_var.get().session.root_message
46
- if root_message:
47
- return root_message.id
48
- return None
49
44
  else:
50
45
  return None
51
46
 
@@ -73,7 +68,6 @@ class LlamaIndexCallbackHandler(TokenCountingHandler):
73
68
  type=step_type,
74
69
  parent_id=self._get_parent_id(parent_id),
75
70
  id=event_id,
76
- disable_feedback=True,
77
71
  )
78
72
 
79
73
  self.steps[event_id] = step
chainlit/message.py CHANGED
@@ -32,7 +32,6 @@ class MessageBase(ABC):
32
32
  author: str
33
33
  content: str = ""
34
34
  type: MessageStepType = "assistant_message"
35
- disable_feedback = False
36
35
  streaming = False
37
36
  created_at: Union[str, None] = None
38
37
  fail_on_persist_error: bool = False
@@ -67,7 +66,6 @@ class MessageBase(ABC):
67
66
  content=_dict["output"],
68
67
  author=_dict.get("name", config.ui.name),
69
68
  type=type, # type: ignore
70
- disable_feedback=_dict.get("disableFeedback", False),
71
69
  language=_dict.get("language"),
72
70
  )
73
71
 
@@ -87,7 +85,6 @@ class MessageBase(ABC):
87
85
  "createdAt": self.created_at,
88
86
  "language": self.language,
89
87
  "streaming": self.streaming,
90
- "disableFeedback": self.disable_feedback,
91
88
  "isError": self.is_error,
92
89
  "waitForAnswer": self.wait_for_answer,
93
90
  "indent": self.indent,
@@ -208,7 +205,6 @@ class Message(MessageBase):
208
205
  language (str, optional): Language of the code is the content is code. See https://react-code-blocks-rajinwonderland.vercel.app/?path=/story/codeblock--supported-languages for a list of supported languages.
209
206
  actions (List[Action], optional): A list of actions to send with the message.
210
207
  elements (List[ElementBased], optional): A list of elements to send with the message.
211
- disable_feedback (bool, optional): Hide the feedback buttons for this specific message
212
208
  """
213
209
 
214
210
  def __init__(
@@ -218,7 +214,6 @@ class Message(MessageBase):
218
214
  language: Optional[str] = None,
219
215
  actions: Optional[List[Action]] = None,
220
216
  elements: Optional[List[ElementBased]] = None,
221
- disable_feedback: bool = False,
222
217
  type: MessageStepType = "assistant_message",
223
218
  metadata: Optional[Dict] = None,
224
219
  tags: Optional[List[str]] = None,
@@ -257,7 +252,6 @@ class Message(MessageBase):
257
252
  self.type = type
258
253
  self.actions = actions if actions is not None else []
259
254
  self.elements = elements if elements is not None else []
260
- self.disable_feedback = disable_feedback
261
255
 
262
256
  super().__post_init__()
263
257
 
@@ -269,8 +263,6 @@ class Message(MessageBase):
269
263
  trace_event("send_message")
270
264
  await super().send()
271
265
 
272
- context.session.root_message = self
273
-
274
266
  # Create tasks for all actions and elements
275
267
  tasks = [action.send(for_id=self.id) for action in self.actions]
276
268
  tasks.extend(element.send(for_id=self.id) for element in self.elements)
@@ -355,7 +347,6 @@ class AskUserMessage(AskMessageBase):
355
347
  Args:
356
348
  content (str): The content of the prompt.
357
349
  author (str, optional): The author of the message, this will be used in the UI. Defaults to the assistant name (see config).
358
- disable_feedback (bool, optional): Hide the feedback buttons for this specific message
359
350
  timeout (int, optional): The number of seconds to wait for an answer before raising a TimeoutError.
360
351
  raise_on_timeout (bool, optional): Whether to raise a socketio TimeoutError if the user does not answer in time.
361
352
  """
@@ -365,7 +356,6 @@ class AskUserMessage(AskMessageBase):
365
356
  content: str,
366
357
  author: str = config.ui.name,
367
358
  type: MessageStepType = "assistant_message",
368
- disable_feedback: bool = True,
369
359
  timeout: int = 60,
370
360
  raise_on_timeout: bool = False,
371
361
  ):
@@ -373,7 +363,6 @@ class AskUserMessage(AskMessageBase):
373
363
  self.author = author
374
364
  self.timeout = timeout
375
365
  self.type = type
376
- self.disable_feedback = disable_feedback
377
366
  self.raise_on_timeout = raise_on_timeout
378
367
 
379
368
  super().__post_init__()
@@ -420,7 +409,6 @@ class AskFileMessage(AskMessageBase):
420
409
  max_size_mb (int, optional): Maximum size per file in MB. Maximum value is 100.
421
410
  max_files (int, optional): Maximum number of files to upload. Maximum value is 10.
422
411
  author (str, optional): The author of the message, this will be used in the UI. Defaults to the assistant name (see config).
423
- disable_feedback (bool, optional): Hide the feedback buttons for this specific message
424
412
  timeout (int, optional): The number of seconds to wait for an answer before raising a TimeoutError.
425
413
  raise_on_timeout (bool, optional): Whether to raise a socketio TimeoutError if the user does not answer in time.
426
414
  """
@@ -433,7 +421,6 @@ class AskFileMessage(AskMessageBase):
433
421
  max_files=1,
434
422
  author=config.ui.name,
435
423
  type: MessageStepType = "assistant_message",
436
- disable_feedback: bool = True,
437
424
  timeout=90,
438
425
  raise_on_timeout=False,
439
426
  ):
@@ -445,7 +432,6 @@ class AskFileMessage(AskMessageBase):
445
432
  self.author = author
446
433
  self.timeout = timeout
447
434
  self.raise_on_timeout = raise_on_timeout
448
- self.disable_feedback = disable_feedback
449
435
 
450
436
  super().__post_init__()
451
437
 
@@ -509,14 +495,12 @@ class AskActionMessage(AskMessageBase):
509
495
  content: str,
510
496
  actions: List[Action],
511
497
  author=config.ui.name,
512
- disable_feedback=True,
513
498
  timeout=90,
514
499
  raise_on_timeout=False,
515
500
  ):
516
501
  self.content = content
517
502
  self.actions = actions
518
503
  self.author = author
519
- self.disable_feedback = disable_feedback
520
504
  self.timeout = timeout
521
505
  self.raise_on_timeout = raise_on_timeout
522
506
 
@@ -1,12 +1,11 @@
1
1
  import asyncio
2
2
  from typing import Union
3
3
 
4
- from literalai import ChatGeneration, CompletionGeneration
5
- from literalai.helper import timestamp_utc
6
-
7
4
  from chainlit.context import get_context
8
5
  from chainlit.step import Step
9
6
  from chainlit.utils import check_module_version
7
+ from literalai import ChatGeneration, CompletionGeneration
8
+ from literalai.helper import timestamp_utc
10
9
 
11
10
 
12
11
  def instrument_mistralai():
@@ -20,8 +19,6 @@ def instrument_mistralai():
20
19
  parent_id = None
21
20
  if context.current_step:
22
21
  parent_id = context.current_step.id
23
- elif context.session.root_message:
24
- parent_id = context.session.root_message.id
25
22
 
26
23
  step = Step(
27
24
  name=generation.model if generation.model else generation.provider,
@@ -24,8 +24,6 @@ def instrument_openai():
24
24
  parent_id = None
25
25
  if context.current_step:
26
26
  parent_id = context.current_step.id
27
- elif context.session.root_message:
28
- parent_id = context.session.root_message.id
29
27
 
30
28
  step = Step(
31
29
  name=generation.model if generation.model else generation.provider,
chainlit/server.py CHANGED
@@ -266,7 +266,7 @@ def get_html_template():
266
266
  )
267
267
  url = config.ui.github or default_url
268
268
  meta_image_url = config.ui.custom_meta_image_url or default_meta_image_url
269
- favicon_path = ROOT_PATH + "/favicon" if ROOT_PATH else "/favicon"
269
+ favicon_path = "/favicon"
270
270
 
271
271
  tags = f"""<title>{config.ui.name}</title>
272
272
  <link rel="icon" href="{favicon_path}" />
@@ -332,7 +332,7 @@ def get_user_facing_url(url: URL):
332
332
  if config_url.path.endswith("/"):
333
333
  config_url = config_url.replace(path=config_url.path[:-1])
334
334
 
335
- return config_url.__str__()
335
+ return config_url.__str__() + url.path
336
336
 
337
337
 
338
338
  @router.get("/auth/config")
chainlit/session.py CHANGED
@@ -35,17 +35,16 @@ class JSONEncoderIgnoreNonSerializable(json.JSONEncoder):
35
35
  return None
36
36
 
37
37
 
38
-
39
38
  def clean_metadata(metadata: Dict, max_size: int = 1048576):
40
39
  cleaned_metadata = json.loads(
41
40
  json.dumps(metadata, cls=JSONEncoderIgnoreNonSerializable, ensure_ascii=False)
42
41
  )
43
42
 
44
- metadata_size = len(json.dumps(cleaned_metadata).encode('utf-8'))
43
+ metadata_size = len(json.dumps(cleaned_metadata).encode("utf-8"))
45
44
  if metadata_size > max_size:
46
45
  # Redact the metadata if it exceeds the maximum size
47
46
  cleaned_metadata = {
48
- 'message': f'Metadata size exceeds the limit of {max_size} bytes. Redacted.'
47
+ "message": f"Metadata size exceeds the limit of {max_size} bytes. Redacted."
49
48
  }
50
49
 
51
50
  return cleaned_metadata
@@ -71,8 +70,6 @@ class BaseSession:
71
70
  token: Optional[str],
72
71
  # User specific environment variables. Empty if no user environment variables are required.
73
72
  user_env: Optional[Dict[str, str]],
74
- # Last message at the root of the chat
75
- root_message: Optional["Message"] = None,
76
73
  # Chat profile selected before the session was created
77
74
  chat_profile: Optional[str] = None,
78
75
  # Origin of the request
@@ -84,7 +81,6 @@ class BaseSession:
84
81
  self.user = user
85
82
  self.client_type = client_type
86
83
  self.token = token
87
- self.root_message = root_message
88
84
  self.has_first_interaction = False
89
85
  self.user_env = user_env or {}
90
86
  self.chat_profile = chat_profile
@@ -178,8 +174,6 @@ class HTTPSession(BaseSession):
178
174
  # Logged-in user token
179
175
  token: Optional[str] = None,
180
176
  user_env: Optional[Dict[str, str]] = None,
181
- # Last message at the root of the chat
182
- root_message: Optional["Message"] = None,
183
177
  # Origin of the request
184
178
  http_referer: Optional[str] = None,
185
179
  ):
@@ -190,7 +184,6 @@ class HTTPSession(BaseSession):
190
184
  token=token,
191
185
  client_type=client_type,
192
186
  user_env=user_env,
193
- root_message=root_message,
194
187
  http_referer=http_referer,
195
188
  )
196
189
 
@@ -233,8 +226,6 @@ class WebsocketSession(BaseSession):
233
226
  user: Optional[Union["User", "PersistedUser"]] = None,
234
227
  # Logged-in user token
235
228
  token: Optional[str] = None,
236
- # Last message at the root of the chat
237
- root_message: Optional["Message"] = None,
238
229
  # Chat profile selected before the session was created
239
230
  chat_profile: Optional[str] = None,
240
231
  # Languages of the user's browser
@@ -249,7 +240,6 @@ class WebsocketSession(BaseSession):
249
240
  token=token,
250
241
  user_env=user_env,
251
242
  client_type=client_type,
252
- root_message=root_message,
253
243
  chat_profile=chat_profile,
254
244
  http_referer=http_referer,
255
245
  )
chainlit/slack/app.py CHANGED
@@ -2,12 +2,13 @@ import asyncio
2
2
  import os
3
3
  import re
4
4
  import uuid
5
+ from datetime import datetime
5
6
  from functools import partial
6
7
  from typing import Dict, List, Optional, Union
7
8
 
8
9
  import httpx
9
10
  from chainlit.config import config
10
- from chainlit.context import ChainlitContext, HTTPSession, context_var
11
+ from chainlit.context import ChainlitContext, HTTPSession, context, context_var
11
12
  from chainlit.data import get_data_layer
12
13
  from chainlit.element import Element, ElementDict
13
14
  from chainlit.emitter import BaseChainlitEmitter
@@ -28,18 +29,16 @@ class SlackEmitter(BaseChainlitEmitter):
28
29
  app: AsyncApp,
29
30
  channel_id: str,
30
31
  say,
31
- enabled=False,
32
32
  thread_ts: Optional[str] = None,
33
33
  ):
34
34
  super().__init__(session)
35
35
  self.app = app
36
36
  self.channel_id = channel_id
37
37
  self.say = say
38
- self.enabled = enabled
39
38
  self.thread_ts = thread_ts
40
39
 
41
40
  async def send_element(self, element_dict: ElementDict):
42
- if not self.enabled or element_dict.get("display") != "inline":
41
+ if element_dict.get("display") != "inline":
43
42
  return
44
43
 
45
44
  persisted_file = self.session.files.get(element_dict.get("chainlitKey") or "")
@@ -64,21 +63,14 @@ class SlackEmitter(BaseChainlitEmitter):
64
63
  )
65
64
 
66
65
  async def send_step(self, step_dict: StepDict):
67
- if not self.enabled:
68
- return
69
-
70
66
  step_type = step_dict.get("type")
71
- is_message = step_type in [
72
- "user_message",
73
- "assistant_message",
74
- ]
75
- is_chain_of_thought = bool(step_dict.get("parentId"))
67
+ is_assistant_message = step_type == "assistant_message"
76
68
  is_empty_output = not step_dict.get("output")
77
69
 
78
- if is_chain_of_thought or is_empty_output or not is_message:
70
+ if is_empty_output or not is_assistant_message:
79
71
  return
80
72
 
81
- enable_feedback = not step_dict.get("disableFeedback") and get_data_layer()
73
+ enable_feedback = get_data_layer()
82
74
  blocks: List[Dict] = [
83
75
  {
84
76
  "type": "section",
@@ -86,6 +78,8 @@ class SlackEmitter(BaseChainlitEmitter):
86
78
  }
87
79
  ]
88
80
  if enable_feedback:
81
+ current_run = context.current_run
82
+ scorable_id = current_run.id if current_run else step_dict.get("id")
89
83
  blocks.append(
90
84
  {
91
85
  "type": "actions",
@@ -98,7 +92,7 @@ class SlackEmitter(BaseChainlitEmitter):
98
92
  "emoji": True,
99
93
  "text": ":thumbsdown:",
100
94
  },
101
- "value": step_dict.get("id"),
95
+ "value": scorable_id,
102
96
  },
103
97
  {
104
98
  "action_id": "thumbup",
@@ -108,7 +102,7 @@ class SlackEmitter(BaseChainlitEmitter):
108
102
  "emoji": True,
109
103
  "text": ":thumbsup:",
110
104
  },
111
- "value": step_dict.get("id"),
105
+ "value": scorable_id,
112
106
  },
113
107
  ],
114
108
  }
@@ -118,7 +112,9 @@ class SlackEmitter(BaseChainlitEmitter):
118
112
  )
119
113
 
120
114
  async def update_step(self, step_dict: StepDict):
121
- if not self.enabled:
115
+ is_assistant_message = step_dict["type"] == "assistant_message"
116
+
117
+ if not is_assistant_message:
122
118
  return
123
119
 
124
120
  await self.send_step(step_dict)
@@ -247,6 +243,7 @@ async def download_slack_files(session: HTTPSession, files, token):
247
243
  async def process_slack_message(
248
244
  event,
249
245
  say,
246
+ thread_id: str,
250
247
  thread_name: Optional[str] = None,
251
248
  bind_thread_to_user=False,
252
249
  thread_ts: Optional[str] = None,
@@ -254,7 +251,6 @@ async def process_slack_message(
254
251
  user = await get_user(event["user"])
255
252
 
256
253
  channel_id = event["channel"]
257
- thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts or channel_id))
258
254
 
259
255
  text = event.get("text")
260
256
  slack_files = event.get("files", [])
@@ -279,6 +275,9 @@ async def process_slack_message(
279
275
  session, slack_files, slack_app.client.token
280
276
  )
281
277
 
278
+ if on_chat_start := config.code.on_chat_start:
279
+ await on_chat_start()
280
+
282
281
  msg = Message(
283
282
  content=clean_content(text),
284
283
  elements=file_elements,
@@ -288,11 +287,6 @@ async def process_slack_message(
288
287
 
289
288
  await msg.send()
290
289
 
291
- ctx.emitter.enabled = True
292
-
293
- if on_chat_start := config.code.on_chat_start:
294
- await on_chat_start()
295
-
296
290
  if on_message := config.code.on_message:
297
291
  await on_message(msg)
298
292
 
@@ -325,14 +319,29 @@ async def handle_app_home_opened(event, say):
325
319
  @slack_app.event("app_mention")
326
320
  async def handle_app_mentions(event, say):
327
321
  thread_ts = event.get("thread_ts", event["ts"])
328
- await process_slack_message(event, say, thread_ts=thread_ts)
322
+ thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts))
323
+
324
+ await process_slack_message(event, say, thread_id=thread_id, thread_ts=thread_ts)
329
325
 
330
326
 
331
327
  @slack_app.event("message")
332
328
  async def handle_message(message, say):
333
- user = await get_user(message["user"])
334
- thread_name = f"{user.identifier} Slack DM"
335
- await process_slack_message(message, say, thread_name, True)
329
+ thread_id = str(
330
+ uuid.uuid5(
331
+ uuid.NAMESPACE_DNS,
332
+ message["channel"] + datetime.today().strftime("%Y-%m-%d"),
333
+ )
334
+ )
335
+ thread_ts = message.get("thread_ts", message["ts"])
336
+ thread_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, thread_ts))
337
+
338
+ await process_slack_message(
339
+ event=message,
340
+ say=say,
341
+ thread_id=thread_id,
342
+ bind_thread_to_user=True,
343
+ thread_ts=thread_ts,
344
+ )
336
345
 
337
346
 
338
347
  @slack_app.block_action("thumbdown")
chainlit/socket.py CHANGED
@@ -7,9 +7,9 @@ from urllib.parse import unquote
7
7
 
8
8
  from chainlit.action import Action
9
9
  from chainlit.auth import get_current_user, require_login
10
+ from chainlit.chat_context import chat_context
10
11
  from chainlit.config import config
11
12
  from chainlit.context import init_ws_context
12
- from chainlit.chat_context import chat_context
13
13
  from chainlit.data import get_data_layer
14
14
  from chainlit.element import Element
15
15
  from chainlit.logger import logger
@@ -184,11 +184,11 @@ async def connection_successful(sid):
184
184
  {"interaction": "resume", "thread_id": thread.get("id")},
185
185
  )
186
186
  await config.code.on_chat_resume(thread)
187
-
187
+
188
188
  for step in thread.get("steps", []):
189
189
  if "message" in step["type"]:
190
190
  chat_context.add(Message.from_dict(step))
191
-
191
+
192
192
  await context.emitter.resume_thread(thread)
193
193
  return
194
194
 
@@ -244,7 +244,7 @@ async def stop(sid):
244
244
  trace_event("stop_task")
245
245
 
246
246
  init_ws_context(session)
247
- await Message(content="Task manually stopped.", disable_feedback=True).send()
247
+ await Message(content="Task manually stopped.").send()
248
248
 
249
249
  if session.current_task:
250
250
  session.current_task.cancel()
@@ -282,18 +282,18 @@ async def edit_message(sid, payload: MessagePayload):
282
282
  context = init_ws_context(session)
283
283
 
284
284
  messages = chat_context.get()
285
-
285
+
286
286
  orig_message = None
287
-
287
+
288
288
  for message in messages:
289
289
  if orig_message:
290
- await message.remove()
291
-
290
+ await message.remove()
291
+
292
292
  if message.id == payload["message"]["id"]:
293
293
  message.content = payload["message"]["output"]
294
294
  await message.update()
295
295
  orig_message = message
296
-
296
+
297
297
  await context.emitter.task_start()
298
298
 
299
299
  if config.code.on_message:
@@ -303,7 +303,7 @@ async def edit_message(sid, payload: MessagePayload):
303
303
  pass
304
304
  finally:
305
305
  await context.emitter.task_end()
306
-
306
+
307
307
 
308
308
  @sio.on("client_message")
309
309
  async def message(sid, payload: MessagePayload):