chainlit 1.0.400__py3-none-any.whl → 1.0.500__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.

@@ -22,7 +22,7 @@
22
22
  <script>
23
23
  const global = globalThis;
24
24
  </script>
25
- <script type="module" crossorigin src="/assets/index-9711593e.js"></script>
25
+ <script type="module" crossorigin src="/assets/index-dc38064c.js"></script>
26
26
  <link rel="stylesheet" href="/assets/index-d088547c.css">
27
27
  </head>
28
28
  <body>
@@ -525,13 +525,15 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
525
525
  # find first message with prompt_id
526
526
  for m in chat_start["input_messages"]:
527
527
  if m.additional_kwargs.get("prompt_id"):
528
- current_step.generation.prompt_id = m.additional_kwargs["prompt_id"]
528
+ current_step.generation.prompt_id = m.additional_kwargs[
529
+ "prompt_id"
530
+ ]
529
531
  if custom_variables := m.additional_kwargs.get("variables"):
530
532
  current_step.generation.variables = custom_variables
531
533
  break
532
-
534
+
533
535
  current_step.language = "json"
534
- current_step.output = json.dumps(message_completion)
536
+ current_step.output = json.dumps(message_completion, indent=4, ensure_ascii=False)
535
537
  else:
536
538
  completion_start = self.completion_generations[str(run.id)]
537
539
  completion = generation.get("text", "")
@@ -558,8 +560,6 @@ class LangchainTracer(BaseTracer, GenerationHelper, FinalStreamHelper):
558
560
  self._run_sync(current_step.update())
559
561
 
560
562
  if self.final_stream and self.has_streamed_final_answer:
561
- if self.final_stream.content:
562
- self.final_stream.content = completion
563
563
  self._run_sync(self.final_stream.update())
564
564
 
565
565
  return
@@ -1,6 +1,6 @@
1
1
  from chainlit.utils import check_module_version
2
2
 
3
- if not check_module_version("llama_index", "0.8.3"):
3
+ if not check_module_version("llama_index.core", "0.10.15"):
4
4
  raise ValueError(
5
- "Expected LlamaIndex version >= 0.8.3. Run `pip install llama_index --upgrade`"
5
+ "Expected LlamaIndex version >= 0.10.15. Run `pip install llama_index --upgrade`"
6
6
  )
@@ -5,9 +5,9 @@ from chainlit.element import Text
5
5
  from chainlit.step import Step, StepType
6
6
  from literalai import ChatGeneration, CompletionGeneration, GenerationMessage
7
7
  from literalai.helper import utc_now
8
- from llama_index.callbacks import TokenCountingHandler
9
- from llama_index.callbacks.schema import CBEventType, EventPayload
10
- from llama_index.llms.base import ChatMessage, ChatResponse, CompletionResponse
8
+ from llama_index.core.callbacks import TokenCountingHandler
9
+ from llama_index.core.callbacks.schema import CBEventType, EventPayload
10
+ from llama_index.core.llms import ChatMessage, ChatResponse, CompletionResponse
11
11
 
