ragbits-chat 1.4.0.dev202601310254__tar.gz → 1.4.0.dev202602030301__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 (73) hide show
  1. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/CHANGELOG.md +1 -0
  2. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/PKG-INFO +2 -2
  3. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/pyproject.toml +2 -2
  4. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/api.py +60 -0
  5. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/cli.py +22 -9
  6. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_api.py +43 -0
  7. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/.gitignore +0 -0
  8. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/README.md +0 -0
  9. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/__init__.py +0 -0
  10. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/_utils.py +0 -0
  11. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/__init__.py +0 -0
  12. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/backends.py +0 -0
  13. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/base.py +0 -0
  14. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/oauth2_providers.py +0 -0
  15. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/provider_config.py +0 -0
  16. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/session_store.py +0 -0
  17. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/auth/types.py +0 -0
  18. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/client/__init__.py +0 -0
  19. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/client/client.py +0 -0
  20. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/client/conversation.py +0 -0
  21. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/client/exceptions.py +0 -0
  22. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/config.py +0 -0
  23. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/history/__init__.py +0 -0
  24. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/history/compressors/__init__.py +0 -0
  25. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/history/compressors/base.py +0 -0
  26. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/history/compressors/llm.py +0 -0
  27. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/interface/__init__.py +0 -0
  28. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/interface/_interface.py +0 -0
  29. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/interface/forms.py +0 -0
  30. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/interface/summary.py +0 -0
  31. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/interface/types.py +0 -0
  32. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/interface/ui_customization.py +0 -0
  33. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/metrics.py +0 -0
  34. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/persistence/__init__.py +0 -0
  35. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/persistence/base.py +0 -0
  36. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/persistence/file.py +0 -0
  37. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/persistence/sql.py +0 -0
  38. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/providers/__init__.py +0 -0
  39. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/providers/model_provider.py +0 -0
  40. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/py.typed +0 -0
  41. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/AuthGuard-D7E88Uir.js +0 -0
  42. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/ChatHistory-D8uJ-pWz.js +0 -0
  43. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/ChatOptionsForm-D2BdUqMs.js +0 -0
  44. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/CredentialsLogin-CEserYG_.js +0 -0
  45. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/FeedbackForm-CihcDF7p.js +0 -0
  46. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/Login-DKdY_IGp.js +0 -0
  47. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/LogoutButton-ibzVLLAx.js +0 -0
  48. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/OAuth2Login-DepasZu7.js +0 -0
  49. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/ShareButton-BzNoTpD6.js +0 -0
  50. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/UploadButton-CfKYWcd6.js +0 -0
  51. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/UsageButton-ByH8ZKPy.js +0 -0
  52. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/authStore-BIM9JG1Q.js +0 -0
  53. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/chunk-IGSAU2ZA-CbPuRduG.js +0 -0
  54. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/chunk-SSA7SXE4-DO9BwTof.js +0 -0
  55. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/index-B-4qdttP.js +0 -0
  56. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/index-B1u136LF.css +0 -0
  57. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/index-CSaYkt4U.js +0 -0
  58. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/index-Cyzr1kIj.js +0 -0
  59. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/index-W9apL6ID.js +0 -0
  60. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/useInitializeUserStore-Be1mCLhv.js +0 -0
  61. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/useMenuTriggerState-DRPPkuuB.js +0 -0
  62. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/assets/useSelectableItem-BHUz-f5B.js +0 -0
  63. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/src/ragbits/chat/ui-build/index.html +0 -0
  64. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/auth/test_list_auth_backend.py +0 -0
  65. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/auth/test_session_store.py +0 -0
  66. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/history/test_llm_compressor.py +0 -0
  67. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/persistence/test_sql.py +0 -0
  68. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_chat_client.py +0 -0
  69. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_conversation.py +0 -0
  70. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_error_response.py +0 -0
  71. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_generic_custom_response.py +0 -0
  72. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_types.py +0 -0
  73. {ragbits_chat-1.4.0.dev202601310254 → ragbits_chat-1.4.0.dev202602030301}/tests/unit/test_upload.py +0 -0
