dasein-core 0.2.10__py3-none-any.whl → 0.2.13__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
@@ -881,9 +881,17 @@ class CognateProxy:
881
881
  # Initialize KPI tracking
882
882
  self._last_run_kpis = None
883
883
 
884
+ # Initialize wrapped LLM (will be set by _wrap_agent_llm if applicable)
885
+ self._wrapped_llm = None
886
+
884
887
  # Wrap the agent's LLM with our trace capture wrapper
885
888
  self._wrap_agent_llm()
886
889
 
890
+ # CRITICAL: Update langgraph_params to use wrapped LLM for recreation
891
+ if self._is_langgraph and self._langgraph_params and self._wrapped_llm:
892
+ print(f" [DASEIN][WRAPPER] Updating langgraph_params to use wrapped LLM")
893
+ self._langgraph_params['model'] = self._wrapped_llm
894
+
887
895
  # Inject universal dead-letter tool
888
896
  self._inject_deadletter_tool()
889
897
 
@@ -1680,7 +1688,69 @@ Follow these rules when planning your actions."""
1680
1688
  self._deadletter_fn = None
1681
1689
 
1682
1690
  def _wrap_agent_llm(self):
1683
- """Monkey-patch ALL LLM classes found in agent + tools."""
1691
+ """Wrap LLM instance (for SQL agent callbacks) AND monkey-patch (for Pipecleaner)."""
1692
+ try:
1693
+ # STEP 1: Wrap the main agent LLM with DaseinLLMWrapper (captures all _generate calls)
1694
+ # This is critical for SQL agents where callbacks don't propagate properly
1695
+ llm = self._find_llm_recursively(self._agent, max_depth=5)
1696
+ if llm:
1697
+ wrapped_llm = DaseinLLMWrapper(llm, self._callback_handler, verbose=self._verbose)
1698
+ # Replace the original LLM with our wrapped version
1699
+ self._replace_llm_in_structure(self._agent, llm, wrapped_llm, max_depth=5)
1700
+ self._wrapped_llm = wrapped_llm
1701
+ self._vprint(f"[DASEIN][WRAPPER] Successfully wrapped {type(llm).__name__} LLM")
1702
+ else:
1703
+ self._vprint(f"[DASEIN][WRAPPER] Could not find any LLM in agent structure")
1704
+ self._wrapped_llm = None
1705
+
1706
+ # STEP 2: Monkey-patch LLM classes for Pipecleaner deduplication
1707
+ # This is critical for research agents with Summary calls that need deduplication
1708
+ self._monkey_patch_llm_classes()
1709
+
1710
+ except Exception as e:
1711
+ self._vprint(f"[DASEIN][WRAPPER] Failed to wrap agent LLM: {e}")
1712
+ import traceback
1713
+ traceback.print_exc()
1714
+ self._wrapped_llm = None
1715
+
1716
+ def _replace_llm_in_structure(self, obj, original_llm, wrapped_llm, max_depth=5, path=""):
1717
+ """Replace the original LLM with wrapped LLM in the structure."""
1718
+ if max_depth <= 0:
1719
+ return
1720
+
1721
+ # Special handling for RunnableSequence - check steps
1722
+ if hasattr(obj, 'steps') and hasattr(obj, '__iter__'):
1723
+ for i, step in enumerate(obj.steps):
1724
+ if step is original_llm:
1725
+ self._vprint(f"[DASEIN][WRAPPER] Replacing LLM at {path}.steps[{i}]")
1726
+ obj.steps[i] = wrapped_llm
1727
+ return
1728
+ # Check if step has bound attribute (RunnableBinding)
1729
+ if hasattr(step, 'bound') and step.bound is original_llm:
1730
+ self._vprint(f"[DASEIN][WRAPPER] Replacing LLM at {path}.steps[{i}].bound")
1731
+ step.bound = wrapped_llm
1732
+ return
1733
+ # Recursively search in the step
1734
+ self._replace_llm_in_structure(step, original_llm, wrapped_llm, max_depth - 1, f"{path}.steps[{i}]")
1735
+
1736
+ # Search in attributes
1737
+ for attr_name in dir(obj):
1738
+ if attr_name.startswith('_'):
1739
+ continue
1740
+ try:
1741
+ attr_value = getattr(obj, attr_name)
1742
+ if attr_value is original_llm:
1743
+ self._vprint(f"[DASEIN][WRAPPER] Replacing LLM at {path}.{attr_name}")
1744
+ setattr(obj, attr_name, wrapped_llm)
1745
+ return
1746
+ # Recursively search in the attribute
1747
+ if hasattr(attr_value, '__dict__') or hasattr(attr_value, '__iter__'):
1748
+ self._replace_llm_in_structure(attr_value, original_llm, wrapped_llm, max_depth - 1, f"{path}.{attr_name}")
1749
+ except:
1750
+ continue
1751
+
1752
+ def _monkey_patch_llm_classes(self):
1753
+ """Monkey-patch ALL LLM classes found in agent + tools for Pipecleaner deduplication."""
1684
1754
  try:
1685
1755
  # Find ALL LLMs in agent structure + tools
1686
1756
  print(f"[DASEIN][WRAPPER] Searching for ALL LLMs in agent+tools...")
@@ -1713,10 +1783,10 @@ Follow these rules when planning your actions."""
1713
1783
  print(f"[DASEIN][WRAPPER] Patching {llm_class.__name__} (found in {location})...")
