chore: remove deprecated files and clean up project structure

This commit is contained in:
2025-08-07 19:17:02 -04:00
parent 64f0f49d56
commit 5654f06a66
84 changed files with 580 additions and 181 deletions

View File

@@ -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,

View File

@@ -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__)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 = (

View File

@@ -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)

View File

@@ -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,

View File

@@ -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(

View File

@@ -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

View File

@@ -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}",

View File

@@ -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,

View File

@@ -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__)

View File

@@ -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

View File

@@ -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")

View File

@@ -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.

View File

@@ -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 (

View File

@@ -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,

View File

@@ -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):

View File

@@ -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

View File

@@ -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(

View File

@@ -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

View File

@@ -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:

View File

@@ -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,
)

View File

@@ -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__)

View File

@@ -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

View File

@@ -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,
)

View File

@@ -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__)

View File

@@ -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")

View File

@@ -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",

View File

@@ -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__)

View File

@@ -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__)

View File

@@ -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

View File

@@ -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__)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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__ = [

View File

@@ -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

View File

@@ -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")

View File

@@ -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"]:

View File

@@ -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"]:

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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",

View File

@@ -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,

View File

@@ -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",

View File

@@ -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):

View File

@@ -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,

View File

@@ -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 = [

View File

@@ -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()

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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 = {

View File

@@ -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(

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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()

View File

@@ -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:

View File

@@ -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({

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 = {}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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):