databricks-tellr-app 0.4.3.dev41__tar.gz → 0.4.3.dev43__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.
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/PKG-INFO +1 -1
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app.egg-info/PKG-INFO +1 -1
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app.egg-info/SOURCES.txt +0 -2
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/pyproject.toml +1 -1
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/export.py +4 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/export_job_queue.py +3 -1
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/design_system_service.py +0 -15
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/image_service.py +31 -17
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/image_tools.py +18 -1
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/image_utils.py +27 -6
- databricks_tellr_app-0.4.3.dev41/src/services/svg_sanitizer.py +0 -403
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/README.md +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app/run.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app.egg-info/dependency_links.txt +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app.egg-info/requires.txt +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/databricks_tellr_app.egg-info/top_level.txt +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/setup.cfg +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/setup.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/_otel_bootstrap.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/fixtures/tour_demo_deck.json +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/main.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/mcp_auth.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/mcp_server.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/middleware/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/middleware/csrf.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/middleware/request_logging.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/middleware/security_headers.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/_authz.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/admin.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/admin_usage.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/agent_config.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/chat.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/deck_contributors.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/feedback.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/google_slides.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/images.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/local_version.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/profiles.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/sessions.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/settings/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/settings/contributors.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/settings/deck_prompts.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/settings/design_systems.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/settings/identities.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/settings/slide_styles.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/setup.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/slides.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/tools.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/tour.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/verification.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/version.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/agent_config.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/feedback.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/requests.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/responses.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/settings/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/settings/requests.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/settings/responses.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/schemas/streaming.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/chat_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/feedback_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/job_queue.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/session_manager.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/session_naming.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/usage_events.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/services/usage_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/utils/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/utils/validation.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/config_loader.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/context_utils.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/database.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/databricks_client.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/defaults.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/encryption.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/init_default_profile.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/lakebase.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/migrate_profiles_to_agent_config.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/mlflow_agent_spans.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/mlflow_tracing.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/otel_logging.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/permission_context.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/prompt_modules.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/settings_db.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/core/user_context.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/deck_contributor.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/design_system.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/encryption_key.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/feedback.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/genie_space.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/google_global_credentials.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/google_oauth_token.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/identity.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/image.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/profile.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/profile_contributor.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/prompts.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/request_log.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/session.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/slide_deck_prompt.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/slide_style_library.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/usage_event.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/models/user_preference.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/database/types.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/domain/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/domain/slide.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/domain/slide_deck.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/agent.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/agent_factory.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/config_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/config_validator.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/ast_guard.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/codeprep.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/gslides_runner.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/jail.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/pptx_runner.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/converter_jail/protocol.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/design_system_compiler.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/design_system_templates.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/drive_uploader.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/evaluation/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/evaluation/llm_judge.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/genie_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/google_slides_auth.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/google_slides_prompts_defaults.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/html_to_google_slides.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/html_to_pptx.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/identity_provider.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/identity_providers/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/identity_providers/account_provider.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/identity_providers/local_provider.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/identity_providers/workspace_provider.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/permission_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/pptx_from_html_huashu.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/pptx_from_records.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/pptx_prompts_defaults.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/profile_service.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/streaming_callback.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/agent_bricks_tool.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/ds_asset_tool.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/genie_tool.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/mcp_tool.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/model_endpoint_tool.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/tools/vector_tool.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/validator.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/__init__.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/css_utils.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/ds_asset_utils.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/error_handling.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/html_safety.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/html_utils.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/js_validator.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/logging_config.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/pi_filter.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/slide_hash.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/spotlight.py +0 -0
- {databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/text_caps.py +0 -0
|
@@ -124,7 +124,6 @@ setup.py
|
|
|
124
124
|
./src/services/pptx_prompts_defaults.py
|
|
125
125
|
./src/services/profile_service.py
|
|
126
126
|
./src/services/streaming_callback.py
|
|
127
|
-
./src/services/svg_sanitizer.py
|
|
128
127
|
./src/services/validator.py
|
|
129
128
|
./src/services/converter_jail/__init__.py
|
|
130
129
|
./src/services/converter_jail/ast_guard.py
|
|
@@ -287,7 +286,6 @@ src/services/pptx_from_records.py
|
|
|
287
286
|
src/services/pptx_prompts_defaults.py
|
|
288
287
|
src/services/profile_service.py
|
|
289
288
|
src/services/streaming_callback.py
|
|
290
|
-
src/services/svg_sanitizer.py
|
|
291
289
|
src/services/validator.py
|
|
292
290
|
src/services/converter_jail/__init__.py
|
|
293
291
|
src/services/converter_jail/ast_guard.py
|
{databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/api/routes/export.py
RENAMED
|
@@ -702,6 +702,7 @@ async def start_pptx_export_async(request: ExportPPTXRequest):
|
|
|
702
702
|
enqueue_export_job,
|
|
703
703
|
generate_job_id,
|
|
704
704
|
)
|
|
705
|
+
from src.services.image_service import resolve_requesting_user
|
|
705
706
|
|
|
706
707
|
import time
|
|
707
708
|
start_time = time.time()
|
|
@@ -759,6 +760,9 @@ async def start_pptx_export_async(request: ExportPPTXRequest):
|
|
|
759
760
|
job_id,
|
|
760
761
|
{
|
|
761
762
|
"session_id": request.session_id,
|
|
763
|
+
# Acting user for {{image:ID}} ownership checks (F-CR-27): the
|
|
764
|
+
# worker runs outside this request's user context.
|
|
765
|
+
"user_identity": resolve_requesting_user(),
|
|
762
766
|
"chart_images_per_slide": chart_images_per_slide,
|
|
763
767
|
"title": slide_deck.get("title", "slides"),
|
|
764
768
|
"total_slides": total_slides,
|
|
@@ -212,7 +212,9 @@ async def process_export_job(job_id: str, payload: dict) -> None:
|
|
|
212
212
|
from src.core.database import get_db_session
|
|
213
213
|
ds_id = resolve_active_design_system_id(session_id)
|
|
214
214
|
with get_db_session() as db:
|
|
215
|
-
substitute_deck_dict_images(
|
|
215
|
+
substitute_deck_dict_images(
|
|
216
|
+
slide_deck, db, requesting_user=payload.get("user_identity")
|
|
217
|
+
)
|
|
216
218
|
substitute_deck_dict_ds_assets(slide_deck, db, design_system_id=ds_id)
|
|
217
219
|
|
|
218
220
|
slides = slide_deck.get("slides", [])
|
|
@@ -74,7 +74,6 @@ from src.database.models.design_system import (
|
|
|
74
74
|
DesignSystemToken,
|
|
75
75
|
)
|
|
76
76
|
from src.services.design_system_compiler import recompute_compiled_style_content
|
|
77
|
-
from src.services.svg_sanitizer import looks_like_svg, sanitize_svg
|
|
78
77
|
|
|
79
78
|
logger = logging.getLogger(__name__)
|
|
80
79
|
|
|
@@ -2165,20 +2164,6 @@ def _collect_assets_and_files(
|
|
|
2165
2164
|
mime = sniffed
|
|
2166
2165
|
else:
|
|
2167
2166
|
mime = _guess_mime(rel)
|
|
2168
|
-
if mime == "image/svg+xml":
|
|
2169
|
-
try:
|
|
2170
|
-
data = sanitize_svg(data)
|
|
2171
|
-
except ValueError as exc:
|
|
2172
|
-
raise DesignSystemImportError(
|
|
2173
|
-
f"Bundle entry '{rel}' is not a valid SVG: {exc}"
|
|
2174
|
-
) from exc
|
|
2175
|
-
elif looks_like_svg(data):
|
|
2176
|
-
# Extension says raster/font/etc. but the bytes are SVG:
|
|
2177
|
-
# never trust the name to skip sanitization.
|
|
2178
|
-
raise DesignSystemImportError(
|
|
2179
|
-
f"Bundle entry '{rel}' contains SVG content but does not "
|
|
2180
|
-
"have an .svg extension"
|
|
2181
|
-
)
|
|
2182
2167
|
width, height = _image_dimensions(data, mime)
|
|
2183
2168
|
asset = DesignSystemAsset(
|
|
2184
2169
|
kind=kind,
|
{databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/image_service.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Image upload, thumbnail generation, and retrieval service."""
|
|
2
2
|
import base64
|
|
3
3
|
import logging
|
|
4
|
+
import os
|
|
4
5
|
import uuid
|
|
5
6
|
from io import BytesIO
|
|
6
7
|
from typing import List, Optional
|
|
@@ -11,7 +12,6 @@ from sqlalchemy.dialects.postgresql import JSONB
|
|
|
11
12
|
from sqlalchemy.orm import Query, Session
|
|
12
13
|
|
|
13
14
|
from src.database.models.image import ImageAsset
|
|
14
|
-
from src.services.svg_sanitizer import looks_like_svg, sanitize_svg
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
@@ -42,20 +42,6 @@ def upload_image(
|
|
|
42
42
|
if len(file_content) > MAX_FILE_SIZE:
|
|
43
43
|
raise ValueError(f"File too large: {len(file_content)} bytes (max {MAX_FILE_SIZE})")
|
|
44
44
|
|
|
45
|
-
# The client-declared MIME type is untrusted: decide on the CONTENT.
|
|
46
|
-
# SVG can carry script, so it is always sanitized; SVG bytes declared as
|
|
47
|
-
# any other type are rejected rather than stored under a raster label.
|
|
48
|
-
if mime_type == "image/svg+xml":
|
|
49
|
-
try:
|
|
50
|
-
file_content = sanitize_svg(file_content)
|
|
51
|
-
except ValueError as exc:
|
|
52
|
-
raise ValueError(f"Invalid SVG upload: {exc}") from exc
|
|
53
|
-
elif looks_like_svg(file_content):
|
|
54
|
-
raise ValueError(
|
|
55
|
-
f"File content is SVG but was declared as {mime_type}; "
|
|
56
|
-
"upload it as image/svg+xml."
|
|
57
|
-
)
|
|
58
|
-
|
|
59
45
|
# Check for duplicate original_filename among active images (case-insensitive).
|
|
60
46
|
# Ephemeral images (paste-to-chat) skip this check — they use throwaway names
|
|
61
47
|
# and should never block each other.
|
|
@@ -101,10 +87,35 @@ def upload_image(
|
|
|
101
87
|
return image
|
|
102
88
|
|
|
103
89
|
|
|
104
|
-
def
|
|
90
|
+
def resolve_requesting_user() -> Optional[str]:
|
|
91
|
+
"""Identity to check image ownership against on non-route fetch paths.
|
|
92
|
+
|
|
93
|
+
Mirrors ``routes.images._get_current_user`` (the identity ``upload_image``
|
|
94
|
+
stamps into ``uploaded_by``) without an extra API call: the dev/test
|
|
95
|
+
``"system"`` fallback, otherwise the request-scoped username set by the auth
|
|
96
|
+
middleware / MCP auth. ``None`` when no identity is bound (fail-closed for
|
|
97
|
+
ephemeral images).
|
|
98
|
+
"""
|
|
99
|
+
if os.getenv("ENVIRONMENT") in ("development", "test"):
|
|
100
|
+
return "system"
|
|
101
|
+
from src.core.user_context import get_current_user
|
|
102
|
+
|
|
103
|
+
return get_current_user()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_image_base64(
|
|
107
|
+
db: Session, token: str, *, requesting_user: Optional[str]
|
|
108
|
+
) -> tuple[str, str]:
|
|
105
109
|
"""
|
|
106
110
|
Get full image as base64 string, keyed by the opaque token (SDR-4437 F-TM-7).
|
|
107
111
|
|
|
112
|
+
Applies the same privacy guard as the ``GET /api/images/{token}`` routes
|
|
113
|
+
(F-CR-27): chat-pasted ("ephemeral") images are private to their uploader,
|
|
114
|
+
so a token for another user's ephemeral image is reported not-found. Library
|
|
115
|
+
images stay open-read. ``requesting_user`` is mandatory and keyword-only so
|
|
116
|
+
every caller makes the acting identity explicit; ``None`` fails closed for
|
|
117
|
+
ephemeral images.
|
|
118
|
+
|
|
108
119
|
Returns:
|
|
109
120
|
Tuple of (base64_data, mime_type)
|
|
110
121
|
"""
|
|
@@ -112,7 +123,10 @@ def get_image_base64(db: Session, token: str) -> tuple[str, str]:
|
|
|
112
123
|
ImageAsset.token == token,
|
|
113
124
|
ImageAsset.is_active == True,
|
|
114
125
|
).first()
|
|
115
|
-
if not image
|
|
126
|
+
if not image or (
|
|
127
|
+
image.category == "ephemeral"
|
|
128
|
+
and (requesting_user is None or image.uploaded_by != requesting_user)
|
|
129
|
+
):
|
|
116
130
|
raise ValueError(f"Image {token} not found")
|
|
117
131
|
|
|
118
132
|
b64 = base64.b64encode(image.image_data).decode("utf-8")
|
{databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/services/image_tools.py
RENAMED
|
@@ -10,6 +10,8 @@ from src.services import image_service
|
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
|
+
_NO_IMAGES_MESSAGE = "No images found matching your criteria."
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
class SearchImagesInput(BaseModel):
|
|
15
17
|
"""Input schema for image search tool."""
|
|
@@ -41,12 +43,27 @@ def search_images(
|
|
|
41
43
|
Returns:
|
|
42
44
|
JSON list of matching images with id, filename, description, and tags
|
|
43
45
|
"""
|
|
46
|
+
# F-CR-27: chat-pasted ("ephemeral") images are private to their uploader and
|
|
47
|
+
# are never discoverable through the agent tool. The user's own pastes reach
|
|
48
|
+
# the agent via their message, not via search.
|
|
49
|
+
if category is not None and category.strip().lower() == "ephemeral":
|
|
50
|
+
logger.warning("search_images: refusing category='ephemeral' (private images)")
|
|
51
|
+
return json.dumps({"message": _NO_IMAGES_MESSAGE, "images": []})
|
|
52
|
+
|
|
53
|
+
# Scope the listing to the caller (same as GET /api/images). Fail closed when
|
|
54
|
+
# no identity is bound rather than listing every user's images.
|
|
55
|
+
requesting_user = image_service.resolve_requesting_user()
|
|
56
|
+
if requesting_user is None:
|
|
57
|
+
logger.warning("search_images: no requesting user bound; returning no images")
|
|
58
|
+
return json.dumps({"message": _NO_IMAGES_MESSAGE, "images": []})
|
|
59
|
+
|
|
44
60
|
with get_db_session() as db:
|
|
45
61
|
images = image_service.search_images(
|
|
46
62
|
db=db,
|
|
47
63
|
query=query,
|
|
48
64
|
category=category,
|
|
49
65
|
tags=tags,
|
|
66
|
+
uploaded_by=requesting_user,
|
|
50
67
|
)
|
|
51
68
|
|
|
52
69
|
# Return metadata only - NEVER base64
|
|
@@ -65,6 +82,6 @@ def search_images(
|
|
|
65
82
|
]
|
|
66
83
|
|
|
67
84
|
if not results:
|
|
68
|
-
return json.dumps({"message":
|
|
85
|
+
return json.dumps({"message": _NO_IMAGES_MESSAGE, "images": []})
|
|
69
86
|
|
|
70
87
|
return json.dumps({"message": f"Found {len(results)} image(s).", "images": results})
|
{databricks_tellr_app-0.4.3.dev41 → databricks_tellr_app-0.4.3.dev43}/src/utils/image_utils.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Image placeholder substitution for generated slides."""
|
|
2
2
|
import logging
|
|
3
3
|
import re
|
|
4
|
+
from typing import Optional
|
|
4
5
|
|
|
5
6
|
from sqlalchemy.orm import Session
|
|
6
7
|
|
|
@@ -12,20 +13,31 @@ logger = logging.getLogger(__name__)
|
|
|
12
13
|
IMAGE_PLACEHOLDER_PATTERN = re.compile(r"\{\{image:([A-Za-z0-9_-]+)\}\}")
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
def substitute_image_placeholders(
|
|
16
|
+
def substitute_image_placeholders(
|
|
17
|
+
html: str, db: Session, *, requesting_user: Optional[str] = None
|
|
18
|
+
) -> str:
|
|
16
19
|
"""
|
|
17
20
|
Replace {{image:ID}} placeholders with base64 data URIs.
|
|
18
21
|
|
|
19
22
|
Called after agent generates HTML, before returning to frontend.
|
|
20
23
|
Works in both HTML img src and CSS url() contexts.
|
|
24
|
+
|
|
25
|
+
Resolution is scoped to the acting user (F-CR-27): another user's ephemeral
|
|
26
|
+
image is left as an unresolved placeholder. ``requesting_user`` defaults to
|
|
27
|
+
the request-scoped identity (``image_service.resolve_requesting_user``);
|
|
28
|
+
background callers without a request context must pass it explicitly.
|
|
21
29
|
"""
|
|
22
30
|
if not html or "{{image:" not in html:
|
|
23
31
|
return html
|
|
32
|
+
if requesting_user is None:
|
|
33
|
+
requesting_user = image_service.resolve_requesting_user()
|
|
24
34
|
|
|
25
35
|
def replace_match(match):
|
|
26
36
|
image_token = match.group(1)
|
|
27
37
|
try:
|
|
28
|
-
b64_data, mime_type = image_service.get_image_base64(
|
|
38
|
+
b64_data, mime_type = image_service.get_image_base64(
|
|
39
|
+
db, image_token, requesting_user=requesting_user
|
|
40
|
+
)
|
|
29
41
|
return f"data:{mime_type};base64,{b64_data}"
|
|
30
42
|
except Exception as e:
|
|
31
43
|
logger.warning(f"Failed to resolve image placeholder {{{{image:{image_token}}}}}: {e}")
|
|
@@ -41,23 +53,32 @@ def substitute_image_placeholders(html: str, db: Session) -> str:
|
|
|
41
53
|
_DECK_IMAGE_FIELDS = ("html_content", "css")
|
|
42
54
|
|
|
43
55
|
|
|
44
|
-
def substitute_deck_dict_images(
|
|
56
|
+
def substitute_deck_dict_images(
|
|
57
|
+
deck_dict: dict, db: Session, *, requesting_user: Optional[str] = None
|
|
58
|
+
) -> dict:
|
|
45
59
|
"""Substitute {{image:ID}} placeholders across a deck dict.
|
|
46
60
|
|
|
47
61
|
Covers every field that can carry the placeholder: each slide's ``html``,
|
|
48
62
|
the deck's ``html_content`` (full knitted HTML) and its top-level ``css``
|
|
49
63
|
(backgrounds). Deck-level fields are resolved independently of the slides
|
|
50
64
|
array, mirroring ``substitute_deck_dict_ds_assets`` — the css gap fixed
|
|
51
|
-
there existed here too.
|
|
65
|
+
there existed here too. ``requesting_user`` is as for
|
|
66
|
+
``substitute_image_placeholders``.
|
|
52
67
|
"""
|
|
53
68
|
if not deck_dict:
|
|
54
69
|
return deck_dict
|
|
70
|
+
if requesting_user is None:
|
|
71
|
+
requesting_user = image_service.resolve_requesting_user()
|
|
55
72
|
for slide in deck_dict.get("slides") or []:
|
|
56
73
|
html = slide.get("html", "")
|
|
57
74
|
if "{{image:" in html:
|
|
58
|
-
slide["html"] = substitute_image_placeholders(
|
|
75
|
+
slide["html"] = substitute_image_placeholders(
|
|
76
|
+
html, db, requesting_user=requesting_user
|
|
77
|
+
)
|
|
59
78
|
for field in _DECK_IMAGE_FIELDS:
|
|
60
79
|
value = deck_dict.get(field)
|
|
61
80
|
if value and "{{image:" in value:
|
|
62
|
-
deck_dict[field] = substitute_image_placeholders(
|
|
81
|
+
deck_dict[field] = substitute_image_placeholders(
|
|
82
|
+
value, db, requesting_user=requesting_user
|
|
83
|
+
)
|
|
63
84
|
return deck_dict
|