ragbits-chat 1.4.0.dev202601170236__tar.gz → 1.4.0.dev202601300258__tar.gz

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.
Files changed (79) hide show
  1. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/CHANGELOG.md +4 -0
  2. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/PKG-INFO +2 -2
  3. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/pyproject.toml +2 -2
  4. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/api.py +44 -45
  5. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/auth/backends.py +3 -7
  6. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/auth/oauth2_providers.py +119 -0
  7. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/config.py +14 -0
  8. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/interface/_interface.py +13 -0
  9. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/interface/types.py +15 -1
  10. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/AuthGuard-FL2hbNSz.js +1 -0
  11. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/ChatHistory-B2hLBYMJ.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/ChatHistory-LRndyrq0.js +2 -2
  12. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/ChatOptionsForm-bfNG8UIW.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/ChatOptionsForm-C7AySsjS.js +1 -1
  13. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/CredentialsLogin-CjWUo2_0.js +1 -0
  14. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/FeedbackForm-BLuzDSTy.js +1 -0
  15. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/Login-DSW_CNFu.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/Login-CGHnIvPP.js +1 -1
  16. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/LogoutButton-BQE8NNsg.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/LogoutButton-C-wYL6PH.js +1 -1
  17. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/OAuth2Login-EmJ39PUe.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/OAuth2Login-CJdQ3WzG.js +1 -1
  18. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/ShareButton-B7DyIVH0.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/ShareButton-Cc7tfnmL.js +1 -1
  19. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/UploadButton-_aV-toOW.js +1 -0
  20. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/UsageButton-BABA7a-w.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/UsageButton-CE7BRQcH.js +1 -1
  21. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/authStore-BfGlL8rp.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/authStore-AVyfzjgs.js +1 -1
  22. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/chunk-IGSAU2ZA-NXd1g0Qd.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/chunk-IGSAU2ZA-BBfo0QFa.js +1 -1
  23. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/chunk-SSA7SXE4-CJa0HuAU.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/chunk-SSA7SXE4-D3GKTPj0.js +1 -1
  24. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/index-Ceq7Rkzy.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/index-B-LIlvZN.js +1 -1
  25. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/index-B1u136LF.css +1 -0
  26. ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/index-BcnaGCUm.js +1 -0
  27. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/index-BZLU40Mk.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/index-CbVbgerL.js +37 -37
  28. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/index-Be0kkf3d.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/index-DTNGcmXG.js +2 -2
  29. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/useInitializeUserStore-DyHP7g8x.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/useInitializeUserStore-CVYyhiv3.js +1 -1
  30. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/useMenuTriggerState-SaFmATkk.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/useMenuTriggerState-C5916IcO.js +1 -1
  31. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/useSelectableItem-DhuFnc0W.js → ragbits_chat-1.4.0.dev202601300258/src/ragbits/chat/ui-build/assets/useSelectableItem-BWC6EImE.js +1 -1
  32. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/ui-build/index.html +2 -2
  33. ragbits_chat-1.4.0.dev202601300258/tests/unit/test_types.py +26 -0
  34. ragbits_chat-1.4.0.dev202601300258/tests/unit/test_upload.py +58 -0
  35. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/auth/oauth2_providers.py +0 -108
  36. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/AuthGuard-Bq7UOJ7y.js +0 -1
  37. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/CredentialsLogin-0g5-w2vR.js +0 -1
  38. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/FeedbackForm-oSbly5oN.js +0 -1
  39. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/index-Bvn9K6h_.js +0 -1
  40. ragbits_chat-1.4.0.dev202601170236/src/ragbits/chat/ui-build/assets/index-ClAYkAiv.css +0 -1
  41. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/.gitignore +0 -0
  42. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/README.md +0 -0
  43. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/__init__.py +0 -0
  44. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/_utils.py +0 -0
  45. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/auth/__init__.py +0 -0
  46. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/auth/base.py +0 -0
  47. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/auth/provider_config.py +0 -0
  48. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/auth/session_store.py +0 -0
  49. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/auth/types.py +0 -0
  50. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/cli.py +0 -0
  51. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/client/__init__.py +0 -0
  52. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/client/client.py +0 -0
  53. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/client/conversation.py +0 -0
  54. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/client/exceptions.py +0 -0
  55. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/history/__init__.py +0 -0
  56. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/history/compressors/__init__.py +0 -0
  57. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/history/compressors/base.py +0 -0
  58. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/history/compressors/llm.py +0 -0
  59. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/interface/__init__.py +0 -0
  60. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/interface/forms.py +0 -0
  61. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/interface/summary.py +0 -0
  62. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/interface/ui_customization.py +0 -0
  63. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/metrics.py +0 -0
  64. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/persistence/__init__.py +0 -0
  65. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/persistence/base.py +0 -0
  66. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/persistence/file.py +0 -0
  67. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/persistence/sql.py +0 -0
  68. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/providers/__init__.py +0 -0
  69. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/providers/model_provider.py +0 -0
  70. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/src/ragbits/chat/py.typed +0 -0
  71. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/auth/test_list_auth_backend.py +0 -0
  72. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/auth/test_session_store.py +0 -0
  73. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/history/test_llm_compressor.py +0 -0
  74. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/persistence/test_sql.py +0 -0
  75. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/test_api.py +0 -0
  76. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/test_chat_client.py +0 -0
  77. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/test_conversation.py +0 -0
  78. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/test_error_response.py +0 -0
  79. {ragbits_chat-1.4.0.dev202601170236 → ragbits_chat-1.4.0.dev202601300258}/tests/unit/test_generic_custom_response.py +0 -0
@@ -1,8 +1,12 @@
1
1
  # CHANGELOG
2
2
 
3
3
  ## Unreleased
