dao-ai 0.0.34__py3-none-any.whl → 0.0.35__py3-none-any.whl

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/config.py CHANGED
@@ -1192,21 +1192,26 @@ class McpFunctionModel(BaseFunctionModel, HasFullName):
1192
1192
  Otherwise, falls back to the default Databricks host.
1193
1193
 
1194
1194
  Returns:
1195
- str: The workspace host URL without trailing slash
1195
+ str: The workspace host URL with https:// scheme and without trailing slash
1196
1196
  """
1197
- from dao_ai.utils import get_default_databricks_host
1197
+ from dao_ai.utils import get_default_databricks_host, normalize_host
1198
1198
 
1199
1199
  # Try to get workspace_host from config
1200
1200
  workspace_host: str | None = (
1201
- 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
1202
1204
  )
1203
1205
 
1204
1206
  # If no workspace_host in config, get it from workspace client
1205
1207
  if not workspace_host:
1206
1208
  # Use connection's workspace client if available
1207
1209
  if self.connection:
1208
- workspace_host = self.connection.workspace_client.config.host
1210
+ workspace_host = normalize_host(
1211
+ self.connection.workspace_client.config.host
1212
+ )
1209
1213
  else:
1214
+ # get_default_databricks_host already normalizes the host
1210
1215
  workspace_host = get_default_databricks_host()
1211
1216
 
1212
1217
  if not workspace_host:
@@ -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:
@@ -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"):
dao_ai/utils.py CHANGED
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dao-ai
3
- Version: 0.0.34
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
@@ -3,7 +3,7 @@ dao_ai/agent_as_code.py,sha256=sviZQV7ZPxE5zkZ9jAbfegI681nra5i8yYxw05e3X7U,552
3
3
  dao_ai/catalog.py,sha256=sPZpHTD3lPx4EZUtIWeQV7VQM89WJ6YH__wluk1v2lE,4947
4
4
  dao_ai/chat_models.py,sha256=uhwwOTeLyHWqoTTgHrs4n5iSyTwe4EQcLKnh3jRxPWI,8626
5
5
  dao_ai/cli.py,sha256=gq-nsapWxDA1M6Jua3vajBvIwf0Oa6YLcB58lEtMKUo,22503
6
- dao_ai/config.py,sha256=Jzb0ePrt2TM2WuXI_LtmTafbseKBlJ8J8J2ExyBowbM,79491
6
+ dao_ai/config.py,sha256=57oObqVD7OHYJ1ZWHFzSgYa1EOh6tGiJ_nuKl5_-iCc,79700
7
7
  dao_ai/graph.py,sha256=9kjJx0oFZKq5J9-Kpri4-0VCJILHYdYyhqQnj0_noxQ,8913
8
8
  dao_ai/guardrails.py,sha256=4TKArDONRy8RwHzOT1plZ1rhy3x9GF_aeGpPCRl6wYA,4016
9
9
  dao_ai/messages.py,sha256=xl_3-WcFqZKCFCiov8sZOPljTdM3gX3fCHhxq-xFg2U,7005
@@ -12,7 +12,7 @@ dao_ai/nodes.py,sha256=iQ_5vL6mt1UcRnhwgz-l1D8Ww4CMQrSMVnP_Lu7fFjU,8781
12
12
  dao_ai/prompts.py,sha256=iA2Iaky7yzjwWT5cxg0cUIgwo1z1UVQua__8WPnvV6g,1633
13
13
  dao_ai/state.py,sha256=_lF9krAYYjvFDMUwZzVKOn0ZnXKcOrbjWKdre0C5B54,1137
14
14
  dao_ai/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- dao_ai/utils.py,sha256=oIPmz02kZ3LMntbqxUajFXh4nswOhbvEjOTi4e5_cvI,8500
15
+ dao_ai/utils.py,sha256=6gmcu2cu4WE2wfrVj45auPxISJ2y0lmyFZisbilB4kQ,9297
16
16
  dao_ai/vector_search.py,sha256=jlaFS_iizJ55wblgzZmswMM3UOL-qOp2BGJc0JqXYSg,2839
17
17
  dao_ai/hooks/__init__.py,sha256=LlHGIuiZt6vGW8K5AQo1XJEkBP5vDVtMhq0IdjcLrD4,417
18
18
  dao_ai/hooks/core.py,sha256=ZShHctUSoauhBgdf1cecy9-D7J6-sGn-pKjuRMumW5U,6663
@@ -22,7 +22,7 @@ dao_ai/memory/core.py,sha256=DnEjQO3S7hXr3CDDd7C2eE7fQUmcCS_8q9BXEgjPH3U,4271
22
22
  dao_ai/memory/postgres.py,sha256=vvI3osjx1EoU5GBA6SCUstTBKillcmLl12hVgDMjfJY,15346
23
23
  dao_ai/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  dao_ai/providers/base.py,sha256=-fjKypCOk28h6vioPfMj9YZSw_3Kcbi2nMuAyY7vX9k,1383
25
- dao_ai/providers/databricks.py,sha256=WEigNPGRTlIPVjwp97My8o1zOHn5ftuMsMrpqrBeaLg,66012
25
+ dao_ai/providers/databricks.py,sha256=t9a3QBQ0v_14PbUtYRj2My423OskDj3VQ9b19vuAeco,66283
26
26
  dao_ai/tools/__init__.py,sha256=G5-5Yi6zpQOH53b5IzLdtsC6g0Ep6leI5GxgxOmgw7Q,1203
27
27
  dao_ai/tools/agent.py,sha256=WbQnyziiT12TLMrA7xK0VuOU029tdmUBXbUl-R1VZ0Q,1886
28
28
  dao_ai/tools/core.py,sha256=kN77fWOzVY7qOs4NiW72cUxCsSTC0DnPp73s6VJEZOQ,1991
@@ -32,10 +32,10 @@ dao_ai/tools/mcp.py,sha256=5aQoRtx2z4xm6zgRslc78rSfEQe-mfhqov2NsiybYfc,8416
32
32
  dao_ai/tools/python.py,sha256=XcQiTMshZyLUTVR5peB3vqsoUoAAy8gol9_pcrhddfI,1831
33
33
  dao_ai/tools/slack.py,sha256=SCvyVcD9Pv_XXPXePE_fSU1Pd8VLTEkKDLvoGTZWy2Y,4775
34
34
  dao_ai/tools/time.py,sha256=Y-23qdnNHzwjvnfkWvYsE7PoWS1hfeKy44tA7sCnNac,8759
35
- dao_ai/tools/unity_catalog.py,sha256=K9t8M4spsbxbecWmV5yEZy16s_AG7AfaoxT-7IDW43I,14438
36
- dao_ai/tools/vector_search.py,sha256=3cdiUaFpox25GSRNec7FKceY3DuLp7dLVH8FRA0BgeY,12624
37
- dao_ai-0.0.34.dist-info/METADATA,sha256=vq51NEV-pg7WTOD5z56jyOrC5_6Q-nUIL51RI5lL-Hg,42761
38
- dao_ai-0.0.34.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
39
- dao_ai-0.0.34.dist-info/entry_points.txt,sha256=Xa-UFyc6gWGwMqMJOt06ZOog2vAfygV_DSwg1AiP46g,43
40
- dao_ai-0.0.34.dist-info/licenses/LICENSE,sha256=YZt3W32LtPYruuvHE9lGk2bw6ZPMMJD8yLrjgHybyz4,1069
41
- dao_ai-0.0.34.dist-info/RECORD,,
35
+ dao_ai/tools/unity_catalog.py,sha256=eB-7lrRqtf47rQab3WPdJiuJGDQzW3mLJUc9-oCm3j8,14622
36
+ dao_ai/tools/vector_search.py,sha256=VnDNhVbDKiG6COhX9Eh44X79yfbi3AEC2eGBvPC6gv0,12700
37
+ dao_ai-0.0.35.dist-info/METADATA,sha256=MPVim3KsOASWHmuVjKjRQIvl_CW1LldpQVysKNjudwM,42761
38
+ dao_ai-0.0.35.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
39
+ dao_ai-0.0.35.dist-info/entry_points.txt,sha256=Xa-UFyc6gWGwMqMJOt06ZOog2vAfygV_DSwg1AiP46g,43
40
+ dao_ai-0.0.35.dist-info/licenses/LICENSE,sha256=YZt3W32LtPYruuvHE9lGk2bw6ZPMMJD8yLrjgHybyz4,1069
41
+ dao_ai-0.0.35.dist-info/RECORD,,