databricks-tellr-app 0.4.2.dev8__tar.gz → 0.4.2.dev9__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 (167) hide show
  1. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/PKG-INFO +1 -1
  2. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app.egg-info/PKG-INFO +1 -1
  3. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/pyproject.toml +1 -1
  4. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/mcp_server.py +21 -2
  5. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/settings/design_systems.py +26 -6
  6. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/database.py +153 -1
  7. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/design_system.py +46 -8
  8. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/design_system_compiler.py +374 -10
  9. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/design_system_service.py +18 -3
  10. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/README.md +0 -0
  11. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app/__init__.py +0 -0
  12. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app/run.py +0 -0
  13. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app.egg-info/SOURCES.txt +0 -0
  14. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app.egg-info/dependency_links.txt +0 -0
  15. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app.egg-info/requires.txt +0 -0
  16. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/databricks_tellr_app.egg-info/top_level.txt +0 -0
  17. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/setup.cfg +0 -0
  18. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/setup.py +0 -0
  19. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/__init__.py +0 -0
  20. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/__init__.py +0 -0
  21. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/_otel_bootstrap.py +0 -0
  22. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/fixtures/tour_demo_deck.json +0 -0
  23. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/main.py +0 -0
  24. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/mcp_auth.py +0 -0
  25. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/middleware/__init__.py +0 -0
  26. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/middleware/csrf.py +0 -0
  27. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/middleware/request_logging.py +0 -0
  28. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/middleware/security_headers.py +0 -0
  29. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/__init__.py +0 -0
  30. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/_authz.py +0 -0
  31. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/admin.py +0 -0
  32. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/admin_usage.py +0 -0
  33. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/agent_config.py +0 -0
  34. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/chat.py +0 -0
  35. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/deck_contributors.py +0 -0
  36. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/export.py +0 -0
  37. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/feedback.py +0 -0
  38. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/google_slides.py +0 -0
  39. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/images.py +0 -0
  40. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/local_version.py +0 -0
  41. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/profiles.py +0 -0
  42. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/sessions.py +0 -0
  43. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/settings/__init__.py +0 -0
  44. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/settings/contributors.py +0 -0
  45. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/settings/deck_prompts.py +0 -0
  46. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/settings/identities.py +0 -0
  47. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/settings/slide_styles.py +0 -0
  48. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/setup.py +0 -0
  49. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/slides.py +0 -0
  50. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/tools.py +0 -0
  51. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/tour.py +0 -0
  52. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/verification.py +0 -0
  53. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/routes/version.py +0 -0
  54. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/__init__.py +0 -0
  55. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/agent_config.py +0 -0
  56. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/feedback.py +0 -0
  57. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/requests.py +0 -0
  58. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/responses.py +0 -0
  59. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/settings/__init__.py +0 -0
  60. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/settings/requests.py +0 -0
  61. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/settings/responses.py +0 -0
  62. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/schemas/streaming.py +0 -0
  63. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/__init__.py +0 -0
  64. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/chat_service.py +0 -0
  65. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/export_job_queue.py +0 -0
  66. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/feedback_service.py +0 -0
  67. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/job_queue.py +0 -0
  68. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/session_manager.py +0 -0
  69. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/session_naming.py +0 -0
  70. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/usage_events.py +0 -0
  71. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/services/usage_service.py +0 -0
  72. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/utils/__init__.py +0 -0
  73. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/api/utils/validation.py +0 -0
  74. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/__init__.py +0 -0
  75. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/config_loader.py +0 -0
  76. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/context_utils.py +0 -0
  77. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/databricks_client.py +0 -0
  78. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/defaults.py +0 -0
  79. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/encryption.py +0 -0
  80. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/init_default_profile.py +0 -0
  81. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/lakebase.py +0 -0
  82. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/migrate_profiles_to_agent_config.py +0 -0
  83. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/mlflow_agent_spans.py +0 -0
  84. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/mlflow_tracing.py +0 -0
  85. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/otel_logging.py +0 -0
  86. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/permission_context.py +0 -0
  87. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/prompt_modules.py +0 -0
  88. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/settings_db.py +0 -0
  89. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/core/user_context.py +0 -0
  90. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/__init__.py +0 -0
  91. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/__init__.py +0 -0
  92. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/deck_contributor.py +0 -0
  93. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/encryption_key.py +0 -0
  94. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/feedback.py +0 -0
  95. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/genie_space.py +0 -0
  96. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/google_global_credentials.py +0 -0
  97. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/google_oauth_token.py +0 -0
  98. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/identity.py +0 -0
  99. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/image.py +0 -0
  100. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/profile.py +0 -0
  101. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/profile_contributor.py +0 -0
  102. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/prompts.py +0 -0
  103. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/request_log.py +0 -0
  104. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/session.py +0 -0
  105. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/slide_deck_prompt.py +0 -0
  106. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/slide_style_library.py +0 -0
  107. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/usage_event.py +0 -0
  108. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/models/user_preference.py +0 -0
  109. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/database/types.py +0 -0
  110. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/domain/__init__.py +0 -0
  111. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/domain/slide.py +0 -0
  112. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/domain/slide_deck.py +0 -0
  113. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/__init__.py +0 -0
  114. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/agent.py +0 -0
  115. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/agent_factory.py +0 -0
  116. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/config_service.py +0 -0
  117. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/config_validator.py +0 -0
  118. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/__init__.py +0 -0
  119. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/ast_guard.py +0 -0
  120. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/codeprep.py +0 -0
  121. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/gslides_runner.py +0 -0
  122. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/jail.py +0 -0
  123. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/pptx_runner.py +0 -0
  124. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/converter_jail/protocol.py +0 -0
  125. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/design_system_templates.py +0 -0
  126. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/drive_uploader.py +0 -0
  127. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/evaluation/__init__.py +0 -0
  128. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/evaluation/llm_judge.py +0 -0
  129. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/genie_service.py +0 -0
  130. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/google_slides_auth.py +0 -0
  131. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/google_slides_prompts_defaults.py +0 -0
  132. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/html_to_google_slides.py +0 -0
  133. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/html_to_pptx.py +0 -0
  134. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/identity_provider.py +0 -0
  135. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/identity_providers/__init__.py +0 -0
  136. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/identity_providers/account_provider.py +0 -0
  137. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/identity_providers/local_provider.py +0 -0
  138. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/identity_providers/workspace_provider.py +0 -0
  139. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/image_service.py +0 -0
  140. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/image_tools.py +0 -0
  141. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/permission_service.py +0 -0
  142. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/pptx_from_html_huashu.py +0 -0
  143. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/pptx_from_records.py +0 -0
  144. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/pptx_prompts_defaults.py +0 -0
  145. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/profile_service.py +0 -0
  146. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/streaming_callback.py +0 -0
  147. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/__init__.py +0 -0
  148. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/agent_bricks_tool.py +0 -0
  149. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/ds_asset_tool.py +0 -0
  150. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/genie_tool.py +0 -0
  151. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/mcp_tool.py +0 -0
  152. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/model_endpoint_tool.py +0 -0
  153. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/tools/vector_tool.py +0 -0
  154. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/services/validator.py +0 -0
  155. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/__init__.py +0 -0
  156. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/css_utils.py +0 -0
  157. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/ds_asset_utils.py +0 -0
  158. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/error_handling.py +0 -0
  159. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/html_safety.py +0 -0
  160. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/html_utils.py +0 -0
  161. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/image_utils.py +0 -0
  162. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/js_validator.py +0 -0
  163. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/logging_config.py +0 -0
  164. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/pi_filter.py +0 -0
  165. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/slide_hash.py +0 -0
  166. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/spotlight.py +0 -0
  167. {databricks_tellr_app-0.4.2.dev8 → databricks_tellr_app-0.4.2.dev9}/src/utils/text_caps.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databricks-tellr-app
