databricks-tellr-app 0.4.3.dev3463__tar.gz → 0.4.3.dev3464__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 (246) hide show
  1. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/PKG-INFO +2 -2
  2. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app.egg-info/PKG-INFO +2 -2
  3. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app.egg-info/SOURCES.txt +8 -0
  4. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app.egg-info/requires.txt +1 -1
  5. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/pyproject.toml +2 -2
  6. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/main.py +25 -1
  7. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/middleware/security_headers.py +8 -1
  8. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/settings/slide_styles.py +201 -0
  9. databricks_tellr_app-0.4.3.dev3464/src/api/services/slide_style_preview_queue.py +583 -0
  10. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/database.py +70 -0
  11. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/defaults.py +1 -1
  12. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/__init__.py +2 -0
  13. databricks_tellr_app-0.4.3.dev3464/src/database/models/slide_style_library.py +79 -0
  14. databricks_tellr_app-0.4.3.dev3464/src/database/models/slide_style_preview.py +55 -0
  15. databricks_tellr_app-0.4.3.dev3464/src/services/agent_definition_manifest_v1.py +3 -0
  16. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/model_endpoint_catalog.py +64 -20
  17. databricks_tellr_app-0.4.3.dev3464/src/services/slide_style_preview_fixture.py +204 -0
  18. databricks_tellr_app-0.4.3.dev3464/src/services/slide_style_preview_storage.py +119 -0
  19. databricks_tellr_app-0.4.3.dev3463/src/database/models/slide_style_library.py +0 -47
  20. databricks_tellr_app-0.4.3.dev3463/src/services/agent_definition_manifest_v1.py +0 -3
  21. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/README.md +0 -0
  22. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app/__init__.py +0 -0
  23. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app/run.py +0 -0
  24. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app.egg-info/dependency_links.txt +0 -0
  25. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/databricks_tellr_app.egg-info/top_level.txt +0 -0
  26. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/setup.cfg +0 -0
  27. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/setup.py +0 -0
  28. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/__init__.py +0 -0
  29. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/__init__.py +0 -0
  30. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/_otel_bootstrap.py +0 -0
  31. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/fixtures/tour_demo_deck.json +0 -0
  32. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/mcp_auth.py +0 -0
  33. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/mcp_server.py +0 -0
  34. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/middleware/__init__.py +0 -0
  35. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/middleware/csrf.py +0 -0
  36. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/middleware/request_logging.py +0 -0
  37. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/__init__.py +0 -0
  38. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/_authz.py +0 -0
  39. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/admin.py +0 -0
  40. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/admin_usage.py +0 -0
  41. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/agent_config.py +0 -0
  42. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/agent_definitions.py +0 -0
  43. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/chat.py +0 -0
  44. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/deck_contributors.py +0 -0
  45. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/export.py +0 -0
  46. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/feedback.py +0 -0
  47. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/google_slides.py +0 -0
  48. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/images.py +0 -0
  49. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/local_version.py +0 -0
  50. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/profiles.py +0 -0
  51. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/sessions.py +0 -0
  52. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/settings/__init__.py +0 -0
  53. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/settings/contributors.py +0 -0
  54. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/settings/deck_prompts.py +0 -0
  55. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/settings/design_systems.py +0 -0
  56. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/settings/identities.py +0 -0
  57. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/setup.py +0 -0
  58. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/slides.py +0 -0
  59. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/tools.py +0 -0
  60. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/tour.py +0 -0
  61. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/verification.py +0 -0
  62. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/routes/version.py +0 -0
  63. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/__init__.py +0 -0
  64. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/agent_config.py +0 -0
  65. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/agent_definitions.py +0 -0
  66. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/feedback.py +0 -0
  67. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/graph_release_history.py +0 -0
  68. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/graph_releases.py +0 -0
  69. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/requests.py +0 -0
  70. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/responses.py +0 -0
  71. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/settings/__init__.py +0 -0
  72. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/settings/requests.py +0 -0
  73. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/settings/responses.py +0 -0
  74. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/schemas/streaming.py +0 -0
  75. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/__init__.py +0 -0
  76. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/chat_service.py +0 -0
  77. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/deck_level_writer.py +0 -0
  78. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/export_job_queue.py +0 -0
  79. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/feedback_service.py +0 -0
  80. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/job_queue.py +0 -0
  81. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/session_manager.py +0 -0
  82. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/session_naming.py +0 -0
  83. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/slide_repository.py +0 -0
  84. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/usage_events.py +0 -0
  85. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/services/usage_service.py +0 -0
  86. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/utils/__init__.py +0 -0
  87. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/api/utils/validation.py +0 -0
  88. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/__init__.py +0 -0
  89. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/backfill_session_slides_startup.py +0 -0
  90. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/checkpointer.py +0 -0
  91. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/config_loader.py +0 -0
  92. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/context_utils.py +0 -0
  93. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/databricks_client.py +0 -0
  94. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/encryption.py +0 -0
  95. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/init_default_profile.py +0 -0
  96. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/lakebase.py +0 -0
  97. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/migrate_profiles_to_agent_config.py +0 -0
  98. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/mlflow_agent_spans.py +0 -0
  99. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/mlflow_tracing.py +0 -0
  100. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/otel_logging.py +0 -0
  101. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/permission_context.py +0 -0
  102. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/prompt_modules.py +0 -0
  103. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/settings_db.py +0 -0
  104. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/__init__.py +0 -0
  105. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/architect.py +0 -0
  106. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/build_reviewer.py +0 -0
  107. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/builder.py +0 -0
  108. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/data_analyst.py +0 -0
  109. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/deck_reviewer.py +0 -0
  110. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/fix_reviewer.py +0 -0
  111. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/skills/fixer.py +0 -0
  112. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/strip_retired_prompt_keys.py +0 -0
  113. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/core/user_context.py +0 -0
  114. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/__init__.py +0 -0
  115. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/data_migration.py +0 -0
  116. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/deck_contributor.py +0 -0
  117. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/deck_review.py +0 -0
  118. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/design_system.py +0 -0
  119. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/encryption_key.py +0 -0
  120. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/feedback.py +0 -0
  121. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/genie_space.py +0 -0
  122. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/google_global_credentials.py +0 -0
  123. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/google_oauth_token.py +0 -0
  124. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/graph_checkpoint.py +0 -0
  125. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/graph_configuration.py +0 -0
  126. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/identity.py +0 -0
  127. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/image.py +0 -0
  128. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/profile.py +0 -0
  129. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/profile_contributor.py +0 -0
  130. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/prompts.py +0 -0
  131. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/request_log.py +0 -0
  132. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/session.py +0 -0
  133. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/slide_deck_prompt.py +0 -0
  134. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/usage_event.py +0 -0
  135. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/models/user_preference.py +0 -0
  136. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/database/types.py +0 -0
  137. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/__init__.py +0 -0
  138. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/conversation_engine.py +0 -0
  139. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/conversation_turns.py +0 -0
  140. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/deck_spec.py +0 -0
  141. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/deck_spec_slides.py +0 -0
  142. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/finding.py +0 -0
  143. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/finding_copy.py +0 -0
  144. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/skill_io.py +0 -0
  145. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/slide.py +0 -0
  146. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/slide_alignment.py +0 -0
  147. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/slide_deck.py +0 -0
  148. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/domain/slide_numbering.py +0 -0
  149. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/__init__.py +0 -0
  150. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent.py +0 -0
  151. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_factory.py +0 -0
  152. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_model_payload.py +0 -0
  153. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_resolution.py +0 -0
  154. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_runtime.py +0 -0
  155. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_runtime_identity.py +0 -0
  156. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_schema_registry.py +0 -0
  157. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_schema_types.py +0 -0
  158. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/agent_test_workbench.py +0 -0
  159. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/collaboration_history.py +0 -0
  160. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/config_service.py +0 -0
  161. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/config_validator.py +0 -0
  162. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/conversation_pins.py +0 -0
  163. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/__init__.py +0 -0
  164. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/ast_guard.py +0 -0
  165. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/codeprep.py +0 -0
  166. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/gslides_runner.py +0 -0
  167. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/jail.py +0 -0
  168. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/pptx_runner.py +0 -0
  169. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/converter_jail/protocol.py +0 -0
  170. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/deck_css_aggregator.py +0 -0
  171. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/deck_review_store.py +0 -0
  172. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/design_system_compiler.py +0 -0
  173. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/design_system_service.py +0 -0
  174. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/design_system_templates.py +0 -0
  175. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/drive_uploader.py +0 -0
  176. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/evaluation/__init__.py +0 -0
  177. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/evaluation/llm_judge.py +0 -0
  178. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/foreman_service.py +0 -0
  179. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/gateway_openai.py +0 -0
  180. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/genie_service.py +0 -0
  181. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/google_slides_auth.py +0 -0
  182. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/google_slides_prompts_defaults.py +0 -0
  183. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/__init__.py +0 -0
  184. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/builder.py +0 -0
  185. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/event_emitter.py +0 -0
  186. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/nodes.py +0 -0
  187. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/progress.py +0 -0
  188. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/routers.py +0 -0
  189. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/state.py +0 -0
  190. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph/user_notices.py +0 -0
  191. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration.py +0 -0
  192. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_bootstrap.py +0 -0
  193. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_content.py +0 -0
  194. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_draft.py +0 -0
  195. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_publication.py +0 -0
  196. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_rollback.py +0 -0
  197. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_seed.py +0 -0
  198. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_configuration_workbench.py +0 -0
  199. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_definition_manifest.py +0 -0
  200. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_release_evidence.py +0 -0
  201. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/graph_release_history.py +0 -0
  202. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/html_to_google_slides.py +0 -0
  203. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/html_to_pptx.py +0 -0
  204. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/identity_provider.py +0 -0
  205. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/identity_providers/__init__.py +0 -0
  206. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/identity_providers/account_provider.py +0 -0
  207. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/identity_providers/local_provider.py +0 -0
  208. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/identity_providers/scim_filter.py +0 -0
  209. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/identity_providers/workspace_provider.py +0 -0
  210. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/image_service.py +0 -0
  211. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/image_tools.py +0 -0
  212. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/model_endpoint_probe.py +0 -0
  213. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/permission_service.py +0 -0
  214. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/persisted_graph_release.py +0 -0
  215. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/pptx_from_html_huashu.py +0 -0
  216. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/pptx_from_records.py +0 -0
  217. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/pptx_prompts_defaults.py +0 -0
  218. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/profile_service.py +0 -0
  219. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/prompt_assembler.py +0 -0
  220. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/shared_deck_attribution.py +0 -0
  221. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/spec_sync.py +0 -0
  222. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/streaming_callback.py +0 -0
  223. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/svg_sanitizer.py +0 -0
  224. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/template_sections.py +0 -0
  225. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/__init__.py +0 -0
  226. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/agent_bricks_tool.py +0 -0
  227. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/ds_asset_tool.py +0 -0
  228. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/genie_tool.py +0 -0
  229. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/mcp_tool.py +0 -0
  230. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/model_endpoint_tool.py +0 -0
  231. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/tools/vector_tool.py +0 -0
  232. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/services/validator.py +0 -0
  233. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/__init__.py +0 -0
  234. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/css_utils.py +0 -0
  235. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/ds_asset_utils.py +0 -0
  236. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/error_handling.py +0 -0
  237. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/graph_safety.py +0 -0
  238. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/html_safety.py +0 -0
  239. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/html_utils.py +0 -0
  240. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/image_utils.py +0 -0
  241. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/js_validator.py +0 -0
  242. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/logging_config.py +0 -0
  243. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/pi_filter.py +0 -0
  244. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/slide_hash.py +0 -0
  245. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/src/utils/spotlight.py +0 -0
  246. {databricks_tellr_app-0.4.3.dev3463 → databricks_tellr_app-0.4.3.dev3464}/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.3.dev3463
