databricks-tellr-app 0.4.2.dev5__tar.gz → 0.4.2.dev7__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 (161) hide show
  1. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/PKG-INFO +1 -1
  2. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app.egg-info/PKG-INFO +1 -1
  3. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app.egg-info/SOURCES.txt +2 -0
  4. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/pyproject.toml +1 -1
  5. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/main.py +11 -0
  6. databricks_tellr_app-0.4.2.dev7/src/core/backfill_session_slides_startup.py +311 -0
  7. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/README.md +0 -0
  8. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app/__init__.py +0 -0
  9. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app/run.py +0 -0
  10. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app.egg-info/dependency_links.txt +0 -0
  11. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app.egg-info/requires.txt +0 -0
  12. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/databricks_tellr_app.egg-info/top_level.txt +0 -0
  13. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/setup.cfg +0 -0
  14. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/setup.py +0 -0
  15. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/__init__.py +0 -0
  16. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/__init__.py +0 -0
  17. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/_otel_bootstrap.py +0 -0
  18. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/fixtures/tour_demo_deck.json +0 -0
  19. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/mcp_auth.py +0 -0
  20. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/mcp_server.py +0 -0
  21. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/middleware/__init__.py +0 -0
  22. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/middleware/csrf.py +0 -0
  23. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/middleware/request_logging.py +0 -0
  24. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/middleware/security_headers.py +0 -0
  25. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/__init__.py +0 -0
  26. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/_authz.py +0 -0
  27. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/admin.py +0 -0
  28. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/admin_usage.py +0 -0
  29. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/agent_config.py +0 -0
  30. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/chat.py +0 -0
  31. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/deck_contributors.py +0 -0
  32. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/export.py +0 -0
  33. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/feedback.py +0 -0
  34. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/google_slides.py +0 -0
  35. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/images.py +0 -0
  36. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/local_version.py +0 -0
  37. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/profiles.py +0 -0
  38. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/sessions.py +0 -0
  39. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/settings/__init__.py +0 -0
  40. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/settings/contributors.py +0 -0
  41. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/settings/deck_prompts.py +0 -0
  42. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/settings/identities.py +0 -0
  43. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/settings/slide_styles.py +0 -0
  44. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/setup.py +0 -0
  45. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/slides.py +0 -0
  46. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/tools.py +0 -0
  47. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/tour.py +0 -0
  48. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/verification.py +0 -0
  49. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/routes/version.py +0 -0
  50. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/__init__.py +0 -0
  51. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/agent_config.py +0 -0
  52. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/feedback.py +0 -0
  53. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/requests.py +0 -0
  54. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/responses.py +0 -0
  55. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/settings/__init__.py +0 -0
  56. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/settings/requests.py +0 -0
  57. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/settings/responses.py +0 -0
  58. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/schemas/streaming.py +0 -0
  59. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/__init__.py +0 -0
  60. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/chat_service.py +0 -0
  61. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/export_job_queue.py +0 -0
  62. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/feedback_service.py +0 -0
  63. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/job_queue.py +0 -0
  64. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/session_manager.py +0 -0
  65. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/session_naming.py +0 -0
  66. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/slide_repository.py +0 -0
  67. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/usage_events.py +0 -0
  68. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/services/usage_service.py +0 -0
  69. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/utils/__init__.py +0 -0
  70. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/api/utils/validation.py +0 -0
  71. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/__init__.py +0 -0
  72. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/config_loader.py +0 -0
  73. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/context_utils.py +0 -0
  74. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/database.py +0 -0
  75. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/databricks_client.py +0 -0
  76. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/defaults.py +0 -0
  77. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/encryption.py +0 -0
  78. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/init_default_profile.py +0 -0
  79. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/lakebase.py +0 -0
  80. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/migrate_profiles_to_agent_config.py +0 -0
  81. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/mlflow_agent_spans.py +0 -0
  82. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/mlflow_tracing.py +0 -0
  83. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/otel_logging.py +0 -0
  84. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/permission_context.py +0 -0
  85. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/prompt_modules.py +0 -0
  86. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/settings_db.py +0 -0
  87. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/core/user_context.py +0 -0
  88. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/__init__.py +0 -0
  89. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/__init__.py +0 -0
  90. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/deck_contributor.py +0 -0
  91. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/encryption_key.py +0 -0
  92. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/feedback.py +0 -0
  93. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/genie_space.py +0 -0
  94. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/google_global_credentials.py +0 -0
  95. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/google_oauth_token.py +0 -0
  96. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/identity.py +0 -0
  97. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/image.py +0 -0
  98. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/profile.py +0 -0
  99. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/profile_contributor.py +0 -0
  100. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/prompts.py +0 -0
  101. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/request_log.py +0 -0
  102. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/session.py +0 -0
  103. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/slide_deck_prompt.py +0 -0
  104. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/slide_style_library.py +0 -0
  105. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/usage_event.py +0 -0
  106. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/database/models/user_preference.py +0 -0
  107. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/domain/__init__.py +0 -0
  108. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/domain/slide.py +0 -0
  109. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/domain/slide_deck.py +0 -0
  110. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/__init__.py +0 -0
  111. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/agent.py +0 -0
  112. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/agent_factory.py +0 -0
  113. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/config_service.py +0 -0
  114. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/config_validator.py +0 -0
  115. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/__init__.py +0 -0
  116. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/ast_guard.py +0 -0
  117. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/codeprep.py +0 -0
  118. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/gslides_runner.py +0 -0
  119. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/jail.py +0 -0
  120. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/pptx_runner.py +0 -0
  121. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/converter_jail/protocol.py +0 -0
  122. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/drive_uploader.py +0 -0
  123. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/evaluation/__init__.py +0 -0
  124. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/evaluation/llm_judge.py +0 -0
  125. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/genie_service.py +0 -0
  126. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/google_slides_auth.py +0 -0
  127. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/google_slides_prompts_defaults.py +0 -0
  128. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/html_to_google_slides.py +0 -0
  129. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/html_to_pptx.py +0 -0
  130. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/identity_provider.py +0 -0
  131. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/identity_providers/__init__.py +0 -0
  132. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/identity_providers/account_provider.py +0 -0
  133. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/identity_providers/local_provider.py +0 -0
  134. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/identity_providers/workspace_provider.py +0 -0
  135. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/image_service.py +0 -0
  136. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/image_tools.py +0 -0
  137. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/permission_service.py +0 -0
  138. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/pptx_from_html_huashu.py +0 -0
  139. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/pptx_from_records.py +0 -0
  140. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/pptx_prompts_defaults.py +0 -0
  141. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/profile_service.py +0 -0
  142. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/streaming_callback.py +0 -0
  143. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/tools/__init__.py +0 -0
  144. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/tools/agent_bricks_tool.py +0 -0
  145. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/tools/genie_tool.py +0 -0
  146. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/tools/mcp_tool.py +0 -0
  147. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/tools/model_endpoint_tool.py +0 -0
  148. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/tools/vector_tool.py +0 -0
  149. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/services/validator.py +0 -0
  150. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/__init__.py +0 -0
  151. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/css_utils.py +0 -0
  152. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/error_handling.py +0 -0
  153. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/html_safety.py +0 -0
  154. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/html_utils.py +0 -0
  155. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/image_utils.py +0 -0
  156. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/js_validator.py +0 -0
  157. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/logging_config.py +0 -0
  158. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/pi_filter.py +0 -0
  159. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/slide_hash.py +0 -0
  160. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/src/utils/spotlight.py +0 -0
  161. {databricks_tellr_app-0.4.2.dev5 → databricks_tellr_app-0.4.2.dev7}/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.dev5
