databricks-tellr-app 0.3.11.dev7__tar.gz → 0.3.11.dev8__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.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/PKG-INFO +1 -1
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app.egg-info/PKG-INFO +1 -1
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app.egg-info/SOURCES.txt +8 -14
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/pyproject.toml +1 -1
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/main.py +10 -3
- databricks_tellr_app-0.3.11.dev8/src/api/routes/admin_usage.py +69 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/agent_config.py +3 -56
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/export.py +2 -4
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/feedback.py +27 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/google_slides.py +1 -5
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/sessions.py +5 -2
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/settings/__init__.py +0 -2
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/agent_config.py +0 -8
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/chat_service.py +5 -38
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/export_job_queue.py +2 -4
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/feedback_service.py +43 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/session_manager.py +19 -3
- databricks_tellr_app-0.3.11.dev8/src/api/services/usage_events.py +117 -0
- databricks_tellr_app-0.3.11.dev8/src/api/services/usage_service.py +400 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/database.py +0 -117
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/prompt_modules.py +3 -53
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/__init__.py +3 -12
- databricks_tellr_app-0.3.11.dev8/src/database/models/usage_event.py +39 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/agent_factory.py +5 -95
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/tools/__init__.py +0 -4
- databricks_tellr_app-0.3.11.dev7/src/api/routes/settings/design_systems.py +0 -847
- databricks_tellr_app-0.3.11.dev7/src/database/models/design_system.py +0 -357
- databricks_tellr_app-0.3.11.dev7/src/services/design_system_compiler.py +0 -603
- databricks_tellr_app-0.3.11.dev7/src/services/design_system_service.py +0 -1004
- databricks_tellr_app-0.3.11.dev7/src/services/design_system_templates.py +0 -641
- databricks_tellr_app-0.3.11.dev7/src/services/tools/ds_asset_tool.py +0 -105
- databricks_tellr_app-0.3.11.dev7/src/utils/ds_asset_utils.py +0 -76
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/README.md +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app/run.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app.egg-info/dependency_links.txt +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app.egg-info/requires.txt +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/databricks_tellr_app.egg-info/top_level.txt +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/setup.cfg +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/setup.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/_otel_bootstrap.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/fixtures/tour_demo_deck.json +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/mcp_auth.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/mcp_server.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/middleware/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/middleware/request_logging.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/admin.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/chat.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/deck_contributors.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/images.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/local_version.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/profiles.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/settings/contributors.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/settings/deck_prompts.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/settings/identities.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/settings/slide_styles.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/setup.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/slides.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/tools.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/tour.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/verification.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/version.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/feedback.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/requests.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/responses.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/settings/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/settings/requests.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/settings/responses.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/schemas/streaming.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/job_queue.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/services/session_naming.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/utils/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/utils/validation.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/config_loader.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/context_utils.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/databricks_client.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/defaults.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/encryption.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/init_default_profile.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/lakebase.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/migrate_profiles_to_agent_config.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/mlflow_agent_spans.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/mlflow_tracing.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/otel_logging.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/permission_context.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/settings_db.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/core/user_context.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/deck_contributor.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/feedback.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/genie_space.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/google_global_credentials.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/google_oauth_token.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/identity.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/image.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/profile.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/profile_contributor.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/prompts.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/request_log.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/session.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/slide_deck_prompt.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/slide_style_library.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/database/models/user_preference.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/domain/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/domain/slide.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/domain/slide_deck.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/agent.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/config_service.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/config_validator.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/drive_uploader.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/evaluation/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/evaluation/llm_judge.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/genie_service.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/google_slides_auth.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/google_slides_prompts_defaults.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/html_to_google_slides.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/html_to_pptx.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/identity_provider.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/identity_providers/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/identity_providers/account_provider.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/identity_providers/local_provider.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/identity_providers/workspace_provider.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/image_service.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/image_tools.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/permission_service.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/pptx_from_html_huashu.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/pptx_from_records.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/pptx_prompts_defaults.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/profile_service.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/streaming_callback.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/tools/agent_bricks_tool.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/tools/genie_tool.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/tools/mcp_tool.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/tools/model_endpoint_tool.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/tools/vector_tool.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/services/validator.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/__init__.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/css_utils.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/error_handling.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/html_safety.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/html_utils.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/image_utils.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/js_validator.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/logging_config.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/pi_filter.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/slide_hash.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/spotlight.py +0 -0
- {databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/utils/text_caps.py +0 -0
|
@@ -14,6 +14,7 @@ setup.py
|
|
|
14
14
|
./src/api/middleware/request_logging.py
|
|
15
15
|
./src/api/routes/__init__.py
|
|
16
16
|
./src/api/routes/admin.py
|
|
17
|
+
./src/api/routes/admin_usage.py
|
|
17
18
|
./src/api/routes/agent_config.py
|
|
18
19
|
./src/api/routes/chat.py
|
|
19
20
|
./src/api/routes/deck_contributors.py
|
|
@@ -33,7 +34,6 @@ setup.py
|
|
|
33
34
|
./src/api/routes/settings/__init__.py
|
|
34
35
|
./src/api/routes/settings/contributors.py
|
|
35
36
|
./src/api/routes/settings/deck_prompts.py
|
|
36
|
-
./src/api/routes/settings/design_systems.py
|
|
37
37
|
./src/api/routes/settings/identities.py
|
|
38
38
|
./src/api/routes/settings/slide_styles.py
|
|
39
39
|
./src/api/schemas/__init__.py
|
|
@@ -52,6 +52,8 @@ setup.py
|
|
|
52
52
|
./src/api/services/job_queue.py
|
|
53
53
|
./src/api/services/session_manager.py
|
|
54
54
|
./src/api/services/session_naming.py
|
|
55
|
+
./src/api/services/usage_events.py
|
|
56
|
+
./src/api/services/usage_service.py
|
|
55
57
|
./src/api/utils/__init__.py
|
|
56
58
|
./src/api/utils/validation.py
|
|
57
59
|
./src/core/__init__.py
|
|
@@ -74,7 +76,6 @@ setup.py
|
|
|
74
76
|
./src/database/__init__.py
|
|
75
77
|
./src/database/models/__init__.py
|
|
76
78
|
./src/database/models/deck_contributor.py
|
|
77
|
-
./src/database/models/design_system.py
|
|
78
79
|
./src/database/models/feedback.py
|
|
79
80
|
./src/database/models/genie_space.py
|
|
80
81
|
./src/database/models/google_global_credentials.py
|
|
@@ -88,6 +89,7 @@ setup.py
|
|
|
88
89
|
./src/database/models/session.py
|
|
89
90
|
./src/database/models/slide_deck_prompt.py
|
|
90
91
|
./src/database/models/slide_style_library.py
|
|
92
|
+
./src/database/models/usage_event.py
|
|
91
93
|
./src/database/models/user_preference.py
|
|
92
94
|
./src/domain/__init__.py
|
|
93
95
|
./src/domain/slide.py
|
|
@@ -97,9 +99,6 @@ setup.py
|
|
|
97
99
|
./src/services/agent_factory.py
|
|
98
100
|
./src/services/config_service.py
|
|
99
101
|
./src/services/config_validator.py
|
|
100
|
-
./src/services/design_system_compiler.py
|
|
101
|
-
./src/services/design_system_service.py
|
|
102
|
-
./src/services/design_system_templates.py
|
|
103
102
|
./src/services/drive_uploader.py
|
|
104
103
|
./src/services/genie_service.py
|
|
105
104
|
./src/services/google_slides_auth.py
|
|
@@ -124,14 +123,12 @@ setup.py
|
|
|
124
123
|
./src/services/identity_providers/workspace_provider.py
|
|
125
124
|
./src/services/tools/__init__.py
|
|
126
125
|
./src/services/tools/agent_bricks_tool.py
|
|
127
|
-
./src/services/tools/ds_asset_tool.py
|
|
128
126
|
./src/services/tools/genie_tool.py
|
|
129
127
|
./src/services/tools/mcp_tool.py
|
|
130
128
|
./src/services/tools/model_endpoint_tool.py
|
|
131
129
|
./src/services/tools/vector_tool.py
|
|
132
130
|
./src/utils/__init__.py
|
|
133
131
|
./src/utils/css_utils.py
|
|
134
|
-
./src/utils/ds_asset_utils.py
|
|
135
132
|
./src/utils/error_handling.py
|
|
136
133
|
./src/utils/html_safety.py
|
|
137
134
|
./src/utils/html_utils.py
|
|
@@ -160,6 +157,7 @@ src/api/middleware/__init__.py
|
|
|
160
157
|
src/api/middleware/request_logging.py
|
|
161
158
|
src/api/routes/__init__.py
|
|
162
159
|
src/api/routes/admin.py
|
|
160
|
+
src/api/routes/admin_usage.py
|
|
163
161
|
src/api/routes/agent_config.py
|
|
164
162
|
src/api/routes/chat.py
|
|
165
163
|
src/api/routes/deck_contributors.py
|
|
@@ -179,7 +177,6 @@ src/api/routes/version.py
|
|
|
179
177
|
src/api/routes/settings/__init__.py
|
|
180
178
|
src/api/routes/settings/contributors.py
|
|
181
179
|
src/api/routes/settings/deck_prompts.py
|
|
182
|
-
src/api/routes/settings/design_systems.py
|
|
183
180
|
src/api/routes/settings/identities.py
|
|
184
181
|
src/api/routes/settings/slide_styles.py
|
|
185
182
|
src/api/schemas/__init__.py
|
|
@@ -198,6 +195,8 @@ src/api/services/feedback_service.py
|
|
|
198
195
|
src/api/services/job_queue.py
|
|
199
196
|
src/api/services/session_manager.py
|
|
200
197
|
src/api/services/session_naming.py
|
|
198
|
+
src/api/services/usage_events.py
|
|
199
|
+
src/api/services/usage_service.py
|
|
201
200
|
src/api/utils/__init__.py
|
|
202
201
|
src/api/utils/validation.py
|
|
203
202
|
src/core/__init__.py
|
|
@@ -220,7 +219,6 @@ src/core/user_context.py
|
|
|
220
219
|
src/database/__init__.py
|
|
221
220
|
src/database/models/__init__.py
|
|
222
221
|
src/database/models/deck_contributor.py
|
|
223
|
-
src/database/models/design_system.py
|
|
224
222
|
src/database/models/feedback.py
|
|
225
223
|
src/database/models/genie_space.py
|
|
226
224
|
src/database/models/google_global_credentials.py
|
|
@@ -234,6 +232,7 @@ src/database/models/request_log.py
|
|
|
234
232
|
src/database/models/session.py
|
|
235
233
|
src/database/models/slide_deck_prompt.py
|
|
236
234
|
src/database/models/slide_style_library.py
|
|
235
|
+
src/database/models/usage_event.py
|
|
237
236
|
src/database/models/user_preference.py
|
|
238
237
|
src/domain/__init__.py
|
|
239
238
|
src/domain/slide.py
|
|
@@ -243,9 +242,6 @@ src/services/agent.py
|
|
|
243
242
|
src/services/agent_factory.py
|
|
244
243
|
src/services/config_service.py
|
|
245
244
|
src/services/config_validator.py
|
|
246
|
-
src/services/design_system_compiler.py
|
|
247
|
-
src/services/design_system_service.py
|
|
248
|
-
src/services/design_system_templates.py
|
|
249
245
|
src/services/drive_uploader.py
|
|
250
246
|
src/services/genie_service.py
|
|
251
247
|
src/services/google_slides_auth.py
|
|
@@ -270,14 +266,12 @@ src/services/identity_providers/local_provider.py
|
|
|
270
266
|
src/services/identity_providers/workspace_provider.py
|
|
271
267
|
src/services/tools/__init__.py
|
|
272
268
|
src/services/tools/agent_bricks_tool.py
|
|
273
|
-
src/services/tools/ds_asset_tool.py
|
|
274
269
|
src/services/tools/genie_tool.py
|
|
275
270
|
src/services/tools/mcp_tool.py
|
|
276
271
|
src/services/tools/model_endpoint_tool.py
|
|
277
272
|
src/services/tools/vector_tool.py
|
|
278
273
|
src/utils/__init__.py
|
|
279
274
|
src/utils/css_utils.py
|
|
280
|
-
src/utils/ds_asset_utils.py
|
|
281
275
|
src/utils/error_handling.py
|
|
282
276
|
src/utils/html_safety.py
|
|
283
277
|
src/utils/html_utils.py
|
|
@@ -16,7 +16,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|
|
16
16
|
from fastapi.responses import FileResponse
|
|
17
17
|
from fastapi.staticfiles import StaticFiles
|
|
18
18
|
|
|
19
|
-
from src.api.routes import admin, agent_config, chat, export, feedback, images, profiles, sessions, slides, tools, tour, verification, version, google_slides, setup, local_version
|
|
19
|
+
from src.api.routes import admin, admin_usage, agent_config, chat, export, feedback, images, profiles, sessions, slides, tools, tour, verification, version, google_slides, setup, local_version
|
|
20
20
|
from src.api.routes.deck_contributors import router as deck_contributors_router
|
|
21
21
|
from src.core.databricks_client import get_or_create_user_client, set_user_client
|
|
22
22
|
from src.core.user_context import get_current_user as get_ctx_user, set_current_user
|
|
@@ -27,7 +27,6 @@ from src.core.permission_context import (
|
|
|
27
27
|
from src.api.routes.settings import (
|
|
28
28
|
contributors_router,
|
|
29
29
|
deck_prompts_router,
|
|
30
|
-
design_systems_router,
|
|
31
30
|
identities_router,
|
|
32
31
|
slide_styles_router,
|
|
33
32
|
)
|
|
@@ -382,6 +381,14 @@ async def user_auth_middleware(request: Request, call_next):
|
|
|
382
381
|
)
|
|
383
382
|
set_permission_context(permission_ctx)
|
|
384
383
|
|
|
384
|
+
# Record login usage-event (visit-deduped, non-blocking, all envs)
|
|
385
|
+
if user_name:
|
|
386
|
+
try:
|
|
387
|
+
from src.api.services.usage_events import record_login
|
|
388
|
+
record_login(user_name)
|
|
389
|
+
except Exception as e:
|
|
390
|
+
logger.debug(f"Failed to record login usage event: {e}")
|
|
391
|
+
|
|
385
392
|
# Record user login for local identity table (non-blocking)
|
|
386
393
|
if user_id and user_name and IS_PRODUCTION:
|
|
387
394
|
try:
|
|
@@ -412,6 +419,7 @@ app.add_middleware(RequestLoggingMiddleware)
|
|
|
412
419
|
|
|
413
420
|
# Include API routers
|
|
414
421
|
app.include_router(admin.router)
|
|
422
|
+
app.include_router(admin_usage.router)
|
|
415
423
|
app.include_router(agent_config.router)
|
|
416
424
|
app.include_router(chat.router)
|
|
417
425
|
app.include_router(feedback.router)
|
|
@@ -435,7 +443,6 @@ app.include_router(contributors_router, prefix="/api/settings", tags=["settings"
|
|
|
435
443
|
app.include_router(deck_prompts_router, prefix="/api/settings", tags=["settings"])
|
|
436
444
|
app.include_router(identities_router, prefix="/api/settings", tags=["settings"])
|
|
437
445
|
app.include_router(slide_styles_router, prefix="/api/settings", tags=["settings"])
|
|
438
|
-
app.include_router(design_systems_router, prefix="/api/settings", tags=["settings"])
|
|
439
446
|
|
|
440
447
|
# MCP server — mount the FastMCP streamable-HTTP ASGI app at /mcp.
|
|
441
448
|
# Must be registered before the SPA catch-all (which is added lazily by
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Admin usage-analytics endpoints (ungated, like the rest of /admin)."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
|
6
|
+
from sqlalchemy.orm import Session
|
|
7
|
+
|
|
8
|
+
from src.api.services.usage_service import ALLOWED_WINDOWS, UsageService
|
|
9
|
+
from src.core.database import get_db
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
router = APIRouter(prefix="/api/admin/usage", tags=["admin-usage"])
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _validated_days(days: int) -> int:
|
|
16
|
+
if days not in ALLOWED_WINDOWS:
|
|
17
|
+
raise HTTPException(
|
|
18
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
19
|
+
detail=f"days must be one of {sorted(ALLOWED_WINDOWS)}",
|
|
20
|
+
)
|
|
21
|
+
return days
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _handle(callable_, *args, **kwargs):
|
|
25
|
+
try:
|
|
26
|
+
return callable_(*args, **kwargs)
|
|
27
|
+
except HTTPException:
|
|
28
|
+
raise
|
|
29
|
+
except Exception as e:
|
|
30
|
+
logger.error(f"Usage analytics error: {e}", exc_info=True)
|
|
31
|
+
raise HTTPException(
|
|
32
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
33
|
+
detail="Failed to compute usage analytics",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@router.get("/summary")
|
|
38
|
+
def get_summary(days: int = Query(default=7), db: Session = Depends(get_db)):
|
|
39
|
+
days = _validated_days(days)
|
|
40
|
+
return _handle(UsageService().get_summary, db, days=days)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@router.get("/daily")
|
|
44
|
+
def get_daily(days: int = Query(default=7), db: Session = Depends(get_db)):
|
|
45
|
+
days = _validated_days(days)
|
|
46
|
+
return _handle(UsageService().get_daily, db, days=days)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@router.get("/top-users")
|
|
50
|
+
def get_top_users(days: int = Query(default=7), db: Session = Depends(get_db)):
|
|
51
|
+
days = _validated_days(days)
|
|
52
|
+
return _handle(UsageService().get_top_users, db, days=days)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@router.get("/funnel")
|
|
56
|
+
def get_funnel(days: int = Query(default=7), db: Session = Depends(get_db)):
|
|
57
|
+
days = _validated_days(days)
|
|
58
|
+
return _handle(UsageService().get_funnel, db, days=days)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@router.get("/retention")
|
|
62
|
+
def get_retention(db: Session = Depends(get_db)):
|
|
63
|
+
return _handle(UsageService().get_retention, db)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@router.get("/heatmap")
|
|
67
|
+
def get_heatmap(days: int = Query(default=7), db: Session = Depends(get_db)):
|
|
68
|
+
days = _validated_days(days)
|
|
69
|
+
return _handle(UsageService().get_heatmap, db, days=days)
|
{databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/agent_config.py
RENAMED
|
@@ -21,61 +21,10 @@ router = APIRouter(prefix="/api/sessions/{session_id}/agent-config", tags=["agen
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def _validate_references(config: AgentConfig) -> None:
|
|
24
|
-
"""Validate
|
|
25
|
-
|
|
26
|
-
``design_system_id``, ``slide_style_id`` and ``deck_prompt_id`` stay STRICT
|
|
27
|
-
(422 on a missing/inactive entry — the existing convention). The template
|
|
28
|
-
pin is SELF-HEALING instead: template ids are re-minted by the sanctioned
|
|
29
|
-
delete+re-upload workflow, so a persisted config can legitimately hold a
|
|
30
|
-
stale pin — rejecting it would wedge EVERY later config update. When
|
|
31
|
-
``template_id`` does not resolve to a template belonging to the selected
|
|
32
|
-
design system (pin with no design system, another system's template, or a
|
|
33
|
-
missing/re-materialized template), it is cleared in place with a warning;
|
|
34
|
-
the caller persists and returns the sanitized config so the frontend state
|
|
35
|
-
syncs. This mirrors the deliberately lenient generation path.
|
|
36
|
-
"""
|
|
37
|
-
from src.database.models import (
|
|
38
|
-
DesignSystem,
|
|
39
|
-
DesignSystemTemplate,
|
|
40
|
-
SlideDeckPromptLibrary,
|
|
41
|
-
SlideStyleLibrary,
|
|
42
|
-
)
|
|
24
|
+
"""Validate that slide_style_id and deck_prompt_id reference existing library entries."""
|
|
25
|
+
from src.database.models import SlideStyleLibrary, SlideDeckPromptLibrary
|
|
43
26
|
|
|
44
27
|
with get_db_session() as db:
|
|
45
|
-
if config.design_system_id is not None:
|
|
46
|
-
design_system = (
|
|
47
|
-
db.query(DesignSystem)
|
|
48
|
-
.filter(
|
|
49
|
-
DesignSystem.id == config.design_system_id,
|
|
50
|
-
DesignSystem.is_active == True, # noqa: E712
|
|
51
|
-
)
|
|
52
|
-
.first()
|
|
53
|
-
)
|
|
54
|
-
if not design_system:
|
|
55
|
-
raise HTTPException(
|
|
56
|
-
status_code=422,
|
|
57
|
-
detail=f"design_system_id {config.design_system_id} not found",
|
|
58
|
-
)
|
|
59
|
-
if config.template_id is not None:
|
|
60
|
-
template = None
|
|
61
|
-
if config.design_system_id is not None:
|
|
62
|
-
template = (
|
|
63
|
-
db.query(DesignSystemTemplate)
|
|
64
|
-
.filter(
|
|
65
|
-
DesignSystemTemplate.id == config.template_id,
|
|
66
|
-
DesignSystemTemplate.design_system_id == config.design_system_id,
|
|
67
|
-
)
|
|
68
|
-
.first()
|
|
69
|
-
)
|
|
70
|
-
if template is None:
|
|
71
|
-
logger.warning(
|
|
72
|
-
"Clearing stale template pin %s (design_system_id=%s): the "
|
|
73
|
-
"template does not exist or does not belong to the selected "
|
|
74
|
-
"design system; saving the config without it",
|
|
75
|
-
config.template_id,
|
|
76
|
-
config.design_system_id,
|
|
77
|
-
)
|
|
78
|
-
config.template_id = None
|
|
79
28
|
if config.slide_style_id is not None:
|
|
80
29
|
style = (
|
|
81
30
|
db.query(SlideStyleLibrary)
|
|
@@ -151,9 +100,7 @@ async def get_agent_config(session_id: str):
|
|
|
151
100
|
async def put_agent_config(session_id: str, config: AgentConfig):
|
|
152
101
|
"""Replace the full agent config for a session."""
|
|
153
102
|
# Pydantic already validated duplicates via model_validator.
|
|
154
|
-
# Now validate foreign-key references
|
|
155
|
-
# (cleared in place) rather than rejected, so what is persisted and
|
|
156
|
-
# returned below is the effective config.
|
|
103
|
+
# Now validate foreign-key references.
|
|
157
104
|
_validate_references(config)
|
|
158
105
|
|
|
159
106
|
try:
|
{databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/export.py
RENAMED
|
@@ -405,14 +405,12 @@ async def export_to_pptx(request: ExportPPTXRequest):
|
|
|
405
405
|
if not slide_deck or not slide_deck.get("slides"):
|
|
406
406
|
raise HTTPException(status_code=404, detail="No slides available")
|
|
407
407
|
|
|
408
|
-
# Substitute {{image:ID}}
|
|
409
|
-
# so the PPTX converter can extract and embed the actual images
|
|
410
|
-
from src.utils.ds_asset_utils import substitute_deck_dict_ds_assets
|
|
408
|
+
# Substitute {{image:ID}} placeholders with base64 data URIs
|
|
409
|
+
# so the PPTX converter can extract and embed the actual images
|
|
411
410
|
from src.utils.image_utils import substitute_deck_dict_images
|
|
412
411
|
from src.core.database import get_db_session
|
|
413
412
|
with get_db_session() as db:
|
|
414
413
|
substitute_deck_dict_images(slide_deck, db)
|
|
415
|
-
substitute_deck_dict_ds_assets(slide_deck, db)
|
|
416
414
|
|
|
417
415
|
slide_count = len(slide_deck.get("slides", []))
|
|
418
416
|
log_msg = (
|
{databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/feedback.py
RENAMED
|
@@ -88,6 +88,33 @@ def get_stats_report(weeks: int = Query(default=12, ge=1, le=52), db: Session =
|
|
|
88
88
|
)
|
|
89
89
|
|
|
90
90
|
|
|
91
|
+
@router.get("/list")
|
|
92
|
+
def list_feedback(
|
|
93
|
+
weeks: int = Query(default=12, ge=1, le=52),
|
|
94
|
+
category: str | None = Query(default=None),
|
|
95
|
+
severity: str | None = Query(default=None),
|
|
96
|
+
page: int = Query(default=1, ge=1),
|
|
97
|
+
page_size: int = Query(default=20, ge=1, le=100),
|
|
98
|
+
db: Session = Depends(get_db),
|
|
99
|
+
):
|
|
100
|
+
try:
|
|
101
|
+
service = FeedbackService()
|
|
102
|
+
return service.list_feedback(
|
|
103
|
+
db=db,
|
|
104
|
+
weeks=weeks,
|
|
105
|
+
category=category,
|
|
106
|
+
severity=severity,
|
|
107
|
+
page=page,
|
|
108
|
+
page_size=page_size,
|
|
109
|
+
)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.error(f"Feedback list error: {e}", exc_info=True)
|
|
112
|
+
raise HTTPException(
|
|
113
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
114
|
+
detail="Failed to list feedback",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
91
118
|
@router.get("/report/summary")
|
|
92
119
|
def get_feedback_summary(weeks: int = Query(default=4, ge=1, le=52), db: Session = Depends(get_db)):
|
|
93
120
|
try:
|
|
@@ -276,13 +276,11 @@ async def start_google_slides_export(
|
|
|
276
276
|
if not slide_deck or not slide_deck.get("slides"):
|
|
277
277
|
raise HTTPException(status_code=404, detail="No slides available")
|
|
278
278
|
|
|
279
|
-
# Substitute {{image:ID}}
|
|
280
|
-
from src.utils.ds_asset_utils import substitute_deck_dict_ds_assets
|
|
279
|
+
# Substitute {{image:ID}} placeholders with base64 data URIs
|
|
281
280
|
from src.utils.image_utils import substitute_deck_dict_images
|
|
282
281
|
from src.core.database import get_db_session
|
|
283
282
|
with get_db_session() as db:
|
|
284
283
|
substitute_deck_dict_images(slide_deck, db)
|
|
285
|
-
substitute_deck_dict_ds_assets(slide_deck, db)
|
|
286
284
|
|
|
287
285
|
slides_data = slide_deck.get("slides", [])
|
|
288
286
|
total = len(slides_data)
|
|
@@ -504,11 +502,9 @@ async def export_google_slides_from_huashu(
|
|
|
504
502
|
# legacy /export route). Use a fresh session because the request's `db`
|
|
505
503
|
# is held by the route's transaction context.
|
|
506
504
|
from src.core.database import get_db_session
|
|
507
|
-
from src.utils.ds_asset_utils import substitute_deck_dict_ds_assets
|
|
508
505
|
from src.utils.image_utils import substitute_deck_dict_images
|
|
509
506
|
with get_db_session() as imdb:
|
|
510
507
|
substitute_deck_dict_images(slide_deck, imdb)
|
|
511
|
-
substitute_deck_dict_ds_assets(slide_deck, imdb)
|
|
512
508
|
|
|
513
509
|
title = slide_deck.get("title") or "Presentation"
|
|
514
510
|
slides_data = slide_deck.get("slides") or []
|
{databricks_tellr_app-0.3.11.dev7 → databricks_tellr_app-0.3.11.dev8}/src/api/routes/sessions.py
RENAMED
|
@@ -25,6 +25,7 @@ from src.api.services.session_manager import (
|
|
|
25
25
|
SessionNotFoundError,
|
|
26
26
|
get_session_manager,
|
|
27
27
|
)
|
|
28
|
+
from src.api.services.usage_events import record_deck_retrieved
|
|
28
29
|
from src.core.database import get_db, get_db_session
|
|
29
30
|
from src.core.permission_context import get_permission_context
|
|
30
31
|
from src.core.user_context import get_current_user
|
|
@@ -149,12 +150,10 @@ def _check_deck_permission_for_session(
|
|
|
149
150
|
def _substitute_deck_images(deck_dict: dict) -> None:
|
|
150
151
|
"""Substitute {{image:ID}} placeholders in a deck dict with base64 data URIs."""
|
|
151
152
|
from src.core.database import get_db_session
|
|
152
|
-
from src.utils.ds_asset_utils import substitute_deck_dict_ds_assets
|
|
153
153
|
from src.utils.image_utils import substitute_deck_dict_images
|
|
154
154
|
|
|
155
155
|
with get_db_session() as db:
|
|
156
156
|
substitute_deck_dict_images(deck_dict, db)
|
|
157
|
-
substitute_deck_dict_ds_assets(deck_dict, db)
|
|
158
157
|
|
|
159
158
|
|
|
160
159
|
@router.post("")
|
|
@@ -469,6 +468,10 @@ async def get_session(session_id: str, db: Session = Depends(get_db)):
|
|
|
469
468
|
# Check permission
|
|
470
469
|
permission = _require_session_access(session, db, PermissionLevel.CAN_VIEW)
|
|
471
470
|
|
|
471
|
+
# Record deck-open usage event (deduped per user+deck, non-blocking)
|
|
472
|
+
if current_user:
|
|
473
|
+
record_deck_retrieved(current_user, session.get("id"))
|
|
474
|
+
|
|
472
475
|
# Only the session creator sees chat messages — conversations are private
|
|
473
476
|
is_creator = session.get("created_by") == current_user
|
|
474
477
|
messages = []
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"""Configuration API routes."""
|
|
2
2
|
from src.api.routes.settings.contributors import router as contributors_router
|
|
3
3
|
from src.api.routes.settings.deck_prompts import router as deck_prompts_router
|
|
4
|
-
from src.api.routes.settings.design_systems import router as design_systems_router
|
|
5
4
|
from src.api.routes.settings.identities import router as identities_router
|
|
6
5
|
from src.api.routes.settings.slide_styles import router as slide_styles_router
|
|
7
6
|
|
|
8
7
|
__all__ = [
|
|
9
8
|
"contributors_router",
|
|
10
9
|
"deck_prompts_router",
|
|
11
|
-
"design_systems_router",
|
|
12
10
|
"identities_router",
|
|
13
11
|
"slide_styles_router",
|
|
14
12
|
]
|
|
@@ -59,14 +59,6 @@ class AgentConfig(BaseModel):
|
|
|
59
59
|
"""Agent configuration stored as JSON on sessions and profiles."""
|
|
60
60
|
tools: list[ToolEntry] = Field(default_factory=list)
|
|
61
61
|
slide_style_id: Optional[int] = None
|
|
62
|
-
# A selected design system compiles to prompt text and, when set, takes
|
|
63
|
-
# precedence over slide_style_id (see agent_factory._get_prompt_content).
|
|
64
|
-
design_system_id: Optional[int] = None
|
|
65
|
-
# Optionally pins ONE of the selected design system's templates
|
|
66
|
-
# (design_system_template.id). Meaningful only alongside design_system_id;
|
|
67
|
-
# generation IGNORES it (with a log) unless the template exists and belongs
|
|
68
|
-
# to that design system, so a stale pin can never fail a request.
|
|
69
|
-
template_id: Optional[int] = None
|
|
70
62
|
deck_prompt_id: Optional[int] = None
|
|
71
63
|
system_prompt: Optional[str] = None
|
|
72
64
|
slide_editing_instructions: Optional[str] = None
|
|
@@ -35,10 +35,6 @@ from src.utils.html_utils import (
|
|
|
35
35
|
extract_canvas_ids_from_html,
|
|
36
36
|
split_script_by_canvas,
|
|
37
37
|
)
|
|
38
|
-
from src.utils.ds_asset_utils import (
|
|
39
|
-
substitute_deck_dict_ds_assets,
|
|
40
|
-
substitute_ds_asset_placeholders,
|
|
41
|
-
)
|
|
42
38
|
from src.utils.image_utils import substitute_deck_dict_images, substitute_image_placeholders
|
|
43
39
|
|
|
44
40
|
logger = logging.getLogger(__name__)
|
|
@@ -87,13 +83,11 @@ class ChatService:
|
|
|
87
83
|
logger.info("ChatService initialized successfully")
|
|
88
84
|
|
|
89
85
|
def _substitute_images_for_response(self, deck_dict, raw_html=None):
|
|
90
|
-
"""Apply image
|
|
86
|
+
"""Apply image placeholder substitution before sending to client.
|
|
91
87
|
|
|
92
|
-
Converts {{image:ID}} placeholders
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
keeps lightweight placeholders (avoiding LLM context bloat). The two
|
|
96
|
-
namespaces are resolved independently.
|
|
88
|
+
Converts {{image:ID}} placeholders to base64 data URIs in deck dicts
|
|
89
|
+
and raw HTML. Called at API response boundaries so that stored/cached
|
|
90
|
+
HTML keeps lightweight placeholders (avoiding LLM context bloat).
|
|
97
91
|
"""
|
|
98
92
|
from src.core.database import get_db_session
|
|
99
93
|
|
|
@@ -103,39 +97,12 @@ class ChatService:
|
|
|
103
97
|
needs_html = raw_html and "{{image:" in raw_html
|
|
104
98
|
needs_deck_html = deck_dict and deck_dict.get("html_content") and "{{image:" in deck_dict.get("html_content", "")
|
|
105
99
|
|
|
106
|
-
|
|
107
|
-
ds_needs_deck = deck_dict and any(
|
|
108
|
-
"{{ds-asset:" in s.get("html", "") for s in deck_dict.get("slides", [])
|
|
109
|
-
)
|
|
110
|
-
ds_needs_html = raw_html and "{{ds-asset:" in raw_html
|
|
111
|
-
ds_needs_deck_html = bool(
|
|
112
|
-
deck_dict
|
|
113
|
-
and deck_dict.get("html_content")
|
|
114
|
-
and "{{ds-asset:" in deck_dict.get("html_content", "")
|
|
115
|
-
)
|
|
116
|
-
# @font-face src url() fonts and background-image url() live in the deck's
|
|
117
|
-
# top-level ``css``, not in slide html — gate on it too, else a deck whose
|
|
118
|
-
# only brand-asset reference is in css skips the resolver entirely
|
|
119
|
-
# (substitute_deck_dict_ds_assets covers the css field).
|
|
120
|
-
ds_needs_deck_css = bool(
|
|
121
|
-
deck_dict
|
|
122
|
-
and deck_dict.get("css")
|
|
123
|
-
and "{{ds-asset:" in deck_dict.get("css", "")
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
needs_deck or needs_html or needs_deck_html
|
|
128
|
-
or ds_needs_deck or ds_needs_html or ds_needs_deck_html or ds_needs_deck_css
|
|
129
|
-
):
|
|
100
|
+
if needs_deck or needs_html or needs_deck_html:
|
|
130
101
|
with get_db_session() as db:
|
|
131
102
|
if needs_deck or needs_deck_html:
|
|
132
103
|
substitute_deck_dict_images(deck_dict, db)
|
|
133
104
|
if needs_html:
|
|
134
105
|
raw_html = substitute_image_placeholders(raw_html, db)
|
|
135
|
-
if ds_needs_deck or ds_needs_deck_html or ds_needs_deck_css:
|
|
136
|
-
substitute_deck_dict_ds_assets(deck_dict, db)
|
|
137
|
-
if ds_needs_html:
|
|
138
|
-
raw_html = substitute_ds_asset_placeholders(raw_html, db)
|
|
139
106
|
return deck_dict, raw_html
|
|
140
107
|
|
|
141
108
|
def _build_agent_for_session(
|
|
@@ -203,14 +203,12 @@ async def process_export_job(job_id: str, payload: dict) -> None:
|
|
|
203
203
|
if not slide_deck or not slide_deck.get("slides"):
|
|
204
204
|
raise ValueError("No slides available")
|
|
205
205
|
|
|
206
|
-
# Substitute {{image:ID}}
|
|
207
|
-
# so the PPTX converter can extract and embed the actual images
|
|
208
|
-
from src.utils.ds_asset_utils import substitute_deck_dict_ds_assets
|
|
206
|
+
# Substitute {{image:ID}} placeholders with base64 data URIs
|
|
207
|
+
# so the PPTX converter can extract and embed the actual images
|
|
209
208
|
from src.utils.image_utils import substitute_deck_dict_images
|
|
210
209
|
from src.core.database import get_db_session
|
|
211
210
|
with get_db_session() as db:
|
|
212
211
|
substitute_deck_dict_images(slide_deck, db)
|
|
213
|
-
substitute_deck_dict_ds_assets(slide_deck, db)
|
|
214
212
|
|
|
215
213
|
slides = slide_deck.get("slides", [])
|
|
216
214
|
total_slides = len(slides)
|
|
@@ -215,6 +215,49 @@ class FeedbackService:
|
|
|
215
215
|
"usage": usage,
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
def list_feedback(
|
|
219
|
+
self,
|
|
220
|
+
db: Session,
|
|
221
|
+
weeks: int = 12,
|
|
222
|
+
category: str | None = None,
|
|
223
|
+
severity: str | None = None,
|
|
224
|
+
page: int = 1,
|
|
225
|
+
page_size: int = 20,
|
|
226
|
+
) -> Dict[str, Any]:
|
|
227
|
+
"""Paginated raw feedback conversations, newest first. Anonymous."""
|
|
228
|
+
cutoff = datetime.utcnow() - timedelta(weeks=weeks)
|
|
229
|
+
query = db.query(FeedbackConversation).filter(
|
|
230
|
+
FeedbackConversation.created_at >= cutoff
|
|
231
|
+
)
|
|
232
|
+
if category:
|
|
233
|
+
query = query.filter(FeedbackConversation.category == category)
|
|
234
|
+
if severity:
|
|
235
|
+
query = query.filter(FeedbackConversation.severity == severity)
|
|
236
|
+
|
|
237
|
+
total = query.count()
|
|
238
|
+
items = (
|
|
239
|
+
query.order_by(FeedbackConversation.created_at.desc())
|
|
240
|
+
.offset((page - 1) * page_size)
|
|
241
|
+
.limit(page_size)
|
|
242
|
+
.all()
|
|
243
|
+
)
|
|
244
|
+
return {
|
|
245
|
+
"items": [
|
|
246
|
+
{
|
|
247
|
+
"id": item.id,
|
|
248
|
+
"created_at": item.created_at.isoformat(),
|
|
249
|
+
"category": item.category,
|
|
250
|
+
"severity": item.severity,
|
|
251
|
+
"summary": item.summary,
|
|
252
|
+
"raw_conversation": item.raw_conversation,
|
|
253
|
+
}
|
|
254
|
+
for item in items
|
|
255
|
+
],
|
|
256
|
+
"total": total,
|
|
257
|
+
"page": page,
|
|
258
|
+
"page_size": page_size,
|
|
259
|
+
}
|
|
260
|
+
|
|
218
261
|
def get_feedback_summary(self, db: Session, weeks: int = 4) -> Dict[str, Any]:
|
|
219
262
|
"""Generate an AI summary of feedback conversations."""
|
|
220
263
|
cutoff = datetime.utcnow() - timedelta(weeks=weeks)
|