databricks-tellr-app 0.4.2.dev20__tar.gz → 0.4.3.dev1__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.2.dev20 → databricks_tellr_app-0.4.3.dev1}/PKG-INFO +1 -1
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app.egg-info/PKG-INFO +1 -1
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/pyproject.toml +1 -1
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/images.py +45 -27
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/requests.py +2 -2
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/chat_service.py +12 -9
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/database.py +40 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/image.py +15 -1
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/types.py +12 -1
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/image_service.py +9 -9
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/image_tools.py +2 -2
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/image_utils.py +5 -4
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/README.md +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app/run.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app.egg-info/SOURCES.txt +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app.egg-info/dependency_links.txt +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app.egg-info/requires.txt +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app.egg-info/top_level.txt +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/setup.cfg +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/setup.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/_otel_bootstrap.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/fixtures/tour_demo_deck.json +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/main.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/mcp_auth.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/mcp_server.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/middleware/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/middleware/csrf.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/middleware/request_logging.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/middleware/security_headers.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/_authz.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/admin.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/admin_usage.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/agent_config.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/chat.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/deck_contributors.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/export.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/feedback.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/google_slides.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/local_version.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/profiles.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/sessions.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/settings/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/settings/contributors.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/settings/deck_prompts.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/settings/design_systems.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/settings/identities.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/settings/slide_styles.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/setup.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/slides.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/tools.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/tour.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/verification.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/version.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/agent_config.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/feedback.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/responses.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/settings/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/settings/requests.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/settings/responses.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/streaming.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/export_job_queue.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/feedback_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/job_queue.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/session_manager.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/session_naming.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/usage_events.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/usage_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/utils/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/utils/validation.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/config_loader.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/context_utils.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/databricks_client.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/defaults.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/encryption.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/init_default_profile.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/lakebase.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/migrate_profiles_to_agent_config.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/mlflow_agent_spans.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/mlflow_tracing.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/otel_logging.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/permission_context.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/prompt_modules.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/settings_db.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/user_context.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/deck_contributor.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/design_system.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/encryption_key.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/feedback.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/genie_space.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/google_global_credentials.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/google_oauth_token.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/identity.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/profile.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/profile_contributor.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/prompts.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/request_log.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/session.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/slide_deck_prompt.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/slide_style_library.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/usage_event.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/user_preference.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/domain/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/domain/slide.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/domain/slide_deck.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/agent.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/agent_factory.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/config_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/config_validator.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/ast_guard.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/codeprep.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/gslides_runner.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/jail.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/pptx_runner.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/converter_jail/protocol.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/design_system_compiler.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/design_system_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/design_system_templates.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/drive_uploader.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/evaluation/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/evaluation/llm_judge.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/genie_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/google_slides_auth.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/google_slides_prompts_defaults.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/html_to_google_slides.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/html_to_pptx.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/identity_provider.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/identity_providers/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/identity_providers/account_provider.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/identity_providers/local_provider.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/identity_providers/workspace_provider.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/permission_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/pptx_from_html_huashu.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/pptx_from_records.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/pptx_prompts_defaults.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/profile_service.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/streaming_callback.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/agent_bricks_tool.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/ds_asset_tool.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/genie_tool.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/mcp_tool.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/model_endpoint_tool.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/vector_tool.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/validator.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/__init__.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/css_utils.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/ds_asset_utils.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/error_handling.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/html_safety.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/html_utils.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/js_validator.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/logging_config.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/pi_filter.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/slide_hash.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/spotlight.py +0 -0
- {databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/text_caps.py +0 -0
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/images.py
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Image upload and management API endpoints."""
|
|
2
|
+
import base64
|
|
2
3
|
import logging
|
|
3
4
|
import os
|
|
4
5
|
from typing import List, Optional
|
|
@@ -20,7 +21,7 @@ router = APIRouter(prefix="/api/images", tags=["images"])
|
|
|
20
21
|
|
|
21
22
|
class ImageResponse(BaseModel):
|
|
22
23
|
"""Response schema for image metadata."""
|
|
23
|
-
id: int
|
|
24
|
+
id: str # Opaque token (SDR-4437 F-TM-7) — the internal int PK is never exposed.
|
|
24
25
|
filename: str
|
|
25
26
|
original_filename: str
|
|
26
27
|
mime_type: str
|
|
@@ -46,7 +47,7 @@ class ImageListResponse(BaseModel):
|
|
|
46
47
|
|
|
47
48
|
class ImageDataResponse(BaseModel):
|
|
48
49
|
"""Response containing image base64 data."""
|
|
49
|
-
id:
|
|
50
|
+
id: str # Opaque token (SDR-4437 F-TM-7).
|
|
50
51
|
mime_type: str
|
|
51
52
|
base64_data: str
|
|
52
53
|
data_uri: str # Ready-to-use: "data:image/png;base64,..."
|
|
@@ -80,7 +81,7 @@ def _get_current_user() -> str:
|
|
|
80
81
|
|
|
81
82
|
def _image_to_response(img: ImageAsset) -> ImageResponse:
|
|
82
83
|
return ImageResponse(
|
|
83
|
-
id=img.
|
|
84
|
+
id=img.token, # Expose the opaque token, never the enumerable int PK.
|
|
84
85
|
filename=img.filename,
|
|
85
86
|
original_filename=img.original_filename,
|
|
86
87
|
mime_type=img.mime_type,
|
|
@@ -167,58 +168,75 @@ def list_images(
|
|
|
167
168
|
)
|
|
168
169
|
|
|
169
170
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
def _deny_ephemeral_cross_user(image: ImageAsset) -> None:
|
|
172
|
+
"""Defense-in-depth (SDR-4437 F-TM-7): chat-pasted ("ephemeral") images are
|
|
173
|
+
private to their uploader. Library images stay open-read. Raise 404 (not 403)
|
|
174
|
+
so a wrong caller cannot even confirm the image exists.
|
|
175
|
+
"""
|
|
176
|
+
if image.category == "ephemeral" and image.uploaded_by != _get_current_user():
|
|
177
|
+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Image not found")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@router.get("/{token}", response_model=ImageResponse)
|
|
181
|
+
def get_image(token: str, db: Session = Depends(get_db)):
|
|
182
|
+
"""Get image metadata by opaque token."""
|
|
173
183
|
try:
|
|
174
184
|
image = db.query(ImageAsset).filter(
|
|
175
|
-
ImageAsset.
|
|
185
|
+
ImageAsset.token == token,
|
|
176
186
|
ImageAsset.is_active == True,
|
|
177
187
|
).first()
|
|
178
188
|
if not image:
|
|
179
189
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Image not found")
|
|
190
|
+
_deny_ephemeral_cross_user(image)
|
|
180
191
|
return _image_to_response(image)
|
|
181
192
|
except HTTPException:
|
|
182
193
|
raise
|
|
183
194
|
except Exception as e:
|
|
184
|
-
logger.error(f"Error getting image
|
|
195
|
+
logger.error(f"Error getting image: {e}", exc_info=True)
|
|
185
196
|
raise HTTPException(
|
|
186
197
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
187
198
|
detail="Failed to get image",
|
|
188
199
|
)
|
|
189
200
|
|
|
190
201
|
|
|
191
|
-
@router.get("/{
|
|
192
|
-
def get_image_data(
|
|
193
|
-
"""Get full image as base64 data (for embedding in slides)."""
|
|
202
|
+
@router.get("/{token}/data", response_model=ImageDataResponse)
|
|
203
|
+
def get_image_data(token: str, db: Session = Depends(get_db)):
|
|
204
|
+
"""Get full image as base64 data (for embedding in slides), keyed by token."""
|
|
194
205
|
try:
|
|
195
|
-
|
|
206
|
+
image = db.query(ImageAsset).filter(
|
|
207
|
+
ImageAsset.token == token,
|
|
208
|
+
ImageAsset.is_active == True,
|
|
209
|
+
).first()
|
|
210
|
+
if not image:
|
|
211
|
+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Image not found")
|
|
212
|
+
_deny_ephemeral_cross_user(image)
|
|
213
|
+
b64_data = base64.b64encode(image.image_data).decode("utf-8")
|
|
196
214
|
return ImageDataResponse(
|
|
197
|
-
id=
|
|
198
|
-
mime_type=mime_type,
|
|
215
|
+
id=image.token,
|
|
216
|
+
mime_type=image.mime_type,
|
|
199
217
|
base64_data=b64_data,
|
|
200
|
-
data_uri=f"data:{mime_type};base64,{b64_data}",
|
|
218
|
+
data_uri=f"data:{image.mime_type};base64,{b64_data}",
|
|
201
219
|
)
|
|
202
|
-
except
|
|
203
|
-
raise
|
|
220
|
+
except HTTPException:
|
|
221
|
+
raise
|
|
204
222
|
except Exception as e:
|
|
205
|
-
logger.error(f"Error getting image data
|
|
223
|
+
logger.error(f"Error getting image data: {e}", exc_info=True)
|
|
206
224
|
raise HTTPException(
|
|
207
225
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
208
226
|
detail="Failed to get image data",
|
|
209
227
|
)
|
|
210
228
|
|
|
211
229
|
|
|
212
|
-
@router.put("/{
|
|
230
|
+
@router.put("/{token}", response_model=ImageResponse)
|
|
213
231
|
def update_image(
|
|
214
|
-
|
|
232
|
+
token: str,
|
|
215
233
|
request: ImageUpdateRequest,
|
|
216
234
|
db: Session = Depends(get_db),
|
|
217
235
|
):
|
|
218
236
|
"""Update image metadata (tags, description, category)."""
|
|
219
237
|
try:
|
|
220
238
|
image = db.query(ImageAsset).filter(
|
|
221
|
-
ImageAsset.
|
|
239
|
+
ImageAsset.token == token,
|
|
222
240
|
ImageAsset.is_active == True,
|
|
223
241
|
).first()
|
|
224
242
|
if not image:
|
|
@@ -246,20 +264,20 @@ def update_image(
|
|
|
246
264
|
raise
|
|
247
265
|
except Exception as e:
|
|
248
266
|
db.rollback()
|
|
249
|
-
logger.error(f"Error updating image
|
|
267
|
+
logger.error(f"Error updating image: {e}", exc_info=True)
|
|
250
268
|
raise HTTPException(
|
|
251
269
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
252
270
|
detail="Failed to update image",
|
|
253
271
|
)
|
|
254
272
|
|
|
255
273
|
|
|
256
|
-
@router.delete("/{
|
|
257
|
-
def delete_image(
|
|
274
|
+
@router.delete("/{token}", status_code=status.HTTP_204_NO_CONTENT)
|
|
275
|
+
def delete_image(token: str, db: Session = Depends(get_db)):
|
|
258
276
|
"""Soft-delete an image."""
|
|
259
277
|
try:
|
|
260
278
|
user = _get_current_user()
|
|
261
279
|
image = db.query(ImageAsset).filter(
|
|
262
|
-
ImageAsset.
|
|
280
|
+
ImageAsset.token == token,
|
|
263
281
|
ImageAsset.is_active == True, # noqa: E712
|
|
264
282
|
).first()
|
|
265
283
|
if not image:
|
|
@@ -270,14 +288,14 @@ def delete_image(image_id: int, db: Session = Depends(get_db)):
|
|
|
270
288
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
271
289
|
detail="You don't have permission to modify this image",
|
|
272
290
|
)
|
|
273
|
-
image_service.delete_image(db,
|
|
291
|
+
image_service.delete_image(db, token, user)
|
|
274
292
|
except HTTPException:
|
|
275
293
|
raise
|
|
276
294
|
except ValueError as e:
|
|
277
295
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
|
278
296
|
except Exception as e:
|
|
279
297
|
db.rollback()
|
|
280
|
-
logger.error(f"Error deleting image
|
|
298
|
+
logger.error(f"Error deleting image: {e}", exc_info=True)
|
|
281
299
|
raise HTTPException(
|
|
282
300
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
283
301
|
detail="Failed to delete image",
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/requests.py
RENAMED
|
@@ -74,9 +74,9 @@ class ChatRequest(BaseModel):
|
|
|
74
74
|
default=None,
|
|
75
75
|
description="Optional context containing the slides to edit",
|
|
76
76
|
)
|
|
77
|
-
image_ids: Optional[list[
|
|
77
|
+
image_ids: Optional[list[str]] = Field(
|
|
78
78
|
default=None,
|
|
79
|
-
description="
|
|
79
|
+
description="Opaque tokens of images attached to this message (SDR-4437 F-TM-7)",
|
|
80
80
|
)
|
|
81
81
|
agent_config: Optional[dict] = Field(
|
|
82
82
|
default=None,
|
|
@@ -345,7 +345,7 @@ class ChatService:
|
|
|
345
345
|
session_id: str,
|
|
346
346
|
message: str,
|
|
347
347
|
slide_context: Optional[Dict[str, Any]] = None,
|
|
348
|
-
image_ids: Optional[List[
|
|
348
|
+
image_ids: Optional[List[str]] = None,
|
|
349
349
|
) -> Dict[str, Any]:
|
|
350
350
|
"""Send a message to the agent and get response.
|
|
351
351
|
|
|
@@ -828,7 +828,7 @@ class ChatService:
|
|
|
828
828
|
message: str,
|
|
829
829
|
slide_context: Optional[Dict[str, Any]] = None,
|
|
830
830
|
request_id: Optional[str] = None,
|
|
831
|
-
image_ids: Optional[List[
|
|
831
|
+
image_ids: Optional[List[str]] = None,
|
|
832
832
|
is_first_message_override: Optional[bool] = None,
|
|
833
833
|
) -> Generator[StreamEvent, None, None]:
|
|
834
834
|
"""Send a message and yield streaming events.
|
|
@@ -1993,27 +1993,30 @@ class ChatService:
|
|
|
1993
1993
|
|
|
1994
1994
|
return ([], None)
|
|
1995
1995
|
|
|
1996
|
-
def _inject_image_context(self, message: str, image_ids: List[
|
|
1997
|
-
"""Append image metadata to user message so the agent knows about attached images.
|
|
1996
|
+
def _inject_image_context(self, message: str, image_ids: List[str]) -> str:
|
|
1997
|
+
"""Append image metadata to user message so the agent knows about attached images.
|
|
1998
|
+
|
|
1999
|
+
``image_ids`` are opaque image tokens (SDR-4437 F-TM-7), not int PKs.
|
|
2000
|
+
"""
|
|
1998
2001
|
from src.core.database import get_db_session
|
|
1999
2002
|
from src.services import image_service
|
|
2000
2003
|
|
|
2001
2004
|
image_descriptions = []
|
|
2002
2005
|
with get_db_session() as db:
|
|
2003
|
-
for
|
|
2006
|
+
for img_token in image_ids:
|
|
2004
2007
|
try:
|
|
2005
2008
|
img = db.query(image_service.ImageAsset).filter(
|
|
2006
|
-
image_service.ImageAsset.
|
|
2009
|
+
image_service.ImageAsset.token == img_token,
|
|
2007
2010
|
image_service.ImageAsset.is_active == True,
|
|
2008
2011
|
).first()
|
|
2009
2012
|
if img:
|
|
2010
2013
|
image_descriptions.append(
|
|
2011
|
-
f'- Image ID {img.
|
|
2014
|
+
f'- Image ID {img.token}: "{img.original_filename}" '
|
|
2012
2015
|
f'({img.description or "no description"}). '
|
|
2013
|
-
f'Use: <img src="{{{{image:{img.
|
|
2016
|
+
f'Use: <img src="{{{{image:{img.token}}}}}" alt="{img.description or img.original_filename}" />'
|
|
2014
2017
|
)
|
|
2015
2018
|
except Exception as e:
|
|
2016
|
-
logger.warning(f"Failed to load image {
|
|
2019
|
+
logger.warning(f"Failed to load image {img_token} for context injection: {e}")
|
|
2017
2020
|
|
|
2018
2021
|
if not image_descriptions:
|
|
2019
2022
|
return message
|
|
@@ -524,6 +524,8 @@ def _run_migrations(engine, schema: str | None = None):
|
|
|
524
524
|
# --- image_assets.tags: json → jsonb (PostgreSQL) for native @> queries ---
|
|
525
525
|
_migrate_image_assets_tags_json_to_jsonb(conn, schema, _qual, is_sqlite)
|
|
526
526
|
|
|
527
|
+
# --- image_assets.token: unguessable external id + backfill (SDR-4437 F-TM-7) ---
|
|
528
|
+
_migrate_image_assets_add_token(conn, inspector, schema, _qual, is_sqlite)
|
|
527
529
|
# --- agent_config: style precedence in the DB, for the raw-SQL writers no
|
|
528
530
|
# --- Python-side bind hook can see (PostgreSQL only; no-op on SQLite) ---
|
|
529
531
|
_migrate_agent_config_precedence_trigger(
|
|
@@ -1058,6 +1060,44 @@ def _ensure_llm_judge_backend_default(
|
|
|
1058
1060
|
)
|
|
1059
1061
|
|
|
1060
1062
|
|
|
1063
|
+
def _migrate_image_assets_add_token(conn, inspector, schema, _qual, is_sqlite) -> None:
|
|
1064
|
+
"""Add the unguessable ``token`` column to image_assets and backfill (SDR-4437 F-TM-7).
|
|
1065
|
+
|
|
1066
|
+
The int PK is enumerable, so image reads now key on an opaque token. Fresh
|
|
1067
|
+
installs get the column via create_all(); existing tables need this ALTER +
|
|
1068
|
+
per-row backfill. Idempotent: gated on the column's absence.
|
|
1069
|
+
"""
|
|
1070
|
+
import secrets
|
|
1071
|
+
|
|
1072
|
+
from sqlalchemy import text
|
|
1073
|
+
|
|
1074
|
+
table = "image_assets"
|
|
1075
|
+
try:
|
|
1076
|
+
cols = {c["name"] for c in inspector.get_columns(table, schema=schema)}
|
|
1077
|
+
except Exception:
|
|
1078
|
+
return
|
|
1079
|
+
if not cols or "token" in cols:
|
|
1080
|
+
return
|
|
1081
|
+
|
|
1082
|
+
q = _qual(table)
|
|
1083
|
+
logger.info(f"Migration: adding token column to {table} (SDR-4437 F-TM-7)")
|
|
1084
|
+
# Add nullable first so the ALTER succeeds on a populated table.
|
|
1085
|
+
conn.execute(text(f"ALTER TABLE {q} ADD COLUMN token VARCHAR(64)"))
|
|
1086
|
+
|
|
1087
|
+
# Backfill every existing row with a distinct unguessable token.
|
|
1088
|
+
row_ids = [r[0] for r in conn.execute(text(f"SELECT id FROM {q} WHERE token IS NULL")).fetchall()]
|
|
1089
|
+
for row_id in row_ids:
|
|
1090
|
+
conn.execute(
|
|
1091
|
+
text(f"UPDATE {q} SET token = :tok WHERE id = :id"),
|
|
1092
|
+
{"tok": secrets.token_urlsafe(32), "id": row_id},
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
# Enforce uniqueness (and non-null on PostgreSQL, now that every row has a token).
|
|
1096
|
+
conn.execute(text(
|
|
1097
|
+
f"CREATE UNIQUE INDEX IF NOT EXISTS ix_image_assets_token ON {q} (token)"
|
|
1098
|
+
))
|
|
1099
|
+
if not is_sqlite:
|
|
1100
|
+
conn.execute(text(f"ALTER TABLE {q} ALTER COLUMN token SET NOT NULL"))
|
|
1061
1101
|
#: The one place the precedence rule is written in SQL. ``$$``-quoted so the body
|
|
1062
1102
|
#: needs no escaping, and named after the rule rather than the tables, since both
|
|
1063
1103
|
#: ``agent_config`` columns share it.
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/image.py
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Image asset model — metadata and binary data stored together in Lakebase."""
|
|
2
|
+
import secrets
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
|
|
4
5
|
from sqlalchemy import Boolean, Column, DateTime, Integer, JSON, LargeBinary, String, Text
|
|
@@ -10,6 +11,17 @@ from src.core.database import Base
|
|
|
10
11
|
_TagsColumn = JSON().with_variant(JSONB(), "postgresql")
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
def _new_image_token() -> str:
|
|
15
|
+
"""Unguessable external identifier (SDR-4437 F-TM-7).
|
|
16
|
+
|
|
17
|
+
The autoincrement int PK is enumerable, so it is never exposed. This
|
|
18
|
+
opaque token is the only identifier that leaves the server — it is what
|
|
19
|
+
the API returns, what chat sends in ``image_ids``, and what goes in
|
|
20
|
+
``{{image:...}}`` slide placeholders.
|
|
21
|
+
"""
|
|
22
|
+
return secrets.token_urlsafe(32)
|
|
23
|
+
|
|
24
|
+
|
|
13
25
|
class ImageAsset(Base):
|
|
14
26
|
"""Uploaded image with binary data stored directly in PostgreSQL.
|
|
15
27
|
|
|
@@ -20,7 +32,9 @@ class ImageAsset(Base):
|
|
|
20
32
|
|
|
21
33
|
__tablename__ = "image_assets"
|
|
22
34
|
|
|
23
|
-
id = Column(Integer, primary_key=True)
|
|
35
|
+
id = Column(Integer, primary_key=True) # Internal only — never serialized.
|
|
36
|
+
# Unguessable external identifier (SDR-4437 F-TM-7). token_urlsafe(32) → 43 chars.
|
|
37
|
+
token = Column(String(64), unique=True, nullable=False, index=True, default=_new_image_token)
|
|
24
38
|
filename = Column(String(255), nullable=False) # Generated: {uuid}.{ext}
|
|
25
39
|
original_filename = Column(String(255), nullable=False) # User's original filename
|
|
26
40
|
mime_type = Column(String(50), nullable=False) # image/png, image/jpeg, image/gif, image/svg+xml
|
|
@@ -70,9 +70,20 @@ class NormalizedAgentConfig(TypeDecorator):
|
|
|
70
70
|
not have its caller's dict edited underneath it).
|
|
71
71
|
|
|
72
72
|
Emits an ordinary ``JSON`` column, so adopting it needs no migration.
|
|
73
|
+
|
|
74
|
+
``none_as_null=True`` is load-bearing, not tidiness. ``sqlalchemy.JSON`` defaults
|
|
75
|
+
to ``none_as_null=False``, which serializes a bound ``None`` into the two-byte
|
|
76
|
+
document ``null`` instead of leaving the column as SQL NULL — and the JSON scalar
|
|
77
|
+
``null`` is NOT SQL NULL. It is a stored value that merely READS as empty:
|
|
78
|
+
``IS NULL`` does not match it, while the ORM attribute deserializes it to ``None``
|
|
79
|
+
exactly like SQL NULL, so nothing above the driver can tell the two apart. The
|
|
80
|
+
startup backfill ``migrate_profiles`` selects the rows it has to fill with
|
|
81
|
+
``agent_config.is_(None)``, so adopting this type silently made every freshly
|
|
82
|
+
seeded profile invisible to it. See
|
|
83
|
+
``tests/unit/test_unset_agent_config_is_sql_null.py``.
|
|
73
84
|
"""
|
|
74
85
|
|
|
75
|
-
impl = JSON
|
|
86
|
+
impl = JSON(none_as_null=True)
|
|
76
87
|
cache_ok = True
|
|
77
88
|
|
|
78
89
|
def process_bind_param(self, value: Any, dialect: Any) -> Any:
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/image_service.py
RENAMED
|
@@ -51,7 +51,7 @@ def upload_image(
|
|
|
51
51
|
).first()
|
|
52
52
|
if existing:
|
|
53
53
|
raise ValueError(
|
|
54
|
-
f"An image named '{original_filename}' already exists
|
|
54
|
+
f"An image named '{original_filename}' already exists. "
|
|
55
55
|
"Please rename the file or delete the existing image first."
|
|
56
56
|
)
|
|
57
57
|
|
|
@@ -86,19 +86,19 @@ def upload_image(
|
|
|
86
86
|
return image
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
def get_image_base64(db: Session,
|
|
89
|
+
def get_image_base64(db: Session, token: str) -> tuple[str, str]:
|
|
90
90
|
"""
|
|
91
|
-
Get full image as base64 string.
|
|
91
|
+
Get full image as base64 string, keyed by the opaque token (SDR-4437 F-TM-7).
|
|
92
92
|
|
|
93
93
|
Returns:
|
|
94
94
|
Tuple of (base64_data, mime_type)
|
|
95
95
|
"""
|
|
96
96
|
image = db.query(ImageAsset).filter(
|
|
97
|
-
ImageAsset.
|
|
97
|
+
ImageAsset.token == token,
|
|
98
98
|
ImageAsset.is_active == True,
|
|
99
99
|
).first()
|
|
100
100
|
if not image:
|
|
101
|
-
raise ValueError(f"Image {
|
|
101
|
+
raise ValueError(f"Image {token} not found")
|
|
102
102
|
|
|
103
103
|
b64 = base64.b64encode(image.image_data).decode("utf-8")
|
|
104
104
|
return b64, image.mime_type
|
|
@@ -175,11 +175,11 @@ def search_images(
|
|
|
175
175
|
).all()
|
|
176
176
|
|
|
177
177
|
|
|
178
|
-
def delete_image(db: Session,
|
|
179
|
-
"""Soft-delete an image."""
|
|
180
|
-
image = db.query(ImageAsset).filter(ImageAsset.
|
|
178
|
+
def delete_image(db: Session, token: str, user: str) -> None:
|
|
179
|
+
"""Soft-delete an image, keyed by the opaque token (SDR-4437 F-TM-7)."""
|
|
180
|
+
image = db.query(ImageAsset).filter(ImageAsset.token == token).first()
|
|
181
181
|
if not image:
|
|
182
|
-
raise ValueError(f"Image {
|
|
182
|
+
raise ValueError(f"Image {token} not found")
|
|
183
183
|
|
|
184
184
|
image.is_active = False
|
|
185
185
|
image.updated_by = user
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/image_tools.py
RENAMED
|
@@ -53,13 +53,13 @@ def search_images(
|
|
|
53
53
|
# Must build results inside session scope to avoid DetachedInstanceError
|
|
54
54
|
results = [
|
|
55
55
|
{
|
|
56
|
-
"id": img.
|
|
56
|
+
"id": img.token, # Opaque token (SDR-4437 F-TM-7), never the int PK.
|
|
57
57
|
"filename": img.original_filename,
|
|
58
58
|
"description": img.description,
|
|
59
59
|
"tags": img.tags,
|
|
60
60
|
"category": img.category,
|
|
61
61
|
"mime_type": img.mime_type,
|
|
62
|
-
"usage": f'<img src="{{{{image:{img.
|
|
62
|
+
"usage": f'<img src="{{{{image:{img.token}}}}}" alt="{img.description or img.original_filename}" />',
|
|
63
63
|
}
|
|
64
64
|
for img in images
|
|
65
65
|
]
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/image_utils.py
RENAMED
|
@@ -8,7 +8,8 @@ from src.services import image_service
|
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# Tokens are secrets.token_urlsafe(...) → [A-Za-z0-9_-] (SDR-4437 F-TM-7).
|
|
12
|
+
IMAGE_PLACEHOLDER_PATTERN = re.compile(r"\{\{image:([A-Za-z0-9_-]+)\}\}")
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
def substitute_image_placeholders(html: str, db: Session) -> str:
|
|
@@ -22,12 +23,12 @@ def substitute_image_placeholders(html: str, db: Session) -> str:
|
|
|
22
23
|
return html
|
|
23
24
|
|
|
24
25
|
def replace_match(match):
|
|
25
|
-
|
|
26
|
+
image_token = match.group(1)
|
|
26
27
|
try:
|
|
27
|
-
b64_data, mime_type = image_service.get_image_base64(db,
|
|
28
|
+
b64_data, mime_type = image_service.get_image_base64(db, image_token)
|
|
28
29
|
return f"data:{mime_type};base64,{b64_data}"
|
|
29
30
|
except Exception as e:
|
|
30
|
-
logger.warning(f"Failed to resolve image placeholder {{{{image:{
|
|
31
|
+
logger.warning(f"Failed to resolve image placeholder {{{{image:{image_token}}}}}: {e}")
|
|
31
32
|
return match.group(0) # Leave placeholder if image not found
|
|
32
33
|
|
|
33
34
|
return IMAGE_PLACEHOLDER_PATTERN.sub(replace_match, html)
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/databricks_tellr_app/run.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/_otel_bootstrap.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/middleware/__init__.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/middleware/csrf.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/__init__.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/_authz.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/admin.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/admin_usage.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/agent_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/export.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/feedback.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/google_slides.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/local_version.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/profiles.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/sessions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/setup.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/slides.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/tools.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/verification.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/routes/version.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/__init__.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/agent_config.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/feedback.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/responses.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/schemas/streaming.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/services/job_queue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/utils/__init__.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/api/utils/validation.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/config_loader.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/context_utils.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/databricks_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/mlflow_agent_spans.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/mlflow_tracing.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/otel_logging.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/permission_context.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/prompt_modules.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/settings_db.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/core/user_context.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/__init__.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/feedback.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/identity.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/profile.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/prompts.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/database/models/session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/domain/slide_deck.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/agent_factory.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/config_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/drive_uploader.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/genie_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/html_to_pptx.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/profile_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/tools/mcp_tool.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/services/validator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/ds_asset_utils.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/error_handling.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/html_safety.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/html_utils.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/js_validator.py
RENAMED
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/logging_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{databricks_tellr_app-0.4.2.dev20 → databricks_tellr_app-0.4.3.dev1}/src/utils/slide_hash.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|