3
+ Version: 0.4.2.dev7
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.dev5
3
+ Version: 0.4.2.dev7
4
4
  Summary: Tellr application package for Databricks Apps
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -61,6 +61,7 @@ setup.py
61
61
  ./src/api/utils/__init__.py
62
62
  ./src/api/utils/validation.py
63
63
  ./src/core/__init__.py
64
+ ./src/core/backfill_session_slides_startup.py
64
65
  ./src/core/config_loader.py
65
66
  ./src/core/context_utils.py
66
67
  ./src/core/database.py
@@ -216,6 +217,7 @@ src/api/services/usage_service.py
216
217
  src/api/utils/__init__.py
217
218
  src/api/utils/validation.py
218
219
  src/core/__init__.py
220
+ src/core/backfill_session_slides_startup.py
219
221
  src/core/config_loader.py
220
222
  src/core/context_utils.py
221
223
  src/core/database.py
@@ -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.dev5"
7
+ version = "0.4.2.dev7"
8
8
  description = "Tellr application package for Databricks Apps"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -40,6 +40,7 @@ from src.core.database import (
40
40
  stop_token_refresh,
41
41
  )
42
42
  from src.core.migrate_profiles_to_agent_config import migrate_profiles, backfill_sessions
43
+ from src.core.backfill_session_slides_startup import backfill_unmigrated_decks
43
44
 