3
+ Version: 0.4.3.dev3464
4
4
  Summary: Tellr application package for Databricks Apps
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -42,7 +42,7 @@ Requires-Dist: google-auth-oauthlib==1.2.4
42
42
  Requires-Dist: google-auth-httplib2==0.3.0
43
43
  Requires-Dist: cryptography==46.0.3
44
44
  Requires-Dist: sse-starlette==3.0.3
45
- Requires-Dist: databricks-sdk==0.120.0
45
+ Requires-Dist: databricks-sdk==0.157.0
46
46
  Requires-Dist: mlflow[databricks]==3.14.0
47
47
  Requires-Dist: mlflow-skinny==3.14.0
48
48
  Requires-Dist: databricks-agents==1.11.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databricks-tellr-app
3
- Version: 0.4.3.dev3463
3
+ Version: 0.4.3.dev3464
4
4
  Summary: Tellr application package for Databricks Apps
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -42,7 +42,7 @@ Requires-Dist: google-auth-oauthlib==1.2.4
42
42
  Requires-Dist: google-auth-httplib2==0.3.0
43
43
  Requires-Dist: cryptography==46.0.3
44
44
  Requires-Dist: sse-starlette==3.0.3
45
- Requires-Dist: databricks-sdk==0.120.0
45
+ Requires-Dist: databricks-sdk==0.157.0
46
46
  Requires-Dist: mlflow[databricks]==3.14.0
