chore: remove deprecated files and clean up project structure
This commit is contained in:
@@ -14,12 +14,19 @@ from biz_bud.agents.buddy_state_manager import StateHelper
|
||||
|
||||
# Removed broken core import
|
||||
from biz_bud.core.errors import ValidationError
|
||||
from biz_bud.core.langgraph import StateUpdater, ensure_immutable_node, handle_errors, standard_node
|
||||
from biz_bud.core.langgraph import (
|
||||
StateUpdater,
|
||||
ensure_immutable_node,
|
||||
handle_errors,
|
||||
standard_node,
|
||||
)
|
||||
from biz_bud.logging import get_logger
|
||||
|
||||
# ToolFactory removed - using direct imports instead
|
||||
from biz_bud.states.buddy import BuddyState
|
||||
from biz_bud.tools.capabilities.extraction.core.base import extract_text_from_multimodal_content
|
||||
from biz_bud.tools.capabilities.extraction.core.base import (
|
||||
extract_text_from_multimodal_content,
|
||||
)
|
||||
from biz_bud.tools.capabilities.workflow.execution import (
|
||||
ExecutionRecordFactory,
|
||||
IntermediateResultsConverter,
|
||||
|
||||
@@ -12,7 +12,9 @@ from langchain_core.messages import HumanMessage
|
||||
from biz_bud.core.config.schemas import AppConfig
|
||||
from biz_bud.logging import get_logger
|
||||
from biz_bud.states.buddy import BuddyState
|
||||
from biz_bud.tools.capabilities.extraction.core.base import extract_text_from_multimodal_content
|
||||
from biz_bud.tools.capabilities.extraction.core.base import (
|
||||
extract_text_from_multimodal_content,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -26,7 +26,12 @@ from .research import (
|
||||
SearchOptimizationConfig,
|
||||
VectorStoreEnhancedConfig,
|
||||
)
|
||||
from .services import APIConfigModel, DatabaseConfigModel, ProxyConfigModel, RedisConfigModel
|
||||
from .services import (
|
||||
APIConfigModel,
|
||||
DatabaseConfigModel,
|
||||
ProxyConfigModel,
|
||||
RedisConfigModel,
|
||||
)
|
||||
from .tools import (
|
||||
BrowserConfig,
|
||||
ExtractToolConfigModel,
|
||||
|
||||
@@ -49,9 +49,18 @@ from .core import (
|
||||
create_status_router,
|
||||
create_threshold_router,
|
||||
)
|
||||
from .error_handling import detect_errors_list, fallback_to_default, handle_error, retry_on_failure
|
||||
from .error_handling import (
|
||||
detect_errors_list,
|
||||
fallback_to_default,
|
||||
handle_error,
|
||||
retry_on_failure,
|
||||
)
|
||||
from .flow_control import multi_step_progress, should_continue, timeout_check
|
||||
from .monitoring import check_resource_availability, log_and_monitor, trigger_notifications
|
||||
from .monitoring import (
|
||||
check_resource_availability,
|
||||
log_and_monitor,
|
||||
trigger_notifications,
|
||||
)
|
||||
from .secure_routing import (
|
||||
SecureGraphRouter,
|
||||
execute_graph_securely,
|
||||
|
||||
@@ -20,7 +20,13 @@ from openai import RateLimitError as OpenAIRateLimitError
|
||||
|
||||
from biz_bud.logging import error_highlight, warning_highlight
|
||||
|
||||
from .base import AuthenticationError, ErrorContext, ErrorNamespace, LLMError, RateLimitError
|
||||
from .base import (
|
||||
AuthenticationError,
|
||||
ErrorContext,
|
||||
ErrorNamespace,
|
||||
LLMError,
|
||||
RateLimitError,
|
||||
)
|
||||
|
||||
# Define specific retriable exceptions - no broad Exception catching
|
||||
RETRIABLE_EXCEPTIONS = (
|
||||
|
||||
@@ -251,7 +251,9 @@ if new_tools_available:
|
||||
|
||||
async def _validate():
|
||||
from biz_bud.services.factory import get_global_factory
|
||||
from biz_bud.tools.capabilities.url_processing.service import URLProcessingService
|
||||
from biz_bud.tools.capabilities.url_processing.service import (
|
||||
URLProcessingService,
|
||||
)
|
||||
factory = await get_global_factory()
|
||||
service = await factory.get_service(URLProcessingService)
|
||||
result = await service.validate_url(url, "strict" if strict else "standard")
|
||||
@@ -274,7 +276,9 @@ if new_tools_available:
|
||||
|
||||
async def _normalize():
|
||||
from biz_bud.services.factory import get_global_factory
|
||||
from biz_bud.tools.capabilities.url_processing.service import URLProcessingService
|
||||
from biz_bud.tools.capabilities.url_processing.service import (
|
||||
URLProcessingService,
|
||||
)
|
||||
factory = await get_global_factory()
|
||||
service = await factory.get_service(URLProcessingService)
|
||||
return service.normalize_url(url)
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
from typing import Any
|
||||
|
||||
# Context detection utilities - re-export from networking for convenience
|
||||
from ..networking import AsyncContextInfo, detect_async_context, run_in_appropriate_context
|
||||
from ..networking import (
|
||||
AsyncContextInfo,
|
||||
detect_async_context,
|
||||
run_in_appropriate_context,
|
||||
)
|
||||
from ..networking.async_utils import gather_with_concurrency
|
||||
from .json_extractor import (
|
||||
JsonExtractionError,
|
||||
|
||||
@@ -554,6 +554,7 @@ class JsonExtractorCore:
|
||||
raise ValidationError(f"Input text too long ({len(text)} chars), max allowed: {max_length}")
|
||||
|
||||
# Check for patterns that could cause ReDoS
|
||||
# These patterns are simple and safe to check with regular re.search
|
||||
dangerous_patterns = [
|
||||
r'(\{){10,}', # Many opening braces
|
||||
r'(\[){10,}', # Many opening brackets
|
||||
@@ -585,18 +586,26 @@ class JsonExtractorCore:
|
||||
|
||||
# Set up timeout alarm (Unix/Linux only)
|
||||
old_handler = None
|
||||
alarm_set = False
|
||||
try:
|
||||
old_handler = signal.signal(signal.SIGALRM, timeout_handler)
|
||||
signal.alarm(int(timeout_seconds))
|
||||
# Check if we can use signal.SIGALRM (Unix/Linux only)
|
||||
if hasattr(signal, 'SIGALRM'):
|
||||
old_handler = signal.signal(signal.SIGALRM, timeout_handler)
|
||||
signal.alarm(int(timeout_seconds))
|
||||
alarm_set = True
|
||||
yield
|
||||
except AttributeError:
|
||||
# Windows doesn't support SIGALRM, skip timeout protection
|
||||
yield
|
||||
finally:
|
||||
with contextlib.suppress(AttributeError, NameError):
|
||||
signal.alarm(0)
|
||||
if 'old_handler' in locals() and old_handler is not None:
|
||||
signal.signal(signal.SIGALRM, old_handler)
|
||||
# Only restore if we actually set an alarm
|
||||
if alarm_set:
|
||||
try:
|
||||
signal.alarm(0)
|
||||
if old_handler is not None:
|
||||
signal.signal(signal.SIGALRM, old_handler)
|
||||
except (AttributeError, ValueError):
|
||||
pass
|
||||
|
||||
def _validate_against_schema(self, data: JsonDict) -> tuple[bool, list[str]]:
|
||||
"""Validate extracted JSON against provided schema.
|
||||
@@ -744,12 +753,9 @@ class JsonExtractorCore:
|
||||
|
||||
if self.config.get("log_performance", True):
|
||||
logger.debug(
|
||||
"Starting JSON extraction",
|
||||
extra={
|
||||
"text_length": len(text),
|
||||
"text_preview": text[:100],
|
||||
"config": dict(self.config),
|
||||
}
|
||||
"Starting JSON extraction (length=%d, preview=%s...)",
|
||||
len(text),
|
||||
text[:50] if text else "",
|
||||
)
|
||||
|
||||
# Pre-process text
|
||||
@@ -765,12 +771,10 @@ class JsonExtractorCore:
|
||||
|
||||
if self.config.get("log_performance", True):
|
||||
logger.info(
|
||||
"JSON extraction successful",
|
||||
extra={
|
||||
"pattern_used": pattern_name,
|
||||
"extraction_time_ms": result["extraction_time_ms"],
|
||||
"recovery_used": result["recovery_used"],
|
||||
}
|
||||
"JSON extraction successful (pattern=%s, time=%.2fms, recovery=%s)",
|
||||
pattern_name,
|
||||
result["extraction_time_ms"],
|
||||
result["recovery_used"],
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -788,8 +792,8 @@ class JsonExtractorCore:
|
||||
)
|
||||
|
||||
logger.error(
|
||||
"JSON extraction completely failed",
|
||||
extra=extraction_error.to_extraction_context(),
|
||||
"JSON extraction completely failed (time=%.2fms)",
|
||||
elapsed * 1000,
|
||||
)
|
||||
|
||||
return self._create_result(
|
||||
@@ -903,8 +907,9 @@ class JsonExtractorCore:
|
||||
except Exception as e:
|
||||
if self.config.get("log_performance", True):
|
||||
logger.debug(
|
||||
f"Pattern {pattern_name} failed with exception",
|
||||
extra={"pattern": pattern_name, "error": str(e)}
|
||||
"Pattern %s failed with exception: %s",
|
||||
pattern_name,
|
||||
str(e),
|
||||
)
|
||||
|
||||
return self._create_result(
|
||||
|
||||
@@ -45,7 +45,9 @@ def _execute_with_timeout(func: Callable[[], Any], timeout_seconds: float, opera
|
||||
return future.result(timeout=timeout_seconds)
|
||||
except FutureTimeoutError as e:
|
||||
# Attempt to cancel the future (may not always work for CPU-bound tasks)
|
||||
future.cancel()
|
||||
cancelled = future.cancel()
|
||||
if not cancelled:
|
||||
logger.warning(f"Could not cancel regex {operation_type} task - it may continue running")
|
||||
raise TimeoutError(
|
||||
f"Regex {operation_type} exceeded {timeout_seconds}s timeout"
|
||||
) from e
|
||||
|
||||
@@ -688,7 +688,9 @@ class URLAnalyzer:
|
||||
if "cache_size" in config:
|
||||
cache_size = config["cache_size"]
|
||||
if cache_size < 0:
|
||||
from biz_bud.core.errors.specialized_exceptions import URLConfigurationError
|
||||
from biz_bud.core.errors.specialized_exceptions import (
|
||||
URLConfigurationError,
|
||||
)
|
||||
raise URLConfigurationError(
|
||||
"cache_size must be a non-negative integer",
|
||||
config_field="cache_size",
|
||||
@@ -716,7 +718,9 @@ class URLAnalyzer:
|
||||
if processor_config is not None and isinstance(processor_config, dict):
|
||||
validation_level = processor_config.get("validation_level")
|
||||
if validation_level and validation_level not in ["basic", "standard", "strict"]:
|
||||
from biz_bud.core.errors.specialized_exceptions import URLConfigurationError
|
||||
from biz_bud.core.errors.specialized_exceptions import (
|
||||
URLConfigurationError,
|
||||
)
|
||||
raise URLConfigurationError(
|
||||
"validation_level must be 'basic', 'standard', or 'strict'",
|
||||
config_field="validation_level",
|
||||
@@ -860,7 +864,9 @@ class URLAnalyzer:
|
||||
logger.error(f"Enhanced URL processing failed: {e}")
|
||||
# Import here to avoid circular import
|
||||
try:
|
||||
from biz_bud.core.errors.specialized_exceptions import URLProcessingError
|
||||
from biz_bud.core.errors.specialized_exceptions import (
|
||||
URLProcessingError,
|
||||
)
|
||||
|
||||
raise URLProcessingError(
|
||||
f"Bulk URL processing failed: {e}",
|
||||
@@ -986,7 +992,9 @@ class URLAnalyzer:
|
||||
logger.error(f"URL validation failed for {url}: {e}")
|
||||
# Import here to avoid circular import
|
||||
try:
|
||||
from biz_bud.core.errors.specialized_exceptions import URLValidationError
|
||||
from biz_bud.core.errors.specialized_exceptions import (
|
||||
URLValidationError,
|
||||
)
|
||||
|
||||
raise URLValidationError(
|
||||
f"URL validation failed for {url}: {e}",
|
||||
@@ -1040,7 +1048,9 @@ class URLAnalyzer:
|
||||
logger.error(f"URL normalization failed for {url}: {e}")
|
||||
# Import here to avoid circular import
|
||||
try:
|
||||
from biz_bud.core.errors.specialized_exceptions import URLNormalizationError
|
||||
from biz_bud.core.errors.specialized_exceptions import (
|
||||
URLNormalizationError,
|
||||
)
|
||||
|
||||
raise URLNormalizationError(
|
||||
f"URL normalization failed for {url}: {e}",
|
||||
@@ -1094,7 +1104,9 @@ class URLAnalyzer:
|
||||
logger.error(f"URL deduplication failed: {e}")
|
||||
# Import here to avoid circular import
|
||||
try:
|
||||
from biz_bud.core.errors.specialized_exceptions import URLDeduplicationError
|
||||
from biz_bud.core.errors.specialized_exceptions import (
|
||||
URLDeduplicationError,
|
||||
)
|
||||
|
||||
raise URLDeduplicationError(
|
||||
f"URL deduplication failed: {e}",
|
||||
|
||||
@@ -50,7 +50,11 @@ from .config import (
|
||||
validate_tools_config,
|
||||
)
|
||||
from .content_type import detect_content_type
|
||||
from .content_validation import preprocess_content, should_skip_content, validate_content
|
||||
from .content_validation import (
|
||||
preprocess_content,
|
||||
should_skip_content,
|
||||
validate_content,
|
||||
)
|
||||
from .document_processing import is_document_url, process_document
|
||||
from .graph_validation import (
|
||||
GraphValidationError,
|
||||
|
||||
@@ -35,7 +35,12 @@ from pydantic import BaseModel, ConfigDict
|
||||
from biz_bud.core.types import ErrorInfo, create_error_info
|
||||
|
||||
# Business Buddy state and logging utilities
|
||||
from biz_bud.logging import error_highlight, get_logger, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
error_highlight,
|
||||
get_logger,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@ from .graph import GRAPH_METADATA, catalog_graph_factory, create_catalog_graph
|
||||
|
||||
# Import catalog-specific nodes from nodes directory
|
||||
from .nodes import c_intel_node # All available catalog nodes
|
||||
from .nodes import catalog_research_node, component_default_node, load_catalog_data_node
|
||||
from .nodes import (
|
||||
catalog_research_node,
|
||||
component_default_node,
|
||||
load_catalog_data_node,
|
||||
)
|
||||
|
||||
# Create aliases for expected nodes
|
||||
catalog_impact_analysis_node = c_intel_node # Main impact analysis
|
||||
|
||||
@@ -12,7 +12,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
|
||||
@standard_node(node_name="catalog_impact_analysis", metric_name="impact_analysis")
|
||||
|
||||
@@ -191,9 +191,6 @@ from biz_bud.core.langgraph import create_type_safe_wrapper
|
||||
route_error_severity_wrapper = create_type_safe_wrapper(route_error_severity)
|
||||
route_llm_output_wrapper = create_type_safe_wrapper(route_llm_output)
|
||||
|
||||
|
||||
|
||||
|
||||
# Replace manual routing with edge helper-based recovery routing
|
||||
def _determine_recovery_action(state: dict[str, Any]) -> str:
|
||||
"""Determine recovery action based on error handler decisions.
|
||||
|
||||
@@ -12,7 +12,12 @@ The Paperless graph integrates with Paperless-NGX API to provide
|
||||
automated document management capabilities within the Business Buddy framework.
|
||||
"""
|
||||
|
||||
from .graph import GRAPH_METADATA, create_paperless_graph, paperless_graph, paperless_graph_factory
|
||||
from .graph import (
|
||||
GRAPH_METADATA,
|
||||
create_paperless_graph,
|
||||
paperless_graph,
|
||||
paperless_graph_factory,
|
||||
)
|
||||
|
||||
# Import Paperless-specific nodes
|
||||
from .nodes import (
|
||||
|
||||
@@ -35,7 +35,9 @@ from biz_bud.core.utils.graph_helpers import (
|
||||
from biz_bud.logging import get_logger
|
||||
from biz_bud.prompts.paperless import PAPERLESS_SYSTEM_PROMPT
|
||||
from biz_bud.states.base import BaseState
|
||||
from biz_bud.tools.capabilities.batch.receipt_processing import batch_process_receipt_items
|
||||
from biz_bud.tools.capabilities.batch.receipt_processing import (
|
||||
batch_process_receipt_items,
|
||||
)
|
||||
from biz_bud.tools.capabilities.database.tool import (
|
||||
postgres_reconcile_receipt_items,
|
||||
postgres_search_normalized_items,
|
||||
@@ -87,24 +89,30 @@ async def get_paperless_tags_batch(tag_ids: list[int]) -> dict[str, Any]:
|
||||
"""
|
||||
try:
|
||||
# Execute tag fetches concurrently
|
||||
tasks = []
|
||||
for tag_id in tag_ids:
|
||||
task = asyncio.create_task(get_paperless_tag.ainvoke({"tag_id": tag_id}))
|
||||
tasks.append((tag_id, task))
|
||||
tasks = [
|
||||
asyncio.create_task(get_paperless_tag.ainvoke({"tag_id": tag_id}))
|
||||
for tag_id in tag_ids
|
||||
]
|
||||
|
||||
# Gather results with timeout
|
||||
# Gather results with timeout and proper exception handling
|
||||
results_list: list[dict[str, Any] | Exception]
|
||||
try:
|
||||
gathered_results = await asyncio.wait_for(
|
||||
asyncio.gather(*tasks, return_exceptions=True),
|
||||
timeout=5.0
|
||||
)
|
||||
# Cast the gathered results to the expected type
|
||||
results_list = cast(list[dict[str, Any] | Exception], list(gathered_results))
|
||||
except asyncio.TimeoutError:
|
||||
results_list = [{"success": False, "error": "Timeout fetching tag"} for _ in tag_ids]
|
||||
|
||||
# Process results
|
||||
results = {}
|
||||
for tag_id, task in tasks:
|
||||
try:
|
||||
result = await asyncio.wait_for(task, timeout=5.0)
|
||||
for tag_id, result in zip(tag_ids, results_list):
|
||||
if isinstance(result, Exception):
|
||||
results[str(tag_id)] = {"success": False, "error": str(result)}
|
||||
else:
|
||||
results[str(tag_id)] = result
|
||||
except asyncio.TimeoutError:
|
||||
results[str(tag_id)] = {
|
||||
"success": False,
|
||||
"error": "Timeout fetching tag",
|
||||
}
|
||||
except Exception as e:
|
||||
results[str(tag_id)] = {"success": False, "error": str(e)}
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
|
||||
@@ -13,7 +13,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
|
||||
class DocumentResult(TypedDict):
|
||||
|
||||
@@ -8,7 +8,12 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage, ToolMessage
|
||||
from langchain_core.messages import (
|
||||
BaseMessage,
|
||||
HumanMessage,
|
||||
SystemMessage,
|
||||
ToolMessage,
|
||||
)
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.config.constants import STATE_KEY_MESSAGES
|
||||
|
||||
@@ -12,7 +12,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
|
||||
@standard_node(
|
||||
|
||||
@@ -17,7 +17,12 @@ from pydantic import BaseModel, Field
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
from biz_bud.states.receipt import ReceiptLineItem, ReceiptState
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
# Import from local nodes directory
|
||||
try:
|
||||
|
||||
@@ -6,7 +6,9 @@ with specific defaults for the RAG graph use case.
|
||||
|
||||
from typing import Any
|
||||
|
||||
from biz_bud.nodes.integrations.firecrawl.config import FirecrawlSettings
|
||||
from biz_bud.nodes.integrations.firecrawl.config import (
|
||||
FirecrawlSettings,
|
||||
)
|
||||
from biz_bud.nodes.integrations.firecrawl.config import (
|
||||
load_firecrawl_settings as _load_firecrawl_settings,
|
||||
)
|
||||
|
||||
@@ -11,7 +11,9 @@ from biz_bud.core.utils.regex_security import search_safe
|
||||
from biz_bud.core.utils.url_analyzer import analyze_url_type
|
||||
from biz_bud.logging import get_logger
|
||||
from biz_bud.nodes import NodeLLMConfigOverride, call_model_node
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import extract_json_from_text
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import (
|
||||
extract_json_from_text,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -13,7 +13,12 @@ The research graph is designed to be used both standalone and as a tool
|
||||
within larger workflows through the graph-as-tool pattern.
|
||||
"""
|
||||
|
||||
from .graph import GRAPH_METADATA, create_research_graph, get_research_graph, research_graph_factory
|
||||
from .graph import (
|
||||
GRAPH_METADATA,
|
||||
create_research_graph,
|
||||
get_research_graph,
|
||||
research_graph_factory,
|
||||
)
|
||||
|
||||
# Import research-specific nodes
|
||||
from .nodes import derive_research_query_node
|
||||
|
||||
@@ -8,7 +8,9 @@ from .prepare import prepare_search_results
|
||||
from .query_derivation import derive_research_query_node
|
||||
from .synthesis import synthesize_search_results
|
||||
from .synthesis_processing import derive_research_query_node as enhanced_derive_research_query_node
|
||||
from .synthesis_processing import synthesize_research_results_node
|
||||
from .synthesis_processing import (
|
||||
synthesize_research_results_node,
|
||||
)
|
||||
from .synthesis_processing import (
|
||||
validate_research_synthesis_node as enhanced_validate_research_synthesis_node,
|
||||
)
|
||||
|
||||
@@ -15,11 +15,15 @@ from biz_bud.states.research import ResearchState
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from biz_bud.core import ErrorInfo
|
||||
|
||||
from biz_bud.states.domain_types import SourceDict
|
||||
|
||||
from biz_bud.core import BusinessBuddyError, ErrorCategory, ErrorContext, ErrorSeverity
|
||||
from biz_bud.logging import error_highlight, get_logger, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
error_highlight,
|
||||
get_logger,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -12,7 +12,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
|
||||
@standard_node(node_name="research_query_derivation", metric_name="query_derivation")
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
from .analyzer import error_analyzer_node
|
||||
from .guidance import generate_error_summary, user_guidance_node
|
||||
from .interceptor import error_interceptor_node, should_intercept_error
|
||||
from .recovery import recovery_executor_node, recovery_planner_node, register_custom_recovery_action
|
||||
from .recovery import (
|
||||
recovery_executor_node,
|
||||
recovery_planner_node,
|
||||
register_custom_recovery_action,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"error_interceptor_node",
|
||||
|
||||
@@ -10,7 +10,11 @@ from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.core.utils.regex_security import search_safe
|
||||
from biz_bud.logging import get_logger
|
||||
from biz_bud.services.llm.client import LangchainLLMClient
|
||||
from biz_bud.states.error_handling import ErrorAnalysis, ErrorContext, ErrorHandlingState
|
||||
from biz_bud.states.error_handling import (
|
||||
ErrorAnalysis,
|
||||
ErrorContext,
|
||||
ErrorHandlingState,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -11,7 +11,11 @@ from langchain_core.runnables import RunnableConfig
|
||||
from biz_bud.core.errors import ValidationError
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import get_logger
|
||||
from biz_bud.states.error_handling import ErrorHandlingState, RecoveryAction, RecoveryResult
|
||||
from biz_bud.states.error_handling import (
|
||||
ErrorHandlingState,
|
||||
RecoveryAction,
|
||||
RecoveryResult,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -21,7 +21,12 @@ from typing import Any, TypedDict
|
||||
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import ErrorCategory, ErrorSeverity, create_error_info, report_error
|
||||
from biz_bud.core.errors import (
|
||||
ErrorCategory,
|
||||
ErrorSeverity,
|
||||
create_error_info,
|
||||
report_error,
|
||||
)
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.core.types import ExtractedEntity
|
||||
from biz_bud.logging import error_highlight, info_highlight, warning_highlight
|
||||
|
||||
@@ -29,7 +29,9 @@ from biz_bud.core.validation.chunking import chunk_text
|
||||
from biz_bud.logging import async_error_highlight, get_logger, info_highlight
|
||||
from biz_bud.nodes.models import ExtractionResultModel
|
||||
from biz_bud.prompts.research import EXTRACTION_PROMPT_TEMPLATE
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import extract_json_from_text
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import (
|
||||
extract_json_from_text,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -8,7 +8,11 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from biz_bud.core.langgraph import ConfigurationProvider, ensure_immutable_node, standard_node
|
||||
from biz_bud.core.langgraph import (
|
||||
ConfigurationProvider,
|
||||
ensure_immutable_node,
|
||||
standard_node,
|
||||
)
|
||||
from biz_bud.core.types import create_error_info
|
||||
from biz_bud.logging import get_logger, info_highlight, warning_highlight
|
||||
|
||||
|
||||
@@ -46,7 +46,13 @@ Modules:
|
||||
from .batch_process import batch_process_urls_node
|
||||
from .discover_urls import discover_urls_node
|
||||
from .route_url import route_url_node
|
||||
from .scrape_url import ScrapedContent, ScrapeNodeConfig, ScrapeNodeOutput, URLInfo, scrape_url_node
|
||||
from .scrape_url import (
|
||||
ScrapedContent,
|
||||
ScrapeNodeConfig,
|
||||
ScrapeNodeOutput,
|
||||
URLInfo,
|
||||
scrape_url_node,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Main nodes
|
||||
|
||||
@@ -18,7 +18,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
from .scrape_url import scrape_url_node
|
||||
|
||||
|
||||
@@ -15,7 +15,12 @@ from langchain_core.runnables import RunnableConfig
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.core.utils.url_analyzer import analyze_url_type
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
debug_highlight,
|
||||
error_highlight,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
|
||||
|
||||
class URLInfo(TypedDict):
|
||||
|
||||
@@ -460,7 +460,12 @@ from .orchestrator import optimized_search_node
|
||||
from .query_optimizer import OptimizedQuery, QueryOptimizer, QueryType
|
||||
from .ranker import RankedSearchResult, SearchResultRanker
|
||||
from .research_web_search import research_web_search_node
|
||||
from .search_orchestrator import ConcurrentSearchOrchestrator, SearchBatch, SearchStatus, SearchTask
|
||||
from .search_orchestrator import (
|
||||
ConcurrentSearchOrchestrator,
|
||||
SearchBatch,
|
||||
SearchStatus,
|
||||
SearchTask,
|
||||
)
|
||||
from .web_search import SearchNodeConfig, SearchNodeOutput, web_search_node
|
||||
|
||||
__all__ = [
|
||||
|
||||
@@ -18,7 +18,9 @@ from langchain_core.runnables import RunnableConfig
|
||||
# Removed broken core import
|
||||
from biz_bud.core.errors import ConfigurationError, ParsingError
|
||||
from biz_bud.logging import get_logger
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import extract_json_from_text
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import (
|
||||
extract_json_from_text,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from biz_bud.states.research import ResearchState
|
||||
|
||||
@@ -13,7 +13,10 @@ from langchain_core.runnables import RunnableConfig
|
||||
from biz_bud.core.errors import create_error_info
|
||||
from biz_bud.core.langgraph import standard_node
|
||||
from biz_bud.logging import debug_highlight, error_highlight, info_highlight
|
||||
from biz_bud.tools.capabilities.url_processing import discover_urls, discover_urls_detailed
|
||||
from biz_bud.tools.capabilities.url_processing import (
|
||||
discover_urls,
|
||||
discover_urls_detailed,
|
||||
)
|
||||
|
||||
|
||||
@standard_node(node_name="discover_urls", metric_name="url_discovery")
|
||||
|
||||
@@ -475,7 +475,9 @@ class ServiceFactory:
|
||||
from biz_bud.tools.capabilities.extraction.structured import (
|
||||
extract_structured_content,
|
||||
)
|
||||
from biz_bud.tools.capabilities.fetch.tool import fetch_content_from_urls
|
||||
from biz_bud.tools.capabilities.fetch.tool import (
|
||||
fetch_content_from_urls,
|
||||
)
|
||||
|
||||
tools.extend([extract_structured_content, fetch_content_from_urls])
|
||||
elif capability in ["document_management", "paperless_ngx"]:
|
||||
|
||||
@@ -10,7 +10,14 @@ import asyncio
|
||||
import concurrent.futures
|
||||
import json
|
||||
from typing import cast # noqa: ANN401,
|
||||
from typing import TYPE_CHECKING, Any, AsyncGenerator, Callable, Literal, Sequence
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
AsyncGenerator,
|
||||
Callable,
|
||||
Literal,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
|
||||
@@ -36,9 +43,16 @@ from biz_bud.core.tool_types import (
|
||||
from biz_bud.core.utils.cache import LRUCacheWithExpiration
|
||||
from biz_bud.core.utils.capability_inference import infer_capabilities_from_messages
|
||||
from biz_bud.core.validation import merge_chunk_results
|
||||
from biz_bud.logging import error_highlight, get_logger, info_highlight, warning_highlight
|
||||
from biz_bud.logging import (
|
||||
error_highlight,
|
||||
get_logger,
|
||||
info_highlight,
|
||||
warning_highlight,
|
||||
)
|
||||
from biz_bud.services.base import BaseService, BaseServiceConfig
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import count_tokens
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import (
|
||||
count_tokens,
|
||||
)
|
||||
|
||||
from .config import get_model_params_from_config
|
||||
from .types import (
|
||||
@@ -506,7 +520,9 @@ class LangchainLLMClient(BaseService[LLMServiceConfig]):
|
||||
from biz_bud.tools.capabilities.extraction.structured import (
|
||||
extract_structured_content,
|
||||
)
|
||||
from biz_bud.tools.capabilities.fetch.tool import fetch_content_from_urls
|
||||
from biz_bud.tools.capabilities.fetch.tool import (
|
||||
fetch_content_from_urls,
|
||||
)
|
||||
|
||||
tools.extend([extract_structured_content, fetch_content_from_urls])
|
||||
elif capability in ["document_management", "paperless_ngx"]:
|
||||
|
||||
@@ -15,11 +15,15 @@ from typing import TYPE_CHECKING, TypedDict, cast
|
||||
from biz_bud.core.errors import ErrorNamespace, JsonParsingError, ParsingError
|
||||
from biz_bud.core.utils.json_extractor import JsonRecoveryStrategies
|
||||
from biz_bud.logging import error_highlight, get_logger, warning_highlight
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import extract_json_from_text
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import (
|
||||
extract_json_from_text,
|
||||
)
|
||||
|
||||
from .types import MAX_SUMMARY_TOKENS # noqa: F401
|
||||
from .types import LLMCallKwargsTypedDict # noqa: F401
|
||||
from .types import LLMJsonResponseTypedDict
|
||||
from .types import (
|
||||
LLMJsonResponseTypedDict,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .client import LangchainLLMClient # noqa: F401
|
||||
|
||||
@@ -264,7 +264,10 @@ class CacheSingletonManager(BaseSingletonManager):
|
||||
|
||||
async def _reset_impl(self) -> None:
|
||||
"""Reset cache singletons for testing."""
|
||||
from biz_bud.core.caching.decorators import _cache_decorator_manager, _default_cache_manager
|
||||
from biz_bud.core.caching.decorators import (
|
||||
_cache_decorator_manager,
|
||||
_default_cache_manager,
|
||||
)
|
||||
|
||||
await _default_cache_manager.cleanup()
|
||||
await _cache_decorator_manager.cleanup()
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
from typing import TYPE_CHECKING, Any, TypedDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from biz_bud.states.common_types import AnalysisPlanTypedDict, InterpretationResult, Report
|
||||
from biz_bud.states.common_types import (
|
||||
AnalysisPlanTypedDict,
|
||||
InterpretationResult,
|
||||
Report,
|
||||
)
|
||||
else:
|
||||
# Runtime fallback - these are TypedDict types
|
||||
AnalysisPlanTypedDict = dict
|
||||
|
||||
@@ -7,6 +7,7 @@ from typing import Any
|
||||
from langchain_core.tools import tool
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from biz_bud.core.utils.regex_security import findall_safe
|
||||
from biz_bud.tools.capabilities.extraction.receipt import (
|
||||
determine_canonical_name,
|
||||
extract_structured_line_item_data,
|
||||
@@ -41,18 +42,24 @@ def extract_prices_from_text(text: str) -> list[float]:
|
||||
]
|
||||
|
||||
for pattern in price_patterns:
|
||||
matches = re.findall(pattern, text, re.IGNORECASE)
|
||||
for match in matches:
|
||||
try:
|
||||
# Clean up the match (remove commas)
|
||||
clean_match = match.replace(',', '') if isinstance(match, str) else match
|
||||
price_val = float(clean_match)
|
||||
try:
|
||||
# Use safe regex findall with timeout protection
|
||||
matches = findall_safe(pattern, text, re.IGNORECASE, timeout=1.0)
|
||||
for match in matches:
|
||||
try:
|
||||
# Clean up the match (remove commas)
|
||||
clean_match = match.replace(',', '') if isinstance(match, str) else match
|
||||
price_val = float(clean_match)
|
||||
|
||||
# Filter reasonable price ranges for food items (0.10 to 999.99)
|
||||
if 0.10 <= price_val <= 999.99:
|
||||
prices.append(price_val)
|
||||
except (ValueError, TypeError):
|
||||
continue
|
||||
# Filter reasonable price ranges for food items (0.10 to 999.99)
|
||||
if 0.10 <= price_val <= 999.99:
|
||||
prices.append(price_val)
|
||||
except (ValueError, TypeError):
|
||||
continue
|
||||
except Exception:
|
||||
# Skip pattern if it fails to compile or execute safely
|
||||
logger.warning(f"Failed to process price pattern safely: {pattern}")
|
||||
continue
|
||||
|
||||
# Remove duplicates and sort
|
||||
return sorted(list(set(prices)))
|
||||
@@ -157,7 +164,9 @@ async def batch_process_receipt_items(
|
||||
try:
|
||||
from biz_bud.core.config.loader import load_config
|
||||
from biz_bud.services.factory import get_global_factory
|
||||
from biz_bud.tools.capabilities.database.tool import postgres_reconcile_receipt_items
|
||||
from biz_bud.tools.capabilities.database.tool import (
|
||||
postgres_reconcile_receipt_items,
|
||||
)
|
||||
from biz_bud.tools.capabilities.search.tool import web_search
|
||||
|
||||
# Ensure global factory is initialized with proper config for web_search to work
|
||||
@@ -437,4 +446,4 @@ async def batch_process_receipt_items(
|
||||
f"{processing_stats['failed_items']} failed)"
|
||||
)
|
||||
|
||||
return result
|
||||
return result
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Database operations tools consolidating R2R, vector search, document management, and PostgreSQL operations."""
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from langchain_core.tools import tool
|
||||
@@ -361,13 +362,18 @@ async def postgres_reconcile_receipt_items(
|
||||
db_password = os.getenv("POSTGRES_PASSWORD", "")
|
||||
db_name = os.getenv("POSTGRES_DB", "langgraph_db")
|
||||
|
||||
# Connect to PostgreSQL
|
||||
conn = await asyncpg.connect(
|
||||
host=db_host,
|
||||
port=db_port,
|
||||
user=db_user,
|
||||
password=db_password,
|
||||
database=db_name,
|
||||
# Connect to PostgreSQL with timeout and connection limits
|
||||
conn = await asyncio.wait_for(
|
||||
asyncpg.connect(
|
||||
host=db_host,
|
||||
port=db_port,
|
||||
user=db_user,
|
||||
password=db_password,
|
||||
database=db_name,
|
||||
command_timeout=30,
|
||||
server_settings={'application_name': 'paperless_agent'}
|
||||
),
|
||||
timeout=10.0
|
||||
)
|
||||
|
||||
reconciliation_results = []
|
||||
@@ -932,13 +938,18 @@ async def postgres_search_normalized_items(
|
||||
db_password = os.getenv("POSTGRES_PASSWORD", "")
|
||||
db_name = os.getenv("POSTGRES_DB", "langgraph_db")
|
||||
|
||||
# Connect to PostgreSQL
|
||||
conn = await asyncpg.connect(
|
||||
host=db_host,
|
||||
port=db_port,
|
||||
user=db_user,
|
||||
password=db_password,
|
||||
database=db_name,
|
||||
# Connect to PostgreSQL with timeout and connection limits
|
||||
conn = await asyncio.wait_for(
|
||||
asyncpg.connect(
|
||||
host=db_host,
|
||||
port=db_port,
|
||||
user=db_user,
|
||||
password=db_password,
|
||||
database=db_name,
|
||||
command_timeout=30,
|
||||
server_settings={'application_name': 'paperless_agent'}
|
||||
),
|
||||
timeout=10.0
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
"""Numeric extraction tools."""
|
||||
|
||||
from .numeric import extract_monetary_values, extract_percentages, extract_year
|
||||
from .quality import assess_source_quality, extract_credibility_terms, rate_statistic_quality
|
||||
from .quality import (
|
||||
assess_source_quality,
|
||||
extract_credibility_terms,
|
||||
rate_statistic_quality,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"extract_monetary_values",
|
||||
|
||||
@@ -5,7 +5,9 @@ import re
|
||||
from typing import Any
|
||||
|
||||
from biz_bud.core.utils.regex_security import findall_safe, search_safe
|
||||
from biz_bud.tools.capabilities.extraction.numeric.numeric import extract_monetary_values
|
||||
from biz_bud.tools.capabilities.extraction.numeric.numeric import (
|
||||
extract_monetary_values,
|
||||
)
|
||||
from biz_bud.tools.capabilities.extraction.text.structured_extraction import (
|
||||
extract_key_value_pairs,
|
||||
extract_structured_data,
|
||||
|
||||
@@ -11,7 +11,12 @@ Available tools:
|
||||
- filter_scraping_results: Filter results by quality criteria
|
||||
"""
|
||||
|
||||
from .tool import filter_scraping_results, list_scrape_providers, scrape_url, scrape_urls_batch
|
||||
from .tool import (
|
||||
filter_scraping_results,
|
||||
list_scrape_providers,
|
||||
scrape_url,
|
||||
scrape_urls_batch,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"scrape_url",
|
||||
|
||||
@@ -9,7 +9,12 @@ from __future__ import annotations
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any
|
||||
|
||||
from .models import BatchProcessingResult, DiscoveryResult, ProcessedURL, ValidationResult
|
||||
from .models import (
|
||||
BatchProcessingResult,
|
||||
DiscoveryResult,
|
||||
ProcessedURL,
|
||||
ValidationResult,
|
||||
)
|
||||
|
||||
|
||||
class URLValidationProvider(ABC):
|
||||
|
||||
@@ -30,7 +30,11 @@ from .execution import (
|
||||
create_success_execution_record,
|
||||
format_final_workflow_response,
|
||||
)
|
||||
from .planning import extract_plan_dependencies, parse_execution_plan, validate_execution_plan
|
||||
from .planning import (
|
||||
extract_plan_dependencies,
|
||||
parse_execution_plan,
|
||||
validate_execution_plan,
|
||||
)
|
||||
from .tool import (
|
||||
create_agent_workflow,
|
||||
escalate_to_human,
|
||||
|
||||
@@ -49,7 +49,11 @@ class TestR2RMultiPageE2E:
|
||||
self, mock_firecrawl, mock_stream_writer, cleanup_r2r, url_to_rag_state_factory
|
||||
):
|
||||
"""Test complete pipeline from crawl to R2R upload."""
|
||||
from biz_bud.tools.models import FirecrawlData, FirecrawlMetadata, FirecrawlResult
|
||||
from biz_bud.tools.models import (
|
||||
FirecrawlData,
|
||||
FirecrawlMetadata,
|
||||
FirecrawlResult,
|
||||
)
|
||||
|
||||
# Mock Firecrawl response
|
||||
mock_pages = [
|
||||
|
||||
@@ -341,7 +341,11 @@ async def test_optimized_state_creation() -> None:
|
||||
@pytest.mark.asyncio
|
||||
async def test_backward_compatibility() -> None:
|
||||
"""Test that backward compatibility is maintained."""
|
||||
from biz_bud.graphs.graph import create_initial_state_sync, get_graph, get_initial_state
|
||||
from biz_bud.graphs.graph import (
|
||||
create_initial_state_sync,
|
||||
get_graph,
|
||||
get_initial_state,
|
||||
)
|
||||
|
||||
# Test sync functions still work
|
||||
graph = get_graph()
|
||||
|
||||
@@ -298,7 +298,9 @@ class TestResearchGraphWiring:
|
||||
return_value=mock_service_factory,
|
||||
):
|
||||
# Create and run just the synthesis part
|
||||
from biz_bud.graphs.research.nodes.synthesis import synthesize_search_results
|
||||
from biz_bud.graphs.research.nodes.synthesis import (
|
||||
synthesize_search_results,
|
||||
)
|
||||
|
||||
# synthesize_search_results creates its own service factory from config
|
||||
result = await synthesize_search_results(state)
|
||||
|
||||
@@ -6,7 +6,10 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.graphs.rag.nodes.upload_r2r import extract_collection_name, upload_to_r2r_node
|
||||
from biz_bud.graphs.rag.nodes.upload_r2r import (
|
||||
extract_collection_name,
|
||||
upload_to_r2r_node,
|
||||
)
|
||||
from biz_bud.states.url_to_rag import URLToRAGState
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
|
||||
from biz_bud.graphs.rag.nodes.analyzer import analyze_content_for_rag_node
|
||||
from biz_bud.graphs.rag.nodes.upload_r2r import extract_collection_name, upload_to_r2r_node
|
||||
from biz_bud.graphs.rag.nodes.upload_r2r import (
|
||||
extract_collection_name,
|
||||
upload_to_r2r_node,
|
||||
)
|
||||
from biz_bud.states.url_to_rag import URLToRAGState
|
||||
|
||||
|
||||
|
||||
@@ -148,7 +148,9 @@ async def test_r2r_upload_node():
|
||||
@pytest.mark.asyncio
|
||||
async def test_status_summary_node():
|
||||
"""Test the status summary node in isolation."""
|
||||
from biz_bud.graphs.rag.nodes.scraping.scrape_summary import scrape_status_summary_node
|
||||
from biz_bud.graphs.rag.nodes.scraping.scrape_summary import (
|
||||
scrape_status_summary_node,
|
||||
)
|
||||
|
||||
# Create state with progress
|
||||
state: URLToRAGState = {
|
||||
|
||||
@@ -465,7 +465,10 @@ class TestToolsConfigModel:
|
||||
|
||||
def test_tools_config_creation(self):
|
||||
"""Test ToolsConfigModel creation."""
|
||||
from biz_bud.core.config.schemas.tools import ExtractToolConfigModel, SearchToolConfigModel
|
||||
from biz_bud.core.config.schemas.tools import (
|
||||
ExtractToolConfigModel,
|
||||
SearchToolConfigModel,
|
||||
)
|
||||
tools_config = ToolsConfigModel(
|
||||
search=SearchToolConfigModel(),
|
||||
extract=ExtractToolConfigModel()
|
||||
@@ -478,7 +481,10 @@ class TestToolsConfigModel:
|
||||
|
||||
def test_tools_config_defaults(self):
|
||||
"""Test ToolsConfigModel with default values."""
|
||||
from biz_bud.core.config.schemas.tools import ExtractToolConfigModel, SearchToolConfigModel
|
||||
from biz_bud.core.config.schemas.tools import (
|
||||
ExtractToolConfigModel,
|
||||
SearchToolConfigModel,
|
||||
)
|
||||
tools_config = ToolsConfigModel(
|
||||
search=SearchToolConfigModel(),
|
||||
extract=ExtractToolConfigModel()
|
||||
@@ -491,7 +497,10 @@ class TestToolsConfigModel:
|
||||
def test_tools_config_validation(self):
|
||||
"""Test ToolsConfigModel field validation."""
|
||||
# Test invalid concurrent tools count
|
||||
from biz_bud.core.config.schemas.tools import ExtractToolConfigModel, SearchToolConfigModel
|
||||
from biz_bud.core.config.schemas.tools import (
|
||||
ExtractToolConfigModel,
|
||||
SearchToolConfigModel,
|
||||
)
|
||||
|
||||
# ToolsConfigModel validation is done at the tool level, not the main config level
|
||||
tools_config = ToolsConfigModel(
|
||||
@@ -915,7 +924,10 @@ class TestConfigurationIntegration:
|
||||
def test_full_configuration_compatibility(self):
|
||||
"""Test that all configuration components work together."""
|
||||
# Create comprehensive configuration
|
||||
from biz_bud.core.config.schemas.tools import ExtractToolConfigModel, SearchToolConfigModel
|
||||
from biz_bud.core.config.schemas.tools import (
|
||||
ExtractToolConfigModel,
|
||||
SearchToolConfigModel,
|
||||
)
|
||||
from biz_bud.core.types import LLMProfile
|
||||
full_config = AppConfig(
|
||||
api_config=APIConfigModel(
|
||||
|
||||
@@ -8,8 +8,18 @@ from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.core.errors.base import ErrorCategory, ErrorInfo, ErrorNamespace, ErrorSeverity
|
||||
from biz_bud.core.errors.router import ErrorRoute, ErrorRouter, RouteAction, RouteCondition
|
||||
from biz_bud.core.errors.base import (
|
||||
ErrorCategory,
|
||||
ErrorInfo,
|
||||
ErrorNamespace,
|
||||
ErrorSeverity,
|
||||
)
|
||||
from biz_bud.core.errors.router import (
|
||||
ErrorRoute,
|
||||
ErrorRouter,
|
||||
RouteAction,
|
||||
RouteCondition,
|
||||
)
|
||||
from biz_bud.core.errors.router_config import (
|
||||
EXAMPLE_CONFIG,
|
||||
RouterConfig,
|
||||
|
||||
@@ -6,7 +6,10 @@ from unittest.mock import Mock
|
||||
import pytest
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
|
||||
from biz_bud.core.langgraph.runnable_config import ConfigurationProvider, create_runnable_config
|
||||
from biz_bud.core.langgraph.runnable_config import (
|
||||
ConfigurationProvider,
|
||||
create_runnable_config,
|
||||
)
|
||||
|
||||
# ================================
|
||||
# FIXTURES
|
||||
|
||||
@@ -5,7 +5,11 @@ from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.core.utils.message_helpers import convert_to_langchain, get_messages, normalize_content
|
||||
from biz_bud.core.utils.message_helpers import (
|
||||
convert_to_langchain,
|
||||
get_messages,
|
||||
normalize_content,
|
||||
)
|
||||
|
||||
# ================================
|
||||
# GET MESSAGES TESTS
|
||||
|
||||
@@ -128,7 +128,9 @@ class TestResearchGraph:
|
||||
result_state = await synthesize_search_results(initial_state)
|
||||
|
||||
# 4. Assert
|
||||
from tests.helpers.assertions.custom_assertions import assert_state_has_no_errors
|
||||
from tests.helpers.assertions.custom_assertions import (
|
||||
assert_state_has_no_errors,
|
||||
)
|
||||
|
||||
assert_state_has_no_errors(cast("dict[str, Any]", result_state))
|
||||
assert "synthesis" in result_state
|
||||
|
||||
@@ -9,7 +9,10 @@ from langchain_core.runnables import RunnableConfig
|
||||
from biz_bud.graphs.rag.graph import url_to_r2r_graph
|
||||
from biz_bud.graphs.rag.nodes.integrations.repomix import repomix_process_node
|
||||
from biz_bud.graphs.rag.nodes.scraping.url_router import route_url_node
|
||||
from biz_bud.graphs.rag.nodes.upload_r2r import extract_collection_name, upload_to_r2r_node
|
||||
from biz_bud.graphs.rag.nodes.upload_r2r import (
|
||||
extract_collection_name,
|
||||
upload_to_r2r_node,
|
||||
)
|
||||
from biz_bud.states.url_to_rag import URLToRAGState
|
||||
|
||||
# Mock repository content constants
|
||||
|
||||
@@ -235,7 +235,11 @@ class TestLoadCatalogDataNode:
|
||||
|
||||
# Mock the config to include catalog metadata
|
||||
with patch("biz_bud.config.loader.load_config") as mock_load_config:
|
||||
from biz_bud.core.config.schemas.app import AppConfig, CatalogConfig, InputStateModel
|
||||
from biz_bud.core.config.schemas.app import (
|
||||
AppConfig,
|
||||
CatalogConfig,
|
||||
InputStateModel,
|
||||
)
|
||||
|
||||
mock_config = AppConfig(
|
||||
DEFAULT_QUERY="Test query",
|
||||
|
||||
@@ -33,7 +33,9 @@ class TestR2RDeduplication:
|
||||
@pytest.fixture
|
||||
def base_state(self) -> RAGAgentState:
|
||||
"""Provide base state for testing using factory."""
|
||||
from tests.helpers.factories.state_factories import create_minimal_rag_agent_state
|
||||
from tests.helpers.factories.state_factories import (
|
||||
create_minimal_rag_agent_state,
|
||||
)
|
||||
|
||||
return create_minimal_rag_agent_state(
|
||||
input_url="https://example.com/page",
|
||||
@@ -166,7 +168,9 @@ class TestR2RUrlVariations:
|
||||
|
||||
# All should generate same hash for deduplication
|
||||
for url in url_variations:
|
||||
from tests.helpers.factories.state_factories import create_minimal_rag_agent_state
|
||||
from tests.helpers.factories.state_factories import (
|
||||
create_minimal_rag_agent_state,
|
||||
)
|
||||
|
||||
state: RAGAgentState = create_minimal_rag_agent_state(
|
||||
input_url=url,
|
||||
@@ -205,7 +209,9 @@ class TestR2RUrlVariations:
|
||||
],
|
||||
]
|
||||
|
||||
from tests.helpers.factories.state_factories import create_minimal_rag_agent_state
|
||||
from tests.helpers.factories.state_factories import (
|
||||
create_minimal_rag_agent_state,
|
||||
)
|
||||
|
||||
state: RAGAgentState = create_minimal_rag_agent_state(
|
||||
input_url="https://new.example.com/install",
|
||||
|
||||
@@ -5,7 +5,10 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.tools.clients.r2r_utils import ensure_collection_exists, r2r_direct_api_call
|
||||
from biz_bud.tools.clients.r2r_utils import (
|
||||
ensure_collection_exists,
|
||||
r2r_direct_api_call,
|
||||
)
|
||||
|
||||
|
||||
class TestR2RDirectAPICall:
|
||||
|
||||
@@ -17,7 +17,10 @@ from biz_bud.graphs.rag.nodes.upload_r2r import (
|
||||
from biz_bud.states.url_to_rag import URLToRAGState
|
||||
|
||||
# Removed import of deleted function _upload_document_with_collection
|
||||
from biz_bud.tools.clients.r2r_utils import ensure_collection_exists, r2r_direct_api_call
|
||||
from biz_bud.tools.clients.r2r_utils import (
|
||||
ensure_collection_exists,
|
||||
r2r_direct_api_call,
|
||||
)
|
||||
|
||||
|
||||
# Mock LangGraph's get_stream_writer to avoid runtime errors
|
||||
|
||||
@@ -11,7 +11,12 @@ from unittest.mock import AsyncMock, Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.nodes.search import ConcurrentSearchOrchestrator, SearchBatch, SearchStatus, SearchTask
|
||||
from biz_bud.nodes.search import (
|
||||
ConcurrentSearchOrchestrator,
|
||||
SearchBatch,
|
||||
SearchStatus,
|
||||
SearchTask,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from biz_bud.nodes.search.search_orchestrator import SearchResult
|
||||
|
||||
@@ -83,7 +83,11 @@ class TestServiceFactory:
|
||||
@pytest.fixture
|
||||
def app_config(self) -> AppConfig:
|
||||
"""Create a test app config."""
|
||||
from biz_bud.core.config.schemas import DatabaseConfigModel, LoggingConfig, RedisConfigModel
|
||||
from biz_bud.core.config.schemas import (
|
||||
DatabaseConfigModel,
|
||||
LoggingConfig,
|
||||
RedisConfigModel,
|
||||
)
|
||||
|
||||
return AppConfig(
|
||||
DEFAULT_QUERY="Test query",
|
||||
|
||||
@@ -7,7 +7,9 @@ import pytest
|
||||
|
||||
from biz_bud.core.config.schemas import AppConfig, ExtractionConfig
|
||||
from biz_bud.services.semantic_extraction import SemanticExtractionService
|
||||
from biz_bud.tools.capabilities.extraction.types import SemanticExtractionResultTypedDict
|
||||
from biz_bud.tools.capabilities.extraction.types import (
|
||||
SemanticExtractionResultTypedDict,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.tools.browser.browser_helper import get_browser_config, setup_browser_options
|
||||
from biz_bud.tools.browser.browser_helper import (
|
||||
get_browser_config,
|
||||
setup_browser_options,
|
||||
)
|
||||
|
||||
|
||||
class TestGetBrowserConfig:
|
||||
|
||||
@@ -7,7 +7,11 @@ import pytest
|
||||
from bs4 import Tag
|
||||
|
||||
from biz_bud.core.errors import BrowserError
|
||||
from biz_bud.tools.browser.browser import Browser, DefaultBrowserConfig, _create_chrome_driver
|
||||
from biz_bud.tools.browser.browser import (
|
||||
Browser,
|
||||
DefaultBrowserConfig,
|
||||
_create_chrome_driver,
|
||||
)
|
||||
|
||||
|
||||
class TestBrowserConfiguration:
|
||||
|
||||
@@ -12,7 +12,10 @@ from biz_bud.core.errors import ConfigurationError
|
||||
# We'll test by patching the PaperlessClient
|
||||
async def _search_paperless_documents(query: str, limit: int = 10) -> dict[str, Any]:
|
||||
"""Test implementation of search_paperless_documents logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -30,7 +33,10 @@ async def _search_paperless_documents(query: str, limit: int = 10) -> dict[str,
|
||||
|
||||
async def _get_paperless_document(document_id: int) -> dict[str, Any]:
|
||||
"""Test implementation of get_paperless_document logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -49,7 +55,10 @@ async def _update_paperless_document(
|
||||
tag_ids: list[int] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Test implementation of update_paperless_document logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -84,7 +93,10 @@ async def _update_paperless_document(
|
||||
|
||||
async def _create_paperless_tag(name: str, color: str = "#a6cee3") -> dict[str, Any]:
|
||||
"""Test implementation of create_paperless_tag logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -97,7 +109,10 @@ async def _create_paperless_tag(name: str, color: str = "#a6cee3") -> dict[str,
|
||||
|
||||
async def _list_paperless_tags() -> dict[str, Any]:
|
||||
"""Test implementation of list_paperless_tags logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -110,7 +125,10 @@ async def _list_paperless_tags() -> dict[str, Any]:
|
||||
|
||||
async def _list_paperless_correspondents() -> dict[str, Any]:
|
||||
"""Test implementation of list_paperless_correspondents logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -127,7 +145,10 @@ async def _list_paperless_correspondents() -> dict[str, Any]:
|
||||
|
||||
async def _list_paperless_document_types() -> dict[str, Any]:
|
||||
"""Test implementation of list_paperless_document_types logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
@@ -144,7 +165,10 @@ async def _list_paperless_document_types() -> dict[str, Any]:
|
||||
|
||||
async def _get_paperless_statistics() -> dict[str, Any]:
|
||||
"""Test implementation of get_paperless_statistics logic."""
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import PaperlessClient, logger
|
||||
from biz_bud.tools.capabilities.external.paperless.tool import (
|
||||
PaperlessClient,
|
||||
logger,
|
||||
)
|
||||
|
||||
try:
|
||||
client = PaperlessClient()
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
|
||||
|
||||
from biz_bud.tools.capabilities.extraction.core.types import FactTypedDict, JsonDict, JsonValue
|
||||
from biz_bud.tools.capabilities.extraction.core.types import (
|
||||
FactTypedDict,
|
||||
JsonDict,
|
||||
JsonValue,
|
||||
)
|
||||
|
||||
|
||||
class TestJsonValueType:
|
||||
|
||||
@@ -25,7 +25,9 @@ class TestContentExtractionCore:
|
||||
mock_tool.ainvoke = AsyncMock(return_value=mock_result)
|
||||
|
||||
# Import and call the function directly
|
||||
from biz_bud.tools.capabilities.extraction.content import process_url_for_extraction
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
process_url_for_extraction,
|
||||
)
|
||||
|
||||
# Since it's a tool, we call the ainvoke method
|
||||
result = await process_url_for_extraction.ainvoke(
|
||||
@@ -53,7 +55,9 @@ class TestContentExtractionCore:
|
||||
with patch(
|
||||
"biz_bud.tools.capabilities.extraction.content.logger"
|
||||
) as mock_logger:
|
||||
from biz_bud.tools.capabilities.extraction.content import process_url_for_extraction
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
process_url_for_extraction,
|
||||
)
|
||||
|
||||
result = await process_url_for_extraction.ainvoke(
|
||||
{
|
||||
@@ -130,7 +134,9 @@ class TestContentExtractionCore:
|
||||
@pytest.mark.asyncio
|
||||
async def test_batch_extract_empty_urls(self):
|
||||
"""Test batch extraction with empty URL list."""
|
||||
from biz_bud.tools.capabilities.extraction.content import batch_extract_from_urls
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
batch_extract_from_urls,
|
||||
)
|
||||
|
||||
result = await batch_extract_from_urls.ainvoke(
|
||||
{"urls": [], "query": "Extract information"}
|
||||
@@ -156,7 +162,9 @@ class TestContentExtractionCore:
|
||||
},
|
||||
]
|
||||
|
||||
from biz_bud.tools.capabilities.extraction.content import filter_extraction_results
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
filter_extraction_results,
|
||||
)
|
||||
|
||||
result = filter_extraction_results.invoke({
|
||||
"results": results,
|
||||
@@ -172,7 +180,9 @@ class TestContentExtractionCore:
|
||||
|
||||
def test_filter_extraction_results_empty_input(self):
|
||||
"""Test filtering with empty results."""
|
||||
from biz_bud.tools.capabilities.extraction.content import filter_extraction_results
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
filter_extraction_results,
|
||||
)
|
||||
|
||||
result = filter_extraction_results.invoke({
|
||||
"results": [],
|
||||
@@ -191,7 +201,9 @@ class TestContentExtractionCore:
|
||||
results = [{"invalid": "data"}]
|
||||
|
||||
with patch("biz_bud.tools.capabilities.extraction.content.logger"):
|
||||
from biz_bud.tools.capabilities.extraction.content import filter_extraction_results
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
filter_extraction_results,
|
||||
)
|
||||
|
||||
result = filter_extraction_results.invoke({
|
||||
"results": results,
|
||||
@@ -269,7 +281,9 @@ class TestContentExtractionConfiguration:
|
||||
}
|
||||
mock_tool.ainvoke = AsyncMock(return_value=mock_result)
|
||||
|
||||
from biz_bud.tools.capabilities.extraction.content import process_url_for_extraction
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
process_url_for_extraction,
|
||||
)
|
||||
|
||||
extract_config = {
|
||||
"chunk_size": 4000,
|
||||
@@ -300,7 +314,9 @@ class TestContentExtractionConfiguration:
|
||||
{"facts": ["f1", "f2", "f3"], "relevance_score": 0.1, "success": True},
|
||||
]
|
||||
|
||||
from biz_bud.tools.capabilities.extraction.content import filter_extraction_results
|
||||
from biz_bud.tools.capabilities.extraction.content import (
|
||||
filter_extraction_results,
|
||||
)
|
||||
|
||||
# Test high fact requirement
|
||||
result = filter_extraction_results.invoke({
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.tools.capabilities.introspection.providers.default import DefaultIntrospectionProvider
|
||||
from biz_bud.tools.capabilities.introspection.providers.default import (
|
||||
DefaultIntrospectionProvider,
|
||||
)
|
||||
|
||||
|
||||
class TestDefaultProviderCapabilityAnalysis:
|
||||
|
||||
@@ -7,7 +7,9 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from biz_bud.tools.capabilities.scrape.providers.beautifulsoup import BeautifulSoupScrapeProvider
|
||||
from biz_bud.tools.capabilities.scrape.providers.beautifulsoup import (
|
||||
BeautifulSoupScrapeProvider,
|
||||
)
|
||||
from biz_bud.tools.models import ContentType, PageMetadata, ScrapedContent
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.tools.capabilities.scrape.providers.beautifulsoup import BeautifulSoupScrapeProvider
|
||||
from biz_bud.tools.capabilities.scrape.providers.beautifulsoup import (
|
||||
BeautifulSoupScrapeProvider,
|
||||
)
|
||||
from biz_bud.tools.models import ScrapedContent
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from biz_bud.tools.capabilities.scrape.providers.firecrawl import FirecrawlScrapeProvider
|
||||
from biz_bud.tools.capabilities.scrape.providers.firecrawl import (
|
||||
FirecrawlScrapeProvider,
|
||||
)
|
||||
from biz_bud.tools.models import ContentType, PageMetadata, ScrapedContent
|
||||
|
||||
|
||||
|
||||
@@ -550,7 +550,9 @@ class TestExtractionToolsEdgeCases:
|
||||
|
||||
async def test_extraction_state_methods_functionality(self):
|
||||
"""Test extraction state methods work with various state formats."""
|
||||
from biz_bud.tools.capabilities.extraction.legacy_tools import EXTRACTION_STATE_METHODS
|
||||
from biz_bud.tools.capabilities.extraction.legacy_tools import (
|
||||
EXTRACTION_STATE_METHODS,
|
||||
)
|
||||
|
||||
# Test statistics extraction from state
|
||||
state = {
|
||||
@@ -569,7 +571,9 @@ class TestExtractionToolsEdgeCases:
|
||||
|
||||
async def test_extraction_state_methods_missing_data(self):
|
||||
"""Test extraction state methods handle missing data gracefully."""
|
||||
from biz_bud.tools.capabilities.extraction.legacy_tools import EXTRACTION_STATE_METHODS
|
||||
from biz_bud.tools.capabilities.extraction.legacy_tools import (
|
||||
EXTRACTION_STATE_METHODS,
|
||||
)
|
||||
|
||||
# Test with empty state
|
||||
empty_state = {}
|
||||
|
||||
@@ -10,7 +10,10 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||
import pytest
|
||||
|
||||
from biz_bud.core.errors import URLDiscoveryError
|
||||
from biz_bud.tools.capabilities.url_processing.models import DiscoveryMethod, DiscoveryResult
|
||||
from biz_bud.tools.capabilities.url_processing.models import (
|
||||
DiscoveryMethod,
|
||||
DiscoveryResult,
|
||||
)
|
||||
from biz_bud.tools.capabilities.url_processing.providers.discovery import (
|
||||
ComprehensiveDiscoveryProvider,
|
||||
HTMLParsingDiscoveryProvider,
|
||||
|
||||
@@ -11,7 +11,10 @@ from unittest.mock import AsyncMock, patch
|
||||
import pytest
|
||||
|
||||
from biz_bud.core.errors import URLValidationError
|
||||
from biz_bud.tools.capabilities.url_processing.models import ValidationResult, ValidationStatus
|
||||
from biz_bud.tools.capabilities.url_processing.models import (
|
||||
ValidationResult,
|
||||
ValidationStatus,
|
||||
)
|
||||
from biz_bud.tools.capabilities.url_processing.providers.validation import (
|
||||
BasicValidationProvider,
|
||||
StandardValidationProvider,
|
||||
|
||||
@@ -6,7 +6,11 @@ from typing import Any
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from biz_bud.core import is_sensitive_field, redact_sensitive_data, safe_serialize_response
|
||||
from biz_bud.core import (
|
||||
is_sensitive_field,
|
||||
redact_sensitive_data,
|
||||
safe_serialize_response,
|
||||
)
|
||||
|
||||
|
||||
class SamplePydanticModel(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user