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.
Files changed (361) hide show
  1. {dao_ai-0.0.33 → dao_ai-0.0.35}/PKG-INFO +1 -1
  2. {dao_ai-0.0.33 → dao_ai-0.0.35}/environment.yaml +1 -1
  3. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/05_deploy_agent.py +1 -1
  4. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/99_scratchpad.py +1 -1
  5. {dao_ai-0.0.33 → dao_ai-0.0.35}/pyproject.toml +1 -1
  6. {dao_ai-0.0.33 → dao_ai-0.0.35}/requirements.txt +0 -1
  7. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/config.py +35 -6
  8. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/models.py +22 -2
  9. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/providers/databricks.py +28 -60
  10. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/genie.py +15 -4
  11. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/unity_catalog.py +5 -2
  12. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/vector_search.py +4 -2
  13. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/utils.py +27 -3
  14. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_genie_databricks_integration.py +29 -29
  15. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_prompts.py +39 -94
  16. {dao_ai-0.0.33 → dao_ai-0.0.35}/.gitignore +0 -0
  17. {dao_ai-0.0.33 → dao_ai-0.0.35}/.python-version +0 -0
  18. {dao_ai-0.0.33 → dao_ai-0.0.35}/CHANGELOG.md +0 -0
  19. {dao_ai-0.0.33 → dao_ai-0.0.35}/CONTRIBUTING.md +0 -0
  20. {dao_ai-0.0.33 → dao_ai-0.0.35}/LICENSE +0 -0
  21. {dao_ai-0.0.33 → dao_ai-0.0.35}/Makefile +0 -0
  22. {dao_ai-0.0.33 → dao_ai-0.0.35}/README.md +0 -0
  23. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/Makefile +0 -0
  24. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/REFACTORING_SUMMARY.md +0 -0
  25. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/base-environment-serverless.yaml +0 -0
  26. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/demo_docs/BRAND_REP_DEMO_SUMMARY.md +0 -0
  27. {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
  28. {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
  29. {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
  30. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/development_workflows.md +0 -0
  31. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/.gitkeep +0 -0
  32. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/Makefile +0 -0
  33. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agent_implementation.mmd +0 -0
  34. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agent_tools_architecture.mmd +0 -0
  35. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agent-troubleshooting.md +0 -0
  36. {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
  37. {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
  38. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agents/agent-performance.md +0 -0
  39. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/agents/agent-quickstart.md +0 -0
  40. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/ai-agents.md +0 -0
  41. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/overview.md +0 -0
  42. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/references/agent-reference.md +0 -0
  43. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/agents-and-tools/references/tools-reference.md +0 -0
  44. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/applications/streamlit-app.md +0 -0
  45. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/architecture/overview.md +0 -0
  46. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/architecture.mmd +0 -0
  47. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/architecture.png +0 -0
  48. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/customer_preparation_guide.md +0 -0
  49. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/databricks_integration.mmd +0 -0
  50. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/deployment/production.md +0 -0
  51. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/development/contributing.md +0 -0
  52. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/employee_tools_guide.md +0 -0
  53. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/getting-started/installation.md +0 -0
  54. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/getting-started/mkdocs-quickstart.md +0 -0
  55. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/getting-started/quick-start.md +0 -0
  56. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/index.md +0 -0
  57. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/mkdocs.yml +0 -0
  58. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/scenario_1_architecture.mmd +0 -0
  59. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/scenario_1_flow.mmd +0 -0
  60. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/setup-docs.sh +0 -0
  61. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/task_assignment_workflow_guide.md +0 -0
  62. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/docs/tools/overview.md +0 -0
  63. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/examples/customer_preparation_workflow.py +0 -0
  64. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/examples/task_assignment_workflow.py +0 -0
  65. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/load-env.sh +0 -0
  66. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/CSS_REFACTORING_SUMMARY.md +0 -0
  67. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/DEMO_CONTROLS_RESTORED.md +0 -0
  68. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/DEMO_IMPLEMENTATION_SUMMARY.md +0 -0
  69. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/DEMO_QUICK_START.md +0 -0
  70. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/Dockerfile +0 -0
  71. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/HOMEPAGE_README.md +0 -0
  72. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/Makefile +0 -0
  73. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/README.md +0 -0
  74. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/app.py +0 -0
  75. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/app.yaml +0 -0
  76. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/__init__.py +0 -0
  77. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/backup_homepage.py +0 -0
  78. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/chat.py +0 -0
  79. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/enhanced_charts.py +0 -0
  80. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/enhanced_navigation.py +0 -0
  81. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/__init__.py +0 -0
  82. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/associate/__init__.py +0 -0
  83. {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
  84. {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
  85. {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
  86. {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
  87. {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
  88. {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
  89. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/common/__init__.py +0 -0
  90. {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
  91. {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
  92. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/common/notifications.py +0 -0
  93. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/homepage/homepage.py +0 -0
  94. {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
  95. {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
  96. {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
  97. {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
  98. {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
  99. {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
  100. {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
  101. {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
  102. {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
  103. {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
  104. {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
  105. {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
  106. {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
  107. {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
  108. {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
  109. {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
  110. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/metrics.py +0 -0
  111. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/navigation.py +0 -0
  112. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/oldhomepage.py +0 -0
  113. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/components/styles.py +0 -0
  114. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/config.yaml +0 -0
  115. {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
  116. {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
  117. {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
  118. {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
  119. {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
  120. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/README.md +0 -0
  121. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/__init__.py +0 -0
  122. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/components/__init__.py +0 -0
  123. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/components/dashboard_card.py +0 -0
  124. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/demo_alerts.py +0 -0
  125. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/dev/examples/sample_dashboard.py +0 -0
  126. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/__init__.py +0 -0
  127. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/component_showcase.py +0 -0
  128. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/dev_playground.py +0 -0
  129. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages/playground.py +0 -0
  130. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/daily_operations.py +0 -0
  131. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/inventory.py +0 -0
  132. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/my_schedule.py +0 -0
  133. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/my_tasks.py +0 -0
  134. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/orders.py +0 -0
  135. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/products_promotions.py +0 -0
  136. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/staff.py +0 -0
  137. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pages_wip/team_insights.py +0 -0
  138. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/pyproject.toml +0 -0
  139. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/requirements.txt +0 -0
  140. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/static/css/style.css +0 -0
  141. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/README.md +0 -0
  142. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/__init__.py +0 -0
  143. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/base.py +0 -0
  144. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/components.py +0 -0
  145. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/dashboard.py +0 -0
  146. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/homepage.py +0 -0
  147. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/styles/theme.py +0 -0
  148. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/test_vip_notification.py +0 -0
  149. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/tests/test_calculations.py +0 -0
  150. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/config.py +0 -0
  151. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/database.py +0 -0
  152. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/model_serving.py +0 -0
  153. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app/utils/store_context.py +0 -0
  154. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/Makefile +0 -0
  155. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/README.md +0 -0
  156. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/app.py +0 -0
  157. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/components/tailadmin/__init__.py +0 -0
  158. {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
  159. {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
  160. {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
  161. {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
  162. {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
  163. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/TAILADMIN_README.md +0 -0
  164. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/homepage_tailadmin.py +0 -0
  165. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/old/tailadmin_demo.py +0 -0
  166. {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
  167. {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
  168. {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
  169. {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
  170. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/components_demo.py +0 -0
  171. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/homepage.py +0 -0
  172. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pages/implementation_guide.py +0 -0
  173. {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
  174. {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
  175. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/pyproject.toml +0 -0
  176. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/tests/__init__.py +0 -0
  177. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/streamlit_store_app_tailadmin/tests/test_imports.py +0 -0
  178. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/.gitkeep +0 -0
  179. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/README.md +0 -0
  180. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/images/doritos_upc.png +0 -0
  181. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/images/lays_upc.png +0 -0
  182. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/manager_demo_script.md +0 -0
  183. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/notebook_vector_search_test.py +0 -0
  184. {dao_ai-0.0.33 → dao_ai-0.0.35}/apps/dais2025/store-app/tests/test_vector_search_integration.py +0 -0
  185. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/dais2025/model_config_dais.yaml +0 -0
  186. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/deep_research.yaml +0 -0
  187. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/executive_assistant.yaml +0 -0
  188. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie.yaml +0 -0
  189. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie_and_genie_mcp.yaml +0 -0
  190. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie_and_vector_search.yaml +0 -0
  191. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/genie_with_conversion_id.yaml +0 -0
  192. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/human_in_the_loop.yaml +0 -0
  193. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/jira.yaml +0 -0
  194. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/mcp.yaml +0 -0
  195. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/mcp_with_uc_connection.yaml +0 -0
  196. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/minimal.yaml +0 -0
  197. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/prompt_optimization.yaml +0 -0
  198. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/prompt_registry.yaml +0 -0
  199. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/reservations.yaml +0 -0
  200. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/slack.yaml +0 -0
  201. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/examples/vector_search_with_reranking.yaml +0 -0
  202. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/hardware_store/supervisor.yaml +0 -0
  203. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/hardware_store/supervisor_postgres.yaml +0 -0
  204. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/hardware_store/swarm.yaml +0 -0
  205. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/quick_serve_restaurant/.gitkeep +0 -0
  206. {dao_ai-0.0.33 → dao_ai-0.0.35}/config/quick_serve_restaurant/quick-serve-restaurant.yaml +0 -0
  207. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/appointments.sql +0 -0
  208. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/appointments_data.sql +0 -0
  209. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_data.sql +0 -0
  210. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_queries.sql +0 -0
  211. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_tables.sql +0 -0
  212. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/brand_rep_demo_validation.sql +0 -0
  213. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/customers.sql +0 -0
  214. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/customers_data.sql +0 -0
  215. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/dim_stores.sql +0 -0
  216. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/dim_stores_data.sql +0 -0
  217. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_performance.sql +0 -0
  218. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_performance_data.sql +0 -0
  219. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_tasks.sql +0 -0
  220. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/employee_tasks_data.sql +0 -0
  221. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/inventory.sql +0 -0
  222. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/inventory_data.sql +0 -0
  223. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/managers.sql +0 -0
  224. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/managers_data.sql +0 -0
  225. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/product_data.sql +0 -0
  226. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/products.sql +0 -0
  227. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/dais2025/task_assignments.sql +0 -0
  228. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/inventory.snappy.parquet +0 -0
  229. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/inventory.sql +0 -0
  230. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/products.snappy.parquet +0 -0
  231. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/hardware_store/products.sql +0 -0
  232. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/.gitkeep +0 -0
  233. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/fulfil_item_orders.sql +0 -0
  234. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_description.csv +0 -0
  235. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_description.sql +0 -0
  236. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_raw.csv +0 -0
  237. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/items_raw.sql +0 -0
  238. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/orders_raw.csv +0 -0
  239. {dao_ai-0.0.33 → dao_ai-0.0.35}/data/quick_serve_restaurant/orders_raw.sql +0 -0
  240. {dao_ai-0.0.33 → dao_ai-0.0.35}/databricks.yaml.template +0 -0
  241. {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/genie.png +0 -0
  242. {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/hardware_store/README.md +0 -0
  243. {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/hardware_store/retail_supervisor.png +0 -0
  244. {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/hardware_store/retail_swarm.png +0 -0
  245. {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/quick_serve_restaurant/.gitkeep +0 -0
  246. {dao_ai-0.0.33 → dao_ai-0.0.35}/docs/quick_serve_restaurant/quick-serve-restaurant.png +0 -0
  247. {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/dais2025/examples.yaml +0 -0
  248. {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/deep_research/examples.yaml +0 -0
  249. {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/executive_assistant/examples.yaml +0 -0
  250. {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/hardware_store/examples.yaml +0 -0
  251. {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/quick_serve_restaurant/.gitkeep +0 -0
  252. {dao_ai-0.0.33 → dao_ai-0.0.35}/examples/quick_serve_restaurant/examples.yaml +0 -0
  253. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/extract_store_numbers.sql +0 -0
  254. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_inventory_by_sku.sql +0 -0
  255. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_inventory_by_upc.sql +0 -0
  256. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_product_by_sku.sql +0 -0
  257. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_product_by_upc.sql +0 -0
  258. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_store_by_number.sql +0 -0
  259. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_store_inventory_by_sku.sql +0 -0
  260. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/dais2025/find_store_inventory_by_upc.sql +0 -0
  261. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_inventory_by_sku.sql +0 -0
  262. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_inventory_by_upc.sql +0 -0
  263. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_product_by_sku.sql +0 -0
  264. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_product_by_upc.sql +0 -0
  265. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_store_inventory_by_sku.sql +0 -0
  266. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/hardware_store/find_store_inventory_by_upc.sql +0 -0
  267. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/.gitkeep +0 -0
  268. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/insert_coffee_order.sql +0 -0
  269. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/lookup_items_by_descriptions.sql +0 -0
  270. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/match_historical_item_order_by_date.sql +0 -0
  271. {dao_ai-0.0.33 → dao_ai-0.0.35}/functions/quick_serve_restaurant/match_item_by_description_and_price.sql +0 -0
  272. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/01_ingest_and_transform.py +0 -0
  273. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/02_provision_vector_search.py +0 -0
  274. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/03_provision_lakebase.py +0 -0
  275. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/04_unity_catalog_tools.py +0 -0
  276. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/06_generate_evaluation_data.py +0 -0
  277. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/07_run_evaluation.py +0 -0
  278. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/08_run_examples.py +0 -0
  279. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/09_evaluate_inferences.py +0 -0
  280. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/10_optimize_prompts.py +0 -0
  281. {dao_ai-0.0.33 → dao_ai-0.0.35}/notebooks/INVESTech.py +0 -0
  282. {dao_ai-0.0.33 → dao_ai-0.0.35}/schemas/bundle_config_schema.json +0 -0
  283. {dao_ai-0.0.33 → dao_ai-0.0.35}/schemas/model_config_schema.json +0 -0
  284. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/__init__.py +0 -0
  285. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/models.py +0 -0
  286. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/__init__.py +0 -0
  287. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/customer.py +0 -0
  288. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/employee.py +0 -0
  289. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/executive.py +0 -0
  290. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/genie.py +0 -0
  291. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/inventory.py +0 -0
  292. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/models.py +0 -0
  293. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dais2025/tools/store.py +0 -0
  294. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/__init__.py +0 -0
  295. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/agent_as_code.py +0 -0
  296. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/catalog.py +0 -0
  297. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/chat_models.py +0 -0
  298. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/cli.py +0 -0
  299. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/graph.py +0 -0
  300. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/guardrails.py +0 -0
  301. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/hooks/__init__.py +0 -0
  302. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/hooks/core.py +0 -0
  303. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/__init__.py +0 -0
  304. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/base.py +0 -0
  305. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/core.py +0 -0
  306. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/memory/postgres.py +0 -0
  307. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/messages.py +0 -0
  308. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/nodes.py +0 -0
  309. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/prompts.py +0 -0
  310. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/providers/__init__.py +0 -0
  311. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/providers/base.py +0 -0
  312. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/state.py +0 -0
  313. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/__init__.py +0 -0
  314. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/agent.py +0 -0
  315. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/core.py +0 -0
  316. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/human_in_the_loop.py +0 -0
  317. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/mcp.py +0 -0
  318. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/python.py +0 -0
  319. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/slack.py +0 -0
  320. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/tools/time.py +0 -0
  321. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/types.py +0 -0
  322. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/dao_ai/vector_search.py +0 -0
  323. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/hardware_store/__init__.py +0 -0
  324. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/hardware_store/hooks.py +0 -0
  325. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/hardware_store/tools.py +0 -0
  326. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/quick_serve_restaurant/.gitkeep +0 -0
  327. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/quick_serve_restaurant/__init__.py +0 -0
  328. {dao_ai-0.0.33 → dao_ai-0.0.35}/src/quick_serve_restaurant/tools.py +0 -0
  329. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/config/test_model_config.yaml +0 -0
  330. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/conftest.py +0 -0
  331. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_catalog.py +0 -0
  332. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_chat_history.py +0 -0
  333. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_config.py +0 -0
  334. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_databricks.py +0 -0
  335. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_function_parsing.py +0 -0
  336. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_genie.py +0 -0
  337. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_genie_conversation_ids_in_outputs.py +0 -0
  338. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_hooks.py +0 -0
  339. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_inference.py +0 -0
  340. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_inference_integration.py +0 -0
  341. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_mcp.py +0 -0
  342. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_mcp_function_model.py +0 -0
  343. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_messages.py +0 -0
  344. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_models.py +0 -0
  345. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_postgres_integration.py +0 -0
  346. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_prompt_optimizations.py +0 -0
  347. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_reranking.py +0 -0
  348. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_reranking_integration.py +0 -0
  349. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_state.py +0 -0
  350. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_summarization_inference.py +0 -0
  351. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_tools.py +0 -0
  352. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_types.py +0 -0
  353. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_unity_catalog.py +0 -0
  354. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_utils.py +0 -0
  355. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/test_vector_search.py +0 -0
  356. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/dao_ai/weather_server_mcp.py +0 -0
  357. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/hardware_store/.gitkeep +0 -0
  358. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/hardware_store/test_graph.py +0 -0
  359. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/images/doritos_upc.png +0 -0
  360. {dao_ai-0.0.33 → dao_ai-0.0.35}/tests/images/lays_upc.png +0 -0
  361. {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.33
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
@@ -59,7 +59,7 @@ dependencies:
59
59
  - flask-cors==6.0.1
60
60
  - gunicorn==23.0.0
61
61
  # Search and tools
62
- - duckduckgo-search==8.0.4
62
+ - ddgs==9.9.3
63
63
  - flashrank==0.2.8
64
64
  - litellm==1.75.9
65
65
  # Utilities
@@ -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"duckduckgo-search=={version('duckduckgo-search')}",
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"duckduckgo-search=={version('duckduckgo-search')}",
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.33"
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" }
@@ -55,7 +55,6 @@ grandalf==0.8
55
55
  graphene==3.4.3
56
56
  graphql-core==3.2.6
57
57
  graphql-relay==3.2.0
58
- greenlet==3.2.3
59
58
  grpcio==1.73.0
60
59
  grpcio-status==1.71.0
61
60
  gunicorn==23.0.0
@@ -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) if self.workspace_host else None
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 = self.connection.workspace_client.config.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
- {"messages": messages}, context=context, config=custom_inputs
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
- {"messages": messages},
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
- if client_id and client_secret and workspace_host:
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=workspace_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=workspace_host, token=pat, auth_type="pat")
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
- if client_id and client_secret and workspace_host:
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=workspace_host,
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 workspace_host:
133
+ elif pat and normalized_host:
127
134
  return VectorSearchClient(
128
- workspace_url=workspace_host,
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 version (max version number from search_prompt_versions)
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 to get latest version by finding the max version number
1206
+ # 2. Try latest alias
1201
1207
  try:
1202
- versions = mlflow_client.search_prompt_versions(
1203
- prompt_name, max_results=100
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"Failed to find latest version for '{prompt_name}': {e}")
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._sync_default_template_to_registry(
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 _sync_default_template_to_registry(
1238
+ def _register_default_template(
1239
1239
  self, prompt_name: str, default_template: str, description: str | None = None
1240
1240
  ) -> PromptVersion:
1241
- """Get the best available prompt version, or register default_template if possible.
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
- # 2. Try to get the latest version by finding the max version number
1259
- try:
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
- # 3. Try default alias
1273
- try:
1274
- default = mlflow.genai.load_prompt(f"prompts:/{prompt_name}@default")
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, tool
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 = False,
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
- if os.environ.get("DATABRICKS_HOST"):
112
- client_args["workspace_url"] = os.environ.get("DATABRICKS_HOST")
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 test_genie_tool_schema_excludes_injected_parameters(self, mock_genie_tool):
102
- """Test that the tool schema properly marks injected parameters using Annotated."""
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
- # The @tool decorator creates its own schema, but it should have injected parameters marked
106
- # Verify the schema includes all parameters
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
- # With @tool decorator, all parameters are in schema but injected ones are marked with Annotated
111
- assert "question" in properties
112
- # Note: With @tool decorator, state and tool_call_id may appear in schema
113
- # but they're marked as injected via Annotated types
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 all three parameters: question, state, tool_call_id
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 injected state pattern.
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 state with conversation mapping
221
- mock_state = SharedState(
222
- context={},
223
- conversations={"test-space-123": "existing-conversation-id"},
224
- messages=[],
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 test_original_error_reproduction_prevention(self, mock_genie_tool):
247
+ def test_injected_state_pattern(self, mock_genie_tool):
247
248
  """
248
- Test that demonstrates the original error is prevented by using @tool decorator.
249
+ Test that the tool uses the InjectedState pattern.
249
250
 
250
- The @tool decorator with Annotated types (InjectedState, InjectedToolCallId)
251
- tells LangGraph to inject these parameters at runtime, so they don't need
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
- # All parameters should be present in signature
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 key fix: Using Annotated with InjectedState and InjectedToolCallId
272
- # tells LangGraph to inject these at runtime, preventing validation errors
271
+ # The InjectedState and InjectedToolCallId annotations tell LangGraph
272
+ # to inject these parameters at runtime
273
273
 
274
274
 
275
275
  if __name__ == "__main__":