1714
1784
 
1715
1785
  # Check what methods the LLM class has
1716
- # Only patch TOP-LEVEL methods to avoid double-deduplication from internal calls
1786
+ # Patch both user-facing AND internal methods since SQL agents bypass invoke
1717
1787
  print(f"[DASEIN][WRAPPER] Checking LLM methods...")
1718
1788
  methods_to_patch = []
1719
- for method in ['invoke', 'ainvoke']: # Only patch user-facing methods, not internal _generate
1789
+ for method in ['invoke', 'ainvoke', '_generate', '_agenerate']: # Include internal methods for SQL agents
1720
1790
  if hasattr(llm_class, method):
1721
1791
  print(f"[DASEIN][WRAPPER] - Has {method}")
1722
1792
  methods_to_patch.append(method)
@@ -1811,7 +1881,7 @@ Follow these rules when planning your actions."""
1811
1881
  prompt_strings.append(msg.content)
1812
1882
  elif isinstance(msg, str):
1813
1883
  prompt_strings.append(msg)
1814
- else:
1884
+ else:
1815
1885
  prompt_strings.append(str(msg))
1816
1886
 
1817
1887
  # =============================================================
@@ -1929,6 +1999,7 @@ Follow these rules when planning your actions."""
1929
1999
  break
1930
2000
 
1931
2001
  if should_dedupe:
2002
+ try:
1932
2003
  # Deduplicate each prompt
1933
2004
  from .pipecleaner import get_or_create_corpus
1934
2005
  import hashlib
@@ -1969,14 +2040,53 @@ Follow these rules when planning your actions."""
1969
2040
  kwargs['messages'] = messages_to_dedupe
1970
2041
  elif 'prompts' in kwargs:
1971
2042
  kwargs['prompts'] = messages_to_dedupe
2043
+ except Exception as e:
2044
+ print(f"[🔥 HOTPATH] ⚠️ Deduplication error: {e}")
2045
+ import traceback
2046
+ traceback.print_exc()
1972
2047
  except Exception as e:
1973
- print(f"[🔥 HOTPATH] ⚠️ Deduplication error: {e}")
2048
+ print(f"[🔥 HOTPATH] ⚠️ Error in pipecleaner preprocessing: {e}")
1974
2049
  import traceback
1975
2050
  traceback.print_exc()
1976
2051
 
1977
2052
  try:
2053
+ # CRITICAL FIX: Ensure callbacks propagate to _generate/_agenerate
2054
+ # AgentExecutor doesn't pass run_manager to these internal methods
2055
+ # So we need to manually inject the callback handler
2056
+ if meth_name in ['_generate', '_agenerate'] and callback_handler:
2057
+ if 'run_manager' not in kwargs and hasattr(callback_handler, 'on_llm_start'):
2058
+ # Manually trigger on_llm_start since no run_manager
2059
+ import uuid
2060
+ run_id = uuid.uuid4()
2061
+ # Extract messages for on_llm_start
2062
+ messages = args[0] if args else []
2063
+ prompts = []
2064
+ for msg in (messages if isinstance(messages, list) else [messages]):
2065
+ if hasattr(msg, 'content'):
2066
+ prompts.append(str(msg.content))
2067
+ else:
2068
+ prompts.append(str(msg))
2069
+
2070
+ # Call on_llm_start
2071
+ callback_handler.on_llm_start(
2072
+ serialized={'name': type(self_llm).__name__},
2073
+ prompts=prompts,
2074
+ run_id=run_id
2075
+ )
2076
+
2077
+ # Store run_id for on_llm_end
2078
+ if not hasattr(self_llm, '_dasein_pending_run_ids'):
2079
+ self_llm._dasein_pending_run_ids = []
2080
+ self_llm._dasein_pending_run_ids.append(run_id)
2081
+
1978
2082
  result = await orig_method(self_llm, *args, **kwargs)
1979
2083
 
2084
+ # Call on_llm_end if we called on_llm_start
2085
+ if meth_name in ['_generate', '_agenerate'] and callback_handler:
2086
+ if hasattr(self_llm, '_dasein_pending_run_ids') and self_llm._dasein_pending_run_ids:
2087
+ run_id = self_llm._dasein_pending_run_ids.pop(0)
2088
+ callback_handler.on_llm_end(result, run_id=run_id)
2089
+
1980
2090
  # 🚨 MICROTURN ENFORCEMENT - DISABLED
1981
2091
  # Microturn can interfere with tool execution, so it's disabled
1982
2092
  # TODO: Re-enable with proper gating if needed for specific use cases
@@ -2205,8 +2315,43 @@ Follow these rules when planning your actions."""
2205
2315
  traceback.print_exc()