12
12
  DEFAULT_IGNORE = [
13
13
  CBEventType.CHUNKING,
chainlit/markdown.py CHANGED
@@ -30,9 +30,19 @@ def init_markdown(root: str):
30
30
  logger.info(f"Created default chainlit markdown file at {chainlit_md_file}")
31
31
 
32
32
 
33
- def get_markdown_str(root: str):
33
+ def get_markdown_str(root: str, language: str):
34
34
  """Get the chainlit.md file as a string."""
35
- chainlit_md_path = os.path.join(root, "chainlit.md")
35
+ translated_chainlit_md_path = os.path.join(root, f"chainlit_{language}.md")
36
+ default_chainlit_md_path = os.path.join(root, "chainlit.md")
37
+
38
+ if os.path.exists(translated_chainlit_md_path):
39
+ chainlit_md_path = translated_chainlit_md_path
40
+ else:
41
+ chainlit_md_path = default_chainlit_md_path
42
+ logger.warning(
43
+ f"Translated markdown file for {language} not found. Defaulting to chainlit.md."
44
+ )
45
+
36
46
  if os.path.exists(chainlit_md_path):
37
47
  with open(chainlit_md_path, "r", encoding="utf-8") as f:
38
48
  chainlit_md = f.read()
chainlit/message.py CHANGED
@@ -542,7 +542,7 @@ class AskActionMessage(AskMessageBase):
542
542
  if res is None:
543
543
  self.content = "Timed out: no action was taken"
544
544
  else:
545
- self.content = f'**Selected action:** {res["label"]}'
545
+ self.content = f'**Selected:** {res["label"]}'
546
546
 
547
547
  self.wait_for_answer = False
548
548
 
chainlit/server.py CHANGED
@@ -41,6 +41,7 @@ from chainlit.types import (
41
41
  GetThreadsRequest,
42
42
  Theme,
43
43
  UpdateFeedbackRequest,
44
+ DeleteFeedbackRequest,
44
45
  )
45
46
  from chainlit.user import PersistedUser, User
46
47
  from fastapi import (
@@ -53,6 +54,7 @@ from fastapi import (
53
54
  UploadFile,
54
55
  status,
55
56
  )
57
+ from fastapi.middleware.gzip import GZipMiddleware
56
58
  from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, RedirectResponse
57
59
  from fastapi.security import OAuth2PasswordRequestForm
58
60
  from fastapi.staticfiles import StaticFiles
@@ -139,7 +141,12 @@ async def lifespan(app: FastAPI):
139
141
  def get_build_dir(local_target: str, packaged_target: str):
140
142
  local_build_dir = os.path.join(PACKAGE_ROOT, local_target, "dist")
141
143
  packaged_build_dir = os.path.join(BACKEND_ROOT, packaged_target, "dist")
142
- if os.path.exists(local_build_dir):
144
+
145
+ if config.ui.custom_build and os.path.exists(
146
+ os.path.join(APP_ROOT, config.ui.custom_build, packaged_target, "dist")
147
+ ):
148
+ return os.path.join(APP_ROOT, config.ui.custom_build, packaged_target, "dist")
149
+ elif os.path.exists(local_build_dir):
143
150
  return local_build_dir
144
151
  elif os.path.exists(packaged_build_dir):
145
152
  return packaged_build_dir
@@ -181,6 +188,8 @@ app.add_middleware(
181
188
  allow_headers=["*"],
182
189
  )
183
190
 
191
+ app.add_middleware(GZipMiddleware)
192
+
184
193
  socket = SocketManager(
185
194
  app,
186
195
  cors_allowed_origins=[],
@@ -498,6 +507,22 @@ async def get_providers(
498
507
  return JSONResponse(content={"providers": providers})
499
508
 
500
509
 
510
+ @app.get("/project/translations")
511
+ async def project_translations(
512
+ language: str = Query(default="en-US", description="Language code"),
513
+ ):
514
+ """Return project translations."""
515
+
516
+ # Load translation based on the provided language
517
+ translation = config.load_translation(language)
518
+
519
+ return JSONResponse(
520
+ content={
521
+ "translation": translation,
522
+ }
523
+ )
524
+
525
+
501
526
  @app.get("/project/settings")
502
527
  async def project_settings(
503
528
  current_user: Annotated[Union[User, PersistedUser], Depends(get_current_user)],
@@ -505,8 +530,8 @@ async def project_settings(
505
530
  ):
506
531
  """Return project settings. This is called by the UI before the establishing the websocket connection."""
507
532
 
508
- # Load translation based on the provided language
509
- translation = config.load_translation(language)
533
+ # Load the markdown file based on the provided language
534
+ markdown = get_markdown_str(config.root, language)
510
535
 
511
536
  profiles = []
512
537
  if config.code.set_chat_profiles:
@@ -520,9 +545,8 @@ async def project_settings(
520
545
  "userEnv": config.project.user_env,
521
546
  "dataPersistence": get_data_layer() is not None,
522
547
  "threadResumable": bool(config.code.on_chat_resume),
523
- "markdown": get_markdown_str(config.root),
548
+ "markdown": markdown,
524
549
  "chatProfiles": profiles,
525
- "translation": translation,
526
550
  }
527
551
  )
528
552
 
@@ -545,6 +569,24 @@ async def update_feedback(
545
569
 
546
570
  return JSONResponse(content={"success": True, "feedbackId": feedback_id})
547
571
 
572
+ @app.delete("/feedback")
573
+ async def delete_feedback(
574
+ request: Request,
575
+ payload: DeleteFeedbackRequest,
576
+ current_user: Annotated[Union[User, PersistedUser], Depends(get_current_user)],
577
+ ):
578
+ """Delete a feedback."""
579
+
580
+ data_layer = get_data_layer()
581
+
582
+ if not data_layer:
583
+ raise HTTPException(status_code=400, detail="Data persistence is not enabled")
584
+
585
+ feedback_id = payload.feedbackId
586
+
587
+ await data_layer.delete_feedback(feedback_id)
588
+ return JSONResponse(content={"success": True})
589
+
548
590
 
549
591
  @app.post("/project/threads")
550
592
  async def get_user_threads(
@@ -560,7 +602,10 @@ async def get_user_threads(
560
602
  if not data_layer:
561
603
  raise HTTPException(status_code=400, detail="Data persistence is not enabled")
562
604
 
563
- payload.filter.userIdentifier = current_user.identifier
605
+ if not isinstance(current_user, PersistedUser):
606
+ raise HTTPException(status_code=400, detail="User not persisted")
607
+
608
+ payload.filter.userId = current_user.id
564
609
 
565
610
  res = await data_layer.list_threads(payload.pagination, payload.filter)
566
611
  return JSONResponse(content=res.to_dict())
@@ -737,6 +782,11 @@ async def get_logo(theme: Optional[Theme] = Query(Theme.light)):
737
782
  return FileResponse(logo_path, media_type=media_type)
738
783
 
739
784
 
785
+ @app.head('/')
786
+ def status_check():
787
+ return {"message": "Site is operational"}
788
+
789
+
740
790
  def register_wildcard_route_handler():
741
791
  @app.get("/{path:path}")
742
792
  async def serve(request: Request, path: str):
chainlit/socket.py CHANGED
@@ -42,7 +42,7 @@ async def resume_thread(session: WebsocketSession):
42
42
  if not thread:
43
43
  return
44
44
 
45
- author = thread.get("user").get("identifier") if thread["user"] else None
45
+ author = thread.get("userIdentifier")
46
46
  user_is_author = author == session.user.identifier
47
47
 
48
48
  if user_is_author:
chainlit/step.py CHANGED
@@ -194,13 +194,13 @@ class Step:
194
194
  if set_language:
195
195
  self.language = "json"
196
196
  except TypeError:
197
- processed_content = str(content)
197
+ processed_content = str(content).replace("\\n", "\n")
198
198
  if set_language:
199
199
  self.language = "text"
200
200
  elif isinstance(content, str):
201
201
  processed_content = content
202
202
  else:
203
- processed_content = str(content)
203
+ processed_content = str(content).replace("\\n", "\n")
204
204
  if set_language:
205
205
  self.language = "text"
206
206
  return processed_content
@@ -0,0 +1,161 @@
1
+ {
2
+ "components": {
3
+ "atoms": {
4
+ "buttons": {
5
+ "userButton": {
6
+ "menu": {
7
+ "settings": "Einstellungen",
8
+ "settingsKey": "S",
9
+ "APIKeys": "API-Schl\u00fcssel",
10
+ "logout": "Abmelden"
11
+ }
12
+ }
13
+ }
14
+ },
15
+ "molecules": {
16
+ "newChatButton": {
17
+ "newChat": "Neuer Chat"
18
+ },
19
+ "tasklist": {
20
+ "TaskList": {
21
+ "title": "\ud83d\uddd2\ufe0f Aufgabenliste",
22
+ "loading": "L\u00e4dt...",
23
+ "error": "Ein Fehler ist aufgetreten"
24
+ }
25
+ },
26
+ "attachments": {
27
+ "cancelUpload": "Upload abbrechen",
28
+ "removeAttachment": "Anhang entfernen"
29
+ },
30
+ "newChatDialog": {
31
+ "createNewChat": "Neuen Chat erstellen?",
32
+ "clearChat": "Dies wird die aktuellen Nachrichten l\u00f6schen und einen neuen Chat starten.",
33
+ "cancel": "Abbrechen",
34
+ "confirm": "Best\u00e4tigen"
35
+ },
36
+ "settingsModal": {
37
+ "settings": "Einstellungen",
38
+ "expandMessages": "Nachrichten ausklappen",
39
+ "hideChainOfThought": "Zwischenschritte verbergen",
40
+ "darkMode": "Dunkelmodus"
41
+ }
42
+ },
43
+ "organisms": {
44
+ "chat": {
45
+ "history": {
46
+ "index": {
47
+ "showHistory": "Zeige Chatverlauf",
48
+ "lastInputs": "Letzte Eingaben",
49
+ "noInputs": "Leer...",
50
+ "loading": "L\u00e4dt..."
51
+ }
52
+ },
53
+ "inputBox": {
54
+ "input": {
55
+ "placeholder": "Nachricht eingeben..."
56
+ },
57
+ "speechButton": {
58
+ "start": "Aufnahme starten",
59
+ "stop": "Aufnahme stoppen"
60
+ },
61
+ "SubmitButton": {
62
+ "sendMessage": "Nachricht senden",
63
+ "stopTask": "Aufgabe stoppen"
64
+ },
65
+ "UploadButton": {
66
+ "attachFiles": "Dateien anh\u00e4ngen"
67
+ },
68
+ "waterMark": {
69
+ "text": "Erstellt mit"
70
+ }
71
+ },
72
+ "Messages": {
73
+ "index": {
74
+ "running": "L\u00e4uft",
75
+ "executedSuccessfully": "erfolgreich ausgef\u00fchrt",
76
+ "failed": "fehlgeschlagen",
77
+ "feedbackUpdated": "Feedback aktualisiert",
78
+ "updating": "Aktualisiert"
79
+ }
80
+ },
81
+ "dropScreen": {
82
+ "dropYourFilesHere": "Ziehe deine Dateien hierher"
83
+ },
84
+ "index": {
85
+ "failedToUpload": "Upload fehlgeschlagen",
86
+ "cancelledUploadOf": "Upload abgebrochen von",
87
+ "couldNotReachServer": "Konnte den Server nicht erreichen",
88
+ "continuingChat": "Vorherigen Chat fortsetzen"
89
+ },
90
+ "settings": {
91
+ "settingsPanel": "Einstellungsfenster",
92
+ "reset": "Zur\u00fccksetzen",
93
+ "cancel": "Abbrechen",
94
+ "confirm": "Best\u00e4tigen"
95
+ }
96
+ },
97
+ "threadHistory": {
98
+ "sidebar": {
99
+ "filters": {
100
+ "FeedbackSelect": {
101
+ "feedbackAll": "Feedback: Alle",
102
+ "feedbackPositive": "Feedback: Positiv",
103
+ "feedbackNegative": "Feedback: Negativ"
104
+ },
105
+ "SearchBar": {
106
+ "search": "Suche"
107
+ }
108
+ },
109
+ "DeleteThreadButton": {
110
+ "confirmMessage": "Dies wird den Thread sowie seine Nachrichten und Elemente l\u00f6schen.",
111
+ "cancel": "Abbrechen",
112
+ "confirm": "Best\u00e4tigen",
113
+ "deletingChat": "Chat wird gel\u00f6scht",
114
+ "chatDeleted": "Chat gel\u00f6scht"
115
+ },
116
+ "index": {
117
+ "pastChats": "Vergangene Chats"
118
+ },
119
+ "ThreadList": {
120
+ "empty": "Leer...",
121
+ "today": "Heute",
122
+ "yesterday": "Gestern",
123
+ "previous7days": "Vor 7 Tagen",
124
+ "previous30days": "Vor 30 Tagen"
125
+ },
126
+ "TriggerButton": {
127
+ "closeSidebar": "Seitenleiste schlie\u00dfen",
128
+ "openSidebar": "Seitenleiste \u00f6ffnen"
129
+ }
130
+ },
131
+ "Thread": {
132
+ "backToChat": "Zur\u00fcck zum Chat",
133
+ "chatCreatedOn": "Dieser Chat wurde erstellt am"
134
+ }
135
+ },
136
+ "header": {
137
+ "chat": "Chat",
138
+ "readme": "Liesmich"
139
+ }
140
+ }
141
+ },
142
+ "hooks": {
143
+ "useLLMProviders": {
144
+ "failedToFetchProviders": "Anbieter konnten nicht geladen werden:"
145
+ }
146
+ },
147
+ "pages": {
148
+ "Design": {},
149
+ "Env": {
150
+ "savedSuccessfully": "Erfolgreich gespeichert",
151
+ "requiredApiKeys": "Ben\u00f6tigte API-Schl\u00fcssel",
152
+ "requiredApiKeysInfo": "Um diese App zu nutzen, werden die folgenden API-Schl\u00fcssel ben\u00f6tigt. Die Schl\u00fcssel werden im lokalen Speicher Ihres Ger\u00e4ts gespeichert."
153
+ },
154
+ "Page": {
155
+ "notPartOfProject": "Sie sind nicht Teil dieses Projekts."
156
+ },
157
+ "ResumeButton": {
158
+ "resumeChat": "Chat fortsetzen"
159
+ }
160
+ }
161
+ }
@@ -34,15 +34,87 @@
34
34
  "confirm": "Confirm"
35
35
  },
36
36
  "settingsModal": {
37
+ "settings": "Settings",
37
38
  "expandMessages": "Expand Messages",
38
39
  "hideChainOfThought": "Hide Chain of Thought",
39
40
  "darkMode": "Dark Mode"
41
+ },
42
+ "detailsButton": {
43
+ "using": "Using",
44
+ "running": "Running",
45
+ "took_one": "Took {{count}} step",
46
+ "took_other": "Took {{count}} steps"
47
+ },
48
+ "auth": {
49
+ "authLogin": {
50
+ "title": "Login to access the app.",
51
+ "form": {
52
+ "email": "Email address",
53
+ "password": "Password",
54
+ "noAccount": "Don't have an account?",
55
+ "alreadyHaveAccount": "Already have an account?",
56
+ "signup": "Sign Up",
57
+ "signin": "Sign In",
58
+ "or": "OR",
59
+ "continue": "Continue",
60
+ "forgotPassword": "Forgot password?",
61
+ "passwordMustContain": "Your password must contain:",
62
+ "emailRequired": "email is a required field",
63
+ "passwordRequired": "password is a required field"
64
+ },
65
+ "error": {
66
+ "default": "Unable to sign in.",
67
+ "signin": "Try signing in with a different account.",
68
+ "oauthsignin": "Try signing in with a different account.",
69
+ "redirect_uri_mismatch": "The redirect URI is not matching the oauth app configuration.",
70
+ "oauthcallbackerror": "Try signing in with a different account.",
71
+ "oauthcreateaccount": "Try signing in with a different account.",
72
+ "emailcreateaccount": "Try signing in with a different account.",
73
+ "callback": "Try signing in with a different account.",
74
+ "oauthaccountnotlinked": "To confirm your identity, sign in with the same account you used originally.",
75
+ "emailsignin": "The e-mail could not be sent.",
76
+ "emailverify": "Please verify your email, a new email has been sent.",
77
+ "credentialssignin": "Sign in failed. Check the details you provided are correct.",
78
+ "sessionrequired": "Please sign in to access this page."
79
+ }
80
+ },
81
+ "authVerifyEmail": {
82
+ "almostThere": "You're almost there! We've sent an email to ",
83
+ "verifyEmailLink": "Please click on the link in that email to complete your signup.",
84
+ "didNotReceive": "Can't find the email?",
85
+ "resendEmail": "Resend email",
86
+ "goBack": "Go Back",
87
+ "emailSent": "Email sent successfully.",
88
+ "verifyEmail": "Verify your email address"
89
+ },
90
+ "providerButton": {
91
+ "continue": "Continue with {{provider}}",
92
+ "signup": "Sign up with {{provider}}"
93
+ },
94
+ "authResetPassword": {
95
+ "newPasswordRequired": "New password is a required field",
96
+ "passwordsMustMatch": "Passwords must match",
97
+ "confirmPasswordRequired": "Confirm password is a required field",
98
+ "newPassword": "New password",
99
+ "confirmPassword": "Confirm password",
100
+ "resetPassword": "Reset Password"
101
+ },
102
+ "authForgotPassword": {
103
+ "email": "Email address",
104
+ "emailRequired": "email is a required field",
105
+ "emailSent": "Please check the email address {{email}} for instructions to reset your password.",
106
+ "enterEmail": "Enter your email address and we will send you instructions to reset your password.",
107
+ "resendEmail": "Resend email",
108
+ "continue": "Continue",
109
+ "goBack": "Go Back"
110
+ }
40
111
  }
41
112
  },
42
113
  "organisms": {
43
114
  "chat": {
44
115
  "history": {
45
116
  "index": {
117
+ "showHistory": "Show history",
46
118
  "lastInputs": "Last Inputs",
47
119
  "noInputs": "Such empty...",
48
120
  "loading": "Loading..."
@@ -115,7 +187,11 @@
115
187
  "pastChats": "Past Chats"
116
188
  },
117
189
  "ThreadList": {
118
- "empty": "Empty..."
190
+ "empty": "Empty...",
191
+ "today": "Today",
192
+ "yesterday": "Yesterday",
193
+ "previous7days": "Previous 7 days",
194
+ "previous30days": "Previous 30 days"
119
195
  },
120
196
  "TriggerButton": {
121
197
  "closeSidebar": "Close sidebar",
@@ -34,6 +34,7 @@
34
34
  "confirm": "Confirmar"
35
35
  },
36
36
  "settingsModal": {
37
+ "settings": "Configurações",
37
38
  "expandMessages": "Expandir Mensagens",
38
39
  "hideChainOfThought": "Esconder Sequência de Pensamento",
39
40
  "darkMode": "Modo Escuro"
@@ -43,6 +44,7 @@
43
44
  "chat": {
44
45
  "history": {
45
46
  "index": {
47
+ "showHistory": "Mostrar histórico",
46
48
  "lastInputs": "Últimas Entradas",
47
49
  "noInputs": "Vazio...",
48
50
  "loading": "Carregando..."
@@ -0,0 +1,60 @@
1
+ # TODO:
2
+ # - Support linting plural
3
+ # - Support interpolation
4
+
5
+
6
+ def compare_json_structures(truth, to_compare, path=""):
7
+ """
8
+ Compare the structure of two deeply nested JSON objects.
9
+ Args:
10
+ truth (dict): The 'truth' JSON object.
11
+ to_compare (dict): The 'to_compare' JSON object.
12
+ path (str): The current path for error reporting (used internally).
13
+ Returns:
14
+ A list of differences found.
15
+ """
16
+ if not isinstance(truth, dict) or not isinstance(to_compare, dict):
17
+ raise ValueError("Both inputs must be dictionaries.")
18
+
19
+ errors = []
20
+
21
+ truth_keys = set(truth.keys())
22
+ to_compare_keys = set(to_compare.keys())
23
+
24
+ extra_keys = to_compare_keys - truth_keys
25
+ missing_keys = truth_keys - to_compare_keys
26
+
27
+ for key in extra_keys:
28
+ errors.append(f"⚠️ Extra key: '{path + '.' + key if path else key}'")
29
+
30
+ for key in missing_keys:
31
+ errors.append(f"❌ Missing key: '{path + '.' + key if path else key}'")
32
+
33
+ for key in truth_keys & to_compare_keys:
34
+ if isinstance(truth[key], dict) and isinstance(to_compare[key], dict):
35
+ # Recursive call to navigate through nested dictionaries
36
+ errors += compare_json_structures(
37
+ truth[key], to_compare[key], path + "." + key if path else key
38
+ )
39
+ elif not isinstance(truth[key], dict) and not isinstance(to_compare[key], dict):
40
+ # If both are not dicts, we are at leaf nodes and structure matches; skip value comparison
41
+ continue
42
+ else:
43
+ # Structure mismatch: one is a dict, the other is not
44
+ errors.append(
45
+ f"❌ Structure mismatch at: '{path + '.' + key if path else key}'"
46
+ )
47
+
48
+ return errors
49
+
50
+
51
+ def lint_translation_json(file, truth, to_compare):
52
+ print(f"\nLinting {file}...")
53
+
54
+ errors = compare_json_structures(truth, to_compare)
55
+
56
+ if errors:
57
+ for error in errors:
58
+ print(f"{error}")
59
+ else:
60
+ print(f"✅ No errors found in {file}")
chainlit/types.py CHANGED
@@ -3,7 +3,6 @@ from typing import TYPE_CHECKING, Dict, List, Literal, Optional, TypedDict, Unio
3
3
 
4
4
  if TYPE_CHECKING:
5
5
  from chainlit.element import ElementDict
6
- from chainlit.user import UserDict
7
6
  from chainlit.step import StepDict
8
7
 
9
8
  from dataclasses_json import DataClassJsonMixin
@@ -20,7 +19,8 @@ class ThreadDict(TypedDict):
20
19
  id: str
21
20
  createdAt: str
22
21
  name: Optional[str]
23
- user: Optional["UserDict"]
22
+ userId: Optional[str]
23
+ userIdentifier: Optional[str]
24
24
  tags: Optional[List[str]]
25
25
  metadata: Optional[Dict]
26
26
  steps: List["StepDict"]
@@ -33,8 +33,8 @@ class Pagination(BaseModel):
33
33
 
34
34
 
35
35
  class ThreadFilter(BaseModel):
36
- feedback: Optional[Literal[-1, 0, 1]] = None
37
- userIdentifier: Optional[str] = None
36
+ feedback: Optional[Literal[0, 1]] = None
37
+ userId: Optional[str] = None
38
38
  search: Optional[str] = None
39
39
 
40
40
 
@@ -123,6 +123,10 @@ class DeleteThreadRequest(BaseModel):
123
123
  threadId: str
124
124
 
125
125
 
126
+ class DeleteFeedbackRequest(BaseModel):
127
+ feedbackId: str
128
+
129
+
126
130
  class GetThreadsRequest(BaseModel):
127
131
  pagination: Pagination
128
132
  filter: ThreadFilter
@@ -146,16 +150,16 @@ FeedbackStrategy = Literal["BINARY"]
146
150
 
147
151
 
148
152
  class FeedbackDict(TypedDict):
149
- value: Literal[-1, 0, 1]
150
- strategy: FeedbackStrategy
153
+ forId: str
154
+ id: Optional[str]
155
+ value: Literal[0, 1]
151
156
  comment: Optional[str]
152
157
 
153
158
 
154
159
  @dataclass
155
160
  class Feedback:
156
161
  forId: str
157
- value: Literal[-1, 0, 1]
158
- strategy: FeedbackStrategy = "BINARY"
162
+ value: Literal[0, 1]
159
163
  id: Optional[str] = None
160
164
  comment: Optional[str] = None
161
165