from typing import Any, Dict, Optional
_PATCHES: Dict[str, Dict[str, Any]] = {}
_SUPPORTED = frozenset(
["langchain", "llamaindex", "ag2", "crewai", "openai-agents", "autogen", "pageindex"]
)
def auto(
framework: str,
*,
exporter: Any = None,
context_version: Optional[str] = None,
async_capture: bool = True,
**kwargs: Any,
) -> Any:
if framework not in _SUPPORTED:
raise ValueError(
f"Unknown framework: {framework!r}. "
f"Supported: {sorted(_SUPPORTED)}"
)
if framework in _PATCHES:
return _PATCHES[framework]["handler"]
dispatch = {
"langchain": _auto_langchain,
"llamaindex": _auto_llamaindex,
"ag2": _auto_ag2,
"crewai": _auto_crewai,
"openai-agents": _auto_openai_agents,
"autogen": _auto_autogen,
"pageindex": _auto_pageindex,
}
return dispatch[framework](
exporter=exporter,
context_version=context_version,
async_capture=async_capture,
**kwargs,
)
def undo(framework: Optional[str] = None) -> None:
if framework is None:
for fw in list(_PATCHES.keys()):
_undo_one(fw)
else:
_undo_one(framework)
def _undo_one(framework: str) -> None:
patch_info = _PATCHES.pop(framework, None)
if patch_info is None:
return
for obj, attr, original in patch_info.get("undos", []):
try:
setattr(obj, attr, original)
except Exception:
pass
cleanup = patch_info.get("cleanup")
if callable(cleanup):
try:
cleanup()
except Exception:
pass
def _auto_langchain(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.langchain_handler import BriefcaseLangChainHandler
handler = BriefcaseLangChainHandler(
exporter=exporter,
context_version=context_version,
async_capture=async_capture,
**kwargs,
)
undos = []
try:
import langchain_core.runnables.config as _lc_config
_orig_ensure_config = _lc_config.ensure_config
def _patched_ensure_config(config=None, **kw):
cfg = _orig_ensure_config(config, **kw)
callbacks = list(cfg.get("callbacks") or [])
if handler not in callbacks:
callbacks.append(handler)
cfg["callbacks"] = callbacks
return cfg
_lc_config.ensure_config = _patched_ensure_config
undos.append((_lc_config, "ensure_config", _orig_ensure_config))
except Exception:
pass
_PATCHES["langchain"] = {"handler": handler, "undos": undos}
return handler
def _auto_llamaindex(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.llamaindex_handler import BriefcaseLlamaIndexHandler
handler = BriefcaseLlamaIndexHandler(
exporter=exporter,
async_capture=async_capture,
**kwargs,
)
undos = []
cleanup = None
try:
from llama_index.core import Settings
Settings.callback_manager.add_handler(handler)
def _cleanup():
try:
Settings.callback_manager.remove_handler(handler)
except Exception:
try:
existing = Settings.callback_manager.handlers
Settings.callback_manager.handlers = [
h for h in existing if h is not handler
]
except Exception:
pass
cleanup = _cleanup
except Exception:
pass
_PATCHES["llamaindex"] = {"handler": handler, "undos": undos, "cleanup": cleanup}
return handler
def _auto_ag2(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.ag2_handler import AG2HookTracer
tracer = AG2HookTracer(
exporter=exporter,
context_version=context_version,
async_capture=async_capture,
**kwargs,
)
undos = []
try:
import autogen as _ag2_mod
_orig_init = _ag2_mod.ConversableAgent.__init__
def _patched_init(self_agent, *args, **kw):
_orig_init(self_agent, *args, **kw)
try:
tracer.instrument(self_agent)
except Exception:
pass
_ag2_mod.ConversableAgent.__init__ = _patched_init
undos.append((_ag2_mod.ConversableAgent, "__init__", _orig_init))
except Exception:
pass
_PATCHES["ag2"] = {"handler": tracer, "undos": undos}
return tracer
def _auto_crewai(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.crewai_handler import CrewAIEventListener
listener = CrewAIEventListener(
exporter=exporter,
context_version=context_version,
async_capture=async_capture,
**kwargs,
)
_PATCHES["crewai"] = {"handler": listener, "undos": []}
return listener
def _auto_openai_agents(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.openai_agents_handler import install
tracer = install(
context_version=context_version,
async_capture=async_capture,
exporter=exporter,
)
_PATCHES["openai-agents"] = {"handler": tracer, "undos": []}
return tracer
def _auto_autogen(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.autogen_handler import install
handler = install(
context_version=context_version,
async_capture=async_capture,
exporter=exporter,
)
_PATCHES["autogen"] = {"handler": handler, "undos": []}
return handler
def _auto_pageindex(exporter, context_version, async_capture, **kwargs):
from briefcase.integrations.frameworks.pageindex_handler import PageIndexTracer
tracer = PageIndexTracer(
exporter=exporter,
context_version=context_version,
async_capture=async_capture,
**kwargs,
)
undos = []
try:
import pageindex as _pi_mod
_orig_chat = _pi_mod.PageIndexClient.chat_completions
_orig_init = _pi_mod.PageIndexClient.__init__
def _patched_init(client_self, *args, **kw):
_orig_init(client_self, *args, **kw)
tracer._client = client_self
def _patched_chat(client_self, messages, doc_id=None, **kw):
tracer._client = client_self
return tracer.chat_completions(messages=messages, doc_id=doc_id, **kw)
_pi_mod.PageIndexClient.__init__ = _patched_init
_pi_mod.PageIndexClient.chat_completions = _patched_chat
undos.append((_pi_mod.PageIndexClient, "__init__", _orig_init))
undos.append((_pi_mod.PageIndexClient, "chat_completions", _orig_chat))
except Exception:
pass
_PATCHES["pageindex"] = {"handler": tracer, "undos": undos}
return tracer