dao-ai 0.1.2__py3-none-any.whl → 0.1.5__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.
@@ -150,7 +150,7 @@ def create_summarization_middleware(
150
150
  chat_history: ChatHistoryModel configuration for summarization
151
151
 
152
152
  Returns:
153
- LoggingSummarizationMiddleware configured with the specified parameters
153
+ List containing LoggingSummarizationMiddleware configured with the specified parameters
154
154
 
155
155
  Example:
156
156
  from dao_ai.config import ChatHistoryModel, LLMModel
@@ -0,0 +1,210 @@
1
+ """
2
+ Tool call limit middleware for DAO AI agents.
3
+
4
+ This module provides a factory for creating LangChain's ToolCallLimitMiddleware
5
+ from DAO AI configuration.
6
+
7
+ Example:
8
+ from dao_ai.middleware import create_tool_call_limit_middleware
9
+
10
+ # Global limit across all tools
11
+ middleware = create_tool_call_limit_middleware(
12
+ thread_limit=20,
13
+ run_limit=10,
14
+ )
15
+
16
+ # Limit specific tool by name
17
+ search_limiter = create_tool_call_limit_middleware(
18
+ tool="search_web",
19
+ run_limit=3,
20
+ exit_behavior="continue",
21
+ )
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any, Literal
27
+
28
+ from langchain.agents.middleware import ToolCallLimitMiddleware
29
+ from langchain_core.tools import BaseTool
30
+ from loguru import logger
31
+
32
+ from dao_ai.config import BaseFunctionModel, ToolModel
33
+
34
+ __all__ = [
35
+ "ToolCallLimitMiddleware",
36
+ "create_tool_call_limit_middleware",
37
+ ]
38
+
39
+
40
+ def _resolve_tool(tool: str | ToolModel | dict[str, Any]) -> list[str]:
41
+ """
42
+ Resolve tool argument to a list of actual tool names.
43
+
44
+ Args:
45
+ tool: String name, ToolModel, or dict to resolve
46
+
47
+ Returns:
48
+ List of tool name strings
49
+
50
+ Raises:
51
+ ValueError: If dict cannot be converted to ToolModel
52
+ TypeError: If tool is not a supported type
53
+ """
54
+ # String: return as single-item list
55
+ if isinstance(tool, str):
56
+ return [tool]
57
+
58
+ # Dict: convert to ToolModel first
59
+ if isinstance(tool, dict):
60
+ try:
61
+ tool_model = ToolModel(**tool)
62
+ except Exception as e:
63
+ raise ValueError(
64
+ f"Failed to construct ToolModel from dict: {e}\n"
65
+ f"Dict must have 'name' and 'function' keys."
66
+ ) from e
67
+ elif isinstance(tool, ToolModel):
68
+ tool_model = tool
69
+ else:
70
+ raise TypeError(
71
+ f"tool must be str, ToolModel, or dict, got {type(tool).__name__}"
72
+ )
73
+
74
+ # Extract tool names from ToolModel
75
+ return _extract_tool_names(tool_model)
76
+
77
+
78
+ def _extract_tool_names(tool_model: ToolModel) -> list[str]:
79
+ """
80
+ Extract actual tool names from a ToolModel.
81
+
82
+ A single ToolModel can produce multiple tools (e.g., UC functions).
83
+ Falls back to ToolModel.name if extraction fails.
84
+ """
85
+ function = tool_model.function
86
+
87
+ # String function references can't be introspected
88
+ if not isinstance(function, BaseFunctionModel):
89
+ logger.debug(
90
+ "Cannot extract names from string function, using ToolModel.name",
91
+ tool_model_name=tool_model.name,
92
+ )
93
+ return [tool_model.name]
94
+
95
+ # Try to extract names from created tools
96
+ try:
97
+ tool_names = [
98
+ tool.name
99
+ for tool in function.as_tools()
100
+ if isinstance(tool, BaseTool) and tool.name
101
+ ]
102
+ if tool_names:
103
+ logger.trace(
104
+ "Extracted tool names",
105
+ tool_model_name=tool_model.name,
106
+ tool_names=tool_names,
107
+ )
108
+ return tool_names
109
+ except Exception as e:
110
+ logger.warning(
111
+ "Error extracting tool names from ToolModel",
112
+ tool_model_name=tool_model.name,
113
+ error=str(e),
114
+ )
115
+
116
+ # Fallback to ToolModel.name
117
+ logger.debug(
118
+ "Falling back to ToolModel.name",
119
+ tool_model_name=tool_model.name,
120
+ )
121
+ return [tool_model.name]
122
+
123
+
124
+ def create_tool_call_limit_middleware(
125
+ tool: str | ToolModel | dict[str, Any] | None = None,
126
+ thread_limit: int | None = None,
127
+ run_limit: int | None = None,
128
+ exit_behavior: Literal["continue", "error", "end"] = "continue",
129
+ ) -> ToolCallLimitMiddleware:
130
+ """
131
+ Create a ToolCallLimitMiddleware with graceful termination support.
132
+
133
+ Factory for LangChain's ToolCallLimitMiddleware that supports DAO AI
134
+ configuration types.
135
+
136
+ Args:
137
+ tool: Tool to limit. Can be:
138
+ - None: Global limit on all tools
139
+ - str: Limit specific tool by name
140
+ - ToolModel: Limit tool(s) from DAO AI config
141
+ - dict: Tool config dict (converted to ToolModel)
142
+ thread_limit: Max calls per thread (conversation). Requires checkpointer.
143
+ run_limit: Max calls per run (single invocation).
144
+ exit_behavior: What to do when limit hit:
145
+ - "continue": Block tool with error message, let agent continue
146
+ - "error": Raise ToolCallLimitExceededError immediately
147
+ - "end": Stop execution gracefully (single-tool only)
148
+
149
+ Returns:
150
+ A ToolCallLimitMiddleware instance. If ToolModel produces multiple tools,
151
+ only the first tool is used (with a warning logged).
152
+
153
+ Raises:
154
+ ValueError: If no limits specified, or invalid dict
155
+ TypeError: If tool is unsupported type
156
+
157
+ Example:
158
+ # Global limit
159
+ limiter = create_tool_call_limit_middleware(run_limit=10)
160
+
161
+ # Tool-specific limit
162
+ limiter = create_tool_call_limit_middleware(
163
+ tool="search_web",
164
+ run_limit=3,
165
+ exit_behavior="continue",
166
+ )
167
+ """
168
+ if thread_limit is None and run_limit is None:
169
+ raise ValueError("At least one of thread_limit or run_limit must be specified.")
170
+
171
+ # Global limit: no tool parameter
172
+ if tool is None:
173
+ logger.debug(
174
+ "Creating global tool call limit",
175
+ thread_limit=thread_limit,
176
+ run_limit=run_limit,
177
+ exit_behavior=exit_behavior,
178
+ )
179
+ return ToolCallLimitMiddleware(
180
+ thread_limit=thread_limit,
181
+ run_limit=run_limit,
182
+ exit_behavior=exit_behavior,
183
+ )
184
+
185
+ # Resolve to list of tool names
186
+ names = _resolve_tool(tool)
187
+
188
+ # Use first tool name (warn if multiple)
189
+ tool_name = names[0]
190
+ if len(names) > 1:
191
+ logger.warning(
192
+ "ToolModel resolved to multiple tool names, using first only",
193
+ tool_names=names,
194
+ using=tool_name,
195
+ )
196
+
197
+ logger.debug(
198
+ "Creating tool call limit middleware",
199
+ tool_name=tool_name,
200
+ thread_limit=thread_limit,
201
+ run_limit=run_limit,
202
+ exit_behavior=exit_behavior,
203
+ )
204
+
205
+ return ToolCallLimitMiddleware(
206
+ tool_name=tool_name,
207
+ thread_limit=thread_limit,
208
+ run_limit=run_limit,
209
+ exit_behavior=exit_behavior,
210
+ )
@@ -0,0 +1,174 @@
1
+ """
2
+ Tool retry middleware for DAO AI agents.
3
+
4
+ Automatically retries failed tool calls with configurable exponential backoff.
5
+
6
+ Example:
7
+ from dao_ai.middleware import create_tool_retry_middleware
8
+
9
+ # Retry failed tool calls with exponential backoff
10
+ middleware = create_tool_retry_middleware(
11
+ max_retries=3,
12
+ backoff_factor=2.0,
13
+ initial_delay=1.0,
14
+ )
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from typing import Any, Callable, Literal
20
+
21
+ from langchain.agents.middleware import ToolRetryMiddleware
22
+ from langchain_core.tools import BaseTool
23
+ from loguru import logger
24
+
25
+ from dao_ai.config import BaseFunctionModel, ToolModel
26
+
27
+ __all__ = [
28
+ "ToolRetryMiddleware",
29
+ "create_tool_retry_middleware",
30
+ ]
31
+
32
+
33
+ def _resolve_tools(
34
+ tools: list[str | ToolModel | dict[str, Any]] | None,
35
+ ) -> list[str] | None:
36
+ """
37
+ Resolve tool specs to a list of tool name strings.
38
+
39
+ Returns None if tools is None (apply to all tools).
40
+ """
41
+ if tools is None:
42
+ return None
43
+
44
+ result: list[str] = []
45
+ for tool in tools:
46
+ if isinstance(tool, str):
47
+ result.append(tool)
48
+ elif isinstance(tool, dict):
49
+ try:
50
+ tool_model = ToolModel(**tool)
51
+ result.extend(_extract_tool_names(tool_model))
52
+ except Exception as e:
53
+ raise ValueError(f"Failed to construct ToolModel from dict: {e}") from e
54
+ elif isinstance(tool, ToolModel):
55
+ result.extend(_extract_tool_names(tool))
56
+ else:
57
+ raise TypeError(
58
+ f"Tool must be str, ToolModel, or dict, got {type(tool).__name__}"
59
+ )
60
+
61
+ return result if result else None
62
+
63
+
64
+ def _extract_tool_names(tool_model: ToolModel) -> list[str]:
65
+ """Extract tool names from ToolModel, falling back to ToolModel.name."""
66
+ function = tool_model.function
67
+
68
+ if not isinstance(function, BaseFunctionModel):
69
+ return [tool_model.name]
70
+
71
+ try:
72
+ tool_names = [
73
+ tool.name
74
+ for tool in function.as_tools()
75
+ if isinstance(tool, BaseTool) and tool.name
76
+ ]
77
+ return tool_names if tool_names else [tool_model.name]
78
+ except Exception:
79
+ return [tool_model.name]
80
+
81
+
82
+ def create_tool_retry_middleware(
83
+ max_retries: int = 3,
84
+ backoff_factor: float = 2.0,
85
+ initial_delay: float = 1.0,
86
+ max_delay: float | None = None,
87
+ jitter: bool = False,
88
+ tools: list[str | ToolModel | dict[str, Any]] | None = None,
89
+ retry_on: tuple[type[Exception], ...] | Callable[[Exception], bool] | None = None,
90
+ on_failure: Literal["continue", "error"] | Callable[[Exception], str] = "continue",
91
+ ) -> ToolRetryMiddleware:
92
+ """
93
+ Create a ToolRetryMiddleware for automatic tool call retries.
94
+
95
+ Handles transient failures in external API calls with exponential backoff.
96
+
97
+ Args:
98
+ max_retries: Max retry attempts after initial call. Default 3.
99
+ backoff_factor: Multiplier for exponential backoff. Default 2.0.
100
+ Delay = initial_delay * (backoff_factor ** retry_number)
101
+ Set to 0.0 for constant delay.
102
+ initial_delay: Initial delay in seconds before first retry. Default 1.0.
103
+ max_delay: Max delay in seconds (caps exponential growth). None = no cap.
104
+ jitter: Add ±25% random jitter to avoid thundering herd. Default False.
105
+ tools: List of tools to apply retry to. Can be:
106
+ - None: Apply to all tools (default)
107
+ - list of str: Tool names
108
+ - list of ToolModel: DAO AI tool models
109
+ - list of dict: Tool config dicts
110
+ retry_on: When to retry:
111
+ - None: Retry on all errors (default)
112
+ - tuple of Exception types: Retry only on these
113
+ - callable: Function(exception) -> bool
114
+ on_failure: Behavior when all retries exhausted:
115
+ - "continue": Return error message, let agent continue (default)
116
+ - "error": Re-raise exception, stop execution
117
+ - callable: Function(exception) -> str for custom message
118
+
119
+ Returns:
120
+ List containing ToolRetryMiddleware instance
121
+
122
+ Example:
123
+ # Basic retry with defaults
124
+ retry = create_tool_retry_middleware()
125
+
126
+ # Retry specific tools with custom backoff
127
+ retry = create_tool_retry_middleware(
128
+ max_retries=5,
129
+ backoff_factor=1.5,
130
+ initial_delay=0.5,
131
+ tools=["search_web", "query_database"],
132
+ )
133
+
134
+ # Retry only on specific exceptions
135
+ retry = create_tool_retry_middleware(
136
+ max_retries=3,
137
+ retry_on=(TimeoutError, ConnectionError),
138
+ on_failure="error",
139
+ )
140
+ """
141
+ tool_names = _resolve_tools(tools)
142
+
143
+ logger.debug(
144
+ "Creating tool retry middleware",
145
+ max_retries=max_retries,
146
+ backoff_factor=backoff_factor,
147
+ initial_delay=initial_delay,
148
+ max_delay=max_delay,
149
+ jitter=jitter,
150
+ tools=tool_names or "all",
151
+ on_failure=on_failure if isinstance(on_failure, str) else "custom",
152
+ )
153
+
154
+ # Build kwargs
155
+ kwargs: dict[str, Any] = {
156
+ "max_retries": max_retries,
157
+ "backoff_factor": backoff_factor,
158
+ "initial_delay": initial_delay,
159
+ "on_failure": on_failure,
160
+ }
161
+
162
+ if tool_names is not None:
163
+ kwargs["tools"] = tool_names
164
+
165
+ if max_delay is not None:
166
+ kwargs["max_delay"] = max_delay
167
+
168
+ if jitter:
169
+ kwargs["jitter"] = jitter
170
+
171
+ if retry_on is not None:
172
+ kwargs["retry_on"] = retry_on
173
+
174
+ return ToolRetryMiddleware(**kwargs)
dao_ai/nodes.py CHANGED
@@ -26,11 +26,9 @@ from dao_ai.config import (
26
26
  from dao_ai.middleware.core import create_factory_middleware
27
27
  from dao_ai.middleware.guardrails import GuardrailMiddleware
28
28
  from dao_ai.middleware.human_in_the_loop import (
29
- HumanInTheLoopMiddleware,
30
29
  create_hitl_middleware_from_tool_models,
31
30
  )
32
31
  from dao_ai.middleware.summarization import (
33
- LoggingSummarizationMiddleware,
34
32
  create_summarization_middleware,
35
33
  )
36
34
  from dao_ai.prompts import make_prompt
@@ -78,8 +76,7 @@ def _create_middleware_list(
78
76
  function_name=middleware_config.name,
79
77
  args=middleware_config.args,
80
78
  )
81
- if middleware is not None:
82
- middleware_list.append(middleware)
79
+ middleware_list.append(middleware)
83
80
 
84
81
  # Add guardrails as middleware
85
82
  if agent.guardrails:
@@ -117,16 +114,12 @@ def _create_middleware_list(
117
114
  max_tokens=chat_history.max_tokens,
118
115
  summary_model=chat_history.model.name,
119
116
  )
120
- summarization_middleware: LoggingSummarizationMiddleware = (
121
- create_summarization_middleware(chat_history)
122
- )
117
+ summarization_middleware = create_summarization_middleware(chat_history)
123
118
  middleware_list.append(summarization_middleware)
124
119
 
125
120
  # Add human-in-the-loop middleware if any tools require it
126
- hitl_middleware: HumanInTheLoopMiddleware | None = (
127
- create_hitl_middleware_from_tool_models(tool_models)
128
- )
129
- if hitl_middleware is not None:
121
+ hitl_middlewares = create_hitl_middleware_from_tool_models(tool_models)
122
+ if hitl_middlewares:
130
123
  # Log which tools require HITL
131
124
  hitl_tool_names: list[str] = [
132
125
  tool.name
@@ -139,7 +132,7 @@ def _create_middleware_list(
139
132
  agent=agent.name,
140
133
  hitl_tools=hitl_tool_names,
141
134
  )
142
- middleware_list.append(hitl_middleware)
135
+ middleware_list.append(hitl_middlewares)
143
136
 
144
137
  logger.info(
145
138
  "Middleware summary",
@@ -190,6 +190,7 @@ def create_supervisor_graph(config: AppConfig) -> CompiledStateGraph:
190
190
  supervisor_tools: list[BaseTool] = list(create_tools(supervisor_config.tools))
191
191
 
192
192
  # Create middleware from configuration
193
+ # All middleware factories return list[AgentMiddleware] for composability
193
194
  middlewares: list[AgentMiddleware] = []
194
195
 
195
196
  for middleware_config in supervisor_config.middleware:
@@ -201,11 +202,11 @@ def create_supervisor_graph(config: AppConfig) -> CompiledStateGraph:
201
202
  function_name=middleware_config.name,
202
203
  args=middleware_config.args,
203
204
  )
204
- if middleware is not None:
205
- middlewares.append(middleware)
206
- logger.debug(
207
- "Created supervisor middleware", middleware=middleware_config.name
208
- )
205
+ middlewares.append(middleware)
206
+ logger.debug(
207
+ "Created supervisor middleware",
208
+ middleware=middleware_config.name,
209
+ )
209
210
 
210
211
  # Set up memory store and checkpointer
211
212
  store: BaseStore | None = create_store(orchestration)
@@ -625,6 +625,17 @@ class DatabricksProvider(ServiceProvider):
625
625
  df.write.mode("overwrite").saveAsTable(table)
626
626
 
627
627
  def create_vector_store(self, vector_store: VectorStoreModel) -> None:
628
+ """
629
+ Create a vector search index from a source table.
630
+
631
+ This method expects a VectorStoreModel in provisioning mode with all
632
+ required fields validated. Use VectorStoreModel.create() which handles
633
+ mode detection and validation.
634
+
635
+ Args:
636
+ vector_store: VectorStoreModel configured for provisioning
637
+ """
638
+ # Ensure endpoint exists
628
639
  if not endpoint_exists(self.vsc, vector_store.endpoint.name):
629
640
  self.vsc.create_endpoint_and_wait(
630
641
  name=vector_store.endpoint.name,
dao_ai/vector_search.py CHANGED
@@ -72,3 +72,40 @@ def index_exists(
72
72
  raise e
73
73
  # If we reach here, the index doesn't exist
74
74
  return False
75
+
76
+
77
+ def find_index(
78
+ vsc: VectorSearchClient, index_full_name: str
79
+ ) -> tuple[bool, str | None]:
80
+ """
81
+ Find a Vector Search index across all endpoints.
82
+
83
+ Searches all available endpoints to find where the index is located.
84
+
85
+ Args:
86
+ vsc: Databricks Vector Search client instance
87
+ index_full_name: Fully qualified name of the index (catalog.schema.index)
88
+
89
+ Returns:
90
+ Tuple of (exists: bool, endpoint_name: str | None)
91
+ - (True, endpoint_name) if index is found
92
+ - (False, None) if index is not found on any endpoint
93
+ """
94
+ try:
95
+ endpoints = vsc.list_endpoints().get("endpoints", [])
96
+ except Exception as e:
97
+ if "REQUEST_LIMIT_EXCEEDED" in str(e):
98
+ print("WARN: couldn't list endpoints due to REQUEST_LIMIT_EXCEEDED error.")
99
+ return (False, None)
100
+ raise e
101
+
102
+ for endpoint in endpoints:
103
+ endpoint_name: str = endpoint["name"]
104
+ try:
105
+ vsc.get_index(endpoint_name, index_full_name).describe()
106
+ return (True, endpoint_name)
107
+ except Exception:
108
+ # Index not on this endpoint, try next
109
+ continue
110
+
111
+ return (False, None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dao-ai
3
- Version: 0.1.2
3
+ Version: 0.1.5
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
@@ -79,7 +79,7 @@ Description-Content-Type: text/markdown
79
79
 
80
80
  # DAO: Declarative Agent Orchestration
81
81
 
82
- [![Version](https://img.shields.io/badge/version-0.1.0-blue.svg)](CHANGELOG.md)
82
+ [![Version](https://img.shields.io/badge/version-0.1.2-blue.svg)](CHANGELOG.md)
83
83
  [![Python](https://img.shields.io/badge/python-3.11+-green.svg)](https://www.python.org/)
84
84
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
85
85
 
@@ -293,6 +293,16 @@ This single command:
293
293
  3. Deploys it to Databricks
294
294
  4. Creates a serving endpoint
295
295
 
296
+ **Deploying to a specific workspace:**
297
+
298
+ ```bash
299
+ # Deploy to AWS workspace
300
+ dao-ai bundle --deploy --run -c config/my_agent.yaml --profile aws-field-eng
301
+
302
+ # Deploy to Azure workspace
303
+ dao-ai bundle --deploy --run -c config/my_agent.yaml --profile azure-retail
304
+ ```
305
+
296
306
  **Step 5: Interact with your agent**
297
307
 
298
308
  Once deployed, you can chat with your agent using Python:
@@ -422,10 +432,34 @@ dao-ai graph -c config/my_config.yaml -o workflow.png
422
432
  # Deploy with Databricks Asset Bundles
423
433
  dao-ai bundle --deploy --run -c config/my_config.yaml
424
434
 
435
+ # Deploy to a specific workspace (multi-cloud support)
436
+ dao-ai bundle --deploy -c config/my_config.yaml --profile aws-field-eng
437
+ dao-ai bundle --deploy -c config/my_config.yaml --profile azure-retail
438
+
425
439
  # Interactive chat with agent
426
440
  dao-ai chat -c config/my_config.yaml
427
441
  ```
428
442
 
443
+ ### Multi-Cloud Deployment
444
+
445
+ DAO AI supports deploying to Azure, AWS, and GCP workspaces with automatic cloud detection:
446
+
447
+ ```bash
448
+ # Deploy to AWS workspace
449
+ dao-ai bundle --deploy -c config/my_config.yaml --profile aws-prod
450
+
451
+ # Deploy to Azure workspace
452
+ dao-ai bundle --deploy -c config/my_config.yaml --profile azure-prod
453
+
454
+ # Deploy to GCP workspace
455
+ dao-ai bundle --deploy -c config/my_config.yaml --profile gcp-prod
456
+ ```
457
+
458
+ The CLI automatically:
459
+ - Detects the cloud provider from your profile's workspace URL
460
+ - Selects appropriate compute node types for each cloud
461
+ - Creates isolated deployment state per profile
462
+
429
463
  👉 **Learn more:** [CLI Reference Documentation](docs/cli-reference.md)
430
464
 
431
465
  ---
@@ -1,19 +1,19 @@
1
1
  dao_ai/__init__.py,sha256=18P98ExEgUaJ1Byw440Ct1ty59v6nxyWtc5S6Uq2m9Q,1062
2
2
  dao_ai/agent_as_code.py,sha256=xIlLDpPVfmDVzLvbdY_V_CrC4Jvj2ItCWJ-NzdrszTo,538
3
3
  dao_ai/catalog.py,sha256=sPZpHTD3lPx4EZUtIWeQV7VQM89WJ6YH__wluk1v2lE,4947
4
- dao_ai/cli.py,sha256=azkzrG0RCKyb_euXsmiLCMXWtz7n-8KMNG-45pufqUg,32655
5
- dao_ai/config.py,sha256=o8BYHB-9R3PVWP0rtGAVrge3CHQqqnIZgfUl_awNPTU,117044
4
+ dao_ai/cli.py,sha256=FWzddUceOoER2EIMwBx_mIMhCWFFZHoAL3KHy7f0Euc,35377
5
+ dao_ai/config.py,sha256=GWBmrbiixMG0ZszLk_XTRKRIS0QqOk_TIQhauK--MIY,120863
6
6
  dao_ai/graph.py,sha256=1-uQlo7iXZQTT3uU8aYu0N5rnhw5_g_2YLwVsAs6M-U,1119
7
7
  dao_ai/logging.py,sha256=lYy4BmucCHvwW7aI3YQkQXKJtMvtTnPDu9Hnd7_O4oc,1556
8
8
  dao_ai/messages.py,sha256=4ZBzO4iFdktGSLrmhHzFjzMIt2tpaL-aQLHOQJysGnY,6959
9
9
  dao_ai/models.py,sha256=AwzwTRTNZF-UOh59HsuXEgFk_YH6q6M-mERNDe64Z8k,81783
10
- dao_ai/nodes.py,sha256=uI2L_icOAB1xYWSOx7W5QBbTxnvrt16hpQJKuSRAqos,10996
10
+ dao_ai/nodes.py,sha256=7W6Ek6Uk9-pKa-H06nVCwuDllCrgX02IYy3rHtuL0aM,10777
11
11
  dao_ai/optimization.py,sha256=phK6t4wYmWPObCjGUBHdZzsaFXGhQOjhAek2bAEfwXo,22971
12
12
  dao_ai/prompts.py,sha256=G0ng5f2PkzfgdKrSl03Rnd6riZn5APedof0GAzsWQI8,4792
13
13
  dao_ai/state.py,sha256=0wbbzfQmldkCu26gdTE5j0Rl-_pfilza-YIHPbSWlvI,6394
14
14
  dao_ai/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  dao_ai/utils.py,sha256=_Urd7Nj2VzrgPKf3NS4E6vt0lWRhEUddBqWN9BksqeE,11543
16
- dao_ai/vector_search.py,sha256=jlaFS_iizJ55wblgzZmswMM3UOL-qOp2BGJc0JqXYSg,2839
16
+ dao_ai/vector_search.py,sha256=8d3xROg9zSIYNXjRRl6rSexsJTlufjRl5Fy1ZA8daKA,4019
17
17
  dao_ai/genie/__init__.py,sha256=vdEyGhrt6L8GlK75SyYvTnl8QpHKDCJC5hJKLg4DesQ,1063
18
18
  dao_ai/genie/core.py,sha256=HPKbocvhnnw_PkQwfoq5bpgQmL9lZyyS6_goTJL8yiY,1073
19
19
  dao_ai/genie/cache/__init__.py,sha256=JfgCJl1NYQ1aZvZ4kly4T6uQK6ZCJ6PX_htuq7nJF50,1203
@@ -28,21 +28,27 @@ dao_ai/memory/base.py,sha256=99nfr2UZJ4jmfTL_KrqUlRSCoRxzkZyWyx5WqeUoMdQ,338
28
28
  dao_ai/memory/core.py,sha256=38H-JLIyUrRDIECLvpXK3iJlWG35X97E-DTo_4c3Jzc,6317
29
29
  dao_ai/memory/databricks.py,sha256=SM6nwLjhSRJO4hLc3GUuht5YydYtTi3BAOae6jPwTm4,14377
30
30
  dao_ai/memory/postgres.py,sha256=q9IIAGs0wuaV-3rUIn4dtzOxbkCCoB-yv1Rtod7ohjI,16467
31
- dao_ai/middleware/__init__.py,sha256=epSCtCtttIogl21nVK768Ln35L0mOShVczyURtR6Ln8,3609
32
- dao_ai/middleware/assertions.py,sha256=VmTBhHKulcDwicEP9IB3_HyI4hDhmq3ZP_85InGgvCc,27360
31
+ dao_ai/middleware/__init__.py,sha256=scEk9Mt9POJe-j9e9t5sf3FNMNPBsu15_oxrlV9IkVE,4871
32
+ dao_ai/middleware/assertions.py,sha256=C1K-TnNZfBEwWouioHCt6c48i1ux9QKfQaX6AzghhgE,27408
33
33
  dao_ai/middleware/base.py,sha256=uG2tpdnjL5xY5jCKvb_m3UTBtl4ZC6fJQUkDsQvV8S4,1279
34
- dao_ai/middleware/core.py,sha256=rRPwNCBAj40lbZK08hdzP9utrqaHl3l520jgBOwI_Z4,2124
35
- dao_ai/middleware/guardrails.py,sha256=qM_V0fb1fa2iuKGy_nmOvVrOP72UiPtKgrfSqxngQUc,13975
36
- dao_ai/middleware/human_in_the_loop.py,sha256=Ylmiqo17dOKsUDhbD103tnknGcidVX0Joy7WPlodo78,7491
37
- dao_ai/middleware/message_validation.py,sha256=evdfozSd2rsEARTrKaYAqNWhZCtgrnFAi6YudvT54qQ,19754
38
- dao_ai/middleware/summarization.py,sha256=moqcR27vEeMc7uN_OJoStOFSEFQu-GqvjH933b3DTPE,7127
34
+ dao_ai/middleware/context_editing.py,sha256=5rNKqH1phFFQTVW-4nzlVH5cbqomD-HFEIy2Z841D4I,7687
35
+ dao_ai/middleware/core.py,sha256=XFzL-A1_jS_pUCw7Q-z1WD0gutmpWZhfCMqHI6ifbhA,2096
36
+ dao_ai/middleware/guardrails.py,sha256=wjH4OwDRagkrKpcGNf7_bf3eJhtMpIWK_RIrrvMeqDs,14023
37
+ dao_ai/middleware/human_in_the_loop.py,sha256=YS11oQcRVzHVuZi309tuXfB4ItGuOz-PRT0fXwupdsY,7537
38
+ dao_ai/middleware/message_validation.py,sha256=SGvXow76BB1eW8zDSSuLJgRkIvLU-WOwA1Cd5_DatmQ,19818
39
+ dao_ai/middleware/model_call_limit.py,sha256=sxv15iNOUMjVLTEXwMBR5zAkxkWbnysbSIsBcuJbNUI,2216
40
+ dao_ai/middleware/model_retry.py,sha256=SlWjAcaEmvj6KBOkjUicChYjhlg7bAJM7-e6KLpHS9Q,3908
41
+ dao_ai/middleware/pii.py,sha256=zetfoz1WlJ-V0vjJp37v8NGimXB27EkZfetUHpGCXno,5137
42
+ dao_ai/middleware/summarization.py,sha256=gp2s9uc4DEJat-mWjWEzMaR-zAAeUOXYvu5EEYtqae4,7143
43
+ dao_ai/middleware/tool_call_limit.py,sha256=WQ3NmA3pLo-pNPBmwM7KwkYpT1segEnWqkhgW1xNkCE,6321
44
+ dao_ai/middleware/tool_retry.py,sha256=QfJ7yTHneME8VtnA88QcmnjXIegSFeJztyngy49wTgM,5568
39
45
  dao_ai/orchestration/__init__.py,sha256=i85CLfRR335NcCFhaXABcMkn6WZfXnJ8cHH4YZsZN0s,1622
40
46
  dao_ai/orchestration/core.py,sha256=qoU7uMXBJCth-sqfu0jRE1L0GOn5H4LoZdRUY1Ib3DI,9585
41
- dao_ai/orchestration/supervisor.py,sha256=0aQLL1a3oBjG9LYTuV1y73rB0mqkIkax7MwtZ7xx_pE,9833
47
+ dao_ai/orchestration/supervisor.py,sha256=alKMEEo9G5LhdpMvTVdAMel234cZj5_MguWl4wFB7XQ,9873
42
48
  dao_ai/orchestration/swarm.py,sha256=8tp1eGmsQqqWpaDcjPoJckddPWohZdmmN0RGRJ_xzOA,9198
43
49
  dao_ai/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
50
  dao_ai/providers/base.py,sha256=-fjKypCOk28h6vioPfMj9YZSw_3Kcbi2nMuAyY7vX9k,1383
45
- dao_ai/providers/databricks.py,sha256=4IBV9_staE6vMci4hUjHWYHc8iS87mM8lT6LX0xh8Mw,61040
51
+ dao_ai/providers/databricks.py,sha256=XxYkyoDYkwGV_Xg1IJBpGOl4d7U5HiFP4RtjjSLgenI,61437
46
52
  dao_ai/tools/__init__.py,sha256=SRd7W2DOCXKbWWy8lclRtJiCskz7SDAm94qaFF47urQ,1664
47
53
  dao_ai/tools/agent.py,sha256=plIWALywRjaDSnot13nYehBsrHRpBUpsVZakoGeajOE,1858
48
54
  dao_ai/tools/core.py,sha256=bRIN3BZhRQX8-Kpu3HPomliodyskCqjxynQmYbk6Vjs,3783
@@ -57,8 +63,8 @@ dao_ai/tools/sql.py,sha256=tKd1gjpLuKdQDyfmyYYtMiNRHDW6MGRbdEVaeqyB8Ok,7632
57
63
  dao_ai/tools/time.py,sha256=tufJniwivq29y0LIffbgeBTIDE6VgrLpmVf8Qr90qjw,9224
58
64
  dao_ai/tools/unity_catalog.py,sha256=AjQfW7bvV8NurqDLIyntYRv2eJuTwNdbvex1L5CRjOk,15534
59
65
  dao_ai/tools/vector_search.py,sha256=oe2uBwl2TfeJIXPpwiS6Rmz7wcHczSxNyqS9P3hE6co,14542
60
- dao_ai-0.1.2.dist-info/METADATA,sha256=hNysdpnl7dp_T1gC5tJQ4YHwSLoeg2UJY0aHg4-gvYc,15615
61
- dao_ai-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
62
- dao_ai-0.1.2.dist-info/entry_points.txt,sha256=Xa-UFyc6gWGwMqMJOt06ZOog2vAfygV_DSwg1AiP46g,43
63
- dao_ai-0.1.2.dist-info/licenses/LICENSE,sha256=YZt3W32LtPYruuvHE9lGk2bw6ZPMMJD8yLrjgHybyz4,1069
64
- dao_ai-0.1.2.dist-info/RECORD,,
66
+ dao_ai-0.1.5.dist-info/METADATA,sha256=Iz_x_25jQut9i8yghsPmQV08iyLBJdrXTAjFmYOjx1Q,16685
67
+ dao_ai-0.1.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
68
+ dao_ai-0.1.5.dist-info/entry_points.txt,sha256=Xa-UFyc6gWGwMqMJOt06ZOog2vAfygV_DSwg1AiP46g,43
69
+ dao_ai-0.1.5.dist-info/licenses/LICENSE,sha256=YZt3W32LtPYruuvHE9lGk2bw6ZPMMJD8yLrjgHybyz4,1069
70
+ dao_ai-0.1.5.dist-info/RECORD,,
File without changes