4
+ - Decoupling of components from ragbits specific logic. Introduction of slot based plugin architecture. Minimal history store implementation (#917)
5
+ - Add timezone field to ChatContext, automatically populated from browser (#916)
4
6
  - Fix PostgreSQL conversation persistence by ensuring session flush after creating new conversation in SQL storage (#903)
7
+ - Add file upload ingestion support with `upload_handler` in `ChatInterface` and `/api/upload` endpoint in `RagbitsAPI`.
5
8
  - Change auth backend from jwt to http-only cookie based authentication, add support for OAuth2 authentication (#867)
9
+ - Add Google OAuth2 provider and refactor providers to use `OAuth2Providers` namespace (e.g., `OAuth2Providers.GOOGLE`) (#915)
6
10
  - Make `SummaryGenerator` optional in `ChatInterface` by providing a default Heuristic implementation.
7
11
  - Refactor ragbits-client types to remove excessive use of any (#881)
8
12
  - Split params into path params, query params in API client (#871)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragbits-chat
3
- Version: 1.4.0.dev202601170236
3
+ Version: 1.4.0.dev202601300258
4
4
  Summary: Building blocks for rapid development of GenAI applications
5
5
  Project-URL: Homepage, https://github.com/deepsense-ai/ragbits
6
6
  Project-URL: Bug Reports, https://github.com/deepsense-ai/ragbits/issues
@@ -26,7 +26,7 @@ Requires-Dist: bcrypt>=4.2.0
26
26
  Requires-Dist: fastapi<1.0.0,>=0.115.0
27
27
  Requires-Dist: httpx<1.0.0,>=0.28.1
28
28
  Requires-Dist: python-jose[cryptography]>=3.5.0
29
- Requires-Dist: ragbits-core==1.4.0.dev202601170236
29
+ Requires-Dist: ragbits-core==1.4.0.dev202601300258
30
30
  Requires-Dist: uvicorn<1.0.0,>=0.31.0
31
31
  Provides-Extra: sql
32
32
  Requires-Dist: sqlalchemy<3.0.0,>=2.0.39; extra == 'sql'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ragbits-chat"
3
- version = "1.4.0.dev202601170236"
3
+ version = "1.4.0.dev202601300258"
4
4
  description = "Building blocks for rapid development of GenAI applications"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -31,7 +31,7 @@ classifiers = [
31
31
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
32
32
  "Topic :: Software Development :: Libraries :: Python Modules",
33
33
  ]
34
- dependencies = ["fastapi>=0.115.0,<1.0.0", "uvicorn>=0.31.0,<1.0.0", "httpx>=0.28.1,<1.0.0", "bcrypt>=4.2.0", "python-jose[cryptography]>=3.5.0", "ragbits-core==1.4.0.dev202601170236"]
34
+ dependencies = ["fastapi>=0.115.0,<1.0.0", "uvicorn>=0.31.0,<1.0.0", "httpx>=0.28.1,<1.0.0", "bcrypt>=4.2.0", "python-jose[cryptography]>=3.5.0", "ragbits-core==1.4.0.dev202601300258"]
35
35
 
36
36
  [project.urls]
37
37
  "Homepage" = "https://github.com/deepsense-ai/ragbits"
@@ -2,7 +2,6 @@ import asyncio
2
2
  import importlib
3
3
  import json
4
4
  import logging
5
- import os
6
5
  import re
7
6
  import time
8
7
  from collections.abc import AsyncGenerator
@@ -11,7 +10,7 @@ from pathlib import Path
11
10
  from typing import Any, cast
12
11
 
13
12
  import uvicorn
14
- from fastapi import FastAPI, HTTPException, Request, status
13
+ from fastapi import FastAPI, HTTPException, Request, UploadFile, status
15
14
  from fastapi.exceptions import RequestValidationError
16
15
  from fastapi.middleware.cors import CORSMiddleware
17
16
  from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse, RedirectResponse, StreamingResponse
@@ -22,6 +21,7 @@ from ragbits.chat.auth import AuthenticationBackend, User
22
21
  from ragbits.chat.auth.backends import MultiAuthenticationBackend, OAuth2AuthenticationBackend
23
22
  from ragbits.chat.auth.provider_config import get_provider_visual_config
24
23
  from ragbits.chat.auth.types import LoginRequest, LoginResponse, OAuth2Credentials
24
+ from ragbits.chat.config import BASE_URL, CHUNK_SIZE, IS_PRODUCTION, SESSION_COOKIE_NAME
25
25
  from ragbits.chat.interface import ChatInterface
26
26
  from ragbits.chat.interface.types import (
27
27
  AuthenticationConfig,
@@ -46,17 +46,6 @@ from .metrics import ChatCounterMetric, ChatHistogramMetric
46
46
 
47
47
  logger = logging.getLogger(__name__)
48
48
 
49
- # Environment-aware cookie security: only require HTTPS in production
50
- IS_PRODUCTION = os.getenv("ENVIRONMENT", "").lower() == "production"
51
-
52
- # Session cookie name - used for storing session ID in HTTP-only cookie
53
- SESSION_COOKIE_NAME = "ragbits_session"
54
-
55
- # Chunk size for large base64 images to prevent SSE message size issues
56
- # Keep chunks extremely small to avoid JSON string length limits in browsers and SSE parsing issues
57
- # Account for JSON overhead: metadata + base64 data should fit comfortably in browser limits
58
- CHUNK_SIZE = 102400 # ~100KB bytes base64 chunks for ultra-safe JSON parsing and SSE transmission
59
-
60
49
 
61
50
  class RagbitsAPI:
62
51
  """
@@ -91,12 +80,7 @@ class RagbitsAPI:
91
80
  self.auth_backend = self._load_auth_backend(auth_backend)
92
81
  self.theme_path = Path(theme_path) if theme_path else None
93
82
 
94
- # get frontend base URL from environment variable or use default
95
- frontend_base_url = os.getenv("FRONTEND_BASE_URL", "http://localhost:8000")
96
- # remove trailing slash from frontend base URL
97
- frontend_base_url = frontend_base_url.rstrip("/")
98
- # set frontend base URL on the API
99
- self.frontend_base_url = frontend_base_url
83
+ self.frontend_base_url = BASE_URL
100
84
 
101
85
  @asynccontextmanager
102
86
  async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
@@ -197,34 +181,23 @@ class RagbitsAPI:
197
181
 
198
182
  return await self._handle_oauth2_callback(code, state, backend)
199
183
 
200
- @self.app.post("/api/chat", response_class=StreamingResponse)
201
- async def chat_message(
202
- request: Request,
203
- chat_request: ChatMessageRequest,
204
- ) -> StreamingResponse:
205
- return await self._handle_chat_message(chat_request, request)
206
-
207
- @self.app.post("/api/feedback", response_class=JSONResponse)
208
- async def feedback(
209
- request: Request,
210
- feedback_request: FeedbackRequest,
211
- ) -> JSONResponse:
212
- return await self._handle_feedback(feedback_request, request)
213
- else:
184
+ @self.app.post("/api/chat", response_class=StreamingResponse)
185
+ async def chat_message(
186
+ request: Request,
187
+ chat_request: ChatMessageRequest,
188
+ ) -> StreamingResponse:
189
+ return await self._handle_chat_message(chat_request, request)
214
190
 
215
- @self.app.post("/api/chat", response_class=StreamingResponse)
216
- async def chat_message(
217
- request: Request,
218
- chat_request: ChatMessageRequest,
219
- ) -> StreamingResponse:
220
- return await self._handle_chat_message(chat_request, request)
191
+ @self.app.post("/api/feedback", response_class=JSONResponse)
192
+ async def feedback(
193
+ request: Request,
194
+ feedback_request: FeedbackRequest,
195
+ ) -> JSONResponse:
196
+ return await self._handle_feedback(feedback_request, request)
221
197
 
222
- @self.app.post("/api/feedback", response_class=JSONResponse)
223
- async def feedback(
224
- request: Request,
225
- feedback_request: FeedbackRequest,
226
- ) -> JSONResponse:
227
- return await self._handle_feedback(feedback_request, request)
198
+ @self.app.post("/api/upload", response_class=JSONResponse)
199
+ async def upload_file(file: UploadFile) -> JSONResponse:
200
+ return await self._handle_file_upload(file)
228
201
 
229
202
  @self.app.get("/api/config", response_class=JSONResponse)
230
203
  async def config() -> JSONResponse:
@@ -294,6 +267,7 @@ class RagbitsAPI:
294
267
  auth_types=auth_types,
295
268
  oauth2_providers=oauth2_providers,
296
269
  ),
270
+ supports_upload=self.chat_interface.upload_handler is not None,
297
271
  )
298
272
 
299
273
  return JSONResponse(content=config_response.model_dump())
@@ -585,6 +559,31 @@ class RagbitsAPI:
585
559
  )
586
560
  raise HTTPException(status_code=500, detail="Internal server error") from None
587
561
 
562
+ async def _handle_file_upload(self, file: UploadFile) -> JSONResponse:
563
+ """
564
+ Handle file upload requests.
565
+
566
+ Args:
567
+ file: The uploaded file.
568
+
569
+ Returns:
570
+ JSONResponse with status.
571
+ """
572
+ if self.chat_interface.upload_handler is None:
573
+ raise HTTPException(status_code=400, detail="File upload not supported")
574
+
575
+ try:
576
+ # Check if handler is async and call it
577
+ if asyncio.iscoroutinefunction(self.chat_interface.upload_handler):
578
+ await self.chat_interface.upload_handler(file)
579
+ else:
580
+ await asyncio.to_thread(self.chat_interface.upload_handler, file)
581
+
582
+ return JSONResponse(content={"status": "success", "filename": file.filename})
583
+ except Exception as e:
584
+ logger.error(f"File upload error: {e}")
585
+ raise HTTPException(status_code=500, detail=str(e)) from e
586
+
588
587
  async def get_current_user_from_cookie(self, request: Request) -> User | None:
589
588
  """
590
589
  Get current user from session cookie.
@@ -11,6 +11,7 @@ import httpx
11
11
  from ragbits.chat.auth.base import AuthenticationBackend, AuthenticationResponse, AuthOptions
12
12
  from ragbits.chat.auth.oauth2_providers import OAuth2Provider
13
13
  from ragbits.chat.auth.types import OAuth2Credentials, Session, SessionStore, User, UserCredentials
14
+ from ragbits.chat.config import BASE_URL
14
15
 
15
16
  logger = logging.getLogger(__name__)
16
17
 
@@ -175,7 +176,7 @@ class OAuth2AuthenticationBackend(AuthenticationBackend):
175
176
 
176
177
  Args:
177
178
  session_store: Session storage backend
178
- provider: OAuth2 provider implementation (e.g., DiscordOAuth2Provider, GoogleOAuth2Provider)
179
+ provider: OAuth2 provider implementation (e.g., OAuth2Providers.DISCORD, OAuth2Providers.GOOGLE)
179
180
  client_id: OAuth2 client ID (or set {PROVIDER}_CLIENT_ID env var)
180
181
  client_secret: OAuth2 client secret (or set {PROVIDER}_CLIENT_SECRET env var)
181
182
  redirect_uri: Callback URL for OAuth2 flow (or set OAUTH2_REDIRECT_URI env var,
@@ -203,12 +204,7 @@ class OAuth2AuthenticationBackend(AuthenticationBackend):
203
204
 
204
205
  # Use provider-specific callback URL for better isolation and debugging
205
206
  if not redirect_uri:
206
- # Get base URL from environment variable or use default
207
- base_url = os.getenv("OAUTH2_CALLBACK_BASE_URL", "http://localhost:8000")
208
- # Remove trailing slash from base URL
209
- base_url = base_url.rstrip("/")
210
- # Construct redirect URI with base URL and provider name
211
- redirect_uri = f"{base_url}/api/auth/callback/{self.provider.name}"
207
+ redirect_uri = f"{BASE_URL}/api/auth/callback/{self.provider.name}"
212
208
 
213
209
  # remove trailing slash from redirect URI
214
210
  redirect_uri = redirect_uri.rstrip("/")
@@ -0,0 +1,119 @@
1
+ """OAuth2 provider implementations for various authentication services."""
2
+
3
+ from collections.abc import Callable
4
+
5
+ from pydantic.config import JsonDict
6
+
7
+ from ragbits.chat.auth.types import User
8
+
9
+
10
+ class OAuth2Provider:
11
+ """Abstract base class for OAuth2 providers."""
12
+
13
+ def __init__(
14
+ self,
15
+ *,
16
+ name: str,
17
+ display_name: str,
18
+ authorize_url: str,
19
+ token_url: str,
20
+ user_info_url: str,
21
+ scopes: list[str],
22
+ user_factory: Callable[[JsonDict], User],
23
+ ) -> None:
24
+ self._name = name
25
+ self._display_name = display_name
26
+ self._authorize_url = authorize_url
27
+ self._token_url = token_url
28
+ self._user_info_url = user_info_url
29
+ self._scopes = scopes
30
+ self._user_factory = user_factory
31
+
32
+ @property
33
+ def name(self) -> str:
34
+ """Provider name (e.g., 'discord')."""
35
+ return self._name
36
+
37
+ @property
38
+ def display_name(self) -> str:
39
+ """Human-readable provider name (e.g., 'Discord')."""
40
+ return self._display_name
41
+
42
+ @property
43
+ def authorize_url(self) -> str:
44
+ """OAuth2 authorization endpoint."""
45
+ return self._authorize_url
46
+
47
+ @property
48
+ def token_url(self) -> str:
49
+ """OAuth2 token exchange endpoint."""
50
+ return self._token_url
51
+
52
+ @property
53
+ def user_info_url(self) -> str:
54
+ """User info endpoint."""
55
+ return self._user_info_url
56
+
57
+ @property
58
+ def scope(self) -> str:
59
+ """OAuth2 scopes to request."""
60
+ return " ".join(self._scopes)
61
+
62
+ def create_user_from_data(self, user_data: JsonDict) -> User:
63
+ """
64
+ Create a User object from provider-specific user data.
65
+
66
+ Args:
67
+ user_data: Raw user data from the provider
68
+
69
+ Returns:
70
+ User object
71
+ """
72
+ return self._user_factory(user_data)
73
+
74
+
75
+ class OAuth2Providers:
76
+ """Namespace for built-in OAuth2 provider configurations."""
77
+
78
+ DISCORD = OAuth2Provider(
79
+ name="discord",
80
+ display_name="Discord",
81
+ authorize_url="https://discord.com/api/oauth2/authorize",
82
+ token_url="https://discord.com/api/oauth2/token", # noqa: S106
83
+ user_info_url="https://discord.com/api/users/@me",
84
+ scopes=["identify", "email"],
85
+ user_factory=lambda user_data: User(
86
+ user_id=f"discord_{user_data['id']}",
87
+ username=str(user_data.get("username", "")),
88
+ email=str(user_data["email"]) if user_data.get("email") else None,
89
+ full_name=str(user_data["global_name"]) if user_data.get("global_name") else None,
90
+ roles=["user"],
91
+ metadata={
92
+ "provider": "discord",
93
+ "avatar": user_data.get("avatar"),
94
+ "discriminator": user_data.get("discriminator"),
95
+ },
96
+ ),
97
+ )
98
+
99
+ GOOGLE = OAuth2Provider(
100
+ name="google",
101
+ display_name="Google",
102
+ authorize_url="https://accounts.google.com/o/oauth2/v2/auth",
103
+ token_url="https://oauth2.googleapis.com/token", # noqa: S106
104
+ user_info_url="https://www.googleapis.com/oauth2/v2/userinfo",
105
+ scopes=["openid", "email", "profile"],
106
+ user_factory=lambda user_data: User(
107
+ user_id=f"google_{user_data['id']}",
108
+ username=str(user_data.get("email", "")).split("@")[0],
109
+ email=str(user_data["email"]) if user_data.get("email") else None,
110
+ full_name=str(user_data["name"]) if user_data.get("name") else None,
111
+ roles=["user"],
112
+ metadata={
113
+ "provider": "google",
114
+ "picture": user_data.get("picture"),
115
+ "verified_email": user_data.get("verified_email"),
116
+ "hd": user_data.get("hd"), # Google Workspace domain
117
+ },
118
+ ),
119
+ )
@@ -0,0 +1,14 @@
1
+ import os
2
+
3
+ # Environment-aware cookie security: only require HTTPS in production
4
+ IS_PRODUCTION = os.getenv("RAGBITS_ENVIRONMENT", "").lower() in ("production", "prod")
5
+
6
+ # Session cookie name - used for storing session ID in HTTP-only cookie
7
+ SESSION_COOKIE_NAME = os.getenv("RAGBITS_COOKIE", "ragbits_session")
8
+
9
+ BASE_URL = os.getenv("RAGBITS_BASE_URL", "http://localhost:8000").rstrip("/")
10
+
11
+ # Chunk size for large base64 images to prevent SSE message size issues
12
+ # Keep chunks extremely small to avoid JSON string length limits in browsers and SSE parsing issues
13
+ # Account for JSON overhead: metadata + base64 data should fit comfortably in browser limits
14
+ CHUNK_SIZE = 102400 # ~100KB bytes base64 chunks for ultra-safe JSON parsing and SSE transmissio
@@ -9,6 +9,8 @@ from abc import ABC, abstractmethod
9
9
  from collections.abc import AsyncGenerator, Callable
10
10
  from typing import Any
11
11
 
12
+ from fastapi import UploadFile
13
+
12
14
  from ragbits.agents.tools.todo import Task
13
15
  from ragbits.chat.interface.summary import HeuristicSummaryGenerator, SummaryGenerator
14
16
  from ragbits.chat.interface.ui_customization import UICustomization
@@ -202,6 +204,16 @@ class ChatInterface(ABC):
202
204
  * Text: Regular text responses streamed chunk by chunk
203
205
  * References: Source documents used to generate the answer
204
206
  * State updates: Updates to the conversation state
207
+
208
+ Attributes:
209
+ upload_handler: Optional async callback for handling file uploads.
210
+ Should accept an UploadFile parameter.
211
+
212
+ Example::
213
+
214
+ async def upload_handler(self, file: UploadFile) -> None:
215
+ content = await file.read()
216
+ # process content
205
217
  """
206
218
 
207
219
  feedback_config: FeedbackConfig = FeedbackConfig()
@@ -211,6 +223,7 @@ class ChatInterface(ABC):
211
223
  ui_customization: UICustomization | None = None
212
224
  history_persistence: HistoryPersistenceStrategy | None = None
213
225
  summary_generator: SummaryGenerator = HeuristicSummaryGenerator()
226
+ upload_handler: Callable[[UploadFile], Any] | None = None
214
227
 
215
228
  def __init_subclass__(cls, **kwargs: dict) -> None:
216
229
  """Automatically apply the with_chat_metadata decorator to the chat method in subclasses."""
@@ -2,8 +2,9 @@ import warnings
2
2
  from abc import ABC, abstractmethod
3
3
  from enum import Enum
4
4
  from typing import Any, Generic, TypeVar, cast
5
+ from zoneinfo import available_timezones
5
6
 
6
- from pydantic import BaseModel, ConfigDict, Field
7
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
7
8
 
8
9
  from ragbits.agents.confirmation import ConfirmationRequest
9
10
  from ragbits.agents.tools.todo import Task
@@ -314,8 +315,20 @@ class ChatContext(BaseModel):
314
315
  default=None,
315
316
  description="List of confirmed/declined tools from the frontend",
316
317
  )
318
+ timezone: str | None = Field(
319
+ default=None,
320
+ description="User's timezone in IANA format (e.g., 'Europe/Warsaw', 'America/New_York')",
321
+ )
317
322
  model_config = ConfigDict(extra="allow")
318
323
 
324
+ @field_validator("timezone")
325
+ @classmethod
326
+ def validate_timezone(cls, v: str | None) -> str | None:
327
+ """Validate that timezone is a valid IANA timezone identifier."""
328
+ if v is not None and v not in available_timezones():
329
+ raise ValueError(f"Invalid timezone: {v}. Must be a valid IANA timezone.")
330
+ return v
331
+
319
332
 
320
333
  # Generic type variable for content, bounded to ResponseContent
321
334
  ChatResponseContentT = TypeVar("ChatResponseContentT", bound=ResponseContent)
@@ -888,6 +901,7 @@ class ConfigResponse(BaseModel):
888
901
  feedback: FeedbackConfig = Field(..., description="Feedback configuration")
889
902
  customization: UICustomization | None = Field(default=None, description="UI customization")
890
903
  user_settings: UserSettings = Field(default_factory=UserSettings, description="User settings")
904
+ supports_upload: bool = Field(default=False, description="Flag indicating whether API supports file upload")
891
905
  debug_mode: bool = Field(default=False, description="Debug mode flag")
892
906
  conversation_history: bool = Field(default=False, description="Flag to enable conversation history")
893
907
  show_usage: bool = Field(default=False, description="Flag to enable usage statistics")
@@ -0,0 +1 @@
1
+ import{r as h,j as e,aW as c,aE as p,c as S,bo as x,bp as l,bq as d,br as m,bs as b}from"./index-CbVbgerL.js";import{a}from"./authStore-AVyfzjgs.js";import{u as j}from"./useInitializeUserStore-CVYyhiv3.js";const v=h.createContext(null);function y({children:t}){const[o]=h.useState(()=>a);return e.jsx(v.Provider,{value:o,children:t})}function U(){const{logout:t,login:o,setHydrated:u}=c(a,f=>f),i=j(),n=p(),s=S("/api/user"),g=x();return h.useEffect(()=>{(async()=>{try{const r=await s.call();r?(o(r),i?i(r.user_id):console.error("Failed to initialize store for user, initializeUserStore() is not defined. Check current HistoryStoreContextProvider implementation."),g.pathname==="/login"&&n("/")):t()}catch(r){console.error("Failed to check session:",r),t(),n("/login")}finally{u()}})()},[]),null}function P({children:t}){const o=x(),u=c(a,s=>s.isAuthenticated),i=c(a,s=>s.hasHydrated),n=c(a,s=>s.logout);return i?o.pathname==="/login"?e.jsx(l,{baseUrl:d,auth:{credentials:"include"},children:t}):u?e.jsx(y,{children:e.jsx(l,{baseUrl:d,auth:{onUnauthorized:n,credentials:"include"},children:t})}):e.jsx(b,{to:"/login",replace:!0}):e.jsxs(l,{baseUrl:d,auth:{credentials:"include"},children:[e.jsx(U,{}),e.jsx(m,{})]})}export{P as default};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-Bvn9K6h_.js","assets/index-BZLU40Mk.js","assets/index-ClAYkAiv.css"])))=>i.map(i=>d[i]);
2
- import{r as P,t as ae,k as Xe,Z as W,ax as Me,$ as Ze,j as t,q as me,L as xe,_ as Ye,n as ye,T as Pe,s as et,v as R,V as tt,d as X,l as se,aq as Ie,o as ot,H as ke,a9 as rt,J as Ne,ay as at,ac as pe,U as st,X as _e,af as he,az as nt,aA as lt,ag as it,K as dt,O as be,Q as ct,W as ut,a0 as pt,ah as ft,a2 as K,a3 as Ae,ai as vt,R as ht,aB as bt,a8 as gt,aC as mt,aD as xt,a5 as yt,a as Pt,aE as Ct,i as fe,aF as Ce,aG as ve,D as we,I as Q,as as wt,aH as $t,aI as $e}from"./index-BZLU40Mk.js";import{u as jt,b as St,c as je,d as Dt,e as Mt,m as It,$ as kt,a as Nt}from"./useMenuTriggerState-SaFmATkk.js";import{$ as _t}from"./useSelectableItem-DhuFnc0W.js";import{i as At}from"./chunk-SSA7SXE4-CJa0HuAU.js";var Ot=(e,r)=>{var n;let s=[];const a=(n=P.Children.map(e,d=>P.isValidElement(d)&&d.type===r?(s.push(d),null):d))==null?void 0:n.filter(Boolean),u=s.length>=0?s:void 0;return[a,u]},Ft=ae({base:["w-full","p-1","min-w-[200px]"]});ae({slots:{base:["flex","group","gap-2","items-center","justify-between","relative","px-2","py-1.5","w-full","h-full","box-border","rounded-small","outline-hidden","cursor-pointer","tap-highlight-transparent","data-[pressed=true]:opacity-70",...Xe,"data-[focus-visible=true]:dark:ring-offset-background-content1"],wrapper:"w-full flex flex-col items-start justify-center",title:"flex-1 text-small font-normal truncate",description:["w-full","text-tiny","text-foreground-500","group-hover:text-current"],selectedIcon:["text-inherit","w-3","h-3","shrink-0"],shortcut:["px-1","py-0.5","rounded-sm","font-sans","text-foreground-500","text-tiny","border-small","border-default-300","group-hover:border-current"]},variants:{variant:{solid:{base:""},bordered:{base:"border-medium border-transparent bg-transparent"},light:{base:"bg-transparent"},faded:{base:"border-small border-transparent hover:border-default data-[hover=true]:bg-default-100"},flat:{base:""},shadow:{base:"data-[hover=true]:shadow-lg"}},color:{default:{},primary:{},secondary:{},success:{},warning:{},danger:{}},isDisabled:{true:{base:"opacity-disabled pointer-events-none"}},disableAnimation:{true:{},false:{}}},defaultVariants:{variant:"solid",color:"default"},compoundVariants:[{variant:"solid",color:"default",class:{base:"data-[hover=true]:bg-default data-[hover=true]:text-default-foreground"}},{variant:"solid",color:"primary",class:{base:"data-[hover=true]:bg-primary data-[hover=true]:text-primary-foreground"}},{variant:"solid",color:"secondary",class:{base:"data-[hover=true]:bg-secondary data-[hover=true]:text-secondary-foreground"}},{variant:"solid",color:"success",class:{base:"data-[hover=true]:bg-success data-[hover=true]:text-success-foreground"}},{variant:"solid",color:"warning",class:{base:"data-[hover=true]:bg-warning data-[hover=true]:text-warning-foreground"}},{variant:"solid",color:"danger",class:{base:"data-[hover=true]:bg-danger data-[hover=true]:text-danger-foreground"}},{variant:"shadow",color:"default",class:{base:"data-[hover=true]:shadow-default/50 data-[hover=true]:bg-default data-[hover=true]:text-default-foreground"}},{variant:"shadow",color:"primary",class:{base:"data-[hover=true]:shadow-primary/30 data-[hover=true]:bg-primary data-[hover=true]:text-primary-foreground"}},{variant:"shadow",color:"secondary",class:{base:"data-[hover=true]:shadow-secondary/30 data-[hover=true]:bg-secondary data-[hover=true]:text-secondary-foreground"}},{variant:"shadow",color:"success",class:{base:"data-[hover=true]:shadow-success/30 data-[hover=true]:bg-success data-[hover=true]:text-success-foreground"}},{variant:"shadow",color:"warning",class:{base:"data-[hover=true]:shadow-warning/30 data-[hover=true]:bg-warning data-[hover=true]:text-warning-foreground"}},{variant:"shadow",color:"danger",class:{base:"data-[hover=true]:shadow-danger/30 data-[hover=true]:bg-danger data-[hover=true]:text-danger-foreground"}},{variant:"bordered",color:"default",class:{base:"data-[hover=true]:border-default"}},{variant:"bordered",color:"primary",class:{base:"data-[hover=true]:border-primary data-[hover=true]:text-primary"}},{variant:"bordered",color:"secondary",class:{base:"data-[hover=true]:border-secondary data-[hover=true]:text-secondary"}},{variant:"bordered",color:"success",class:{base:"data-[hover=true]:border-success data-[hover=true]:text-success"}},{variant:"bordered",color:"warning",class:{base:"data-[hover=true]:border-warning data-[hover=true]:text-warning"}},{variant:"bordered",color:"danger",class:{base:"data-[hover=true]:border-danger data-[hover=true]:text-danger"}},{variant:"flat",color:"default",class:{base:"data-[hover=true]:bg-default/40 data-[hover=true]:text-default-foreground"}},{variant:"flat",color:"primary",class:{base:"data-[hover=true]:bg-primary/20 data-[hover=true]:text-primary"}},{variant:"flat",color:"secondary",class:{base:"data-[hover=true]:bg-secondary/20 data-[hover=true]:text-secondary"}},{variant:"flat",color:"success",class:{base:"data-[hover=true]:bg-success/20 data-[hover=true]:text-success "}},{variant:"flat",color:"warning",class:{base:"data-[hover=true]:bg-warning/20 data-[hover=true]:text-warning"}},{variant:"flat",color:"danger",class:{base:"data-[hover=true]:bg-danger/20 data-[hover=true]:text-danger"}},{variant:"faded",color:"default",class:{base:"data-[hover=true]:text-default-foreground"}},{variant:"faded",color:"primary",class:{base:"data-[hover=true]:text-primary"}},{variant:"faded",color:"secondary",class:{base:"data-[hover=true]:text-secondary"}},{variant:"faded",color:"success",class:{base:"data-[hover=true]:text-success"}},{variant:"faded",color:"warning",class:{base:"data-[hover=true]:text-warning"}},{variant:"faded",color:"danger",class:{base:"data-[hover=true]:text-danger"}},{variant:"light",color:"default",class:{base:"data-[hover=true]:text-default-500"}},{variant:"light",color:"primary",class:{base:"data-[hover=true]:text-primary"}},{variant:"light",color:"secondary",class:{base:"data-[hover=true]:text-secondary"}},{variant:"light",color:"success",class:{base:"data-[hover=true]:text-success"}},{variant:"light",color:"warning",class:{base:"data-[hover=true]:text-warning"}},{variant:"light",color:"danger",class:{base:"data-[hover=true]:text-danger"}}]});ae({slots:{base:"relative mb-2",heading:"pl-1 text-tiny text-foreground-500",group:"data-[has-title=true]:pt-1",divider:"mt-2"}});ae({base:"w-full flex flex-col gap-0.5 p-1"});var Et=(e,r)=>{if(!e&&!r)return{};const n=new Set([...Object.keys(e||{}),...Object.keys(r||{})]);return Array.from(n).reduce((s,a)=>({...s,[a]:W(e?.[a],r?.[a])}),{})},[Tt,Oe]=Me({name:"PopoverContext",errorMessage:"usePopoverContext: `context` is undefined. Seems you forgot to wrap all popover components within `<Popover />`"}),Se=()=>Ye(()=>import("./index-Bvn9K6h_.js"),__vite__mapDeps([0,1,2])).then(e=>e.default),Fe=e=>{const{as:r,children:n,className:s,...a}=e,{Component:u,placement:d,backdrop:h,motionProps:l,disableAnimation:c,getPopoverProps:p,getDialogProps:w,getBackdropProps:b,getContentProps:x,isNonModal:I,onClose:j}=Oe(),f=P.useRef(null),{dialogProps:M,titleProps:D}=Ze({},f),y=w({ref:f,...M,...a}),S=r||u||"div",i=t.jsxs(t.Fragment,{children:[!I&&t.jsx(me,{onDismiss:j}),t.jsx(S,{...y,children:t.jsx("div",{...x({className:s}),children:typeof n=="function"?n(D):n})}),t.jsx(me,{onDismiss:j})]}),v=P.useMemo(()=>h==="transparent"?null:c?t.jsx("div",{...b()}):t.jsx(xe,{features:Se,children:t.jsx(ye.div,{animate:"enter",exit:"exit",initial:"exit",variants:Pe.fade,...b()})}),[h,c,b]),k=d?et(d==="center"?"top":d):void 0,o=t.jsx(t.Fragment,{children:c?i:t.jsx(xe,{features:Se,children:t.jsx(ye.div,{animate:"enter",exit:"exit",initial:"initial",style:k,variants:Pe.scaleSpringOpacity,...l,children:i})})});return t.jsxs("div",{...p(),children:[v,o]})};Fe.displayName="HeroUI.PopoverContent";var Rt=Fe,Ee=e=>{var r;const{triggerRef:n,getTriggerProps:s}=Oe(),{children:a,...u}=e,d=P.useMemo(()=>typeof a=="string"?t.jsx("p",{children:a}):P.Children.only(a),[a]),h=(r=d.props.ref)!=null?r:d.ref,{onPress:l,isDisabled:c,...p}=P.useMemo(()=>s(R(u,d.props),h),[s,d.props,u,h]),[,w]=Ot(a,X),{buttonProps:b}=tt({onPress:l,isDisabled:c},n),x=P.useMemo(()=>w?.[0]!==void 0,[w]);return x||delete p.preventFocusOnPress,P.cloneElement(d,R(p,x?{onPress:l,isDisabled:c}:b))};Ee.displayName="HeroUI.PopoverTrigger";var Ht=Ee,Te=se((e,r)=>{const{children:n,...s}=e,a=jt({...s,ref:r}),[u,d]=P.Children.toArray(n),h=t.jsx(ot,{portalContainer:a.portalContainer,children:d});return t.jsxs(Tt,{value:a,children:[u,a.disableAnimation&&a.isOpen?h:t.jsx(Ie,{children:a.isOpen?h:null})]})});Te.displayName="HeroUI.Popover";var Ut=Te,[Kt,Re]=Me({name:"DropdownContext",errorMessage:"useDropdownContext: `context` is undefined. Seems you forgot to wrap all popover components within `<Dropdown />`"});function Bt(e){const{isSelected:r,disableAnimation:n,...s}=e;return t.jsx("svg",{"aria-hidden":"true","data-selected":r,role:"presentation",viewBox:"0 0 17 18",...s,children:t.jsx("polyline",{fill:"none",points:"1 9 7 14 15 4",stroke:"currentColor",strokeDasharray:22,strokeDashoffset:r?44:66,strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:1.5,style:n?{}:{transition:"stroke-dashoffset 200ms ease"}})})}const He=new WeakMap;function Vt(e,r,n){let{shouldFocusWrap:s=!0,onKeyDown:a,onKeyUp:u,...d}=e;!e["aria-label"]&&e["aria-labelledby"];let h=ke(e,{labelable:!0}),{listProps:l}=rt({...d,ref:n,selectionManager:r.selectionManager,collection:r.collection,disabledKeys:r.disabledKeys,shouldFocusWrap:s,linkBehavior:"override"});return He.set(r,{onClose:e.onClose,onAction:e.onAction,shouldUseVirtualFocus:e.shouldUseVirtualFocus}),{menuProps:Ne(h,{onKeyDown:a,onKeyUp:u},{role:"menu",...l,onKeyDown:c=>{var p;(c.key!=="Escape"||e.shouldUseVirtualFocus)&&((p=l.onKeyDown)===null||p===void 0||p.call(l,c))}})}}function Lt(e,r,n){let{id:s,key:a,closeOnSelect:u,isVirtualized:d,"aria-haspopup":h,onPressStart:l,onPressUp:c,onPress:p,onPressChange:w,onPressEnd:b,onHoverStart:x,onHoverChange:I,onHoverEnd:j,onKeyDown:f,onKeyUp:M,onFocus:D,onFocusChange:y,onBlur:S,selectionManager:i=r.selectionManager}=e,v=!!h,k=v&&e["aria-expanded"]==="true";var o;let C=(o=e.isDisabled)!==null&&o!==void 0?o:i.isDisabled(a);var _;let A=(_=e.isSelected)!==null&&_!==void 0?_:i.isSelected(a),N=He.get(r),g=r.collection.getItem(a),T=e.onClose||N.onClose,B=at(),$=m=>{var J;if(!v){if(!(g==null||(J=g.props)===null||J===void 0)&&J.onAction?g.props.onAction():e.onAction&&e.onAction(a),N.onAction){let ce=N.onAction;ce(a)}m.target instanceof HTMLAnchorElement&&g&&B.open(m.target,m,g.props.href,g.props.routerOptions)}},E="menuitem";v||(i.selectionMode==="single"?E="menuitemradio":i.selectionMode==="multiple"&&(E="menuitemcheckbox"));let O=pe(),H=pe(),q=pe(),V={id:s,"aria-disabled":C||void 0,role:E,"aria-label":e["aria-label"],"aria-labelledby":O,"aria-describedby":[H,q].filter(Boolean).join(" ")||void 0,"aria-controls":e["aria-controls"],"aria-haspopup":h,"aria-expanded":e["aria-expanded"]};i.selectionMode!=="none"&&!v&&(V["aria-checked"]=A),d&&(V["aria-posinset"]=g?.index,V["aria-setsize"]=St(r.collection));let G=m=>{m.pointerType==="keyboard"&&$(m),l?.(m)},Z=()=>{!v&&T&&(u??(i.selectionMode!=="multiple"||i.isLink(a)))&&T()},Y=m=>{m.pointerType==="mouse"&&($(m),Z()),c?.(m)},ne=m=>{m.pointerType!=="keyboard"&&m.pointerType!=="mouse"&&($(m),Z()),p?.(m)},{itemProps:L,isFocused:ee}=_t({id:s,selectionManager:i,key:a,ref:n,shouldSelectOnPressUp:!0,allowsDifferentPressOrigin:!0,linkBehavior:"none",shouldUseVirtualFocus:N.shouldUseVirtualFocus}),{pressProps:le,isPressed:te}=st({onPressStart:G,onPress:ne,onPressUp:Y,onPressChange:w,onPressEnd:b,isDisabled:C}),{hoverProps:ie}=_e({isDisabled:C,onHoverStart(m){!he()&&!(k&&h)&&(i.setFocused(!0),i.setFocusedKey(a)),x?.(m)},onHoverChange:I,onHoverEnd:j}),{keyboardProps:oe}=nt({onKeyDown:m=>{if(m.repeat){m.continuePropagation();return}switch(m.key){case" ":!C&&i.selectionMode==="none"&&!v&&u!==!1&&T&&T();break;case"Enter":!C&&u!==!1&&!v&&T&&T();break;default:v||m.continuePropagation(),f?.(m);break}},onKeyUp:M}),{focusProps:U}=lt({onBlur:S,onFocus:D,onFocusChange:y}),re=ke(g?.props);delete re.id;let de=it(g?.props);return{menuItemProps:{...V,...Ne(re,de,v?{onFocus:L.onFocus,"data-collection":L["data-collection"],"data-key":L["data-key"]}:L,le,ie,oe,U,N.shouldUseVirtualFocus||v?{onMouseDown:m=>m.preventDefault()}:void 0),tabIndex:L.tabIndex!=null&&k&&!N.shouldUseVirtualFocus?-1:L.tabIndex},labelProps:{id:O},descriptionProps:{id:H},keyboardShortcutProps:{id:q},isFocused:ee,isFocusVisible:ee&&i.isFocused&&he()&&!k,isSelected:A,isPressed:te,isDisabled:C}}function zt(e){let{heading:r,"aria-label":n}=e,s=dt();return{itemProps:{role:"presentation"},headingProps:r?{id:s,role:"presentation"}:{},groupProps:{role:"group","aria-label":n,"aria-labelledby":r?s:void 0}}}function Wt(e){var r,n;const s=be(),[a,u]=ct(e,je.variantKeys),{as:d,item:h,state:l,shortcut:c,description:p,startContent:w,endContent:b,isVirtualized:x,selectedIcon:I,className:j,classNames:f,onAction:M,autoFocus:D,onPress:y,onPressStart:S,onPressUp:i,onPressEnd:v,onPressChange:k,onHoverStart:o,onHoverChange:C,onHoverEnd:_,hideSelectedIcon:A=!1,isReadOnly:N=!1,closeOnSelect:g,onClose:T,onClick:B,...$}=a,E=(n=(r=e.disableAnimation)!=null?r:s?.disableAnimation)!=null?n:!1,O=P.useRef(null),H=d||($?.href?"a":"li"),q=typeof H=="string",{rendered:V,key:G}=h,Z=l.disabledKeys.has(G)||e.isDisabled,Y=l.selectionManager.selectionMode!=="none",ne=Dt(),{isFocusVisible:L,focusProps:ee}=ut({autoFocus:D}),le=P.useCallback(F=>{B?.(F),y?.(F)},[B,y]),{isPressed:te,isFocused:ie,isSelected:oe,isDisabled:U,menuItemProps:re,labelProps:de,descriptionProps:m,keyboardShortcutProps:J}=Lt({key:G,onClose:T,isDisabled:Z,onPress:le,onPressStart:S,onPressUp:i,onPressEnd:v,onPressChange:k,"aria-label":a["aria-label"],closeOnSelect:g,isVirtualized:x,onAction:M},l,O);let{hoverProps:ce,isHovered:ge}=_e({isDisabled:U,onHoverStart(F){he()||(l.selectionManager.setFocused(!0),l.selectionManager.setFocusedKey(G)),o?.(F)},onHoverChange:C,onHoverEnd:_}),ue=re;const z=P.useMemo(()=>je({...u,isDisabled:U,disableAnimation:E,hasTitleTextChild:typeof V=="string",hasDescriptionTextChild:typeof p=="string"}),[pt(u),U,E,V,p]),ze=W(f?.base,j);N&&(ue=ft(ue));const We=(F={})=>({ref:O,...R(N?{}:ee,Ae($,{enabled:q}),ue,ce,F),"data-focus":K(ie),"data-selectable":K(Y),"data-hover":K(ne?ge||te:ge),"data-disabled":K(U),"data-selected":K(oe),"data-pressed":K(te),"data-focus-visible":K(L),className:z.base({class:W(ze,F.className)})}),qe=(F={})=>({...R(de,F),className:z.title({class:f?.title})}),Ge=(F={})=>({...R(m,F),className:z.description({class:f?.description})}),Je=(F={})=>({...R(J,F),className:z.shortcut({class:f?.shortcut})}),Qe=P.useCallback((F={})=>({"aria-hidden":K(!0),"data-disabled":K(U),className:z.selectedIcon({class:f?.selectedIcon}),...F}),[U,z,f]);return{Component:H,domRef:O,slots:z,classNames:f,isSelectable:Y,isSelected:oe,isDisabled:U,rendered:V,shortcut:c,description:p,startContent:w,endContent:b,selectedIcon:I,disableAnimation:E,getItemProps:We,getLabelProps:qe,hideSelectedIcon:A,getDescriptionProps:Ge,getKeyboardShortcutProps:Je,getSelectedIconProps:Qe}}var Ue=e=>{const{Component:r,slots:n,classNames:s,rendered:a,shortcut:u,description:d,isSelectable:h,isSelected:l,isDisabled:c,selectedIcon:p,startContent:w,endContent:b,disableAnimation:x,hideSelectedIcon:I,getItemProps:j,getLabelProps:f,getDescriptionProps:M,getKeyboardShortcutProps:D,getSelectedIconProps:y}=Wt(e),S=P.useMemo(()=>{const i=t.jsx(Bt,{disableAnimation:x,isSelected:l});return typeof p=="function"?p({icon:i,isSelected:l,isDisabled:c}):p||i},[p,l,c,x]);return t.jsxs(r,{...j(),children:[w,d?t.jsxs("div",{className:n.wrapper({class:s?.wrapper}),children:[t.jsx("span",{...f(),children:a}),t.jsx("span",{...M(),children:d})]}):t.jsx("span",{...f(),children:a}),u&&t.jsx("kbd",{...D(),children:u}),h&&!I&&t.jsx("span",{...y(),children:S}),b]})};Ue.displayName="HeroUI.MenuItem";var Ke=Ue,Be=se(({item:e,state:r,as:n,variant:s,color:a,disableAnimation:u,onAction:d,closeOnSelect:h,className:l,classNames:c,showDivider:p=!1,hideSelectedIcon:w,dividerProps:b={},itemClasses:x,title:I,...j},f)=>{const M=n||"li",D=P.useMemo(()=>Mt(),[]),y=W(c?.base,l),S=W(c?.divider,b?.className),{itemProps:i,headingProps:v,groupProps:k}=zt({heading:e.rendered,"aria-label":e["aria-label"]});return t.jsxs(M,{"data-slot":"base",...R(i,j),className:D.base({class:y}),children:[e.rendered&&t.jsx("span",{...v,className:D.heading({class:c?.heading}),"data-slot":"heading",children:e.rendered}),t.jsxs("ul",{...k,className:D.group({class:c?.group}),"data-has-title":!!e.rendered,"data-slot":"group",children:[[...e.childNodes].map(o=>{const{key:C,props:_}=o;let A=t.jsx(Ke,{classNames:x,closeOnSelect:h,color:a,disableAnimation:u,hideSelectedIcon:w,item:o,state:r,variant:s,onAction:d,..._},C);return o.wrapper&&(A=o.wrapper(A)),A}),p&&t.jsx(vt,{as:"li",className:D.divider({class:S}),...b})]})]})});Be.displayName="HeroUI.MenuSection";var qt=Be;function Gt(e){var r;const n=be(),{as:s,ref:a,variant:u,color:d,children:h,disableAnimation:l=(r=n?.disableAnimation)!=null?r:!1,onAction:c,closeOnSelect:p,itemClasses:w,className:b,state:x,topContent:I,bottomContent:j,hideEmptyContent:f=!1,hideSelectedIcon:M=!1,emptyContent:D="No items.",menuProps:y,onClose:S,classNames:i,...v}=e,k=s||"ul",o=ht(a),C=typeof k=="string",_=bt({...v,...y,children:h}),A=x||_,{menuProps:N}=Vt({...v,...y,onAction:c},A,o),g=P.useMemo(()=>It({className:b}),[b]),T=W(i?.base,b);return{Component:k,state:A,variant:u,color:d,disableAnimation:l,onClose:S,topContent:I,bottomContent:j,closeOnSelect:p,className:b,itemClasses:w,getBaseProps:(O={})=>({ref:o,"data-slot":"base",className:g.base({class:T}),...Ae(v,{enabled:C}),...O}),getListProps:(O={})=>({"data-slot":"list",className:g.list({class:i?.list}),...N,...O}),hideEmptyContent:f,hideSelectedIcon:M,getEmptyContentProps:(O={})=>({children:D,className:g.emptyContent({class:i?.emptyContent}),...O})}}var Jt=se(function(r,n){const{Component:s,state:a,closeOnSelect:u,color:d,disableAnimation:h,hideSelectedIcon:l,hideEmptyContent:c,variant:p,onClose:w,topContent:b,bottomContent:x,itemClasses:I,getBaseProps:j,getListProps:f,getEmptyContentProps:M}=Gt({...r,ref:n}),D=t.jsxs(s,{...f(),children:[!a.collection.size&&!c&&t.jsx("li",{children:t.jsx("div",{...M()})}),[...a.collection].map(y=>{const S={closeOnSelect:u,color:d,disableAnimation:h,item:y,state:a,variant:p,onClose:w,hideSelectedIcon:l,...y.props},i=Et(I,S?.classNames);if(y.type==="section")return t.jsx(qt,{...S,itemClasses:i},y.key);let v=t.jsx(Ke,{...S,classNames:i},y.key);return y.wrapper&&(v=y.wrapper(v)),v})]});return t.jsxs("div",{...j(),children:[b,D,x]})}),Qt=Jt,Xt=gt,De=Xt,Zt=se(function(r,n){const{getMenuProps:s}=Re();return t.jsx(Rt,{children:t.jsx(mt,{contain:!0,restoreFocus:!0,children:t.jsx(Qt,{...s(r,n)})})})}),Yt=Zt,Ve=e=>{const{getMenuTriggerProps:r}=Re(),{children:n,...s}=e;return t.jsx(Ht,{...r(s),children:n})};Ve.displayName="HeroUI.DropdownTrigger";var eo=Ve,to=(e,r)=>{if(e){const n=Array.isArray(e.children)?e.children:[...e?.items||[]];if(n&&n.length)return n.find(a=>{if(a&&a.key===r)return a})||{}}return null},oo=(e,r,n)=>{const s=n||to(e,r);return s&&s.props&&"closeOnSelect"in s.props?s.props.closeOnSelect:e?.closeOnSelect};function ro(e){var r;const n=be(),{as:s,triggerRef:a,isOpen:u,defaultOpen:d,onOpenChange:h,isDisabled:l,type:c="menu",trigger:p="press",placement:w="bottom",closeOnSelect:b=!0,shouldBlockScroll:x=!0,classNames:I,disableAnimation:j=(r=n?.disableAnimation)!=null?r:!1,onClose:f,className:M,...D}=e,y=s||"div",S=P.useRef(null),i=a||S,v=P.useRef(null),k=P.useRef(null),o=kt({trigger:p,isOpen:u,defaultOpen:d,onOpenChange:$=>{h?.($),$||f?.()}}),{menuTriggerProps:C,menuProps:_}=Nt({type:c,trigger:p,isDisabled:l},o,i),A=P.useMemo(()=>Ft({className:M}),[M]),N=$=>{$!==void 0&&!$||b&&o.close()},g=($={})=>{const E=R(D,$);return{state:o,placement:w,ref:k,disableAnimation:j,shouldBlockScroll:x,scrollRef:v,triggerRef:i,...E,classNames:{...I,...$.classNames,content:W(A,I?.content,$.className)}}},T=($={})=>{const{onPress:E,onPressStart:O,...H}=C;return R(H,{isDisabled:l},$)},B=($,E=null)=>({ref:xt(E,v),menuProps:_,closeOnSelect:b,...R($,{onAction:(O,H)=>{const q=oo($,O,H);N(q)},onClose:o.close})});return{Component:y,menuRef:v,menuProps:_,closeOnSelect:b,onClose:o.close,autoFocus:o.focusStrategy||!0,disableAnimation:j,getPopoverProps:g,getMenuProps:B,getMenuTriggerProps:T}}var Le=e=>{const{children:r,...n}=e,s=ro(n),[a,u]=yt.Children.toArray(r);return t.jsx(Kt,{value:s,children:t.jsxs(Ut,{...s.getPopoverProps(),children:[a,u]})})};Le.displayName="HeroUI.Dropdown";var ao=Le;function co(){const{selectConversation:e,deleteConversation:r,newConversation:n,setConversationProperties:s}=Pt(),a=Ct(),u=fe(Ce(o=>Object.keys(o.conversations).reverse())),d=fe(Ce(o=>Object.values(o.conversations).reverse().map(C=>C.summary))),h=fe(o=>o.currentConversation),[l,c]=P.useState(!1),[p,w]=P.useState(null),[b,x]=P.useState(""),[I,j]=P.useState(!1),f=P.useRef(null),M=l?"Open sidebar":"Close sidebar",D=t.jsx(Q,{icon:"heroicons:pencil-square"}),y=(o,C)=>{w(o),x(C??""),j(!0),setTimeout(()=>{f.current?.focus?.(),setTimeout(()=>j(!1),120)},0)},S=o=>{if(p!==o)return;const C=(b||"").trim();C&&s(o,{summary:C}),w(null),x(""),j(!1)},i=()=>{w(null),x(""),j(!1)},v=()=>{const o=n();a($e(o))},k=o=>{e(o),a($e(o))};return t.jsx(ve.div,{initial:!1,animate:{maxWidth:l?"4.5rem":"16rem"},className:"rounded-l-medium border-small border-divider ml-4 flex h-full w-full min-w-[4.5rem] flex-grow flex-col space-y-2 overflow-hidden border-r-0 p-4 py-3",children:t.jsxs(Ie,{children:[t.jsx(we,{content:M,placement:"bottom",children:t.jsx(X,{isIconOnly:!0,"aria-label":M,variant:"ghost",onPress:()=>c(o=>!o),"data-testid":"chat-history-collapse-button",className:"ml-auto",children:t.jsx(Q,{icon:l?"heroicons:chevron-double-right":"heroicons:chevron-double-left"})})},"collapse-button"),!l&&t.jsx(ve.p,{initial:!1,animate:{opacity:1,width:"100%",height:"auto"},exit:{opacity:0,width:0,height:0,marginBottom:0},className:"text-small text-foreground truncate leading-5 font-semibold",children:"Conversations"},"conversations"),t.jsx(we,{content:"New conversation",placement:"right",children:t.jsx(X,{"aria-label":"New conversation",variant:"ghost",onPress:v,"data-testid":"chat-history-clear-chat-button",startContent:D,isIconOnly:l,children:!l&&"New conversation"})},"new-conversation-button"),!l&&t.jsx(ve.div,{className:"mt-2 flex flex-1 flex-col gap-2 overflow-auto overflow-x-hidden",initial:!1,animate:{opacity:1,width:"100%"},exit:{opacity:0,width:0},children:wt.zip(u,d).map(([o,C])=>{if(!o||$t(o))return null;const _=o===h,A=o===p,N=_?"solid":"light";return t.jsxs("div",{className:"flex w-full justify-between gap-2",children:[A?t.jsx(At,{ref:f,size:"sm",variant:"bordered",value:b,onChange:g=>x(g.target.value),onBlur:()=>{I||S(o)},onKeyDown:g=>{g.key==="Enter"&&S(o),g.key==="Escape"&&i()},className:"flex-1","data-testid":`input-conversation-${o}`}):t.jsx(X,{variant:N,"aria-label":`Select conversation ${o}`,"data-active":_,onPress:()=>k(o),title:C??o,"data-testid":`select-conversation-${o}`,className:"flex-1 justify-start",children:t.jsx("div",{className:"text-small truncate",children:C??o})}),t.jsxs(ao,{children:[t.jsx(eo,{children:t.jsx(X,{isIconOnly:!0,variant:"light","aria-label":`Conversation actions for ${o}`,"data-testid":`dropdown-conversation-${o}`,children:t.jsx(Q,{icon:"heroicons:ellipsis-vertical",className:"rotate-90"})})}),t.jsxs(Yt,{"aria-label":"Conversation actions",children:[t.jsx(De,{startContent:t.jsx(Q,{icon:"heroicons:pencil-square",className:"mb-0.5"}),onPress:()=>y(o,C??o),"data-testid":`edit-conversation-${o}`,children:"Edit"},"edit"),t.jsx(De,{className:"text-danger mb-0.5",color:"danger",startContent:t.jsx(Q,{icon:"heroicons:trash"}),onPress:()=>r(o),"data-testid":`delete-conversation-${o}`,children:"Delete conversation"},"delete")]})]})]},`${o}-${N}`)})},"conversation-list")]})})}export{co as default};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-BcnaGCUm.js","assets/index-CbVbgerL.js","assets/index-B1u136LF.css"])))=>i.map(i=>d[i]);
2
+ import{r as P,t as ae,k as Xe,Z as W,ax as Me,$ as Ze,j as t,q as me,L as xe,_ as Ye,n as ye,T as Pe,s as et,v as R,V as tt,d as X,l as se,aq as Ie,o as ot,H as ke,a9 as rt,J as Ne,ay as at,ac as pe,U as st,X as _e,af as he,az as nt,aA as lt,ag as it,K as dt,O as be,Q as ct,W as ut,a0 as pt,ah as ft,a2 as K,a3 as Ae,ai as vt,R as ht,aB as bt,a8 as gt,aC as mt,aD as xt,a5 as yt,a as Pt,aE as Ct,i as fe,aF as Ce,aG as ve,D as we,I as Q,as as wt,aH as $t,aI as $e}from"./index-CbVbgerL.js";import{u as jt,b as St,c as je,d as Dt,e as Mt,m as It,$ as kt,a as Nt}from"./useMenuTriggerState-C5916IcO.js";import{$ as _t}from"./useSelectableItem-BWC6EImE.js";import{i as At}from"./chunk-SSA7SXE4-D3GKTPj0.js";var Ot=(e,r)=>{var n;let s=[];const a=(n=P.Children.map(e,d=>P.isValidElement(d)&&d.type===r?(s.push(d),null):d))==null?void 0:n.filter(Boolean),u=s.length>=0?s:void 0;return[a,u]},Ft=ae({base:["w-full","p-1","min-w-[200px]"]});ae({slots:{base:["flex","group","gap-2","items-center","justify-between","relative","px-2","py-1.5","w-full","h-full","box-border","rounded-small","outline-hidden","cursor-pointer","tap-highlight-transparent","data-[pressed=true]:opacity-70",...Xe,"data-[focus-visible=true]:dark:ring-offset-background-content1"],wrapper:"w-full flex flex-col items-start justify-center",title:"flex-1 text-small font-normal truncate",description:["w-full","text-tiny","text-foreground-500","group-hover:text-current"],selectedIcon:["text-inherit","w-3","h-3","shrink-0"],shortcut:["px-1","py-0.5","rounded-sm","font-sans","text-foreground-500","text-tiny","border-small","border-default-300","group-hover:border-current"]},variants:{variant:{solid:{base:""},bordered:{base:"border-medium border-transparent bg-transparent"},light:{base:"bg-transparent"},faded:{base:"border-small border-transparent hover:border-default data-[hover=true]:bg-default-100"},flat:{base:""},shadow:{base:"data-[hover=true]:shadow-lg"}},color:{default:{},primary:{},secondary:{},success:{},warning:{},danger:{}},isDisabled:{true:{base:"opacity-disabled pointer-events-none"}},disableAnimation:{true:{},false:{}}},defaultVariants:{variant:"solid",color:"default"},compoundVariants:[{variant:"solid",color:"default",class:{base:"data-[hover=true]:bg-default data-[hover=true]:text-default-foreground"}},{variant:"solid",color:"primary",class:{base:"data-[hover=true]:bg-primary data-[hover=true]:text-primary-foreground"}},{variant:"solid",color:"secondary",class:{base:"data-[hover=true]:bg-secondary data-[hover=true]:text-secondary-foreground"}},{variant:"solid",color:"success",class:{base:"data-[hover=true]:bg-success data-[hover=true]:text-success-foreground"}},{variant:"solid",color:"warning",class:{base:"data-[hover=true]:bg-warning data-[hover=true]:text-warning-foreground"}},{variant:"solid",color:"danger",class:{base:"data-[hover=true]:bg-danger data-[hover=true]:text-danger-foreground"}},{variant:"shadow",color:"default",class:{base:"data-[hover=true]:shadow-default/50 data-[hover=true]:bg-default data-[hover=true]:text-default-foreground"}},{variant:"shadow",color:"primary",class:{base:"data-[hover=true]:shadow-primary/30 data-[hover=true]:bg-primary data-[hover=true]:text-primary-foreground"}},{variant:"shadow",color:"secondary",class:{base:"data-[hover=true]:shadow-secondary/30 data-[hover=true]:bg-secondary data-[hover=true]:text-secondary-foreground"}},{variant:"shadow",color:"success",class:{base:"data-[hover=true]:shadow-success/30 data-[hover=true]:bg-success data-[hover=true]:text-success-foreground"}},{variant:"shadow",color:"warning",class:{base:"data-[hover=true]:shadow-warning/30 data-[hover=true]:bg-warning data-[hover=true]:text-warning-foreground"}},{variant:"shadow",color:"danger",class:{base:"data-[hover=true]:shadow-danger/30 data-[hover=true]:bg-danger data-[hover=true]:text-danger-foreground"}},{variant:"bordered",color:"default",class:{base:"data-[hover=true]:border-default"}},{variant:"bordered",color:"primary",class:{base:"data-[hover=true]:border-primary data-[hover=true]:text-primary"}},{variant:"bordered",color:"secondary",class:{base:"data-[hover=true]:border-secondary data-[hover=true]:text-secondary"}},{variant:"bordered",color:"success",class:{base:"data-[hover=true]:border-success data-[hover=true]:text-success"}},{variant:"bordered",color:"warning",class:{base:"data-[hover=true]:border-warning data-[hover=true]:text-warning"}},{variant:"bordered",color:"danger",class:{base:"data-[hover=true]:border-danger data-[hover=true]:text-danger"}},{variant:"flat",color:"default",class:{base:"data-[hover=true]:bg-default/40 data-[hover=true]:text-default-foreground"}},{variant:"flat",color:"primary",class:{base:"data-[hover=true]:bg-primary/20 data-[hover=true]:text-primary"}},{variant:"flat",color:"secondary",class:{base:"data-[hover=true]:bg-secondary/20 data-[hover=true]:text-secondary"}},{variant:"flat",color:"success",class:{base:"data-[hover=true]:bg-success/20 data-[hover=true]:text-success "}},{variant:"flat",color:"warning",class:{base:"data-[hover=true]:bg-warning/20 data-[hover=true]:text-warning"}},{variant:"flat",color:"danger",class:{base:"data-[hover=true]:bg-danger/20 data-[hover=true]:text-danger"}},{variant:"faded",color:"default",class:{base:"data-[hover=true]:text-default-foreground"}},{variant:"faded",color:"primary",class:{base:"data-[hover=true]:text-primary"}},{variant:"faded",color:"secondary",class:{base:"data-[hover=true]:text-secondary"}},{variant:"faded",color:"success",class:{base:"data-[hover=true]:text-success"}},{variant:"faded",color:"warning",class:{base:"data-[hover=true]:text-warning"}},{variant:"faded",color:"danger",class:{base:"data-[hover=true]:text-danger"}},{variant:"light",color:"default",class:{base:"data-[hover=true]:text-default-500"}},{variant:"light",color:"primary",class:{base:"data-[hover=true]:text-primary"}},{variant:"light",color:"secondary",class:{base:"data-[hover=true]:text-secondary"}},{variant:"light",color:"success",class:{base:"data-[hover=true]:text-success"}},{variant:"light",color:"warning",class:{base:"data-[hover=true]:text-warning"}},{variant:"light",color:"danger",class:{base:"data-[hover=true]:text-danger"}}]});ae({slots:{base:"relative mb-2",heading:"pl-1 text-tiny text-foreground-500",group:"data-[has-title=true]:pt-1",divider:"mt-2"}});ae({base:"w-full flex flex-col gap-0.5 p-1"});var Et=(e,r)=>{if(!e&&!r)return{};const n=new Set([...Object.keys(e||{}),...Object.keys(r||{})]);return Array.from(n).reduce((s,a)=>({...s,[a]:W(e?.[a],r?.[a])}),{})},[Tt,Oe]=Me({name:"PopoverContext",errorMessage:"usePopoverContext: `context` is undefined. Seems you forgot to wrap all popover components within `<Popover />`"}),Se=()=>Ye(()=>import("./index-BcnaGCUm.js"),__vite__mapDeps([0,1,2])).then(e=>e.default),Fe=e=>{const{as:r,children:n,className:s,...a}=e,{Component:u,placement:d,backdrop:h,motionProps:l,disableAnimation:c,getPopoverProps:p,getDialogProps:w,getBackdropProps:b,getContentProps:x,isNonModal:I,onClose:j}=Oe(),f=P.useRef(null),{dialogProps:M,titleProps:D}=Ze({},f),y=w({ref:f,...M,...a}),S=r||u||"div",i=t.jsxs(t.Fragment,{children:[!I&&t.jsx(me,{onDismiss:j}),t.jsx(S,{...y,children:t.jsx("div",{...x({className:s}),children:typeof n=="function"?n(D):n})}),t.jsx(me,{onDismiss:j})]}),v=P.useMemo(()=>h==="transparent"?null:c?t.jsx("div",{...b()}):t.jsx(xe,{features:Se,children:t.jsx(ye.div,{animate:"enter",exit:"exit",initial:"exit",variants:Pe.fade,...b()})}),[h,c,b]),k=d?et(d==="center"?"top":d):void 0,o=t.jsx(t.Fragment,{children:c?i:t.jsx(xe,{features:Se,children:t.jsx(ye.div,{animate:"enter",exit:"exit",initial:"initial",style:k,variants:Pe.scaleSpringOpacity,...l,children:i})})});return t.jsxs("div",{...p(),children:[v,o]})};Fe.displayName="HeroUI.PopoverContent";var Rt=Fe,Ee=e=>{var r;const{triggerRef:n,getTriggerProps:s}=Oe(),{children:a,...u}=e,d=P.useMemo(()=>typeof a=="string"?t.jsx("p",{children:a}):P.Children.only(a),[a]),h=(r=d.props.ref)!=null?r:d.ref,{onPress:l,isDisabled:c,...p}=P.useMemo(()=>s(R(u,d.props),h),[s,d.props,u,h]),[,w]=Ot(a,X),{buttonProps:b}=tt({onPress:l,isDisabled:c},n),x=P.useMemo(()=>w?.[0]!==void 0,[w]);return x||delete p.preventFocusOnPress,P.cloneElement(d,R(p,x?{onPress:l,isDisabled:c}:b))};Ee.displayName="HeroUI.PopoverTrigger";var Ht=Ee,Te=se((e,r)=>{const{children:n,...s}=e,a=jt({...s,ref:r}),[u,d]=P.Children.toArray(n),h=t.jsx(ot,{portalContainer:a.portalContainer,children:d});return t.jsxs(Tt,{value:a,children:[u,a.disableAnimation&&a.isOpen?h:t.jsx(Ie,{children:a.isOpen?h:null})]})});Te.displayName="HeroUI.Popover";var Ut=Te,[Kt,Re]=Me({name:"DropdownContext",errorMessage:"useDropdownContext: `context` is undefined. Seems you forgot to wrap all popover components within `<Dropdown />`"});function Bt(e){const{isSelected:r,disableAnimation:n,...s}=e;return t.jsx("svg",{"aria-hidden":"true","data-selected":r,role:"presentation",viewBox:"0 0 17 18",...s,children:t.jsx("polyline",{fill:"none",points:"1 9 7 14 15 4",stroke:"currentColor",strokeDasharray:22,strokeDashoffset:r?44:66,strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:1.5,style:n?{}:{transition:"stroke-dashoffset 200ms ease"}})})}const He=new WeakMap;function Vt(e,r,n){let{shouldFocusWrap:s=!0,onKeyDown:a,onKeyUp:u,...d}=e;!e["aria-label"]&&e["aria-labelledby"];let h=ke(e,{labelable:!0}),{listProps:l}=rt({...d,ref:n,selectionManager:r.selectionManager,collection:r.collection,disabledKeys:r.disabledKeys,shouldFocusWrap:s,linkBehavior:"override"});return He.set(r,{onClose:e.onClose,onAction:e.onAction,shouldUseVirtualFocus:e.shouldUseVirtualFocus}),{menuProps:Ne(h,{onKeyDown:a,onKeyUp:u},{role:"menu",...l,onKeyDown:c=>{var p;(c.key!=="Escape"||e.shouldUseVirtualFocus)&&((p=l.onKeyDown)===null||p===void 0||p.call(l,c))}})}}function Lt(e,r,n){let{id:s,key:a,closeOnSelect:u,isVirtualized:d,"aria-haspopup":h,onPressStart:l,onPressUp:c,onPress:p,onPressChange:w,onPressEnd:b,onHoverStart:x,onHoverChange:I,onHoverEnd:j,onKeyDown:f,onKeyUp:M,onFocus:D,onFocusChange:y,onBlur:S,selectionManager:i=r.selectionManager}=e,v=!!h,k=v&&e["aria-expanded"]==="true";var o;let C=(o=e.isDisabled)!==null&&o!==void 0?o:i.isDisabled(a);var _;let A=(_=e.isSelected)!==null&&_!==void 0?_:i.isSelected(a),N=He.get(r),g=r.collection.getItem(a),T=e.onClose||N.onClose,B=at(),$=m=>{var J;if(!v){if(!(g==null||(J=g.props)===null||J===void 0)&&J.onAction?g.props.onAction():e.onAction&&e.onAction(a),N.onAction){let ce=N.onAction;ce(a)}m.target instanceof HTMLAnchorElement&&g&&B.open(m.target,m,g.props.href,g.props.routerOptions)}},E="menuitem";v||(i.selectionMode==="single"?E="menuitemradio":i.selectionMode==="multiple"&&(E="menuitemcheckbox"));let O=pe(),H=pe(),q=pe(),V={id:s,"aria-disabled":C||void 0,role:E,"aria-label":e["aria-label"],"aria-labelledby":O,"aria-describedby":[H,q].filter(Boolean).join(" ")||void 0,"aria-controls":e["aria-controls"],"aria-haspopup":h,"aria-expanded":e["aria-expanded"]};i.selectionMode!=="none"&&!v&&(V["aria-checked"]=A),d&&(V["aria-posinset"]=g?.index,V["aria-setsize"]=St(r.collection));let G=m=>{m.pointerType==="keyboard"&&$(m),l?.(m)},Z=()=>{!v&&T&&(u??(i.selectionMode!=="multiple"||i.isLink(a)))&&T()},Y=m=>{m.pointerType==="mouse"&&($(m),Z()),c?.(m)},ne=m=>{m.pointerType!=="keyboard"&&m.pointerType!=="mouse"&&($(m),Z()),p?.(m)},{itemProps:L,isFocused:ee}=_t({id:s,selectionManager:i,key:a,ref:n,shouldSelectOnPressUp:!0,allowsDifferentPressOrigin:!0,linkBehavior:"none",shouldUseVirtualFocus:N.shouldUseVirtualFocus}),{pressProps:le,isPressed:te}=st({onPressStart:G,onPress:ne,onPressUp:Y,onPressChange:w,onPressEnd:b,isDisabled:C}),{hoverProps:ie}=_e({isDisabled:C,onHoverStart(m){!he()&&!(k&&h)&&(i.setFocused(!0),i.setFocusedKey(a)),x?.(m)},onHoverChange:I,onHoverEnd:j}),{keyboardProps:oe}=nt({onKeyDown:m=>{if(m.repeat){m.continuePropagation();return}switch(m.key){case" ":!C&&i.selectionMode==="none"&&!v&&u!==!1&&T&&T();break;case"Enter":!C&&u!==!1&&!v&&T&&T();break;default:v||m.continuePropagation(),f?.(m);break}},onKeyUp:M}),{focusProps:U}=lt({onBlur:S,onFocus:D,onFocusChange:y}),re=ke(g?.props);delete re.id;let de=it(g?.props);return{menuItemProps:{...V,...Ne(re,de,v?{onFocus:L.onFocus,"data-collection":L["data-collection"],"data-key":L["data-key"]}:L,le,ie,oe,U,N.shouldUseVirtualFocus||v?{onMouseDown:m=>m.preventDefault()}:void 0),tabIndex:L.tabIndex!=null&&k&&!N.shouldUseVirtualFocus?-1:L.tabIndex},labelProps:{id:O},descriptionProps:{id:H},keyboardShortcutProps:{id:q},isFocused:ee,isFocusVisible:ee&&i.isFocused&&he()&&!k,isSelected:A,isPressed:te,isDisabled:C}}function zt(e){let{heading:r,"aria-label":n}=e,s=dt();return{itemProps:{role:"presentation"},headingProps:r?{id:s,role:"presentation"}:{},groupProps:{role:"group","aria-label":n,"aria-labelledby":r?s:void 0}}}function Wt(e){var r,n;const s=be(),[a,u]=ct(e,je.variantKeys),{as:d,item:h,state:l,shortcut:c,description:p,startContent:w,endContent:b,isVirtualized:x,selectedIcon:I,className:j,classNames:f,onAction:M,autoFocus:D,onPress:y,onPressStart:S,onPressUp:i,onPressEnd:v,onPressChange:k,onHoverStart:o,onHoverChange:C,onHoverEnd:_,hideSelectedIcon:A=!1,isReadOnly:N=!1,closeOnSelect:g,onClose:T,onClick:B,...$}=a,E=(n=(r=e.disableAnimation)!=null?r:s?.disableAnimation)!=null?n:!1,O=P.useRef(null),H=d||($?.href?"a":"li"),q=typeof H=="string",{rendered:V,key:G}=h,Z=l.disabledKeys.has(G)||e.isDisabled,Y=l.selectionManager.selectionMode!=="none",ne=Dt(),{isFocusVisible:L,focusProps:ee}=ut({autoFocus:D}),le=P.useCallback(F=>{B?.(F),y?.(F)},[B,y]),{isPressed:te,isFocused:ie,isSelected:oe,isDisabled:U,menuItemProps:re,labelProps:de,descriptionProps:m,keyboardShortcutProps:J}=Lt({key:G,onClose:T,isDisabled:Z,onPress:le,onPressStart:S,onPressUp:i,onPressEnd:v,onPressChange:k,"aria-label":a["aria-label"],closeOnSelect:g,isVirtualized:x,onAction:M},l,O);let{hoverProps:ce,isHovered:ge}=_e({isDisabled:U,onHoverStart(F){he()||(l.selectionManager.setFocused(!0),l.selectionManager.setFocusedKey(G)),o?.(F)},onHoverChange:C,onHoverEnd:_}),ue=re;const z=P.useMemo(()=>je({...u,isDisabled:U,disableAnimation:E,hasTitleTextChild:typeof V=="string",hasDescriptionTextChild:typeof p=="string"}),[pt(u),U,E,V,p]),ze=W(f?.base,j);N&&(ue=ft(ue));const We=(F={})=>({ref:O,...R(N?{}:ee,Ae($,{enabled:q}),ue,ce,F),"data-focus":K(ie),"data-selectable":K(Y),"data-hover":K(ne?ge||te:ge),"data-disabled":K(U),"data-selected":K(oe),"data-pressed":K(te),"data-focus-visible":K(L),className:z.base({class:W(ze,F.className)})}),qe=(F={})=>({...R(de,F),className:z.title({class:f?.title})}),Ge=(F={})=>({...R(m,F),className:z.description({class:f?.description})}),Je=(F={})=>({...R(J,F),className:z.shortcut({class:f?.shortcut})}),Qe=P.useCallback((F={})=>({"aria-hidden":K(!0),"data-disabled":K(U),className:z.selectedIcon({class:f?.selectedIcon}),...F}),[U,z,f]);return{Component:H,domRef:O,slots:z,classNames:f,isSelectable:Y,isSelected:oe,isDisabled:U,rendered:V,shortcut:c,description:p,startContent:w,endContent:b,selectedIcon:I,disableAnimation:E,getItemProps:We,getLabelProps:qe,hideSelectedIcon:A,getDescriptionProps:Ge,getKeyboardShortcutProps:Je,getSelectedIconProps:Qe}}var Ue=e=>{const{Component:r,slots:n,classNames:s,rendered:a,shortcut:u,description:d,isSelectable:h,isSelected:l,isDisabled:c,selectedIcon:p,startContent:w,endContent:b,disableAnimation:x,hideSelectedIcon:I,getItemProps:j,getLabelProps:f,getDescriptionProps:M,getKeyboardShortcutProps:D,getSelectedIconProps:y}=Wt(e),S=P.useMemo(()=>{const i=t.jsx(Bt,{disableAnimation:x,isSelected:l});return typeof p=="function"?p({icon:i,isSelected:l,isDisabled:c}):p||i},[p,l,c,x]);return t.jsxs(r,{...j(),children:[w,d?t.jsxs("div",{className:n.wrapper({class:s?.wrapper}),children:[t.jsx("span",{...f(),children:a}),t.jsx("span",{...M(),children:d})]}):t.jsx("span",{...f(),children:a}),u&&t.jsx("kbd",{...D(),children:u}),h&&!I&&t.jsx("span",{...y(),children:S}),b]})};Ue.displayName="HeroUI.MenuItem";var Ke=Ue,Be=se(({item:e,state:r,as:n,variant:s,color:a,disableAnimation:u,onAction:d,closeOnSelect:h,className:l,classNames:c,showDivider:p=!1,hideSelectedIcon:w,dividerProps:b={},itemClasses:x,title:I,...j},f)=>{const M=n||"li",D=P.useMemo(()=>Mt(),[]),y=W(c?.base,l),S=W(c?.divider,b?.className),{itemProps:i,headingProps:v,groupProps:k}=zt({heading:e.rendered,"aria-label":e["aria-label"]});return t.jsxs(M,{"data-slot":"base",...R(i,j),className:D.base({class:y}),children:[e.rendered&&t.jsx("span",{...v,className:D.heading({class:c?.heading}),"data-slot":"heading",children:e.rendered}),t.jsxs("ul",{...k,className:D.group({class:c?.group}),"data-has-title":!!e.rendered,"data-slot":"group",children:[[...e.childNodes].map(o=>{const{key:C,props:_}=o;let A=t.jsx(Ke,{classNames:x,closeOnSelect:h,color:a,disableAnimation:u,hideSelectedIcon:w,item:o,state:r,variant:s,onAction:d,..._},C);return o.wrapper&&(A=o.wrapper(A)),A}),p&&t.jsx(vt,{as:"li",className:D.divider({class:S}),...b})]})]})});Be.displayName="HeroUI.MenuSection";var qt=Be;function Gt(e){var r;const n=be(),{as:s,ref:a,variant:u,color:d,children:h,disableAnimation:l=(r=n?.disableAnimation)!=null?r:!1,onAction:c,closeOnSelect:p,itemClasses:w,className:b,state:x,topContent:I,bottomContent:j,hideEmptyContent:f=!1,hideSelectedIcon:M=!1,emptyContent:D="No items.",menuProps:y,onClose:S,classNames:i,...v}=e,k=s||"ul",o=ht(a),C=typeof k=="string",_=bt({...v,...y,children:h}),A=x||_,{menuProps:N}=Vt({...v,...y,onAction:c},A,o),g=P.useMemo(()=>It({className:b}),[b]),T=W(i?.base,b);return{Component:k,state:A,variant:u,color:d,disableAnimation:l,onClose:S,topContent:I,bottomContent:j,closeOnSelect:p,className:b,itemClasses:w,getBaseProps:(O={})=>({ref:o,"data-slot":"base",className:g.base({class:T}),...Ae(v,{enabled:C}),...O}),getListProps:(O={})=>({"data-slot":"list",className:g.list({class:i?.list}),...N,...O}),hideEmptyContent:f,hideSelectedIcon:M,getEmptyContentProps:(O={})=>({children:D,className:g.emptyContent({class:i?.emptyContent}),...O})}}var Jt=se(function(r,n){const{Component:s,state:a,closeOnSelect:u,color:d,disableAnimation:h,hideSelectedIcon:l,hideEmptyContent:c,variant:p,onClose:w,topContent:b,bottomContent:x,itemClasses:I,getBaseProps:j,getListProps:f,getEmptyContentProps:M}=Gt({...r,ref:n}),D=t.jsxs(s,{...f(),children:[!a.collection.size&&!c&&t.jsx("li",{children:t.jsx("div",{...M()})}),[...a.collection].map(y=>{const S={closeOnSelect:u,color:d,disableAnimation:h,item:y,state:a,variant:p,onClose:w,hideSelectedIcon:l,...y.props},i=Et(I,S?.classNames);if(y.type==="section")return t.jsx(qt,{...S,itemClasses:i},y.key);let v=t.jsx(Ke,{...S,classNames:i},y.key);return y.wrapper&&(v=y.wrapper(v)),v})]});return t.jsxs("div",{...j(),children:[b,D,x]})}),Qt=Jt,Xt=gt,De=Xt,Zt=se(function(r,n){const{getMenuProps:s}=Re();return t.jsx(Rt,{children:t.jsx(mt,{contain:!0,restoreFocus:!0,children:t.jsx(Qt,{...s(r,n)})})})}),Yt=Zt,Ve=e=>{const{getMenuTriggerProps:r}=Re(),{children:n,...s}=e;return t.jsx(Ht,{...r(s),children:n})};Ve.displayName="HeroUI.DropdownTrigger";var eo=Ve,to=(e,r)=>{if(e){const n=Array.isArray(e.children)?e.children:[...e?.items||[]];if(n&&n.length)return n.find(a=>{if(a&&a.key===r)return a})||{}}return null},oo=(e,r,n)=>{const s=n||to(e,r);return s&&s.props&&"closeOnSelect"in s.props?s.props.closeOnSelect:e?.closeOnSelect};function ro(e){var r;const n=be(),{as:s,triggerRef:a,isOpen:u,defaultOpen:d,onOpenChange:h,isDisabled:l,type:c="menu",trigger:p="press",placement:w="bottom",closeOnSelect:b=!0,shouldBlockScroll:x=!0,classNames:I,disableAnimation:j=(r=n?.disableAnimation)!=null?r:!1,onClose:f,className:M,...D}=e,y=s||"div",S=P.useRef(null),i=a||S,v=P.useRef(null),k=P.useRef(null),o=kt({trigger:p,isOpen:u,defaultOpen:d,onOpenChange:$=>{h?.($),$||f?.()}}),{menuTriggerProps:C,menuProps:_}=Nt({type:c,trigger:p,isDisabled:l},o,i),A=P.useMemo(()=>Ft({className:M}),[M]),N=$=>{$!==void 0&&!$||b&&o.close()},g=($={})=>{const E=R(D,$);return{state:o,placement:w,ref:k,disableAnimation:j,shouldBlockScroll:x,scrollRef:v,triggerRef:i,...E,classNames:{...I,...$.classNames,content:W(A,I?.content,$.className)}}},T=($={})=>{const{onPress:E,onPressStart:O,...H}=C;return R(H,{isDisabled:l},$)},B=($,E=null)=>({ref:xt(E,v),menuProps:_,closeOnSelect:b,...R($,{onAction:(O,H)=>{const q=oo($,O,H);N(q)},onClose:o.close})});return{Component:y,menuRef:v,menuProps:_,closeOnSelect:b,onClose:o.close,autoFocus:o.focusStrategy||!0,disableAnimation:j,getPopoverProps:g,getMenuProps:B,getMenuTriggerProps:T}}var Le=e=>{const{children:r,...n}=e,s=ro(n),[a,u]=yt.Children.toArray(r);return t.jsx(Kt,{value:s,children:t.jsxs(Ut,{...s.getPopoverProps(),children:[a,u]})})};Le.displayName="HeroUI.Dropdown";var ao=Le;function co(){const{selectConversation:e,deleteConversation:r,newConversation:n,setConversationProperties:s}=Pt(),a=Ct(),u=fe(Ce(o=>Object.keys(o.conversations).reverse())),d=fe(Ce(o=>Object.values(o.conversations).reverse().map(C=>C.summary))),h=fe(o=>o.currentConversation),[l,c]=P.useState(!1),[p,w]=P.useState(null),[b,x]=P.useState(""),[I,j]=P.useState(!1),f=P.useRef(null),M=l?"Open sidebar":"Close sidebar",D=t.jsx(Q,{icon:"heroicons:pencil-square"}),y=(o,C)=>{w(o),x(C??""),j(!0),setTimeout(()=>{f.current?.focus?.(),setTimeout(()=>j(!1),120)},0)},S=o=>{if(p!==o)return;const C=(b||"").trim();C&&s(o,{summary:C}),w(null),x(""),j(!1)},i=()=>{w(null),x(""),j(!1)},v=()=>{const o=n();a($e(o))},k=o=>{e(o),a($e(o))};return t.jsx(ve.div,{initial:!1,animate:{maxWidth:l?"4.5rem":"16rem"},className:"rounded-l-medium border-small border-divider ml-4 flex h-full w-full min-w-[4.5rem] flex-grow flex-col space-y-2 overflow-hidden border-r-0 p-4 py-3",children:t.jsxs(Ie,{children:[t.jsx(we,{content:M,placement:"bottom",children:t.jsx(X,{isIconOnly:!0,"aria-label":M,variant:"ghost",onPress:()=>c(o=>!o),"data-testid":"chat-history-collapse-button",className:"ml-auto",children:t.jsx(Q,{icon:l?"heroicons:chevron-double-right":"heroicons:chevron-double-left"})})},"collapse-button"),!l&&t.jsx(ve.p,{initial:!1,animate:{opacity:1,width:"100%",height:"auto"},exit:{opacity:0,width:0,height:0,marginBottom:0},className:"text-small text-foreground truncate leading-5 font-semibold",children:"Conversations"},"conversations"),t.jsx(we,{content:"New conversation",placement:"right",children:t.jsx(X,{"aria-label":"New conversation",variant:"ghost",onPress:v,"data-testid":"chat-history-clear-chat-button",startContent:D,isIconOnly:l,children:!l&&"New conversation"})},"new-conversation-button"),!l&&t.jsx(ve.div,{className:"mt-2 flex flex-1 flex-col gap-2 overflow-auto overflow-x-hidden",initial:!1,animate:{opacity:1,width:"100%"},exit:{opacity:0,width:0},children:wt.zip(u,d).map(([o,C])=>{if(!o||$t(o))return null;const _=o===h,A=o===p,N=_?"solid":"light";return t.jsxs("div",{className:"flex w-full justify-between gap-2",children:[A?t.jsx(At,{ref:f,size:"sm",variant:"bordered",value:b,onChange:g=>x(g.target.value),onBlur:()=>{I||S(o)},onKeyDown:g=>{g.key==="Enter"&&S(o),g.key==="Escape"&&i()},className:"flex-1","data-testid":`input-conversation-${o}`}):t.jsx(X,{variant:N,"aria-label":`Select conversation ${o}`,"data-active":_,onPress:()=>k(o),title:C??o,"data-testid":`select-conversation-${o}`,className:"flex-1 justify-start",children:t.jsx("div",{className:"text-small truncate",children:C??o})}),t.jsxs(ao,{children:[t.jsx(eo,{children:t.jsx(X,{isIconOnly:!0,variant:"light","aria-label":`Conversation actions for ${o}`,"data-testid":`dropdown-conversation-${o}`,children:t.jsx(Q,{icon:"heroicons:ellipsis-vertical",className:"rotate-90"})})}),t.jsxs(Yt,{"aria-label":"Conversation actions",children:[t.jsx(De,{startContent:t.jsx(Q,{icon:"heroicons:pencil-square",className:"mb-0.5"}),onPress:()=>y(o,C??o),"data-testid":`edit-conversation-${o}`,children:"Edit"},"edit"),t.jsx(De,{className:"text-danger mb-0.5",color:"danger",startContent:t.jsx(Q,{icon:"heroicons:trash"}),onPress:()=>r(o),"data-testid":`delete-conversation-${o}`,children:"Delete conversation"},"delete")]})]})]},`${o}-${N}`)})},"conversation-list")]})})}export{co as default};
@@ -1 +1 @@
1
- import{g as z,r as f,u as ie,h as ce,a as ue,i as le,b as fe,p as Y,C as Q,j as l,D as de,d as A,I as me,m as ge,e as he,f as pe}from"./index-BZLU40Mk.js";import{g as Z,v as W,F as ve,t as be}from"./index-Be0kkf3d.js";import{m as Se}from"./chunk-IGSAU2ZA-NXd1g0Qd.js";import"./chunk-SSA7SXE4-CJa0HuAU.js";import"./useMenuTriggerState-SaFmATkk.js";import"./useSelectableItem-DhuFnc0W.js";import"./index-Ceq7Rkzy.js";var B,V;function xe(){if(V)return B;V=1;var n="Expected a function",t=NaN,s="[object Symbol]",m=/^\s+|\s+$/g,g=/^[-+]0x[0-9a-f]+$/i,h=/^0b[01]+$/i,i=/^0o[0-7]+$/i,b=parseInt,S=typeof z=="object"&&z&&z.Object===Object&&z,y=typeof self=="object"&&self&&self.Object===Object&&self,C=S||y||Function("return this")(),d=Object.prototype,r=d.toString,c=Math.max,O=Math.min,E=function(){return C.Date.now()};function $(e,u,v){var T,L,P,I,p,j,R=0,G=!1,D=!1,k=!0;if(typeof e!="function")throw new TypeError(n);u=q(u)||0,_(v)&&(G=!!v.leading,D="maxWait"in v,P=D?c(q(v.maxWait)||0,u):P,k="trailing"in v?!!v.trailing:k);function H(o){var x=T,F=L;return T=L=void 0,R=o,I=e.apply(F,x),I}function re(o){return R=o,p=setTimeout(N,u),G?H(o):I}function oe(o){var x=o-j,F=o-R,X=u-x;return D?O(X,P-F):X}function U(o){var x=o-j,F=o-R;return j===void 0||x>=u||x<0||D&&F>=P}function N(){var o=E();if(U(o))return K(o);p=setTimeout(N,oe(o))}function K(o){return p=void 0,k&&T?H(o):(T=L=void 0,I)}function se(){p!==void 0&&clearTimeout(p),R=0,T=j=L=p=void 0}function ae(){return p===void 0?I:K(E())}function M(){var o=E(),x=U(o);if(T=arguments,L=this,j=o,x){if(p===void 0)return re(j);if(D)return p=setTimeout(N,u),H(j)}return p===void 0&&(p=setTimeout(N,u)),I}return M.cancel=se,M.flush=ae,M}function _(e){var u=typeof e;return!!e&&(u=="object"||u=="function")}function a(e){return!!e&&typeof e=="object"}function w(e){return typeof e=="symbol"||a(e)&&r.call(e)==s}function q(e){if(typeof e=="number")return e;if(w(e))return t;if(_(e)){var u=typeof e.valueOf=="function"?e.valueOf():e;e=_(u)?u+"":u}if(typeof e!="string")return e===0?e:+e;e=e.replace(m,"");var v=h.test(e);return v||i.test(e)?b(e.slice(2),v?2:8):g.test(e)?t:+e}return B=$,B}xe();var ne=typeof window<"u"?f.useLayoutEffect:f.useEffect;function ee(n,t,s,m){const g=f.useRef(t);ne(()=>{g.current=t},[t]),f.useEffect(()=>{const h=window;if(!(h&&h.addEventListener))return;const i=b=>{g.current(b)};return h.addEventListener(n,i,m),()=>{h.removeEventListener(n,i,m)}},[n,s,m])}function te(n){const t=f.useRef(()=>{throw new Error("Cannot call an event handler while rendering.")});return ne(()=>{t.current=n},[n]),f.useCallback((...s)=>{var m;return(m=t.current)==null?void 0:m.call(t,...s)},[t])}var J=typeof window>"u";function ye(n,t,s={}){const{initializeWithValue:m=!0}=s,g=f.useCallback(r=>s.serializer?s.serializer(r):JSON.stringify(r),[s]),h=f.useCallback(r=>{if(s.deserializer)return s.deserializer(r);if(r==="undefined")return;const c=t instanceof Function?t():t;let O;try{O=JSON.parse(r)}catch(E){return console.error("Error parsing JSON:",E),c}return O},[s,t]),i=f.useCallback(()=>{const r=t instanceof Function?t():t;if(J)return r;try{const c=window.localStorage.getItem(n);return c?h(c):r}catch(c){return console.warn(`Error reading localStorage key “${n}”:`,c),r}},[t,n,h]),[b,S]=f.useState(()=>m?i():t instanceof Function?t():t),y=te(r=>{J&&console.warn(`Tried setting localStorage key “${n}” even though environment is not a client`);try{const c=r instanceof Function?r(i()):r;window.localStorage.setItem(n,g(c)),S(c),window.dispatchEvent(new StorageEvent("local-storage",{key:n}))}catch(c){console.warn(`Error setting localStorage key “${n}”:`,c)}}),C=te(()=>{J&&console.warn(`Tried removing localStorage key “${n}” even though environment is not a client`);const r=t instanceof Function?t():t;window.localStorage.removeItem(n),S(r),window.dispatchEvent(new StorageEvent("local-storage",{key:n}))});f.useEffect(()=>{S(i())},[n]);const d=f.useCallback(r=>{r.key&&r.key!==n||S(i())},[n,i]);return ee("storage",d),ee("local-storage",d),[b,y,C]}const Ce="ragbits-no-history-chat-options";function Le(){const{isOpen:n,onOpen:t,onClose:s}=ie(),m=ce(a=>a.chatOptions),g=f.useRef(null),{setConversationProperties:h,initializeChatOptions:i}=ue(),b=le(a=>a.currentConversation),{config:{user_settings:S}}=fe(),[y,C]=ye(Ce,null),d=S?.form,r=a=>{Y.isPluginActivated(Q.name)||C(a)},c=()=>{t()},O=(a,w)=>{w.preventDefault(),g.current=a.formData,s()},E=()=>{if(!d)return;const a=Z(W,d);g.current=a,s()},$=()=>{s()},_=a=>{if(a!=="exit"||!g.current)return;const w=g.current;h(b,{chatOptions:w}),r(w),g.current=null};return f.useEffect(()=>{if(!d)return;const a=Z(W,d);Y.isPluginActivated(Q.name)?i(a):y!==null?i(y):(i(a),C(a))},[i,d,b,y,C]),d?l.jsxs(l.Fragment,{children:[l.jsx(de,{content:"Chat Options",placement:"bottom",children:l.jsx(A,{isIconOnly:!0,variant:"ghost",className:"p-0","aria-label":"Open chat options",onPress:c,"data-testid":"open-chat-options",children:l.jsx(me,{icon:"heroicons:cog-6-tooth"})})}),l.jsx(ge,{isOpen:n,onOpenChange:$,motionProps:{onAnimationComplete:_},children:l.jsxs(he,{children:[l.jsx(Se,{className:"text-default-900 flex flex-col gap-1",children:d.title||"Chat Options"}),l.jsx(pe,{children:l.jsx("div",{className:"flex flex-col gap-4",children:l.jsx(ve,{schema:d,validator:W,formData:m,onSubmit:O,transformErrors:be,liveValidate:!0,children:l.jsxs("div",{className:"flex justify-end gap-4 py-4",children:[l.jsx(A,{className:"mr-auto",color:"primary",variant:"light",onPress:E,"aria-label":"Restore default user settings",children:"Restore defaults"}),l.jsx(A,{color:"danger",variant:"light",onPress:s,"aria-label":"Close chat options form",children:"Cancel"}),l.jsx(A,{color:"primary",type:"submit","aria-label":"Save chat options","data-testid":"chat-options-submit",children:"Save"})]})})})})]})})]}):null}export{Le as default};
1
+ import{g as z,r as f,u as ie,h as ce,a as ue,i as le,b as fe,p as Y,C as Q,j as l,D as de,d as A,I as me,m as ge,e as he,f as pe}from"./index-CbVbgerL.js";import{g as Z,v as W,F as ve,t as be}from"./index-DTNGcmXG.js";import{m as Se}from"./chunk-IGSAU2ZA-BBfo0QFa.js";import"./chunk-SSA7SXE4-D3GKTPj0.js";import"./useMenuTriggerState-C5916IcO.js";import"./useSelectableItem-BWC6EImE.js";import"./index-B-LIlvZN.js";var B,V;function xe(){if(V)return B;V=1;var n="Expected a function",t=NaN,s="[object Symbol]",m=/^\s+|\s+$/g,g=/^[-+]0x[0-9a-f]+$/i,h=/^0b[01]+$/i,i=/^0o[0-7]+$/i,b=parseInt,S=typeof z=="object"&&z&&z.Object===Object&&z,y=typeof self=="object"&&self&&self.Object===Object&&self,C=S||y||Function("return this")(),d=Object.prototype,r=d.toString,c=Math.max,O=Math.min,E=function(){return C.Date.now()};function $(e,u,v){var T,L,P,I,p,j,R=0,G=!1,D=!1,k=!0;if(typeof e!="function")throw new TypeError(n);u=q(u)||0,_(v)&&(G=!!v.leading,D="maxWait"in v,P=D?c(q(v.maxWait)||0,u):P,k="trailing"in v?!!v.trailing:k);function H(o){var x=T,F=L;return T=L=void 0,R=o,I=e.apply(F,x),I}function re(o){return R=o,p=setTimeout(N,u),G?H(o):I}function oe(o){var x=o-j,F=o-R,X=u-x;return D?O(X,P-F):X}function U(o){var x=o-j,F=o-R;return j===void 0||x>=u||x<0||D&&F>=P}function N(){var o=E();if(U(o))return K(o);p=setTimeout(N,oe(o))}function K(o){return p=void 0,k&&T?H(o):(T=L=void 0,I)}function se(){p!==void 0&&clearTimeout(p),R=0,T=j=L=p=void 0}function ae(){return p===void 0?I:K(E())}function M(){var o=E(),x=U(o);if(T=arguments,L=this,j=o,x){if(p===void 0)return re(j);if(D)return p=setTimeout(N,u),H(j)}return p===void 0&&(p=setTimeout(N,u)),I}return M.cancel=se,M.flush=ae,M}function _(e){var u=typeof e;return!!e&&(u=="object"||u=="function")}function a(e){return!!e&&typeof e=="object"}function w(e){return typeof e=="symbol"||a(e)&&r.call(e)==s}function q(e){if(typeof e=="number")return e;if(w(e))return t;if(_(e)){var u=typeof e.valueOf=="function"?e.valueOf():e;e=_(u)?u+"":u}if(typeof e!="string")return e===0?e:+e;e=e.replace(m,"");var v=h.test(e);return v||i.test(e)?b(e.slice(2),v?2:8):g.test(e)?t:+e}return B=$,B}xe();var ne=typeof window<"u"?f.useLayoutEffect:f.useEffect;function ee(n,t,s,m){const g=f.useRef(t);ne(()=>{g.current=t},[t]),f.useEffect(()=>{const h=window;if(!(h&&h.addEventListener))return;const i=b=>{g.current(b)};return h.addEventListener(n,i,m),()=>{h.removeEventListener(n,i,m)}},[n,s,m])}function te(n){const t=f.useRef(()=>{throw new Error("Cannot call an event handler while rendering.")});return ne(()=>{t.current=n},[n]),f.useCallback((...s)=>{var m;return(m=t.current)==null?void 0:m.call(t,...s)},[t])}var J=typeof window>"u";function ye(n,t,s={}){const{initializeWithValue:m=!0}=s,g=f.useCallback(r=>s.serializer?s.serializer(r):JSON.stringify(r),[s]),h=f.useCallback(r=>{if(s.deserializer)return s.deserializer(r);if(r==="undefined")return;const c=t instanceof Function?t():t;let O;try{O=JSON.parse(r)}catch(E){return console.error("Error parsing JSON:",E),c}return O},[s,t]),i=f.useCallback(()=>{const r=t instanceof Function?t():t;if(J)return r;try{const c=window.localStorage.getItem(n);return c?h(c):r}catch(c){return console.warn(`Error reading localStorage key “${n}”:`,c),r}},[t,n,h]),[b,S]=f.useState(()=>m?i():t instanceof Function?t():t),y=te(r=>{J&&console.warn(`Tried setting localStorage key “${n}” even though environment is not a client`);try{const c=r instanceof Function?r(i()):r;window.localStorage.setItem(n,g(c)),S(c),window.dispatchEvent(new StorageEvent("local-storage",{key:n}))}catch(c){console.warn(`Error setting localStorage key “${n}”:`,c)}}),C=te(()=>{J&&console.warn(`Tried removing localStorage key “${n}” even though environment is not a client`);const r=t instanceof Function?t():t;window.localStorage.removeItem(n),S(r),window.dispatchEvent(new StorageEvent("local-storage",{key:n}))});f.useEffect(()=>{S(i())},[n]);const d=f.useCallback(r=>{r.key&&r.key!==n||S(i())},[n,i]);return ee("storage",d),ee("local-storage",d),[b,y,C]}const Ce="ragbits-no-history-chat-options";function Le(){const{isOpen:n,onOpen:t,onClose:s}=ie(),m=ce(a=>a.chatOptions),g=f.useRef(null),{setConversationProperties:h,initializeChatOptions:i}=ue(),b=le(a=>a.currentConversation),{config:{user_settings:S}}=fe(),[y,C]=ye(Ce,null),d=S?.form,r=a=>{Y.isPluginActivated(Q.name)||C(a)},c=()=>{t()},O=(a,w)=>{w.preventDefault(),g.current=a.formData,s()},E=()=>{if(!d)return;const a=Z(W,d);g.current=a,s()},$=()=>{s()},_=a=>{if(a!=="exit"||!g.current)return;const w=g.current;h(b,{chatOptions:w}),r(w),g.current=null};return f.useEffect(()=>{if(!d)return;const a=Z(W,d);Y.isPluginActivated(Q.name)?i(a):y!==null?i(y):(i(a),C(a))},[i,d,b,y,C]),d?l.jsxs(l.Fragment,{children:[l.jsx(de,{content:"Chat Options",placement:"bottom",children:l.jsx(A,{isIconOnly:!0,variant:"ghost",className:"p-0","aria-label":"Open chat options",onPress:c,"data-testid":"open-chat-options",children:l.jsx(me,{icon:"heroicons:cog-6-tooth"})})}),l.jsx(ge,{isOpen:n,onOpenChange:$,motionProps:{onAnimationComplete:_},children:l.jsxs(he,{children:[l.jsx(Se,{className:"text-default-900 flex flex-col gap-1",children:d.title||"Chat Options"}),l.jsx(pe,{children:l.jsx("div",{className:"flex flex-col gap-4",children:l.jsx(ve,{schema:d,validator:W,formData:m,onSubmit:O,transformErrors:be,liveValidate:!0,children:l.jsxs("div",{className:"flex justify-end gap-4 py-4",children:[l.jsx(A,{className:"mr-auto",color:"primary",variant:"light",onPress:E,"aria-label":"Restore default user settings",children:"Restore defaults"}),l.jsx(A,{color:"danger",variant:"light",onPress:s,"aria-label":"Close chat options form",children:"Cancel"}),l.jsx(A,{color:"primary",type:"submit","aria-label":"Save chat options","data-testid":"chat-options-submit",children:"Save"})]})})})})]})})]}):null}export{Le as default};
@@ -0,0 +1 @@
1
+ import{r as c,c as x,aW as w,aE as S,j as t,aq as b,aG as j,d as v,bm as C}from"./index-CbVbgerL.js";import{a as P}from"./authStore-AVyfzjgs.js";import{u as q}from"./useInitializeUserStore-CVYyhiv3.js";import{i as m}from"./chunk-SSA7SXE4-D3GKTPj0.js";function z(){const[s,p]=c.useState({username:"",password:""}),l=x("/api/auth/login",{headers:{"Content-Type":"application/json"},method:"POST"}),f=w(P,e=>e.login),g=S(),u=q(),[y,o]=c.useState(!1),h=async e=>{o(!1),e.preventDefault(),e.stopPropagation();const r=new FormData(e.currentTarget),n=r.get("username"),i=r.get("password");try{const a=await l.call({body:{username:n,password:i}});if(!a.success||!a.user){o(!0);return}f(a.user),u?u(a.user.user_id):console.error("Failed to initialize store for user, initializeUserStore() is not defined. Check current HistoryStoreContextProvider implementation."),g("/")}catch(a){console.error("Failed to login",a),o(!0)}},d=e=>r=>p(n=>C(n,i=>{i[e]=r.target.value}));return t.jsxs("form",{className:"flex w-full flex-col gap-4",onSubmit:h,children:[t.jsx(m,{label:"Username",name:"username",labelPlacement:"outside",placeholder:"Your username",required:!0,isRequired:!0,value:s.username,onChange:d("username")}),t.jsx(m,{label:"Password",labelPlacement:"outside",id:"password",name:"password",type:"password",placeholder:"••••••••",required:!0,isRequired:!0,value:s.password,onChange:d("password")}),t.jsx(b,{children:y&&!l.isLoading&&t.jsx(j.div,{className:"text-small text-danger",initial:{opacity:0,y:-10},animate:{opacity:1,y:0},exit:{opacity:0,y:-10},transition:{duration:.3,ease:"easeOut"},children:"We couldn't sign you in. Please verify your credentials and try again."})}),t.jsx(v,{type:"submit",color:s.password&&s.username?"primary":"default",children:"Sign in"})]})}export{z as default};
@@ -0,0 +1 @@
1
+ import{u as g,a as v,b as C,r as _,F as t,c as I,j as e,D as u,d as n,I as b,m as T,e as w,f as D}from"./index-CbVbgerL.js";import{F as O,t as S,v as E}from"./index-DTNGcmXG.js";import{m as N}from"./chunk-IGSAU2ZA-BBfo0QFa.js";import"./chunk-SSA7SXE4-D3GKTPj0.js";import"./useMenuTriggerState-C5916IcO.js";import"./useSelectableItem-BWC6EImE.js";import"./index-B-LIlvZN.js";function z({message:s}){const{isOpen:f,onOpen:h,onClose:r}=g(),{mergeExtensions:p}=v(),{config:{feedback:o}}=C(),[i,x]=_.useState(t.Like),k=I("/api/feedback",{headers:{"Content-Type":"application/json"},method:"POST"});if(!s.serverId)return null;const l=o[i].form,j=()=>{r()},c=async a=>{if(!s.serverId)throw new Error('Feedback is only available for messages with "serverId" set');try{await k.call({body:{message_id:s.serverId,feedback:i,payload:a??{}}})}catch(F){console.error(F)}},y=a=>{p(s.id,{feedbackType:i}),c(a.formData),r()},d=async a=>{if(x(a),o[a].form===null){await c(null);return}h()};if(!l)return null;const m=s.extensions?.feedbackType;return e.jsxs(e.Fragment,{children:[o.like.enabled&&e.jsx(u,{content:"Like",placement:"bottom",children:e.jsx(n,{isIconOnly:!0,variant:"ghost",className:"p-0","aria-label":"Rate message as helpful",onPress:()=>d(t.Like),"data-testid":"feedback-like",children:e.jsx(b,{icon:m===t.Like?"heroicons:hand-thumb-up-solid":"heroicons:hand-thumb-up"})})}),o.dislike.enabled&&e.jsx(u,{content:"Dislike",placement:"bottom",children:e.jsx(n,{isIconOnly:!0,variant:"ghost",className:"p-0","aria-label":"Rate message as unhelpful",onPress:()=>d(t.Dislike),"data-testid":"feedback-dislike",children:e.jsx(b,{icon:m===t.Dislike?"heroicons:hand-thumb-down-solid":"heroicons:hand-thumb-down"})})}),e.jsx(T,{isOpen:f,onOpenChange:j,children:e.jsx(w,{children:a=>e.jsxs(e.Fragment,{children:[e.jsx(N,{className:"text-default-900 flex flex-col gap-1",children:l.title}),e.jsx(D,{children:e.jsx("div",{className:"flex flex-col gap-4",children:e.jsx(O,{schema:l,validator:E,onSubmit:y,transformErrors:S,liveValidate:!0,children:e.jsxs("div",{className:"flex justify-end gap-4 py-4",children:[e.jsx(n,{color:"danger",variant:"light",onPress:a,"aria-label":"Close feedback form",children:"Cancel"}),e.jsx(n,{color:"primary",type:"submit","aria-label":"Submit feedback","data-testid":"feedback-submit",children:"Submit"})]})})})})]})})})]})}export{z as default};
@@ -1 +1 @@
1
- import{r as s,j as e}from"./index-BZLU40Mk.js";function n({children:t}){return s.useEffect(()=>{document.title="Login"},[]),e.jsx("div",{className:"flex h-screen w-screen",children:e.jsxs("div",{className:"rounded-medium border-small border-divider m-auto flex w-full max-w-xs flex-col gap-4 p-4",children:[e.jsxs("div",{className:"text-small",children:[e.jsx("div",{className:"text-foreground truncate leading-5 font-semibold",children:"Sign in"}),e.jsx("div",{className:"text-default-500 truncate leading-5 font-normal",children:"Sign in to start chatting."})]}),t]})})}export{n as default};
1
+ import{r as s,j as e}from"./index-CbVbgerL.js";function n({children:t}){return s.useEffect(()=>{document.title="Login"},[]),e.jsx("div",{className:"flex h-screen w-screen",children:e.jsxs("div",{className:"rounded-medium border-small border-divider m-auto flex w-full max-w-xs flex-col gap-4 p-4",children:[e.jsxs("div",{className:"text-small",children:[e.jsx("div",{className:"text-foreground truncate leading-5 font-semibold",children:"Sign in"}),e.jsx("div",{className:"text-default-500 truncate leading-5 font-normal",children:"Sign in to start chatting."})]}),t]})})}export{n as default};