dasein-core 0.2.5__py3-none-any.whl → 0.2.7__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.
dasein/api.py CHANGED
@@ -2825,6 +2825,97 @@ Follow these rules when planning your actions."""
2825
2825
  return getattr(agent, 'agent_id', None) or f"agent_{id(agent)}"
2826
2826
 
2827
2827
  agent_fingerprint = _minimal_agent_fingerprint(self._agent)
2828
+
2829
+ # Extract tool metadata for Stage 3.5 tool grounding
2830
+ def _extract_tool_metadata(agent):
2831
+ """
2832
+ Extract tool metadata (name, description, args_schema) from agent.
2833
+
2834
+ CRITICAL: Extracts ALL available tools from the agent, not just tools used in trace.
2835
+ Why: If agent used wrong tool (e.g., extract_text instead of get_elements),
2836
+ the trace won't show the correct tool. Stage 3.5 needs to see all options
2837
+ to suggest better alternatives.
2838
+ """
2839
+ tools_metadata = []
2840
+ tools_to_process = []
2841
+
2842
+ # Get ALL tools from agent (LangChain or LangGraph) - not filtered by trace usage
2843
+ tools_attr = getattr(agent, 'tools', None)
2844
+ if tools_attr:
2845
+ try:
2846
+ tools_to_process = list(tools_attr)
2847
+ except Exception:
2848
+ pass
2849
+ elif getattr(agent, 'toolkit', None):
2850
+ tk = getattr(agent, 'toolkit')
2851
+ tk_tools = getattr(tk, 'tools', None) or getattr(tk, 'get_tools', None)
2852
+ try:
2853
+ tools_to_process = list(tk_tools() if callable(tk_tools) else tk_tools or [])
2854
+ except Exception:
2855
+ pass
2856
+
2857
+ # Also try LangGraph tools from compiled graph
2858
+ if hasattr(agent, 'nodes') and 'tools' in agent.nodes:
2859
+ tools_node = agent.nodes['tools']
2860
+ if hasattr(tools_node, 'node') and hasattr(tools_node.node, 'steps'):
2861
+ for step in tools_node.node.steps:
2862
+ if hasattr(step, 'tools_by_name'):
2863
+ tools_to_process.extend(step.tools_by_name.values())
2864
+ break
2865
+
2866
+ # Extract metadata from each tool
2867
+ for tool in tools_to_process:
2868
+ try:
2869
+ tool_meta = {
2870
+ 'name': getattr(tool, 'name', str(tool.__class__.__name__)),
2871
+ 'description': getattr(tool, 'description', ''),
2872
+ }
2873
+
2874
+ # Extract args_schema if available
2875
+ if hasattr(tool, 'args_schema') and tool.args_schema:
2876
+ try:
2877
+ # Try Pydantic v2 method
2878
+ if hasattr(tool.args_schema, 'model_json_schema'):
2879
+ tool_meta['args_schema'] = tool.args_schema.model_json_schema()
2880
+ # Fallback to Pydantic v1 method
2881
+ elif hasattr(tool.args_schema, 'schema'):
2882
+ tool_meta['args_schema'] = tool.args_schema.schema()
2883
+ else:
2884
+ tool_meta['args_schema'] = {}
2885
+ except Exception:
2886
+ tool_meta['args_schema'] = {}
2887
+ else:
2888
+ tool_meta['args_schema'] = {}
2889
+
2890
+ tools_metadata.append(tool_meta)
2891
+ except Exception as e:
2892
+ # Skip tools that fail to extract
2893
+ pass
2894
+
2895
+ return tools_metadata
2896
+
2897
+ tools_metadata = _extract_tool_metadata(self._agent)
2898
+
2899
+ # Reuse existing graph analysis (already extracted in __init__)
2900
+ graph_metadata = None
2901
+ if self._is_langgraph and hasattr(self._agent, 'get_graph'):
2902
+ try:
2903
+ graph = self._agent.get_graph()
2904
+ graph_metadata = {
2905
+ 'nodes': list(graph.nodes.keys()),
2906
+ 'edges': [{'source': e.source, 'target': e.target} for e in graph.edges],
2907
+ 'is_multi_agent': len(graph.nodes) > 1
2908
+ }
2909
+ print(f"[DASEIN] Extracted graph metadata: {len(graph_metadata['nodes'])} nodes, {len(graph_metadata['edges'])} edges")
2910
+ except Exception:
2911
+ pass
2912
+
2913
+ print(f"[DASEIN] Extracted metadata for {len(tools_metadata)} tools")
2914
+
2915
+ if tools_metadata:
2916
+ print(f"[DASEIN] Sample tool: {tools_metadata[0].get('name', 'unknown')}")
2917
+ else:
2918
+ print(f"[DASEIN] WARNING: No tools extracted! Agent type: {type(self._agent)}")
2828
2919
 
2829
2920
  response = self._service_adapter.synthesize_rules(
2830
2921
  run_id=None, # Will use stored run_id from pre-run phase
@@ -2839,7 +2930,9 @@ Follow these rules when planning your actions."""
2839
2930
  agent_fingerprint=agent_fingerprint, # Reuse fingerprint from pre-run (line 2613)