47
47
  Requires-Dist: mlflow-skinny==3.14.0
48
48
  Requires-Dist: databricks-agents==1.11.0
@@ -62,6 +62,7 @@ setup.py
62
62
  ./src/api/services/session_manager.py
63
63
  ./src/api/services/session_naming.py
64
64
  ./src/api/services/slide_repository.py
65
+ ./src/api/services/slide_style_preview_queue.py
65
66
  ./src/api/services/usage_events.py
66
67
  ./src/api/services/usage_service.py
67
68
  ./src/api/utils/__init__.py
@@ -117,6 +118,7 @@ setup.py
117
118
  ./src/database/models/session.py
118
119
  ./src/database/models/slide_deck_prompt.py
119
120
  ./src/database/models/slide_style_library.py
121
+ ./src/database/models/slide_style_preview.py
120
122
  ./src/database/models/usage_event.py
121
123
  ./src/database/models/user_preference.py
122
124
  ./src/domain/__init__.py
@@ -183,6 +185,8 @@ setup.py
183
185
  ./src/services/profile_service.py
184
186
  ./src/services/prompt_assembler.py
185
187
  ./src/services/shared_deck_attribution.py
188
+ ./src/services/slide_style_preview_fixture.py
189
+ ./src/services/slide_style_preview_storage.py
186
190
  ./src/services/spec_sync.py