@@ -1,6 +1,7 @@
1
1
  # CHANGELOG
2
2
 
3
3
  ## Unreleased
4
+ - Autoreload support for UI during development (#924)
4
5
  - Decoupling of components from ragbits specific logic. Introduction of slot based plugin architecture. Minimal history store implementation (#917)
5
6
  - Add timezone field to ChatContext, automatically populated from browser (#916)
6
7
  - Fix PostgreSQL conversation persistence by ensuring session flush after creating new conversation in SQL storage (#903)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragbits-chat
3
- Version: 1.4.0.dev202601310254
3
+ Version: 1.4.0.dev202602030301
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.dev202601310254
29
+ Requires-Dist: ragbits-core==1.4.0.dev202602030301
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.dev202601310254"
3
+ version = "1.4.0.dev202602030301"
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.dev202601310254"]
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.dev202602030301"]
35
35
 
36
36
  [project.urls]
37
37
  "Homepage" = "https://github.com/deepsense-ai/ragbits"
@@ -3,6 +3,7 @@ import importlib
3
3
  import json
4
4
  import logging
5
5
  import re
6
+ import tempfile
6
7
  import time
7
8
  from collections.abc import AsyncGenerator
8
9
  from contextlib import asynccontextmanager, suppress
@@ -944,9 +945,68 @@ class RagbitsAPI:
944
945
  def run(self, host: str = "127.0.0.1", port: int = 8000) -> None:
945
946
  """
946
947
  Used for starting the API
948
+
949
+ Args:
950
+ host: Host to bind the API server to
951
+ port: Port to bind the API server to
947
952
  """
948
953
  uvicorn.run(self.app, host=host, port=port)
949
954
 
955
+ @staticmethod
956
+ def run_with_reload(
957
+ host: str,
958
+ port: int,
959
+ chat_interface: str | None = None,
960
+ cors_origins: list[str] | None = None,
961
+ ui_build_dir: str | None = None,
962
+ debug_mode: bool = False,
963
+ auth_backend: str | None = None,
964
+ theme_path: str | None = None,
965
+ ) -> None:
966
+ """
967
+ Run the API server with auto-reload enabled for development.
968
+
969
+ This method creates a temporary Python file with the API configuration
970
+ that uvicorn can import and reload when code changes are detected.
971
+
972
+ Args:
973
+ host: Host to bind the API server to
974
+ port: Port to bind the API server to
975
+ chat_interface: Path to chat interface module
976
+ cors_origins: List of allowed CORS origins
977
+ ui_build_dir: Path to custom UI build directory
978
+ debug_mode: Enable debug mode
979
+ auth_backend: Path to authentication backend module
980
+ theme_path: Path to theme configuration file
981
+ """
982
+ temp_file_path: Path | None = None
983
+ try:
984
+ with tempfile.NamedTemporaryFile(
985
+ mode="w", suffix=".py", delete=False, dir=".", prefix="_ragbits_app_"
986
+ ) as temp_file:
987
+ temp_file_path = Path(temp_file.name)
988
+ temp_file.write(
989
+ f"""# Auto-generated file for ragbits reload mode - DO NOT EDIT
990
+ from ragbits.chat.api import RagbitsAPI
991
+
992
+ api = RagbitsAPI(
993
+ chat_interface={repr(chat_interface)},
994
+ cors_origins={repr(cors_origins)},
995
+ ui_build_dir={repr(ui_build_dir)},
996
+ debug_mode={repr(debug_mode)},
997
+ auth_backend={repr(auth_backend)},
998
+ theme_path={repr(theme_path)},
999
+ )
1000
+ app = api.app
1001
+ """
1002
+ )
1003
+
1004
+ module_name = temp_file_path.stem
1005
+ uvicorn.run(f"{module_name}:app", host=host, port=port, reload=True)
1006
+ finally:
1007
+ if temp_file_path:
1008
+ temp_file_path.unlink(missing_ok=True)
1009
+
950
1010
  @staticmethod
951
1011
  def _convert_heroui_json_to_css(json_content: str) -> str:
952
1012
  """Convert HeroUI JSON theme configuration to CSS variables."""
@@ -37,16 +37,29 @@ def run(
37
37
  "--theme",
38
38
  help="Path to a HeroUI theme JSON file from heroui.com/themes",
39
39
  ),
40
+ reload: bool = typer.Option(False, "--reload", help="Enable auto-reload on code changes for debugging"),
40
41
  ) -> None:
41
42
  """
42
43
  Run API service with UI demo
43
44
  """
44
- api = RagbitsAPI(
45
- chat_interface=chat_interface,
46
- cors_origins=cors_origins,
47
- ui_build_dir=ui_build_dir,
48
- debug_mode=debug_mode,
49
- auth_backend=auth,
50
- theme_path=theme,
51
- )
52
- api.run(host=host, port=port)
45
+ if reload:
46
+ RagbitsAPI.run_with_reload(
47
+ host=host,
48
+ port=port,
49
+ chat_interface=chat_interface,
50
+ cors_origins=cors_origins,
51
+ ui_build_dir=ui_build_dir,
52
+ debug_mode=debug_mode,
53
+ auth_backend=auth,
54
+ theme_path=theme,
55
+ )
56
+ else:
57
+ api = RagbitsAPI(
58
+ chat_interface=chat_interface,
59
+ cors_origins=cors_origins,
60
+ ui_build_dir=ui_build_dir,
61
+ debug_mode=debug_mode,
62
+ auth_backend=auth,
63
+ theme_path=theme,
64
+ )
65
+ api.run(host=host, port=port)
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  from collections.abc import AsyncGenerator
3
+ from pathlib import Path
3
4
  from typing import Literal
4
5
  from unittest.mock import MagicMock, mock_open, patch
5
6
 
@@ -337,6 +338,48 @@ def test_run_method() -> None:
337
338
  mock_run.assert_called_once_with(api.app, host="localhost", port=9000)
338
339
 
339
340
 
341
+ def test_run_with_reload_method() -> None:
342
+ """Test the run_with_reload method creates temp file and starts uvicorn with reload."""
343
+
344
+ class TempFileCheck:
345
+ """Helper class to verify temp file exists when uvicorn.run is called."""
346
+
347
+ existed_at_run_time: bool = False
348
+ temp_file_path: Path | None = None
349
+
350
+ @classmethod
351
+ def check_and_record(cls, app_path: str, **kwargs: dict) -> None:
352
+ module_name = app_path.split(":")[0]
353
+ cls.temp_file_path = Path(f"./{module_name}.py")
354
+ cls.existed_at_run_time = cls.temp_file_path.exists()
355
+
356
+ with patch("uvicorn.run", side_effect=TempFileCheck.check_and_record) as mock_run:
357
+ RagbitsAPI.run_with_reload(
358
+ host="localhost",
359
+ port=9000,
360
+ chat_interface="test:TestChat",
361
+ debug_mode=True,
362
+ )
363
+
364
+ # Verify uvicorn.run was called with reload=True and an import string
365
+ mock_run.assert_called_once()
366
+ call_args = mock_run.call_args
367
+ assert call_args[1]["reload"] is True
368
+ assert call_args[1]["host"] == "localhost"
369
+ assert call_args[1]["port"] == 9000
370
+ assert isinstance(call_args[0][0], str)
371
+ # Module name format: _ragbits_app_<random>:app
372
+ assert ":app" in call_args[0][0]
373
+ assert "_ragbits_app_" in call_args[0][0]
374
+
375
+ # Verify temp file existed when uvicorn.run was called
376
+ assert TempFileCheck.existed_at_run_time, "Temp file was not created before uvicorn.run"
377
+
378
+ # Verify temp file was cleaned up after
379
+ assert TempFileCheck.temp_file_path is not None
380
+ assert not TempFileCheck.temp_file_path.exists(), "Temp file was not cleaned up"
381
+
382
+
340
383
  def test_login_endpoint(client: TestClient) -> None:
341
384
  """Test the login endpoint with valid credentials sets session cookie."""
342
385
  response = client.post("/api/auth/login", json={"username": "testuser", "password": "testpass"})