2840
2931
  step_id=self._current_step_id, # Pass step_id for parallel execution tracking
2841
2932
  post_run_mode=self._post_run, # Pass post_run mode ("full" or "kpi_only")
2842
- wait_for_synthesis=wait_for_synthesis # Wait for synthesis on retry runs (except last)
2933
+ wait_for_synthesis=wait_for_synthesis, # Wait for synthesis on retry runs (except last)
2934
+ tools_metadata=tools_metadata, # Tool metadata for Stage 3.5 tool grounding
2935
+ graph_metadata=graph_metadata # Graph metadata for Stage 3.5 node grounding
2843
2936
  )
2844
2937
 
2845
2938
  # response is a dict from ServiceAdapter; handle accordingly
@@ -32,6 +32,8 @@ class RuleSynthesisRequest:
32
32
  skip_synthesis: bool = False
33
33
  wait_for_synthesis: bool = False
34
34
  step_id: Optional[str] = None
35
+ tools_metadata: Optional[List[Dict[str, Any]]] = None # Tool metadata for Stage 3.5 tool grounding
36
+ graph_metadata: Optional[Dict[str, Any]] = None # Graph metadata for Stage 3.5 node grounding
35
37
 
36
38
 
37
39
  @dataclass
@@ -95,6 +97,8 @@ class PostRunClient:
95
97
  "performance_tracking_id": request.performance_tracking_id,
96
98
  "skip_synthesis": request.skip_synthesis,
97
99
  "wait_for_synthesis": request.wait_for_synthesis,
100
+ "tools_metadata": request.tools_metadata or [], # Tool metadata for Stage 3.5 tool grounding
101
+ "graph_metadata": request.graph_metadata or {}, # Graph metadata for Stage 3.5 node grounding
98
102
  }
99
103
 
100
104
  logger.info(f"Synthesizing rules for run: {request.run_id}")
@@ -95,7 +95,8 @@ class ServiceAdapter:
95
95
  max_rules: Optional[int] = 5, performance_tracking_id: Optional[str] = None,
96
96
  skip_synthesis: bool = False, agent_fingerprint: Optional[str] = None,
97
97
  step_id: Optional[str] = None, post_run_mode: str = "full",