2206
2316
 
2207
2317
  try:
2318
+ # CRITICAL FIX: Ensure callbacks propagate to _generate/_agenerate
2319
+ # AgentExecutor doesn't pass run_manager to these internal methods
2320
+ # So we need to manually inject the callback handler
2321
+ if meth_name in ['_generate', '_agenerate'] and callback_handler:
2322
+ if 'run_manager' not in kwargs and hasattr(callback_handler, 'on_llm_start'):
2323
+ # Manually trigger on_llm_start since no run_manager
2324
+ import uuid
2325
+ run_id = uuid.uuid4()
2326
+ # Extract messages for on_llm_start
2327
+ messages = args[0] if args else []
2328
+ prompts = []
2329
+ for msg in (messages if isinstance(messages, list) else [messages]):
2330
+ if hasattr(msg, 'content'):
2331
+ prompts.append(str(msg.content))
2332
+ else:
2333
+ prompts.append(str(msg))
2334
+
2335
+ # Call on_llm_start
2336
+ callback_handler.on_llm_start(
2337
+ serialized={'name': type(self_llm).__name__},
2338
+ prompts=prompts,
2339
+ run_id=run_id
2340
+ )
2341
+
2342
+ # Store run_id for on_llm_end
2343
+ if not hasattr(self_llm, '_dasein_pending_run_ids'):
2344
+ self_llm._dasein_pending_run_ids = []
2345
+ self_llm._dasein_pending_run_ids.append(run_id)
2346
+
2208
2347
  result = orig_method(self_llm, *args, **kwargs)
2209
2348
 
2349
+ # Call on_llm_end if we called on_llm_start
2350
+ if meth_name in ['_generate', '_agenerate'] and callback_handler:
2351
+ if hasattr(self_llm, '_dasein_pending_run_ids') and self_llm._dasein_pending_run_ids:
2352
+ run_id = self_llm._dasein_pending_run_ids.pop(0)
2353
+ callback_handler.on_llm_end(result, run_id=run_id)
2354
+
2210
2355
  # 🚨 MICROTURN ENFORCEMENT - DISABLED (can interfere with tool execution)
2211
2356
  # TODO: Re-enable with proper gating if needed
2212
2357
 