44
45
  logger = logging.getLogger(__name__)
45
46
 
@@ -114,6 +115,16 @@ async def lifespan(app: FastAPI):
114
115
  backfilled = backfill_sessions(get_session_local())
115
116
  if backfilled:
116
117
  logger.info(f"Backfilled {backfilled} sessions with agent_config")
118
+
119
+ # Row-per-slide: migrate historical deck_json blobs into session_slides
120
+ # rows. Guarded by a NOT EXISTS anti-join, so this is a no-op scan once
121
+ # every deck has rows. Runs here rather than as a manual script so an
122
+ # upgrade cannot leave decks half-migrated (a deck edited before a
123
+ # hand-run backfill acquires rows without its verdicts, and the
124
+ # idempotency guard then skips it permanently).
125
+ slide_decks = backfill_unmigrated_decks(get_session_local())
126
+ if slide_decks:
127
+ logger.info(f"Backfilled {slide_decks} deck(s) into session_slides rows")
117
128
  except Exception as e:
118
129
  logger.error(f"Failed to initialize database: {e}")
119
130
  raise
@@ -0,0 +1,311 @@
1
+ """Row-per-slide backfill: migrate legacy ``deck_json`` blobs into ``session_slides`` rows.
2
+
3
+ Lives under ``src/`` rather than ``scripts/`` because the app calls
4
+ ``backfill_unmigrated_decks`` from its FastAPI lifespan on every boot, and the
5
+ Databricks Apps wheel ships only ``src/`` (see
6
+ ``packages/databricks-tellr-app/setup.py``, which copytrees ``src`` and the
7
+ frontend/sidecars but NOT ``scripts``). Importing this from ``scripts`` would
8
+ raise ``ModuleNotFoundError`` at startup in production.
9
+
10
+ ``scripts/backfill_session_slides.py`` remains the operator CLI and imports from
11
+ here, so there is exactly ONE implementation of the row mapping.
12
+
13
+ Idempotent: a row already present at ``(session_id, position)`` is skipped.
14
+ Also lifts deck-level presentation fields (``css``, ``external_scripts``) out of
15
+ ``deck_json`` into their dedicated columns — the row read path reads them from
16
+ columns, so without the lift every existing deck would silently lose its
17
+ stylesheet and the Chart.js CDN on the first read after backfill. Orphan rows
18
+ (``position >= slide count``) are pruned in the same transaction as the inserts.
19
+ """
20
+ from __future__ import annotations
21
+
22
+ import json
23
+ import logging
24
+ from typing import Any, Dict, Optional
25
+
26
+ from sqlalchemy import and_
27
+ from sqlalchemy.orm import Session
28
+
29
+ from src.api.services.session_manager import _prune_slide_rows_beyond, _upsert_slide_row
30
+ from src.database.models.session import SessionSlide, SessionSlideDeck
31
+ from src.utils.slide_hash import compute_slide_hash
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ def backfill_session(
37
+ db: Session,
38
+ session_id: int,
39
+ dry_run: bool = True,
40
+ ) -> Dict[str, Any]:
41
+ """Backfill one session's session_slides rows from its deck_json blob.
42
+
43
+ Args:
44
+ db: Live SQLAlchemy session (the caller commits / rolls back).
45
+ session_id: UserSession.id (Integer PK) to backfill. This is NOT the
46
+ string business key — callers that accept a string must resolve it
47
+ first via UserSession.session_id.
48
+ dry_run: When True, counts what would change but mutates NOTHING.
49
+ No ORM adds, no column assignments, no deletes.
50
+
51
+ Returns:
52
+ dict with keys:
53
+ session_id – echoes the argument
54
+ slides_inserted – rows added (or would be added in dry-run)
55
+ slides_skipped – rows that already existed
56
+ verification_migrated – slides whose verification_record was written
57
+ css_backfilled – 1 if deck.css was (or would be) set, else 0
58
+ external_scripts_backfilled – 1 if external_scripts_json was (or would be) set
59
+ head_meta_backfilled – 1 if head_meta_json was (or would be) set
60
+ orphans_pruned – rows deleted (or that would be deleted) above slide count
61
+ """
62
+ result: Dict[str, Any] = {
63
+ "session_id": session_id,
64
+ "slides_inserted": 0,
65
+ "slides_skipped": 0,
66
+ "verification_migrated": 0,
67
+ "css_backfilled": 0,
68
+ "external_scripts_backfilled": 0,
69
+ "head_meta_backfilled": 0,
70
+ "orphans_pruned": 0,
71
+ }
72
+
73
+ # Load the deck for this session.
74
+ deck = (
75
+ db.query(SessionSlideDeck)
76
+ .filter(SessionSlideDeck.session_id == session_id)
77
+ .one_or_none()
78
+ )
79
+ if deck is None:
80
+ logger.info("Session %d has no slide deck — skipping", session_id)
81
+ return result
82
+
83
+ if not deck.deck_json:
84
+ logger.info("Session %d deck_json is empty — skipping", session_id)
85
+ return result
86
+
87
+ try:
88
+ deck_dict = json.loads(deck.deck_json)
89
+ except json.JSONDecodeError as exc:
90
+ logger.error("Session %d deck_json is invalid JSON: %s", session_id, exc)
91
+ return result
92
+
93
+ # Parse verification_map (keyed by content_hash → findings dict).
94
+ verification_map: Dict[str, Any] = {}
95
+ if deck.verification_map:
96
+ try:
97
+ verification_map = json.loads(deck.verification_map)
98
+ except json.JSONDecodeError:
99
+ logger.warning("Session %d verification_map is invalid JSON — skipping", session_id)
100
+
101
+ slides = deck_dict.get("slides") or []
102
+
103
+ # -------------------------------------------------------------------------
104
+ # Per-slide inserts
105
+ # -------------------------------------------------------------------------
106
+ for position, slide_dict in enumerate(slides):
107
+ existing = (
108
+ db.query(SessionSlide)
109
+ .filter(
110
+ and_(
111
+ SessionSlide.session_id == session_id,
112
+ SessionSlide.position == position,
113
+ )
114
+ )
115
+ .one_or_none()
116
+ )
117
+ if existing is not None:
118
+ logger.debug(
119
+ "Session %d position %d already has a row — skipping",
120
+ session_id,
121
+ position,
122
+ )
123
+ result["slides_skipped"] += 1
124
+ continue
125
+
126
+ html = slide_dict.get("html") or ""
127
+
128
+ # Migrate this slide's verification verdict from the deck-wide blob.
129
+ content_hash = compute_slide_hash(html)
130
+ verification: Optional[Dict[str, Any]] = None
131
+ if content_hash in verification_map:
132
+ verification = {content_hash: verification_map[content_hash]}
133
+ result["verification_migrated"] += 1
134
+
135
+ if not dry_run:
136
+ # Shared row writer (session_manager._upsert_slide_row) — one helper
137
+ # owns the full field set for a session_slides row, so the backfill
138
+ # cannot drift from the dual-write, restore or SlideWriter. It also
139
+ # gives this writer the tz normalisation (naive UTC) that used to live
140
+ # here alone, and the fresh-uuid4 `id` decision:
141
+ #
142
+ # `id` is String(64) UNIQUE globally across all sessions, and two
143
+ # sessions' deck_jsons may legitimately carry the same slide_id
144
+ # (duplicate-slide and restore flows), so reusing slide_id would
145
+ # violate the constraint on the second insert and abort the backfill
146
+ # mid-run. slide_id is preserved in the slide_id column.
147
+ #
148
+ # author_fallback is deliberately omitted (None): the backfill has no
149
+ # writer identity, so created_by/modified_by stay NULL when the slide
150
+ # dict has none. The live dual-write DOES pass a fallback. This
151
+ # divergence is intentional — do not "harmonise" it.
152
+ _upsert_slide_row(
153
+ db,
154
+ session_id,
155
+ position,
156
+ slide_dict,
157
+ now_dt=None,
158
+ author_fallback=None,
159
+ verification=verification,
160
+ )
161
+
162
+ result["slides_inserted"] += 1
163
+ logger.info(
164
+ "Session %d position %d: %s (html_len=%d, verification=%s)",
165
+ session_id,
166
+ position,
167
+ "would insert" if dry_run else "inserted",
168
+ len(html),
169
+ bool(verification),
170
+ )
171
+
172
+ # -------------------------------------------------------------------------
173
+ # Lift deck-level presentation fields into their new columns.
174
+ #
175
+ # CSS and external_scripts live INSIDE deck_json for all existing decks.
176
+ # The row read path (Task 5 / get_slide_deck) reads them from the dedicated
177
+ # columns, so without this lift the first read after backfill returns css=""
178
+ # and external_scripts=[] — the stylesheet and Chart.js CDN vanish silently.
179
+ # This is the PRD §3 no-regression gate on the historical-data side.
180
+ # -------------------------------------------------------------------------
181
+ new_css = deck_dict.get("css") or ""
182
+ new_ext = json.dumps(deck_dict.get("external_scripts") or [])
183
+ new_head_meta = json.dumps(deck_dict.get("head_meta") or {})
184
+
185
+ if deck.css is None:
186
+ result["css_backfilled"] += 1
187
+ if not dry_run:
188
+ deck.css = new_css
189
+
190
+ if deck.external_scripts_json is None:
191
+ result["external_scripts_backfilled"] += 1
192
+ if not dry_run:
193
+ deck.external_scripts_json = new_ext
194
+
195
+ # F5: head_meta is the third deck-level presentation field. Without this lift
196
+ # the first row-path read after backfill returns the deck's head_meta from the
197
+ # deck_json fallback only; once deck_json is eventually retired the custom
198
+ # viewport would be lost. Lift it into the column now.
199
+ if deck.head_meta_json is None:
200
+ result["head_meta_backfilled"] += 1
201
+ if not dry_run:
202
+ deck.head_meta_json = new_head_meta
203
+
204
+ # -------------------------------------------------------------------------
205
+ # Prune orphan rows (position >= slide count).
206
+ #
207
+ # A re-run after a deck shrank leaves stale higher-position rows. The read
208
+ # path prefers session_slides whenever ANY rows exist, so get_slide_deck()
209
+ # would return MORE slides than the deck actually has — and PR3's
210
+ # all-committed predicates would wait forever on phantom positions.
211
+ # -------------------------------------------------------------------------
212
+ if not dry_run:
213
+ # Shared prune strategy — see session_manager._prune_slide_rows_beyond.
214
+ result["orphans_pruned"] = _prune_slide_rows_beyond(
215
+ db, session_id, len(slides)
216
+ )
217
+ else:
218
+ orphan_count = (
219
+ db.query(SessionSlide)
220
+ .filter(
221
+ and_(
222
+ SessionSlide.session_id == session_id,
223
+ SessionSlide.position >= len(slides),
224
+ )
225
+ )
226
+ .count()
227
+ )
228
+ result["orphans_pruned"] = orphan_count
229
+
230
+ if not dry_run:
231
+ db.commit()
232
+
233
+ return result
234
+
235
+
236
+ def backfill_unmigrated_decks(session_factory) -> int:
237
+ """Backfill every deck that has NO session_slides rows yet. Returns count migrated.
238
+
239
+ Called from the FastAPI lifespan alongside ``migrate_profiles`` so an upgrade
240
+ migrates historical decks by itself, instead of depending on an operator
241
+ remembering to run this module by hand. Leaving it manual meant every deploy
242
+ sat in a split state: reads still worked (``get_slide_deck`` falls back to
243
+ ``deck_json``), but a deck *edited* before the backfill acquired rows without
244
+ its verdicts, and the idempotency guard then skipped it forever. Running on
245
+ startup closes that window for untouched decks.
246
+
247
+ The guard is a per-deck NOT EXISTS anti-join. Both indexes it needs already
248
+ exist (``session_slides``' composite PK on ``(session_id, position)`` plus
249
+ ``ix_session_slides_session_position``), so each existence check is an
250
+ index-only probe that stops at the first row. Once every deck is backfilled
251
+ the query returns zero rows, making later boots a single cheap scan of a
252
+ small table — far below the cost of the OAuth token fetch and pool setup that
253
+ already happen at startup.
254
+
255
+ NOTE ON SCOPE: this finds decks with no rows AT ALL. A *partially*
256
+ backfilled deck (some positions have rows) is deliberately left to the CLI —
257
+ catching those needs per-position comparison and collides with the
258
+ idempotency guard. See the runbook's "decks edited between deploy and
259
+ backfill" section.
260
+ """
261
+ db = session_factory()
262
+ try:
263
+ unmigrated = [
264
+ row[0]
265
+ for row in db.query(SessionSlideDeck.session_id)
266
+ .filter(
267
+ SessionSlideDeck.deck_json.isnot(None),
268
+ ~db.query(SessionSlide)
269
+ .filter(SessionSlide.session_id == SessionSlideDeck.session_id)
270
+ .exists(),
271
+ )
272
+ .all()
273
+ ]
274
+
275
+ if not unmigrated:
276
+ return 0
277
+
278
+ logger.info(
279
+ "Row-per-slide backfill: %d deck(s) have no session_slides rows; migrating",
280
+ len(unmigrated),
281
+ )
282
+
283
+ migrated = 0
284
+ failed: list[int] = []
285
+ for session_pk in unmigrated:
286
+ # One transaction per deck: a bad deck_json cannot abort the others,
287
+ # and a re-run resumes cleanly because the guard re-evaluates.
288
+ try:
289
+ result = backfill_session(db, session_pk, dry_run=False)
290
+ if result["slides_inserted"]:
291
+ migrated += 1
292
+ except Exception:
293
+ db.rollback()
294
+ failed.append(session_pk)
295
+ logger.exception(
296
+ "Row-per-slide backfill failed for session pk=%d; continuing",
297
+ session_pk,
298
+ )
299
+
300
+ if failed:
301
+ # Deliberately not raised: a deck we cannot parse must not block app
302
+ # startup, and its deck_json is still readable via the fallback path.
303
+ logger.error(
304
+ "Row-per-slide backfill: %d deck(s) failed and remain on deck_json: %s",
305
+ len(failed),
306
+ failed,
307
+ )
308
+
309
+ return migrated
310
+ finally:
311
+ db.close()