187
191
  ./src/services/streaming_callback.py
188
192
  ./src/services/svg_sanitizer.py
@@ -297,6 +301,7 @@ src/api/services/job_queue.py
297
301
  src/api/services/session_manager.py
298
302
  src/api/services/session_naming.py
299
303
  src/api/services/slide_repository.py
304
+ src/api/services/slide_style_preview_queue.py
300
305
  src/api/services/usage_events.py
301
306
  src/api/services/usage_service.py
302
307
  src/api/utils/__init__.py
@@ -352,6 +357,7 @@ src/database/models/request_log.py
352
357
  src/database/models/session.py
353
358
  src/database/models/slide_deck_prompt.py
354
359
  src/database/models/slide_style_library.py
360
+ src/database/models/slide_style_preview.py
355
361
  src/database/models/usage_event.py
356
362
  src/database/models/user_preference.py
357
363
  src/domain/__init__.py
@@ -418,6 +424,8 @@ src/services/pptx_prompts_defaults.py
418
424
  src/services/profile_service.py
419
425
  src/services/prompt_assembler.py
420
426
  src/services/shared_deck_attribution.py
427
+ src/services/slide_style_preview_fixture.py
428
+ src/services/slide_style_preview_storage.py
421
429
  src/services/spec_sync.py
422
430
  src/services/streaming_callback.py
423
431
  src/services/svg_sanitizer.py
@@ -36,7 +36,7 @@ google-auth-oauthlib==1.2.4
36
36
  google-auth-httplib2==0.3.0
37
37
  cryptography==46.0.3
38
38
  sse-starlette==3.0.3
39
- databricks-sdk==0.120.0
39
+ databricks-sdk==0.157.0
40
40
  mlflow[databricks]==3.14.0
41
41
  mlflow-skinny==3.14.0