98
- wait_for_synthesis: bool = False) -> Dict[str, Any]:
98
+ wait_for_synthesis: bool = False, tools_metadata: Optional[List[Dict[str, Any]]] = None,
99
+ graph_metadata: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
99
100
  """
100
101
  Synthesize rules from run telemetry (replaces local rule synthesis)
101
102
 
@@ -138,7 +139,9 @@ class ServiceAdapter:
138
139
  performance_tracking_id=performance_tracking_id,
139
140
  skip_synthesis=should_skip_synthesis,
140
141
  wait_for_synthesis=wait_for_synthesis,
141
- step_id=step_id
142
+ step_id=step_id,
143
+ tools_metadata=tools_metadata,
144
+ graph_metadata=graph_metadata
142
145
  )
143
146
 
144
147
  response = self.post_run_client.synthesize_rules(request)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dasein-core
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Universal memory for agentic AI. Attach a brain to any LangChain/LangGraph agent in a single line.
5
5
  Author-email: Dasein Team <support@dasein.ai>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  dasein/__init__.py,sha256=RY0lhaaWB6yJ_5YMRmaHDvQ0eFbc0BGbYNe5OVyxzYE,2316
2
2
  dasein/advice_format.py,sha256=5-h4J24L_B2Y9dlmyDuIYtmPCWOGAYoinBEXqpcNg2s,5386
3
- dasein/api.py,sha256=GQpZIRFDYCoZvDN2T4Gsh2BBXfCJ7ui3WTxi_ZQGb0Q,172432
3
+ dasein/api.py,sha256=KIWZ5I_8in2xas50IAfUOCmZgjaaXYxPcM0BgMx7Bs0,177347
4
4
  dasein/capture.py,sha256=XrEPsteG5__csqcqXzOmBSzPYgeI-OFzu3IRVMPYj3w,83814
5
5
  dasein/config.py,sha256=lXO8JG4RXbodn3gT5yEnuB0VRwWdrRVwhX3Rm06IZmU,1957
6
6
  dasein/events.py,sha256=mG-lnOvQoZUhXbrPSjrG4RME6ywUcbSZ04PscoJ15GI,12896
@@ -10,12 +10,12 @@ dasein/injector.py,sha256=EItWhlG6oMAf_D7YJnRNyDwAQIK5MsaATu1ig3OENqM,7256
10
10
  dasein/trace_buffer.py,sha256=bIyTpU8ZrNFR_TCwS43HvzUrDHpZ2F8pLVDeUE9jpwM,4117
11
11
  dasein/types.py,sha256=FjGXZowiRYZzWj5GzSnAnA_-xwYqqE7WmXFCosVyGI8,2974
12
12
  dasein/services/__init__.py,sha256=0o6vKEVSYgGo-u-xDFf7Z4cQr8gIht2YovD6eEXUquE,356
13
- dasein/services/post_run_client.py,sha256=bzWKiu-FGo36r6J-QBv6zjLpjI7mMjKmjhvfiddWFno,4352
13
+ dasein/services/post_run_client.py,sha256=UjK3eqf7oWGSuWkKe0vQmeMS0yUUOhYFD4-SZ7uj8WY,4768
14
14
  dasein/services/pre_run_client.py,sha256=tXmz_PQaSfq0xwypiWUAqNkXOmREZ6EwXLC4OM89J-A,4317
15
- dasein/services/service_adapter.py,sha256=nVvPPioYKoxYmR33w1ssYx422UPBeTsq8yIKZum8YHg,7128
15
+ dasein/services/service_adapter.py,sha256=YHk41lR3PXh8WTmxOzzwKf6hwPYGqIdApI92vQKlkAY,7350
16
16
  dasein/services/service_config.py,sha256=8_4tpV4mZvfaOc5_yyHbOyL4rYsPHzkLTEY1rtYgLs8,1629
17
- dasein_core-0.2.5.dist-info/licenses/LICENSE,sha256=7FHjIFEKl_3hSc3tGUVEWmufC_3oi8rh_2zVuL7jMKs,1091
18
- dasein_core-0.2.5.dist-info/METADATA,sha256=k-g7KsEhfAp3b_FgiAwh0i8Swuof9olOFnjJlGGj_zs,10192
19
- dasein_core-0.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- dasein_core-0.2.5.dist-info/top_level.txt,sha256=6yYY9kltjvvPsg9K6KyMKRtzEr5qM7sHXN7VzmrDtp0,7
21
- dasein_core-0.2.5.dist-info/RECORD,,
17
+ dasein_core-0.2.7.dist-info/licenses/LICENSE,sha256=7FHjIFEKl_3hSc3tGUVEWmufC_3oi8rh_2zVuL7jMKs,1091
18
+ dasein_core-0.2.7.dist-info/METADATA,sha256=M7zLIt6gXOfna7oFIMtqECJMqSU4WufP8g2IoeMJqKk,10192
19
+ dasein_core-0.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ dasein_core-0.2.7.dist-info/top_level.txt,sha256=6yYY9kltjvvPsg9K6KyMKRtzEr5qM7sHXN7VzmrDtp0,7
21
+ dasein_core-0.2.7.dist-info/RECORD,,