@@ -3701,7 +3846,11 @@ Follow these rules when planning your actions."""
3701
3846
  print(f"[DASEIN] 🔧 Pre-loading embedding model for pipecleaner (found filter search rules)...")
3702
3847
  from .pipecleaner import _get_embedding_model
3703
3848
  try:
3704
- _get_embedding_model() # Warm up the model
3849
+ # Suppress protobuf warnings from sentence-transformers
3850
+ import warnings
3851
+ with warnings.catch_warnings():
3852
+ warnings.filterwarnings('ignore', category=Warning)
3853
+ _get_embedding_model() # Warm up the model
3705
3854
  print(f"[DASEIN] ✅ Embedding model pre-loaded successfully")
3706
3855
  except Exception as e:
3707
3856
  print(f"[DASEIN] ⚠️ Failed to pre-load embedding model: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dasein-core
3
- Version: 0.2.10
3
+ Version: 0.2.13
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=tQ4OtvWRG6rzYuXPKRj6DkcgIOM0kg3L1xNjOTYBf1Q,247127
3
+ dasein/api.py,sha256=qJVnKdeuCGsaDuwcPP6kiaEJKbO15DsPoMHtuNvSvuM,257060
4
4
  dasein/capture.py,sha256=D4DvknI2wbmVup5WqvNcgw-zW5riEstYG81Rl98uz6o,110942
5
5
  dasein/config.py,sha256=lXO8JG4RXbodn3gT5yEnuB0VRwWdrRVwhX3Rm06IZmU,1957
6
6
  dasein/events.py,sha256=mG-lnOvQoZUhXbrPSjrG4RME6ywUcbSZ04PscoJ15GI,12896
@@ -45,7 +45,7 @@ dasein/services/post_run_client.py,sha256=UjK3eqf7oWGSuWkKe0vQmeMS0yUUOhYFD4-SZ7
45
45
  dasein/services/pre_run_client.py,sha256=tXmz_PQaSfq0xwypiWUAqNkXOmREZ6EwXLC4OM89J-A,4317
46
46
  dasein/services/service_adapter.py,sha256=YHk41lR3PXh8WTmxOzzwKf6hwPYGqIdApI92vQKlkAY,7350
47
47
  dasein/services/service_config.py,sha256=8_4tpV4mZvfaOc5_yyHbOyL4rYsPHzkLTEY1rtYgLs8,1629
48
- dasein_core-0.2.10.dist-info/licenses/LICENSE,sha256=7FHjIFEKl_3hSc3tGUVEWmufC_3oi8rh_2zVuL7jMKs,1091
48
+ dasein_core-0.2.13.dist-info/licenses/LICENSE,sha256=7FHjIFEKl_3hSc3tGUVEWmufC_3oi8rh_2zVuL7jMKs,1091
49
49
  dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/LICENSE,sha256=OTPBdpebaLxtC8yQLH1sEw8dEn9Hbxe6XNuo2Zz9ABI,1056
50
50
  dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/LICENSES_SOURCES,sha256=INnfrNIVESJR8VNB7dGkex-Yvzk6IS8Q8ZT_3H7pipA,2347
51
51
  dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/METADATA,sha256=-vGqRxa_M2RwKtLjBhc4JlBQdJ3k7CwOnseT_ReYcic,2958
@@ -53,7 +53,7 @@ dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/RECORD,sha256=dDb6U7
53
53
  dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
54
54
  dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/entry_points.txt,sha256=OkWs-KxPJtDdpvIFCVXzDC9ECtejhPxv7pP3Tgk2cNg,47
55
55
  dasein/models/en_core_web_sm/en_core_web_sm-3.7.1.dist-info/top_level.txt,sha256=56OIuRbEuhr12HsM9XpCMnTtHRMgNC5Hje4Xeo8wF2c,15
56
- dasein_core-0.2.10.dist-info/METADATA,sha256=BotwsA09ka3tRHCKiI0Ms8Jb8Zss87Q5zBG0OL_3VuA,10297
57
- dasein_core-0.2.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
- dasein_core-0.2.10.dist-info/top_level.txt,sha256=6yYY9kltjvvPsg9K6KyMKRtzEr5qM7sHXN7VzmrDtp0,7
59
- dasein_core-0.2.10.dist-info/RECORD,,
56
+ dasein_core-0.2.13.dist-info/METADATA,sha256=dnUU3veXoiKLGCw4QWJ7Zjc3aKgiXS6ZYPbnizjrERQ,10297
57
+ dasein_core-0.2.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
+ dasein_core-0.2.13.dist-info/top_level.txt,sha256=6yYY9kltjvvPsg9K6KyMKRtzEr5qM7sHXN7VzmrDtp0,7
59
+ dasein_core-0.2.13.dist-info/RECORD,,