42
42
  databricks-agents==1.11.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "databricks-tellr-app"
7
- version = "0.4.3.dev3463"
7
+ version = "0.4.3.dev3464"
8
8
  description = "Tellr application package for Databricks Apps"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -86,7 +86,7 @@ dependencies = [
86
86
  # langgraph-prebuilt 1.0.10→1.1.0, added langgraph-sdk==0.4.2. These match
87
87
  # the repo-root requirements.txt and pyproject.toml. MUST be re-verified via
88
88
  # a devloop deploy on db-tellr-dev-pinfix or equivalent before PR3 ships.
89
- "databricks-sdk==0.120.0",
89
+ "databricks-sdk==0.157.0",
90
90
  "mlflow[databricks]==3.14.0",
91
91
  "mlflow-skinny==3.14.0",
92
92
  "databricks-agents==1.11.0",
@@ -49,6 +49,7 @@ from src.api.services.export_job_queue import (
49
49
  start_export_worker,
50
50
  )
51
51
  from src.api.services.job_queue import recover_stuck_requests, start_worker
52
+ from src.api.services.slide_style_preview_queue import start_preview_worker
52
53
  from src.core.database import (
53
54
  is_lakebase_environment,
54
55
  start_token_refresh,
@@ -70,6 +71,7 @@ IS_TESTING = ENVIRONMENT == "test"
70
71
  _worker_task = None
71
72
  _export_worker_task = None
72
73
  _export_cleanup_task: asyncio.Task | None = None
74
+ _preview_worker_task = None
73
75
  _cleanup_task = None
74
76
  _timeout_task = None
75
77
  _spec_sweeper_task = None
@@ -79,7 +81,7 @@ _frontend_assets_stack: ExitStack | None = None
79
81
  @asynccontextmanager
80
82
  async def lifespan(app: FastAPI):
81
83
  """Lifespan context manager for startup/shutdown events."""
82
- global _worker_task, _export_worker_task, _export_cleanup_task
84
+ global _worker_task, _export_worker_task, _export_cleanup_task, _preview_worker_task
83
85
  global _cleanup_task, _timeout_task, _spec_sweeper_task, _frontend_assets_stack
84
86
 
85
87
  # Startup
@@ -151,6 +153,20 @@ async def lifespan(app: FastAPI):
151
153
  _export_cleanup_task = await start_export_cleanup_worker()
152
154
  logger.info("Export job cleanup worker started")
153
155
 
156
+ # Start the slide-style preview generation worker
157
+ _preview_worker_task = await start_preview_worker()
158
+ logger.info("Slide-style preview worker started")
159
+
160
+ # Pre-warm previews for active styles so viewers hit a warm cache instead
161
+ # of a cold LLM generation. Bounded + deduplicated; runs off the event loop.
162
+ try:
163
+ from src.api.services.slide_style_preview_queue import warm_missing_previews
164
+
165
+ warmed = await asyncio.to_thread(warm_missing_previews)
166
+ logger.info("Slide-style preview warm backfill enqueued", extra={"enqueued": warmed})
167
+ except Exception: # noqa: BLE001 — warming must never block startup
168
+ logger.warning("Slide-style preview warm backfill failed", exc_info=True)
169
+
154
170
  # Start the MCP job timeout sweeper
155
171
  from src.api.services.job_queue import mark_timed_out_jobs_loop
156
172
  _timeout_task = asyncio.create_task(mark_timed_out_jobs_loop())
@@ -214,6 +230,14 @@ async def lifespan(app: FastAPI):
214
230
  pass
215
231
  logger.info("Export job cleanup worker stopped")
216
232
 
233
+ if _preview_worker_task:
234
+ _preview_worker_task.cancel()
235
+ try:
236
+ await _preview_worker_task
237
+ except asyncio.CancelledError:
238
+ pass
239
+ logger.info("Slide-style preview worker stopped")
240
+
217
241
  if _cleanup_task:
218
242
  _cleanup_task.cancel()
219
243
  try:
@@ -24,6 +24,13 @@ Content-Security-Policy differentiated by response type:
24
24
  Radix UI injects inline styles at runtime; CSP hashes apply to
25
25
  <style>/<script> *elements*, not style *attributes*, so
26
26
  ``style-src`` needs 'unsafe-inline'.
27
+ 3. Monaco: the editors load from jsDelivr via @monaco-editor/react, the
28
+ JS through ``script-src`` and ``editor.main.css`` as a stylesheet
29
+ link, so ``style-src`` also allows ``https://cdn.jsdelivr.net``.
30
+ Without it the sheet is blocked and the editor renders broken (its
31
+ input textarea shows as a stray box above the text). Given
32
+ 'unsafe-inline' already, the origin adds no real style-injection
33
+ surface; ``script-src`` already trusts it.
27
34
 
28
35
  ``script-src 'unsafe-inline'`` + CDNs is a deliberate, documented
29
36
  trade-off forced by srcdoc inheritance: slides remain confined by the
@@ -83,7 +90,7 @@ from starlette.responses import Response
83
90
  DOCUMENT_CSP = (
84
91
  "default-src 'self'; "
85
92
  "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdn.tailwindcss.com; "
86
- "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; "
93
+ "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; "
87
94
  "img-src 'self' data:; "
88
95
  "font-src 'self' data: https://cdn.jsdelivr.net https://fonts.gstatic.com; "
89
96
  "connect-src 'self'; "
@@ -16,9 +16,14 @@ from sqlalchemy.orm import Session
16
16
  from src.api.routes._authz import require_admin
17
17
  from src.core.database import get_db, get_db_session
18
18
  from src.database.models import SlideStyleLibrary
19
+ from src.services import slide_style_preview_fixture as preview_fixture
20
+ from src.services import slide_style_preview_storage as preview_storage
19
21
 
20
22
  logger = logging.getLogger(__name__)
21
23
 
24
+ # Fields whose change invalidates a generated preview (see cache-invalidation).
25
+ _PREVIEW_AFFECTING_FIELDS = ("style_content", "image_guidelines")
26
+
22
27
  router = APIRouter(prefix="/slide-styles", tags=["slide-styles"])
23
28
 
24
29
 
@@ -68,6 +73,26 @@ class SlideStyleListResponse(BaseModel):
68
73
  total: int
69
74
 
70
75
 
76
+ class SlideStylePreviewResponse(BaseModel):
77
+ """Read-only preview state for a slide style.
78
+
79
+ ``status`` drives the client: ``ready`` (current), ``stale`` (a usable but
80
+ out-of-date copy while regeneration runs), ``queued``/``generating`` (in
81
+ flight), ``failed`` (with optional last-known-good copy), ``missing`` (never
82
+ generated). HTTP is always 200; the client polls on ``status`` rather than
83
+ on status codes.
84
+ """
85
+ style_id: int
86
+ status: str
87
+ fingerprint: Optional[str] = None
88
+ slides: Optional[List[str]] = None
89
+ css: Optional[str] = None
90
+ assets: Optional[List[dict]] = None
91
+ generated_at: Optional[str] = None
92
+ error_code: Optional[str] = None
93
+ stale: bool = False
94
+
95
+
71
96
  # API endpoints
72
97
 
73
98
  @router.get("", response_model=SlideStyleListResponse)
@@ -238,6 +263,15 @@ def create_slide_style(
238
263
  db.refresh(style)
239
264
 
240
265
  logger.info(f"Created slide style: {style.name} (id={style.id})")
266
+
267
+ # Warm the visual preview immediately so the first viewer gets a cache
268
+ # hit instead of waiting on a cold generation. Deduplicated + best-effort.
269
+ try:
270
+ from src.api.services.slide_style_preview_queue import try_enqueue
271
+
272
+ try_enqueue(style.id)
273
+ except Exception: # noqa: BLE001 — warming must never fail the create
274
+ logger.warning("Preview warm-on-create failed", exc_info=True)
241
275
 
242
276
  return SlideStyleResponse(
243
277
  id=style.id,
@@ -321,11 +355,38 @@ def update_slide_style(
321
355
  style.description = request.description
322
356
  if request.category is not None:
323
357
  style.category = request.category
358
+
359
+ # Detect preview-affecting changes BEFORE mutating, so we can invalidate
360
+ # the cached preview in the SAME transaction as the edit (cache-invalidation).
361
+ preview_affected = False
362
+ if request.style_content is not None and request.style_content != style.style_content:
363
+ preview_affected = True
364
+ if (
365
+ request.image_guidelines is not None
366
+ and request.image_guidelines != style.image_guidelines
367
+ ):
368
+ preview_affected = True
369
+
324
370
  if request.style_content is not None:
325
371
  style.style_content = request.style_content
326
372
  if request.image_guidelines is not None:
327
373
  style.image_guidelines = request.image_guidelines
328
374
 
375
+ if preview_affected:
376
+ # Bump the revision (the generation write-back guard) and reset the
377
+ # cached preview to 'missing' so it regenerates. The last-known-good
378
+ # payload row is left in storage until the next successful prune.
379
+ style.style_revision = (style.style_revision or 0) + 1
380
+ style.preview_status = "missing"
381
+ style.preview_fingerprint = None
382
+ style.preview_payload_id = None
383
+ style.preview_error_code = None
384
+ style.preview_error_message = None
385
+ logger.info(
386
+ "Invalidated slide-style preview after edit",
387
+ extra={"style_id": style.id, "style_revision": style.style_revision},
388
+ )
389
+
329
390
  # Update the user (skip Databricks call in test/dev to avoid network timeout)
330
391
  if os.getenv("ENVIRONMENT") in ("development", "test"):
331
392
  style.updated_by = "system"
@@ -344,6 +405,16 @@ def update_slide_style(
344
405
  db.refresh(style)
345
406
 
346
407
  logger.info(f"Updated slide style: {style.name} (id={style.id})")
408
+
409
+ # If the edit invalidated the preview, warm it right away (against the
410
+ # now-committed new revision) so viewers don't hit a cold regeneration.
411
+ if preview_affected:
412
+ try:
413
+ from src.api.services.slide_style_preview_queue import try_enqueue
414
+
415
+ try_enqueue(style.id)
416
+ except Exception: # noqa: BLE001 — warming must never fail the update
417
+ logger.warning("Preview warm-on-update failed", exc_info=True)
347
418
 
348
419
  return SlideStyleResponse(
349
420
  id=style.id,
@@ -510,3 +581,133 @@ def set_default_slide_style(style_id: int):
510
581
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
511
582
  detail="Failed to set default slide style",
512
583
  )
584
+
585
+
586
+ @router.get("/{style_id}/preview", response_model=SlideStylePreviewResponse)
587
+ def get_slide_style_preview(
588
+ style_id: int,
589
+ db: Session = Depends(get_db),
590
+ ):
591
+ """Read the cached visual preview for a slide style. NEVER generates inline.
592
+
593
+ Visibility mirrors ``GET /{style_id}`` (404 parity). When the cached preview
594
+ is missing or stale relative to the current generation fingerprint, this
595
+ enqueues a deduplicated background job and returns the current state (with a
596
+ stale copy if one exists) so the UI stays fast and crawlers/prefetch/scroll
597
+ never trigger LLM cost.
598
+ """
599
+ from src.api.services.slide_style_preview_queue import try_enqueue
600
+
601
+ style = db.query(SlideStyleLibrary).filter(SlideStyleLibrary.id == style_id).first()
602
+ if not style:
603
+ raise HTTPException(
604
+ status_code=status.HTTP_404_NOT_FOUND,
605
+ detail=f"Slide style {style_id} not found",
606
+ )
607
+
608
+ current_fp = preview_fixture.compute_fingerprint(
609
+ style.style_content,
610
+ style.image_guidelines,
611
+ preview_fixture.current_builder_definition(db),
612
+ )
613
+ status_val = style.preview_status or "missing"
614
+
615
+ # Load any stored payload (ready OR last-known-good) once.
616
+ payload = None
617
+ if style.preview_payload_id:
618
+ payload = preview_storage.load_payload(db, style.preview_payload_id)
619
+
620
+ def _resp(status_str: str, *, include_payload: bool, stale: bool = False):
621
+ has = include_payload and payload
622
+ return SlideStylePreviewResponse(
623
+ style_id=style_id,
624
+ status=status_str,
625
+ fingerprint=style.preview_fingerprint if include_payload else None,
626
+ slides=(payload or {}).get("slides") if has else None,
627
+ css=(payload or {}).get("css") if has else None,
628
+ assets=(payload or {}).get("assets") if has else None,
629
+ generated_at=style.preview_generated_at.isoformat()
630
+ if (has and style.preview_generated_at)
631
+ else None,
632
+ error_code=style.preview_error_code,
633
+ stale=stale,
634
+ )
635
+
636
+ # Ready and current (cache hit).
637
+ if status_val == "ready" and style.preview_fingerprint == current_fp and payload:
638
+ logger.info(
639
+ "slide_style_preview.cache_hit",
640
+ extra={"style_id": style_id, "status": "ready"},
641
+ )
642
+ return _resp("ready", include_payload=True)
643
+
644
+ # Ready but stale (fingerprint moved). Serve the stale copy, kick a refresh.
645
+ if status_val == "ready" and payload:
646
+ age_s = None
647
+ if style.preview_generated_at:
648
+ from datetime import datetime as _dt
649
+
650
+ age_s = (_dt.utcnow() - style.preview_generated_at).total_seconds()
651
+ logger.info(
652
+ "slide_style_preview.cache_stale",
653
+ extra={"style_id": style_id, "stale_age_s": age_s},
654
+ )
655
+ try_enqueue(style_id)
656
+ return _resp("stale", include_payload=True, stale=True)
657
+
658
+ # In flight. Serve stale copy underneath if present. try_enqueue no-ops a
659
+ # live job and re-queues one whose worker died, so a viewer recovers it.
660
+ if status_val in ("queued", "generating"):
661
+ try_enqueue(style_id)
662
+ return _resp(status_val, include_payload=bool(payload), stale=bool(payload))
663
+
664
+ # Failed. Return last-known-good if we have one; otherwise just the error.
665
+ if status_val == "failed":
666
+ return _resp("failed", include_payload=bool(payload), stale=bool(payload))
667
+
668
+ # Missing (or unknown): enqueue and report queued.
669
+ try_enqueue(style_id)
670
+ # Re-read status: try_enqueue may have transitioned it to 'queued'.
671
+ return SlideStylePreviewResponse(style_id=style_id, status="queued")
672
+
673
+
674
+ # SDR-4437 HIGH-3: workspace-global library writes are admin-only.
675
+ @router.post(
676
+ "/{style_id}/preview/regenerate",
677
+ response_model=SlideStylePreviewResponse,
678
+ dependencies=[Depends(require_admin)],
679
+ )
680
+ def regenerate_slide_style_preview(
681
+ style_id: int,
682
+ db: Session = Depends(get_db),
683
+ ):
684
+ """Explicitly (re)generate a slide-style preview. Admin-only, deduplicated.
685
+
686
+ Enqueues a background job against the current style snapshot. Idempotent: if
687
+ a generation is already in flight this is a no-op that returns the in-flight
688
+ status.
689
+ """
690
+ from datetime import datetime as _dt
691
+
692
+ from src.api.services.slide_style_preview_queue import claimable_clause, try_enqueue
693
+
694
+ style = db.query(SlideStyleLibrary).filter(SlideStyleLibrary.id == style_id).first()
695
+ if not style:
696
+ raise HTTPException(
697
+ status_code=status.HTTP_404_NOT_FOUND,
698
+ detail=f"Slide style {style_id} not found",
699
+ )
700
+
701
+ # Force a re-attempt even from a 'failed'/'ready' terminal state by clearing
702
+ # to 'missing' first (in its own committed txn), then enqueue. A live job is
703
+ # left alone (no duplicate generation); an abandoned one is claimable.
704
+ db.query(SlideStyleLibrary).filter(
705
+ SlideStyleLibrary.id == style_id, claimable_clause(_dt.utcnow())
706
+ ).update({"preview_status": "missing"}, synchronize_session=False)
707
+ db.commit()
708
+
709
+ try_enqueue(style_id)
710
+ db.refresh(style)
711
+ return SlideStylePreviewResponse(
712
+ style_id=style_id, status=style.preview_status or "queued"
713
+ )