dao-ai 0.0.33__tar.gz → 0.0.35__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.
- {dao_ai-0.0.33 → dao_ai-0.0.35}/PKG-INFO +1 -1
- {dao_ai-0.0.33 → dao_ai-0.0.35}/environment.yaml +1 -1
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/05_deploy_agent.py +1 -1
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/99_scratchpad.py +1 -1
- {dao_ai-0.0.33 → dao_ai-0.0.35}/pyproject.toml +1 -1
- {dao_ai-0.0.33 → dao_ai-0.0.35}/requirements.txt +0 -1
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/config.py +35 -6
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/models.py +22 -2
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/providers/databricks.py +28 -60
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/genie.py +15 -4
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/unity_catalog.py +5 -2
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/vector_search.py +4 -2
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/utils.py +27 -3
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_genie_databricks_integration.py +29 -29
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_prompts.py +39 -94
- {dao_ai-0.0.33 → dao_ai-0.0.35}/.gitignore +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/.python-version +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/CHANGELOG.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/CONTRIBUTING.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/LICENSE +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/Makefile +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/Makefile +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/REFACTORING_SUMMARY.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/base-environment-serverless.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/demo_docs/BRAND_REP_DEMO_SUMMARY.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/demo_docs/demo_scripts/brand_rep_product_education_demo.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/demo_docs/demo_scripts/store_associate_ai_assistant_demo.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/demo_docs/demo_scripts/store_manager_alert_response_demo.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/development_workflows.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/Makefile +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agent_implementation.mmd +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agent_tools_architecture.mmd +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agent-troubleshooting.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agents/agent-best-practices.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agents/agent-development-patterns.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agents/agent-performance.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agents/agent-quickstart.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/ai-agents.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/overview.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/references/agent-reference.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/references/tools-reference.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/applications/streamlit-app.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/architecture/overview.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/architecture.mmd +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/architecture.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/customer_preparation_guide.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/databricks_integration.mmd +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/deployment/production.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/development/contributing.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/employee_tools_guide.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/getting-started/installation.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/getting-started/mkdocs-quickstart.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/getting-started/quick-start.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/index.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/mkdocs.yml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/scenario_1_architecture.mmd +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/scenario_1_flow.mmd +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/setup-docs.sh +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/task_assignment_workflow_guide.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/tools/overview.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/examples/customer_preparation_workflow.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/examples/task_assignment_workflow.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/load-env.sh +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/CSS_REFACTORING_SUMMARY.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/DEMO_CONTROLS_RESTORED.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/DEMO_IMPLEMENTATION_SUMMARY.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/DEMO_QUICK_START.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/Dockerfile +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/HOMEPAGE_README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/Makefile +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/app.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/app.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/backup_homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/chat.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/enhanced_charts.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/enhanced_navigation.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/associate_homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/dashboard_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/my_tasks_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/performance_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/products_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/schedule_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/common/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/common/chat_integration.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/common/kpi_summary.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/common/notifications.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/alerts_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/analytics_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/dashboard_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/demo_alerts.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/inventory_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/manager_homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/operations_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/store_manager/team_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/ai_insights_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/executive_dashboard_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/geographical_analysis_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/performance_metrics_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/strategic_insights_tab.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/vp_retail_operations/vp_homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/metrics.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/navigation.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/oldhomepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/styles.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/config.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/demo_docs/BRAND_REP_DEMO_SUMMARY.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/demo_docs/comprehensive_demo_script.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/demo_docs/demo_scripts/brand_rep_product_education_demo.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/demo_docs/demo_scripts/store_associate_ai_assistant_demo.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/demo_docs/demo_scripts/store_manager_alert_response_demo.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/components/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/components/dashboard_card.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/demo_alerts.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/examples/sample_dashboard.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/component_showcase.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/dev_playground.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/playground.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/daily_operations.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/inventory.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/my_schedule.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/my_tasks.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/orders.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/products_promotions.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/staff.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/team_insights.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pyproject.toml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/requirements.txt +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/static/css/style.css +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/base.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/components.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/dashboard.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/theme.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/test_vip_notification.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/tests/test_calculations.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/config.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/database.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/model_serving.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/store_context.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/Makefile +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/app.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/tailadmin/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/tailadmin/tailadmin_components.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/tailadmin/tailadmin_components_enhanced.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/tailadmin/tailadmin_styles.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/tailadmin_styles.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/TAILADMIN_README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/homepage_tailadmin.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/tailadmin_demo.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/tailadmin_implementation_guide.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/test_vp_dashboard.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/vp_dashboard_enhanced.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/vp_dashboard_tailadmin.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/components_demo.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/homepage.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/implementation_guide.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/vp_dashboard_clean.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/vp_dashboard_enhanced.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pyproject.toml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/tests/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/tests/test_imports.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/images/doritos_upc.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/images/lays_upc.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/manager_demo_script.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/notebook_vector_search_test.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/test_vector_search_integration.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/dais2025/model_config_dais.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/deep_research.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/executive_assistant.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie_and_genie_mcp.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie_and_vector_search.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie_with_conversion_id.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/human_in_the_loop.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/jira.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/mcp.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/mcp_with_uc_connection.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/minimal.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/prompt_optimization.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/prompt_registry.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/reservations.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/slack.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/vector_search_with_reranking.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/hardware_store/supervisor.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/hardware_store/supervisor_postgres.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/hardware_store/swarm.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/quick_serve_restaurant/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/config/quick_serve_restaurant/quick-serve-restaurant.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/appointments.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/appointments_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_queries.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_tables.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_validation.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/customers.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/customers_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/dim_stores.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/dim_stores_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_performance.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_performance_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_tasks.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_tasks_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/inventory.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/inventory_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/managers.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/managers_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/product_data.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/products.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/task_assignments.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/inventory.snappy.parquet +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/inventory.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/products.snappy.parquet +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/products.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/fulfil_item_orders.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_description.csv +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_description.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_raw.csv +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_raw.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/orders_raw.csv +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/orders_raw.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/databricks.yaml.template +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/genie.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/hardware_store/README.md +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/hardware_store/retail_supervisor.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/hardware_store/retail_swarm.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/quick_serve_restaurant/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/quick_serve_restaurant/quick-serve-restaurant.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/dais2025/examples.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/deep_research/examples.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/executive_assistant/examples.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/hardware_store/examples.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/quick_serve_restaurant/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/quick_serve_restaurant/examples.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/extract_store_numbers.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_inventory_by_sku.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_inventory_by_upc.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_product_by_sku.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_product_by_upc.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_store_by_number.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_store_inventory_by_sku.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_store_inventory_by_upc.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_inventory_by_sku.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_inventory_by_upc.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_product_by_sku.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_product_by_upc.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_store_inventory_by_sku.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_store_inventory_by_upc.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/insert_coffee_order.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/lookup_items_by_descriptions.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/match_historical_item_order_by_date.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/match_item_by_description_and_price.sql +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/01_ingest_and_transform.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/02_provision_vector_search.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/03_provision_lakebase.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/04_unity_catalog_tools.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/06_generate_evaluation_data.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/07_run_evaluation.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/08_run_examples.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/09_evaluate_inferences.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/10_optimize_prompts.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/INVESTech.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/schemas/bundle_config_schema.json +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/schemas/model_config_schema.json +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/models.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/customer.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/employee.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/executive.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/genie.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/inventory.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/models.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/store.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/agent_as_code.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/catalog.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/chat_models.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/cli.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/graph.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/guardrails.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/hooks/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/hooks/core.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/base.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/core.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/postgres.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/messages.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/nodes.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/prompts.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/providers/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/providers/base.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/state.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/agent.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/core.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/human_in_the_loop.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/mcp.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/python.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/slack.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/time.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/types.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/vector_search.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/hardware_store/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/hardware_store/hooks.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/hardware_store/tools.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/quick_serve_restaurant/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/quick_serve_restaurant/__init__.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/src/quick_serve_restaurant/tools.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/config/test_model_config.yaml +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/conftest.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_catalog.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_chat_history.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_config.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_databricks.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_function_parsing.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_genie.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_genie_conversation_ids_in_outputs.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_hooks.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_inference.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_inference_integration.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_mcp.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_mcp_function_model.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_messages.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_models.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_postgres_integration.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_prompt_optimizations.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_reranking.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_reranking_integration.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_state.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_summarization_inference.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_tools.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_types.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_unity_catalog.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_utils.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_vector_search.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/weather_server_mcp.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/hardware_store/.gitkeep +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/hardware_store/test_graph.py +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/images/doritos_upc.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/images/lays_upc.png +0 -0
- {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/quick_serve_restaurant/.gitkeep +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dao-ai
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.35
|
|
4
4
|
Summary: DAO AI: A modular, multi-agent orchestration framework for complex AI workflows. Supports agent handoff, tool integration, and dynamic configuration via YAML.
|
|
5
5
|
Project-URL: Homepage, https://github.com/natefleming/dao-ai
|
|
6
6
|
Project-URL: Documentation, https://natefleming.github.io/dao-ai
|
|
@@ -53,7 +53,7 @@ pip_requirements: Sequence[str] = [
|
|
|
53
53
|
f"databricks-connect=={get_distribution('databricks-connect').version}",
|
|
54
54
|
f"databricks-langchain=={version('databricks-langchain')}",
|
|
55
55
|
f"databricks-sdk=={version('databricks-sdk')}",
|
|
56
|
-
f"
|
|
56
|
+
f"ddgs=={version('ddgs')}",
|
|
57
57
|
f"langchain=={version('langchain')}",
|
|
58
58
|
f"langchain-mcp-adapters=={version('langchain-mcp-adapters')}",
|
|
59
59
|
f"langgraph=={version('langgraph')}",
|
|
@@ -63,7 +63,7 @@ pip_requirements: Sequence[str] = (
|
|
|
63
63
|
f"python-dotenv=={version('python-dotenv')}",
|
|
64
64
|
f"loguru=={version('loguru')}",
|
|
65
65
|
f"openevals=={version('openevals')}",
|
|
66
|
-
f"
|
|
66
|
+
f"ddgs=={version('ddgs')}",
|
|
67
67
|
f"faker=={version('faker')}",
|
|
68
68
|
)
|
|
69
69
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dao-ai"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.35"
|
|
8
8
|
description = "DAO AI: A modular, multi-agent orchestration framework for complex AI workflows. Supports agent handoff, tool integration, and dynamic configuration via YAML."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -236,9 +236,21 @@ class Privilege(str, Enum):
|
|
|
236
236
|
|
|
237
237
|
class PermissionModel(BaseModel):
|
|
238
238
|
model_config = ConfigDict(use_enum_values=True, extra="forbid")
|
|
239
|
-
principals: list[str] = Field(default_factory=list)
|
|
239
|
+
principals: list[ServicePrincipalModel | str] = Field(default_factory=list)
|
|
240
240
|
privileges: list[Privilege]
|
|
241
241
|
|
|
242
|
+
@model_validator(mode="after")
|
|
243
|
+
def resolve_principals(self) -> Self:
|
|
244
|
+
"""Resolve ServicePrincipalModel objects to their client_id."""
|
|
245
|
+
resolved: list[str] = []
|
|
246
|
+
for principal in self.principals:
|
|
247
|
+
if isinstance(principal, ServicePrincipalModel):
|
|
248
|
+
resolved.append(value_of(principal.client_id))
|
|
249
|
+
else:
|
|
250
|
+
resolved.append(principal)
|
|
251
|
+
self.principals = resolved
|
|
252
|
+
return self
|
|
253
|
+
|
|
242
254
|
|
|
243
255
|
class SchemaModel(BaseModel, HasFullName):
|
|
244
256
|
model_config = ConfigDict(use_enum_values=True, extra="forbid")
|
|
@@ -1180,21 +1192,26 @@ class McpFunctionModel(BaseFunctionModel, HasFullName):
|
|
|
1180
1192
|
Otherwise, falls back to the default Databricks host.
|
|
1181
1193
|
|
|
1182
1194
|
Returns:
|
|
1183
|
-
str: The workspace host URL without trailing slash
|
|
1195
|
+
str: The workspace host URL with https:// scheme and without trailing slash
|
|
1184
1196
|
"""
|
|
1185
|
-
from dao_ai.utils import get_default_databricks_host
|
|
1197
|
+
from dao_ai.utils import get_default_databricks_host, normalize_host
|
|
1186
1198
|
|
|
1187
1199
|
# Try to get workspace_host from config
|
|
1188
1200
|
workspace_host: str | None = (
|
|
1189
|
-
value_of(self.workspace_host)
|
|
1201
|
+
normalize_host(value_of(self.workspace_host))
|
|
1202
|
+
if self.workspace_host
|
|
1203
|
+
else None
|
|
1190
1204
|
)
|
|
1191
1205
|
|
|
1192
1206
|
# If no workspace_host in config, get it from workspace client
|
|
1193
1207
|
if not workspace_host:
|
|
1194
1208
|
# Use connection's workspace client if available
|
|
1195
1209
|
if self.connection:
|
|
1196
|
-
workspace_host =
|
|
1210
|
+
workspace_host = normalize_host(
|
|
1211
|
+
self.connection.workspace_client.config.host
|
|
1212
|
+
)
|
|
1197
1213
|
else:
|
|
1214
|
+
# get_default_databricks_host already normalizes the host
|
|
1198
1215
|
workspace_host = get_default_databricks_host()
|
|
1199
1216
|
|
|
1200
1217
|
if not workspace_host:
|
|
@@ -1581,9 +1598,21 @@ class Entitlement(str, Enum):
|
|
|
1581
1598
|
|
|
1582
1599
|
class AppPermissionModel(BaseModel):
|
|
1583
1600
|
model_config = ConfigDict(use_enum_values=True, extra="forbid")
|
|
1584
|
-
principals: list[str] = Field(default_factory=list)
|
|
1601
|
+
principals: list[ServicePrincipalModel | str] = Field(default_factory=list)
|
|
1585
1602
|
entitlements: list[Entitlement]
|
|
1586
1603
|
|
|
1604
|
+
@model_validator(mode="after")
|
|
1605
|
+
def resolve_principals(self) -> Self:
|
|
1606
|
+
"""Resolve ServicePrincipalModel objects to their client_id."""
|
|
1607
|
+
resolved: list[str] = []
|
|
1608
|
+
for principal in self.principals:
|
|
1609
|
+
if isinstance(principal, ServicePrincipalModel):
|
|
1610
|
+
resolved.append(value_of(principal.client_id))
|
|
1611
|
+
else:
|
|
1612
|
+
resolved.append(principal)
|
|
1613
|
+
self.principals = resolved
|
|
1614
|
+
return self
|
|
1615
|
+
|
|
1587
1616
|
|
|
1588
1617
|
class LogLevel(str, Enum):
|
|
1589
1618
|
TRACE = "TRACE"
|
|
@@ -331,13 +331,23 @@ class LanggraphResponsesAgent(ResponsesAgent):
|
|
|
331
331
|
context: Context = self._convert_request_to_context(request)
|
|
332
332
|
custom_inputs: dict[str, Any] = {"configurable": context.model_dump()}
|
|
333
333
|
|
|
334
|
+
# Build the graph input state, including genie_conversation_ids if provided
|
|
335
|
+
graph_input: dict[str, Any] = {"messages": messages}
|
|
336
|
+
if request.custom_inputs and "genie_conversation_ids" in request.custom_inputs:
|
|
337
|
+
graph_input["genie_conversation_ids"] = request.custom_inputs[
|
|
338
|
+
"genie_conversation_ids"
|
|
339
|
+
]
|
|
340
|
+
logger.debug(
|
|
341
|
+
f"Including genie_conversation_ids in graph input: {graph_input['genie_conversation_ids']}"
|
|
342
|
+
)
|
|
343
|
+
|
|
334
344
|
# Use async ainvoke internally for parallel execution
|
|
335
345
|
import asyncio
|
|
336
346
|
|
|
337
347
|
async def _async_invoke():
|
|
338
348
|
try:
|
|
339
349
|
return await self.graph.ainvoke(
|
|
340
|
-
|
|
350
|
+
graph_input, context=context, config=custom_inputs
|
|
341
351
|
)
|
|
342
352
|
except Exception as e:
|
|
343
353
|
logger.error(f"Error in graph.ainvoke: {e}")
|
|
@@ -399,6 +409,16 @@ class LanggraphResponsesAgent(ResponsesAgent):
|
|
|
399
409
|
context: Context = self._convert_request_to_context(request)
|
|
400
410
|
custom_inputs: dict[str, Any] = {"configurable": context.model_dump()}
|
|
401
411
|
|
|
412
|
+
# Build the graph input state, including genie_conversation_ids if provided
|
|
413
|
+
graph_input: dict[str, Any] = {"messages": messages}
|
|
414
|
+
if request.custom_inputs and "genie_conversation_ids" in request.custom_inputs:
|
|
415
|
+
graph_input["genie_conversation_ids"] = request.custom_inputs[
|
|
416
|
+
"genie_conversation_ids"
|
|
417
|
+
]
|
|
418
|
+
logger.debug(
|
|
419
|
+
f"Including genie_conversation_ids in graph input: {graph_input['genie_conversation_ids']}"
|
|
420
|
+
)
|
|
421
|
+
|
|
402
422
|
# Use async astream internally for parallel execution
|
|
403
423
|
import asyncio
|
|
404
424
|
|
|
@@ -408,7 +428,7 @@ class LanggraphResponsesAgent(ResponsesAgent):
|
|
|
408
428
|
|
|
409
429
|
try:
|
|
410
430
|
async for nodes, stream_mode, messages_batch in self.graph.astream(
|
|
411
|
-
|
|
431
|
+
graph_input,
|
|
412
432
|
context=context,
|
|
413
433
|
config=custom_inputs,
|
|
414
434
|
stream_mode=["messages", "custom"],
|
|
@@ -73,6 +73,7 @@ from dao_ai.utils import (
|
|
|
73
73
|
get_installed_packages,
|
|
74
74
|
is_installed,
|
|
75
75
|
is_lib_provided,
|
|
76
|
+
normalize_host,
|
|
76
77
|
normalize_name,
|
|
77
78
|
)
|
|
78
79
|
from dao_ai.vector_search import endpoint_exists, index_exists
|
|
@@ -94,15 +95,18 @@ def _workspace_client(
|
|
|
94
95
|
Create a WorkspaceClient instance with the provided parameters.
|
|
95
96
|
If no parameters are provided, it will use the default configuration.
|
|
96
97
|
"""
|
|
97
|
-
|
|
98
|
+
# Normalize the workspace host to ensure it has https:// scheme
|
|
99
|
+
normalized_host = normalize_host(workspace_host)
|
|
100
|
+
|
|
101
|
+
if client_id and client_secret and normalized_host:
|
|
98
102
|
return WorkspaceClient(
|
|
99
|
-
host=
|
|
103
|
+
host=normalized_host,
|
|
100
104
|
client_id=client_id,
|
|
101
105
|
client_secret=client_secret,
|
|
102
106
|
auth_type="oauth-m2m",
|
|
103
107
|
)
|
|
104
108
|
elif pat:
|
|
105
|
-
return WorkspaceClient(host=
|
|
109
|
+
return WorkspaceClient(host=normalized_host, token=pat, auth_type="pat")
|
|
106
110
|
else:
|
|
107
111
|
return WorkspaceClient()
|
|
108
112
|
|
|
@@ -117,15 +121,18 @@ def _vector_search_client(
|
|
|
117
121
|
Create a VectorSearchClient instance with the provided parameters.
|
|
118
122
|
If no parameters are provided, it will use the default configuration.
|
|
119
123
|
"""
|
|
120
|
-
|
|
124
|
+
# Normalize the workspace host to ensure it has https:// scheme
|
|
125
|
+
normalized_host = normalize_host(workspace_host)
|
|
126
|
+
|
|
127
|
+
if client_id and client_secret and normalized_host:
|
|
121
128
|
return VectorSearchClient(
|
|
122
|
-
workspace_url=
|
|
129
|
+
workspace_url=normalized_host,
|
|
123
130
|
service_principal_client_id=client_id,
|
|
124
131
|
service_principal_client_secret=client_secret,
|
|
125
132
|
)
|
|
126
|
-
elif pat and
|
|
133
|
+
elif pat and normalized_host:
|
|
127
134
|
return VectorSearchClient(
|
|
128
|
-
workspace_url=
|
|
135
|
+
workspace_url=normalized_host,
|
|
129
136
|
personal_access_token=pat,
|
|
130
137
|
)
|
|
131
138
|
else:
|
|
@@ -1151,7 +1158,7 @@ class DatabricksProvider(ServiceProvider):
|
|
|
1151
1158
|
If an explicit version or alias is specified in the prompt_model, uses that directly.
|
|
1152
1159
|
Otherwise, tries to load prompts in this order:
|
|
1153
1160
|
1. champion alias
|
|
1154
|
-
2. latest
|
|
1161
|
+
2. latest alias
|
|
1155
1162
|
3. default alias
|
|
1156
1163
|
4. Register default_template if provided
|
|
1157
1164
|
|
|
@@ -1166,7 +1173,6 @@ class DatabricksProvider(ServiceProvider):
|
|
|
1166
1173
|
"""
|
|
1167
1174
|
|
|
1168
1175
|
prompt_name: str = prompt_model.full_name
|
|
1169
|
-
mlflow_client: MlflowClient = MlflowClient()
|
|
1170
1176
|
|
|
1171
1177
|
# If explicit version or alias is specified, use it directly
|
|
1172
1178
|
if prompt_model.version or prompt_model.alias:
|
|
@@ -1197,19 +1203,13 @@ class DatabricksProvider(ServiceProvider):
|
|
|
1197
1203
|
except Exception as e:
|
|
1198
1204
|
logger.debug(f"Champion alias not found for '{prompt_name}': {e}")
|
|
1199
1205
|
|
|
1200
|
-
# 2. Try
|
|
1206
|
+
# 2. Try latest alias
|
|
1201
1207
|
try:
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
if versions:
|
|
1206
|
-
latest = max(versions, key=lambda v: int(v.version))
|
|
1207
|
-
logger.info(
|
|
1208
|
-
f"Loaded prompt '{prompt_name}' version {latest.version} (latest by max version)"
|
|
1209
|
-
)
|
|
1210
|
-
return latest
|
|
1208
|
+
prompt_version = load_prompt(f"prompts:/{prompt_name}@latest")
|
|
1209
|
+
logger.info(f"Loaded prompt '{prompt_name}' from latest alias")
|
|
1210
|
+
return prompt_version
|
|
1211
1211
|
except Exception as e:
|
|
1212
|
-
logger.debug(f"
|
|
1212
|
+
logger.debug(f"Latest alias not found for '{prompt_name}': {e}")
|
|
1213
1213
|
|
|
1214
1214
|
# 3. Try default alias
|
|
1215
1215
|
try:
|
|
@@ -1225,7 +1225,7 @@ class DatabricksProvider(ServiceProvider):
|
|
|
1225
1225
|
f"No existing prompt found for '{prompt_name}', "
|
|
1226
1226
|
"attempting to register default_template"
|
|
1227
1227
|
)
|
|
1228
|
-
return self.
|
|
1228
|
+
return self._register_default_template(
|
|
1229
1229
|
prompt_name, prompt_model.default_template, prompt_model.description
|
|
1230
1230
|
)
|
|
1231
1231
|
|
|
@@ -1235,49 +1235,17 @@ class DatabricksProvider(ServiceProvider):
|
|
|
1235
1235
|
"and no default_template provided"
|
|
1236
1236
|
)
|
|
1237
1237
|
|
|
1238
|
-
def
|
|
1238
|
+
def _register_default_template(
|
|
1239
1239
|
self, prompt_name: str, default_template: str, description: str | None = None
|
|
1240
1240
|
) -> PromptVersion:
|
|
1241
|
-
"""
|
|
1242
|
-
|
|
1243
|
-
Tries to load prompts in order: champion → latest (max version) → default.
|
|
1244
|
-
If none found and we have write permissions, registers the default_template.
|
|
1245
|
-
If registration fails (e.g., in Model Serving), logs the error and raises.
|
|
1246
|
-
"""
|
|
1247
|
-
mlflow_client: MlflowClient = MlflowClient()
|
|
1248
|
-
|
|
1249
|
-
# Try to find an existing prompt version in priority order
|
|
1250
|
-
# 1. Try champion alias
|
|
1251
|
-
try:
|
|
1252
|
-
champion = mlflow.genai.load_prompt(f"prompts:/{prompt_name}@champion")
|
|
1253
|
-
logger.info(f"Loaded prompt '{prompt_name}' from champion alias")
|
|
1254
|
-
return champion
|
|
1255
|
-
except Exception as e:
|
|
1256
|
-
logger.debug(f"Champion alias not found for '{prompt_name}': {e}")
|
|
1241
|
+
"""Register default_template as a new prompt version.
|
|
1257
1242
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
versions = mlflow_client.search_prompt_versions(
|
|
1261
|
-
prompt_name, max_results=100
|
|
1262
|
-
)
|
|
1263
|
-
if versions:
|
|
1264
|
-
latest = max(versions, key=lambda v: int(v.version))
|
|
1265
|
-
logger.info(
|
|
1266
|
-
f"Loaded prompt '{prompt_name}' version {latest.version} (latest by max version)"
|
|
1267
|
-
)
|
|
1268
|
-
return latest
|
|
1269
|
-
except Exception as e:
|
|
1270
|
-
logger.debug(f"Failed to search versions for '{prompt_name}': {e}")
|
|
1243
|
+
Called when no existing prompt version is found (champion, latest, default all failed).
|
|
1244
|
+
Registers the template and sets both 'default' and 'champion' aliases.
|
|
1271
1245
|
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
logger.info(f"Loaded prompt '{prompt_name}' from default alias")
|
|
1276
|
-
return default
|
|
1277
|
-
except Exception as e:
|
|
1278
|
-
logger.debug(f"Default alias not found for '{prompt_name}': {e}")
|
|
1279
|
-
|
|
1280
|
-
# No existing prompt found - try to register if we have a template
|
|
1246
|
+
If registration fails (e.g., in Model Serving with restricted permissions),
|
|
1247
|
+
logs the error and raises.
|
|
1248
|
+
"""
|
|
1281
1249
|
logger.info(
|
|
1282
1250
|
f"No existing prompt found for '{prompt_name}', attempting to register default_template"
|
|
1283
1251
|
)
|
|
@@ -5,8 +5,9 @@ from typing import Annotated, Any, Callable
|
|
|
5
5
|
|
|
6
6
|
import pandas as pd
|
|
7
7
|
from databricks_ai_bridge.genie import Genie, GenieResponse
|
|
8
|
+
from langchain.tools import tool
|
|
8
9
|
from langchain_core.messages import ToolMessage
|
|
9
|
-
from langchain_core.tools import InjectedToolCallId
|
|
10
|
+
from langchain_core.tools import InjectedToolCallId
|
|
10
11
|
from langgraph.prebuilt import InjectedState
|
|
11
12
|
from langgraph.types import Command
|
|
12
13
|
from loguru import logger
|
|
@@ -43,7 +44,7 @@ def create_genie_tool(
|
|
|
43
44
|
genie_room: GenieRoomModel | dict[str, Any],
|
|
44
45
|
name: str | None = None,
|
|
45
46
|
description: str | None = None,
|
|
46
|
-
persist_conversation: bool =
|
|
47
|
+
persist_conversation: bool = True,
|
|
47
48
|
truncate_results: bool = False,
|
|
48
49
|
) -> Callable[..., Command]:
|
|
49
50
|
"""
|
|
@@ -64,6 +65,16 @@ def create_genie_tool(
|
|
|
64
65
|
Returns:
|
|
65
66
|
A LangGraph tool that processes natural language queries through Genie
|
|
66
67
|
"""
|
|
68
|
+
logger.debug("create_genie_tool")
|
|
69
|
+
logger.debug(f"genie_room type: {type(genie_room)}")
|
|
70
|
+
logger.debug(f"genie_room: {genie_room}")
|
|
71
|
+
logger.debug(f"persist_conversation: {persist_conversation}")
|
|
72
|
+
logger.debug(f"truncate_results: {truncate_results}")
|
|
73
|
+
logger.debug(f"name: {name}")
|
|
74
|
+
logger.debug(f"description: {description}")
|
|
75
|
+
logger.debug(f"genie_room: {genie_room}")
|
|
76
|
+
logger.debug(f"persist_conversation: {persist_conversation}")
|
|
77
|
+
logger.debug(f"truncate_results: {truncate_results}")
|
|
67
78
|
|
|
68
79
|
if isinstance(genie_room, dict):
|
|
69
80
|
genie_room = GenieRoomModel(**genie_room)
|
|
@@ -106,14 +117,13 @@ GenieResponse: A response object containing the conversation ID and result from
|
|
|
106
117
|
state: Annotated[dict, InjectedState],
|
|
107
118
|
tool_call_id: Annotated[str, InjectedToolCallId],
|
|
108
119
|
) -> Command:
|
|
109
|
-
"""Process a natural language question through Databricks Genie."""
|
|
110
|
-
# Create Genie instance using databricks_langchain implementation
|
|
111
120
|
genie: Genie = Genie(
|
|
112
121
|
space_id=space_id,
|
|
113
122
|
client=genie_room.workspace_client,
|
|
114
123
|
truncate_results=truncate_results,
|
|
115
124
|
)
|
|
116
125
|
|
|
126
|
+
"""Process a natural language question through Databricks Genie."""
|
|
117
127
|
# Get existing conversation mapping and retrieve conversation ID for this space
|
|
118
128
|
conversation_ids: dict[str, str] = state.get("genie_conversation_ids", {})
|
|
119
129
|
existing_conversation_id: str | None = conversation_ids.get(space_id)
|
|
@@ -131,6 +141,7 @@ GenieResponse: A response object containing the conversation ID and result from
|
|
|
131
141
|
)
|
|
132
142
|
|
|
133
143
|
# Update the conversation mapping with the new conversation ID for this space
|
|
144
|
+
|
|
134
145
|
update: dict[str, Any] = {
|
|
135
146
|
"messages": [
|
|
136
147
|
ToolMessage(_response_to_json(response), tool_call_id=tool_call_id)
|
|
@@ -15,6 +15,7 @@ from dao_ai.config import (
|
|
|
15
15
|
value_of,
|
|
16
16
|
)
|
|
17
17
|
from dao_ai.tools.human_in_the_loop import as_human_in_the_loop
|
|
18
|
+
from dao_ai.utils import normalize_host
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
def create_uc_tools(
|
|
@@ -299,9 +300,11 @@ def with_partial_args(
|
|
|
299
300
|
if "client_secret" not in resolved_args:
|
|
300
301
|
resolved_args["client_secret"] = value_of(sp.client_secret)
|
|
301
302
|
|
|
302
|
-
# Normalize host/workspace_host - accept either key
|
|
303
|
+
# Normalize host/workspace_host - accept either key, ensure https:// scheme
|
|
303
304
|
if "workspace_host" in resolved_args and "host" not in resolved_args:
|
|
304
|
-
resolved_args["host"] = resolved_args.pop("workspace_host")
|
|
305
|
+
resolved_args["host"] = normalize_host(resolved_args.pop("workspace_host"))
|
|
306
|
+
elif "host" in resolved_args:
|
|
307
|
+
resolved_args["host"] = normalize_host(resolved_args["host"])
|
|
305
308
|
|
|
306
309
|
# Default host from WorkspaceClient if not provided
|
|
307
310
|
if "host" not in resolved_args:
|
|
@@ -20,6 +20,7 @@ from dao_ai.config import (
|
|
|
20
20
|
RetrieverModel,
|
|
21
21
|
VectorStoreModel,
|
|
22
22
|
)
|
|
23
|
+
from dao_ai.utils import normalize_host
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def create_vector_search_tool(
|
|
@@ -108,8 +109,9 @@ def create_vector_search_tool(
|
|
|
108
109
|
# The workspace_client parameter in DatabricksVectorSearch is only used to detect
|
|
109
110
|
# model serving mode - it doesn't pass credentials to VectorSearchClient.
|
|
110
111
|
client_args: dict[str, Any] = {}
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
databricks_host = normalize_host(os.environ.get("DATABRICKS_HOST"))
|
|
113
|
+
if databricks_host:
|
|
114
|
+
client_args["workspace_url"] = databricks_host
|
|
113
115
|
if os.environ.get("DATABRICKS_TOKEN"):
|
|
114
116
|
client_args["personal_access_token"] = os.environ.get("DATABRICKS_TOKEN")
|
|
115
117
|
if os.environ.get("DATABRICKS_CLIENT_ID"):
|
|
@@ -38,6 +38,30 @@ def normalize_name(name: str) -> str:
|
|
|
38
38
|
return normalized.strip("_")
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
def normalize_host(host: str | None) -> str | None:
|
|
42
|
+
"""Ensure host URL has https:// scheme.
|
|
43
|
+
|
|
44
|
+
The DATABRICKS_HOST environment variable should always include the https://
|
|
45
|
+
scheme, but some environments (e.g., Databricks Apps infrastructure) may
|
|
46
|
+
provide the host without it. This function normalizes the host to ensure
|
|
47
|
+
it has the proper scheme.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
host: The host URL, with or without scheme
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
The host URL with https:// scheme, or None if host is None/empty
|
|
54
|
+
"""
|
|
55
|
+
if not host:
|
|
56
|
+
return None
|
|
57
|
+
host = host.strip()
|
|
58
|
+
if not host:
|
|
59
|
+
return None
|
|
60
|
+
if not host.startswith("http://") and not host.startswith("https://"):
|
|
61
|
+
return f"https://{host}"
|
|
62
|
+
return host
|
|
63
|
+
|
|
64
|
+
|
|
41
65
|
def get_default_databricks_host() -> str | None:
|
|
42
66
|
"""Get the default Databricks workspace host.
|
|
43
67
|
|
|
@@ -46,19 +70,19 @@ def get_default_databricks_host() -> str | None:
|
|
|
46
70
|
2. WorkspaceClient ambient authentication (e.g., from ~/.databrickscfg)
|
|
47
71
|
|
|
48
72
|
Returns:
|
|
49
|
-
The Databricks workspace host URL, or None if not available.
|
|
73
|
+
The Databricks workspace host URL (with https:// scheme), or None if not available.
|
|
50
74
|
"""
|
|
51
75
|
# Try environment variable first
|
|
52
76
|
host: str | None = os.environ.get("DATABRICKS_HOST")
|
|
53
77
|
if host:
|
|
54
|
-
return host
|
|
78
|
+
return normalize_host(host)
|
|
55
79
|
|
|
56
80
|
# Fall back to WorkspaceClient
|
|
57
81
|
try:
|
|
58
82
|
from databricks.sdk import WorkspaceClient
|
|
59
83
|
|
|
60
84
|
w: WorkspaceClient = WorkspaceClient()
|
|
61
|
-
return w.config.host
|
|
85
|
+
return normalize_host(w.config.host)
|
|
62
86
|
except Exception:
|
|
63
87
|
logger.debug("Could not get default Databricks host from WorkspaceClient")
|
|
64
88
|
return None
|
|
@@ -26,7 +26,6 @@ from conftest import has_databricks_env
|
|
|
26
26
|
from langchain_core.tools import StructuredTool
|
|
27
27
|
|
|
28
28
|
from dao_ai.config import GenieRoomModel
|
|
29
|
-
from dao_ai.state import SharedState
|
|
30
29
|
from dao_ai.tools.genie import GenieToolInput
|
|
31
30
|
|
|
32
31
|
|
|
@@ -98,19 +97,24 @@ class TestGenieDatabricksIntegration:
|
|
|
98
97
|
RESULT: Tool validation only includes user inputs, not LangGraph injected state
|
|
99
98
|
"""
|
|
100
99
|
|
|
101
|
-
def
|
|
102
|
-
"""Test that the tool
|
|
100
|
+
def test_genie_tool_uses_injected_state_pattern(self, mock_genie_tool):
|
|
101
|
+
"""Test that the tool uses the InjectedState pattern for accessing state."""
|
|
103
102
|
tool = mock_genie_tool
|
|
104
103
|
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
schema = tool.args_schema.model_json_schema()
|
|
108
|
-
properties = schema.get("properties", {})
|
|
104
|
+
# Verify the function signature has injected parameters
|
|
105
|
+
import inspect
|
|
109
106
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
#
|
|
107
|
+
sig = inspect.signature(tool.func)
|
|
108
|
+
params = list(sig.parameters.keys())
|
|
109
|
+
|
|
110
|
+
# With @tool decorator and InjectedState/InjectedToolCallId, the function signature
|
|
111
|
+
# includes question, state, and tool_call_id
|
|
112
|
+
assert "question" in params
|
|
113
|
+
assert "state" in params
|
|
114
|
+
assert "tool_call_id" in params
|
|
115
|
+
|
|
116
|
+
# The InjectedState and InjectedToolCallId parameters will be injected by LangGraph
|
|
117
|
+
# at runtime and hidden from the model
|
|
114
118
|
|
|
115
119
|
def test_genie_tool_input_validation_success(self):
|
|
116
120
|
"""Test that GenieToolInput validates correctly with just question."""
|
|
@@ -177,7 +181,7 @@ class TestGenieDatabricksIntegration:
|
|
|
177
181
|
sig = inspect.signature(tool.func)
|
|
178
182
|
params = list(sig.parameters.keys())
|
|
179
183
|
|
|
180
|
-
# Should have
|
|
184
|
+
# Should have question, state, and tool_call_id parameters
|
|
181
185
|
assert "question" in params
|
|
182
186
|
assert "state" in params
|
|
183
187
|
assert "tool_call_id" in params
|
|
@@ -212,19 +216,16 @@ class TestGenieDatabricksIntegration:
|
|
|
212
216
|
@pytest.mark.skipif(not has_databricks_env(), reason="Databricks env vars not set")
|
|
213
217
|
def test_conversation_persistence_with_injected_state(self, mock_genie_tool):
|
|
214
218
|
"""
|
|
215
|
-
Test that conversation persistence works correctly with
|
|
219
|
+
Test that conversation persistence works correctly with InjectedState pattern.
|
|
216
220
|
|
|
217
221
|
This verifies that the fix doesn't break the core functionality of
|
|
218
222
|
conversation mapping using space_id from the state.
|
|
219
223
|
"""
|
|
220
|
-
# Create
|
|
221
|
-
mock_state =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
config=Mock(),
|
|
226
|
-
user_id="test-user",
|
|
227
|
-
)
|
|
224
|
+
# Create a mock state dict
|
|
225
|
+
mock_state = {
|
|
226
|
+
"genie_conversation_ids": {"test-space-123": "existing-conversation-id"},
|
|
227
|
+
"messages": [],
|
|
228
|
+
}
|
|
228
229
|
|
|
229
230
|
# Use the fixture genie tool
|
|
230
231
|
tool = mock_genie_tool
|
|
@@ -243,13 +244,12 @@ class TestGenieDatabricksIntegration:
|
|
|
243
244
|
assert result.update is not None
|
|
244
245
|
assert "genie_conversation_ids" in result.update
|
|
245
246
|
|
|
246
|
-
def
|
|
247
|
+
def test_injected_state_pattern(self, mock_genie_tool):
|
|
247
248
|
"""
|
|
248
|
-
Test that
|
|
249
|
+
Test that the tool uses the InjectedState pattern.
|
|
249
250
|
|
|
250
|
-
The
|
|
251
|
-
|
|
252
|
-
to be provided by the user.
|
|
251
|
+
The InjectedState and InjectedToolCallId annotations provide access
|
|
252
|
+
to state and tool_call_id through LangGraph's dependency injection.
|
|
253
253
|
"""
|
|
254
254
|
tool = mock_genie_tool
|
|
255
255
|
|
|
@@ -263,13 +263,13 @@ class TestGenieDatabricksIntegration:
|
|
|
263
263
|
sig = inspect.signature(tool.func)
|
|
264
264
|
params = list(sig.parameters.keys())
|
|
265
265
|
|
|
266
|
-
#
|
|
266
|
+
# Should have question, state, and tool_call_id parameters
|
|
267
267
|
assert "question" in params
|
|
268
268
|
assert "state" in params
|
|
269
269
|
assert "tool_call_id" in params
|
|
270
270
|
|
|
271
|
-
# The
|
|
272
|
-
#
|
|
271
|
+
# The InjectedState and InjectedToolCallId annotations tell LangGraph
|
|
272
|
+
# to inject these parameters at runtime
|
|
273
273
|
|
|
274
274
|
|
|
275
275
|
if __name__ == "__main__":
|