3
- Version: 0.4.2.dev8
3
+ Version: 0.4.2.dev9
4
4
  Summary: Tellr application package for Databricks Apps
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databricks-tellr-app
3
- Version: 0.4.2.dev8
3
+ Version: 0.4.2.dev9
4
4
  Summary: Tellr application package for Databricks Apps
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "databricks-tellr-app"
7
- version = "0.4.2.dev8"
7
+ version = "0.4.2.dev9"
8
8
  description = "Tellr application package for Databricks Apps"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -586,10 +586,30 @@ def _render_deck_response(
586
586
  base_url: Public app URL prefix for building deck URLs. Empty
587
587
  string yields relative URLs.
588
588
 
589
- ``SlideDeck.from_dict`` rebuilds the deck from the stored snapshot,
589
+ Image and design-system asset placeholders are substituted at this shared
590
+ response boundary so both MCP deck-returning tools emit standalone data
591
+ without expanding the persisted snapshot. Design-system assets are scoped
592
+ to the session's active design system and fail closed when it has none.
593
+
594
+ ``SlideDeck.from_dict`` rebuilds the deck from the substituted snapshot,
590
595
  including per-slide scripts/metadata and head metadata.
591
596
  """
592
597
  deck_dict = deck_dict or {}
598
+ session_id = session["session_id"]
599
+
600
+ from src.api.services.chat_service import resolve_active_design_system_id
601
+ from src.utils.ds_asset_utils import substitute_deck_dict_ds_assets
602
+ from src.utils.image_utils import substitute_deck_dict_images
603
+
604
+ design_system_id = resolve_active_design_system_id(session_id)
605
+ with get_db_session() as db:
606
+ substitute_deck_dict_images(deck_dict, db)
607
+ substitute_deck_dict_ds_assets(
608
+ deck_dict,
609
+ db,
610
+ design_system_id=design_system_id,
611
+ )
612
+
593
613
  if deck_dict:
594
614
  deck = SlideDeck.from_dict(
595
615
  deck_dict,
@@ -598,7 +618,6 @@ def _render_deck_response(
598
618
  else:
599
619
  deck = SlideDeck(title=session.get("title"))
600
620
 
601
- session_id = session["session_id"]
602
621
  deck_url = (
603
622
  f"{base_url}/sessions/{session_id}/edit"
604
623
  if base_url
@@ -8,10 +8,16 @@ the drop-in equivalent of ``slide_style_library.style_content`` — so it flows
8
8
  through the existing generation seam (see ``agent_factory._get_prompt_content``).
9
9
 
10
10
  Name uniqueness: creation/import return **409 Conflict** on a duplicate name
11
- (``design_system.name`` is unique, spec §6), matching the slide-styles
12
- convention. This is deliberately non-destructive — an org-shared asset is never
13
- silently overwritten; the caller supplies a different name (import accepts a
14
- ``name`` form field) to import a copy.
11
+ (spec §6), matching the slide-styles convention. This is deliberately
12
+ non-destructive — an org-shared asset is never silently overwritten; the caller
13
+ supplies a different name (import accepts a ``name`` form field) to import a copy.
14
+
15
+ Uniqueness is scoped to **LIVE** rows, at both layers: the pre-checks here filter
16
+ ``is_active``, and the database enforces the partial unique index
17
+ ``uq_design_system_name_active`` (``WHERE is_active``). A whole-table rule made the
18
+ soft DELETE below reserve the name FOREVER — the tombstone is hidden from the list
19
+ endpoint, so a user who deleted a design system could never re-import under the same
20
+ name and had nothing left to delete. A name held only by a tombstone is free.
15
21
  """
16
22
  import logging
17
23
  import os
@@ -548,7 +554,14 @@ def create_design_system(
548
554
  ):
549
555
  """Create a design system from structured input (assets arrive via /import)."""
550
556
  try:
551
- existing = db.query(DesignSystem).filter(DesignSystem.name == request.name).first()
557
+ # LIVE rows only, matching the partial unique index
558
+ # ``uq_design_system_name_active``. A soft-deleted system's name is free to
559
+ # reuse — see the DesignSystem model's note on the name column.
560
+ existing = (
561
+ db.query(DesignSystem)
562
+ .filter(DesignSystem.name == request.name, DesignSystem.is_active == True) # noqa: E712
563
+ .first()
564
+ )
552
565
  if existing:
553
566
  raise HTTPException(
554
567
  status_code=status.HTTP_409_CONFLICT,
@@ -638,9 +651,16 @@ def update_design_system(
638
651
  _require_creator_or_admin(ds)
639
652
 
640
653
  if request.name and request.name != ds.name:
654
+ # LIVE rows only, matching the partial unique index
655
+ # ``uq_design_system_name_active`` — the same reason as create/import: a
656
+ # tombstone must not reserve a name the picker no longer shows.
641
657
  clash = (
642
658
  db.query(DesignSystem)
643
- .filter(DesignSystem.name == request.name, DesignSystem.id != ds_id)
659
+ .filter(
660
+ DesignSystem.name == request.name,
661
+ DesignSystem.id != ds_id,
662
+ DesignSystem.is_active == True, # noqa: E712
663
+ )
644
664
  .first()
645
665
  )
646
666
  if clash:
@@ -549,7 +549,15 @@ def _run_migrations(engine, schema: str | None = None):
549
549
  # deleted, so a reader of this list can see what happened to them.
550
550
  _migrate_uncap_brand_text_columns(conn, inspector, schema, _qual, is_sqlite)
551
551
 
552
+ # --- design system: name uniqueness scoped to LIVE rows, so a soft delete
553
+ # --- stops reserving the name forever (partial unique index) ---
554
+ _migrate_design_system_partial_name_index(
555
+ conn, inspector, schema, _qual, is_sqlite
556
+ )
557
+
552
558
  # --- keep newly created objects owned by the shared role (prod forks) ---
559
+ # Runs LAST so every object created above — including the partial name index
560
+ # — is re-homed onto the shared owner.
553
561
  _reassign_new_objects_to_shared_owner(conn, is_sqlite)
554
562
 
555
563
 
@@ -763,7 +771,9 @@ def _migrate_uncap_brand_text_columns(
763
771
  ``VARCHAR(n)`` is a no-rewrite change — ``text`` and ``varchar`` share a
764
772
  storage representation, so Postgres only updates the catalog. Existing values
765
773
  are preserved exactly; ``text`` has no length limit to violate.
766
- ``design_system.name`` carries a UNIQUE constraint, which is unaffected: a
774
+ ``design_system.name`` is covered by a unique index the PARTIAL
775
+ ``uq_design_system_name_active``, see
776
+ :func:`_migrate_design_system_partial_name_index` — which is unaffected: a
767
777
  unique btree index over ``text`` is normal, bounded only by the ~2704-byte
768
778
  index-tuple maximum that a design-system name does not approach. If one ever
769
779
  did, the INSERT would fail loudly rather than truncate — so no prefix or
@@ -832,6 +842,148 @@ def _migrate_uncap_brand_text_columns(
832
842
  )
833
843
 
834
844
 
845
+ #: Name of the partial unique index that scopes design-system name uniqueness to
846
+ #: LIVE rows. Must match the ``Index(...)`` declared in
847
+ #: ``src/database/models/design_system.py`` — ``create_all`` builds it under this
848
+ #: name on fresh installs and this migration builds it under the same name on
849
+ #: already-provisioned ones, so the two paths converge on one schema.
850
+ _DS_NAME_ACTIVE_INDEX = "uq_design_system_name_active"
851
+
852
+
853
+ def _migrate_design_system_partial_name_index(
854
+ conn, inspector, schema, _qual, is_sqlite
855
+ ) -> None:
856
+ """Scope ``design_system.name`` uniqueness to LIVE rows (idempotent).
857
+
858
+ ``design_system.name`` originally carried a whole-table UNIQUE constraint. That
859
+ made the soft delete leak the name PERMANENTLY: ``DELETE`` tombstones the row
860
+ (``is_active = False``), the list endpoint hides it, and the tombstone then held
861
+ its name against every subsequent import — a name the user could no longer see,
862
+ delete, or reuse. The reported symptom was an unfixable
863
+ "A design system named 'X' already exists (id=N)" on re-importing a corrected
864
+ bundle under the name the user had just deleted.
865
+
866
+ Filtering only the application-side name pre-checks would NOT have fixed it: it
867
+ converts the clean 409 into an ``IntegrityError`` at commit, i.e. an HTTP 500 on
868
+ a legitimate upload. The uniqueness RULE itself is what was wrong, so this
869
+ replaces the whole-table constraint with a PARTIAL unique index over
870
+ ``WHERE is_active``. Tombstones are then unconstrained — many may share one name,
871
+ which is what lets a delete/re-import cycle repeat indefinitely instead of
872
+ working exactly once — while two LIVE rows still cannot.
873
+
874
+ Ordering is deliberate: the replacement index is CREATED FIRST and the old
875
+ constraint is dropped ONLY IF that succeeded. The database is therefore never
876
+ left with no uniqueness enforcement at all — including on a database where the
877
+ constraint was already dropped but duplicate live names somehow exist, in which
878
+ case the CREATE fails, the DROP is skipped, and the existing constraint stays.
879
+
880
+ Idempotent: returns early once the partial index is present, so repeat startups
881
+ and a fresh ``create_all`` database (where the ORM already declares the index)
882
+ are both no-ops. Each statement runs in its OWN SAVEPOINT so a failure — e.g.
883
+ insufficient privileges on a locked-down deploy, or an inherited foreign-owned
884
+ table on a copy-on-write branch fork — cannot poison the outer migration
885
+ transaction.
886
+
887
+ Discovery, not assumption: the old constraint's name is REFLECTED rather than
888
+ hardcoded to Postgres's ``design_system_name_key`` default, and both shapes are
889
+ handled — a UNIQUE *constraint* (what a column-level ``unique=True`` emits, and
890
+ what needs ``DROP CONSTRAINT``) and a bare unique *index* (which needs
891
+ ``DROP INDEX``).
892
+
893
+ No-op on SQLite. It is not a deployment target (``_get_database_url`` only ever
894
+ returns PostgreSQL unless ``DATABASE_URL`` is set explicitly), and the tests
895
+ build their schema with ``create_all``, which emits the partial index directly —
896
+ SQLite has supported partial indexes since 3.8, so the unit suite exercises the
897
+ SAME rule as Lakebase. An explicitly-configured pre-existing SQLite file would
898
+ keep its inline table-level UNIQUE, which SQLite cannot drop without rebuilding
899
+ the table; rebuilding a table of brand blobs is not worth doing for a
900
+ configuration nothing deploys, so it is left alone rather than silently rewritten.
901
+ """
902
+ from sqlalchemy import inspect, text
903
+
904
+ if is_sqlite:
905
+ return
906
+
907
+ # Reflect LIVE, with a fresh inspector: the shared one caches its reflection
908
+ # from before the design_system table may have been created earlier in this same
909
+ # migration transaction.
910
+ try:
911
+ insp = inspect(conn)
912
+ indexes = insp.get_indexes("design_system", schema=schema)
913
+ unique_constraints = insp.get_unique_constraints("design_system", schema=schema)
914
+ except Exception:
915
+ return # table absent on this deploy
916
+
917
+ if any(ix.get("name") == _DS_NAME_ACTIVE_INDEX for ix in indexes):
918
+ return # already scoped
919
+
920
+ logger.info(
921
+ "Migration: scoping design_system.name uniqueness to active rows (%s)",
922
+ _DS_NAME_ACTIVE_INDEX,
923
+ )
924
+ try:
925
+ with conn.begin_nested():
926
+ conn.execute(text(
927
+ f"CREATE UNIQUE INDEX {_DS_NAME_ACTIVE_INDEX} "
928
+ f'ON {_qual("design_system")} (name) WHERE is_active'
929
+ ))
930
+ except Exception:
931
+ logger.warning(
932
+ "Migration: could not create %s; design_system.name keeps its existing "
933
+ "whole-table uniqueness and a soft-deleted name stays reserved",
934
+ _DS_NAME_ACTIVE_INDEX,
935
+ exc_info=True,
936
+ )
937
+ return
938
+
939
+ # Only now is it safe to remove the whole-table rule the new index replaces.
940
+ # A column-level ``unique=True`` emits a UNIQUE CONSTRAINT; some databases may
941
+ # instead carry a bare unique index. Drop whichever is actually there, and only
942
+ # when it covers exactly ``(name)`` — a composite unique over more columns is a
943
+ # different rule this migration has no business removing.
944
+ for constraint in unique_constraints:
945
+ if list(constraint.get("column_names") or []) != ["name"]:
946
+ continue
947
+ name = constraint.get("name")
948
+ if not name:
949
+ continue
950
+ try:
951
+ with conn.begin_nested():
952
+ conn.execute(text(
953
+ f'ALTER TABLE {_qual("design_system")} DROP CONSTRAINT "{name}"'
954
+ ))
955
+ logger.info("Migration: dropped whole-table unique constraint %s", name)
956
+ except Exception:
957
+ logger.warning(
958
+ "Migration: could not drop unique constraint %s; a soft-deleted "
959
+ "design-system name stays reserved until it is removed",
960
+ name,
961
+ exc_info=True,
962
+ )
963
+
964
+ constraint_names = {c.get("name") for c in unique_constraints}
965
+ for index in indexes:
966
+ if not index.get("unique") or list(index.get("column_names") or []) != ["name"]:
967
+ continue
968
+ name = index.get("name")
969
+ # A constraint-backing index is dropped with its constraint above; issuing
970
+ # DROP INDEX for it would fail.
971
+ if not name or name in constraint_names:
972
+ continue
973
+ try:
974
+ with conn.begin_nested():
975
+ qualified = f'"{schema}"."{name}"' if schema else f'"{name}"'
976
+ conn.execute(text(f"DROP INDEX {qualified}"))
977
+ logger.info("Migration: dropped whole-table unique index %s", name)
978
+ except Exception:
979
+ logger.warning(
980
+ "Migration: could not drop unique index %s; a soft-deleted "
981
+ "design-system name stays reserved until it is removed",
982
+ name,
983
+ exc_info=True,
984
+ )
985
+
986
+
835
987
  def _reassign_new_objects_to_shared_owner(
836
988
  conn, is_sqlite: bool, owning_role: str = "tellr_app_owners"
837
989
  ) -> None:
@@ -69,6 +69,7 @@ from sqlalchemy import (
69
69
  Column,
70
70
  DateTime,
71
71
  ForeignKey,
72
+ Index,
72
73
  Integer,
73
74
  LargeBinary,
74
75
  String,
@@ -124,14 +125,19 @@ class DesignSystem(Base):
124
125
  # here silently TRUNCATED an imported name to 255 characters, storing the brand
125
126
  # under a name it never chose.
126
127
  #
127
- # ``unique`` is RETAINED on the now-unbounded column. On PostgreSQL/Lakebase a
128
- # UNIQUE constraint on ``text`` is a normal btree index; the only limit is the
129
- # ~2704-byte per-entry index-tuple maximum, which a design-system NAME does not
130
- # approach in practice. If a name ever did, the insert would fail loudly with an
131
- # index-row-size error rather than corrupt or truncate anything so no prefix /
132
- # expression index is needed, and none is used. Uniqueness is a real product
133
- # rule (the picker addresses systems by name), so it is not dropped.
134
- name = Column(Text, nullable=False, unique=True)
128
+ # Uniqueness is enforced, but only over LIVE rows, by the partial unique index
129
+ # ``uq_design_system_name_active`` declared below NOT by a column-level
130
+ # ``unique=True``. A whole-table UNIQUE constraint made a soft delete leak the
131
+ # name permanently: DELETE tombstones the row (``is_active = False``), the list
132
+ # endpoint hides it, and the tombstone then held its name against every later
133
+ # import a name the user could no longer see, delete, or reuse. Scoping the
134
+ # index to ``WHERE is_active`` is what makes the tombstone stop owning the name,
135
+ # and it is the DATABASE half of the fix: the application pre-checks in
136
+ # ``design_system_service.import_bundle`` and the create/rename routes filter
137
+ # ``is_active`` to fail fast with a 409, but this index is what actually decides.
138
+ # Both halves must move together — filtering the pre-checks alone converts the
139
+ # clean 409 into an IntegrityError 500 at commit.
140
+ name = Column(Text, nullable=False)
135
141
  description = Column(Text, nullable=True)
136
142
 
137
143
  # Authorship + org-default flags (org-shared visibility; no per-user isolation)
@@ -195,6 +201,38 @@ class DesignSystem(Base):
195
201
  passive_deletes=True,
196
202
  )
197
203
 
204
+ # Name uniqueness scoped to LIVE rows. See the ``name`` column note for why a
205
+ # whole-table UNIQUE constraint was wrong.
206
+ #
207
+ # Deliberately a partial unique INDEX rather than a UNIQUE constraint: Postgres
208
+ # has no partial unique constraints, only partial unique indexes, and a
209
+ # column-level ``unique=True`` would emit exactly the whole-table constraint this
210
+ # replaces. Declared here so ``create_all`` builds it on fresh installs;
211
+ # ``_migrate_design_system_partial_name_index`` converts already-provisioned
212
+ # databases.
213
+ #
214
+ # ``WHERE is_active`` means MANY tombstones may share one name — intended, so a
215
+ # delete/re-import cycle can repeat indefinitely rather than working exactly once.
216
+ #
217
+ # Emitted identically on both dialects (verified): SQLite has supported partial
218
+ # indexes since 3.8, so the SQLite used in tests enforces the SAME rule as
219
+ # PostgreSQL/Lakebase and the behaviour is actually covered by the unit suite —
220
+ # it would not be under a ``postgresql_where``-only declaration. On
221
+ # PostgreSQL/Lakebase this is a unique btree index over ``text``, bounded only by
222
+ # the ~2704-byte index-tuple maximum a design-system name does not approach; an
223
+ # over-long name still fails loudly and is still translated by
224
+ # ``translate_name_index_limit_error``, so the uncapped-brand-text guarantee is
225
+ # unchanged.
226
+ __table_args__ = (
227
+ Index(
228
+ "uq_design_system_name_active",
229
+ "name",
230
+ unique=True,
231
+ postgresql_where=text("is_active"),
232
+ sqlite_where=text("is_active"),
233
+ ),
234
+ )
235
+
198
236
  def __repr__(self):
199
237
  return (
200
238
  f"<DesignSystem(id={self.id}, name='{self.name}', "