hanzo-mcp 0.7.1__tar.gz → 0.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of hanzo-mcp might be problematic. Click here for more details.
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/PKG-INFO +4 -1
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp.egg-info/PKG-INFO +4 -1
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp.egg-info/SOURCES.txt +3 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp.egg-info/requires.txt +4 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/pyproject.toml +3 -1
- hanzo_mcp-0.7.3/tests/test_find_tool_ffind.py +348 -0
- hanzo_mcp-0.7.3/tests/test_find_tool_integration.py +363 -0
- hanzo_mcp-0.7.3/tests/test_find_tool_registration.py +121 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/README.md +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/__main__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/analytics/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/analytics/posthog_analytics.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/cli.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/cli_enhanced.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/cli_plugin.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/config/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/config/settings.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/config/tool_config.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/dev_server.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/prompts/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/prompts/compact_conversation.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/prompts/create_release.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/prompts/project_system.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/prompts/project_todo_reminder.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/prompts/utils.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/server.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/server_enhanced.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/agent.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/agent_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/agent_tool_v2.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/clarification_protocol.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/clarification_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/claude_cli_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/claude_desktop_auth.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/cli_agent_base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/code_auth.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/code_auth_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/codex_cli_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/critic_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/gemini_cli_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/grok_cli_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/iching_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/network_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/prompt.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/review_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/swarm_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/swarm_tool_v2.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/agent/tool_adapter.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/batch_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/config_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/context.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/context_fix.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/critic_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/decorators.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/enhanced_base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/fastmcp_pagination.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/forgiving_edit.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/mode.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/mode_loader.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/paginated_base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/paginated_response.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/pagination.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/permissions.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/personality.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/plugin_loader.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/stats.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/thinking_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/tool_disable.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/tool_enable.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/tool_list.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/truncate.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/common/validation.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/config/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/config/config_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/config/index_config.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/config/mode_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/database_manager.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/graph.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/graph_add.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/graph_query.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/graph_remove.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/graph_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/graph_stats.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/sql.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/sql_query.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/sql_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/database/sql_stats.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/editor/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/editor/neovim_command.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/editor/neovim_edit.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/editor/neovim_session.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/ast_multi_edit.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/batch_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/content_replace.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/diff.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/directory_tree.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/directory_tree_paginated.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/edit.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/find.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/find_files.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/git_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/grep.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/multi_edit.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/read.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/rules_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/search_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/symbols.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/symbols_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/tree.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/unix_aliases.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/watch.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/filesystem/write.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/jupyter/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/jupyter/base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/jupyter/jupyter.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/jupyter/notebook_edit.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/jupyter/notebook_read.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/llm/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/llm/consensus_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/llm/llm_manage.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/llm/llm_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/llm/provider_tools.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/lsp/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/lsp/lsp_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/mcp/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/mcp/mcp_add.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/mcp/mcp_remove.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/mcp/mcp_stats.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/mcp/mcp_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/memory/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/memory/knowledge_tools.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/memory/memory_tools.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/search/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/search/find_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/search/unified_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/auto_background.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/base_process.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/bash_session.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/bash_session_executor.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/bash_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/command_executor.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/logs.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/npx.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/npx_background.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/npx_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/open.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/pkill.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/process_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/processes.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/run_background.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/run_command.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/run_command_windows.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/session_manager.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/session_storage.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/streaming_command.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/uvx.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/uvx_background.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/shell/uvx_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/todo/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/todo/base.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/todo/todo.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/todo/todo_read.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/todo/todo_write.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/__init__.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/ast_analyzer.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/git_ingester.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/index_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/infinity_store.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/mock_infinity.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/project_manager.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/vector.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/vector_index.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/tools/vector/vector_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp/types.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp.egg-info/dependency_links.txt +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp.egg-info/entry_points.txt +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/hanzo_mcp.egg-info/top_level.txt +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/setup.cfg +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_async_support.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_batch_tool_edge_cases.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_cli.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_cli_agents.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_failure_cases.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_git_ingestion.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_hanzo_mcp_integration.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_hanzo_mcp_local.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_hanzo_mcp_simple.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_hanzo_network_integration.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_integration.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_litellm_warnings.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_lsp_tool.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_manual.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_memory_edge_cases.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_memory_tools.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_memory_tools_comprehensive.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_new_tools.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_performance.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_search_quality.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_shell_features.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_simple.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_stdio_protocol.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_stdio_simple.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_streaming_command.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_swarm_simple.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_tools_suite.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_unified_search.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_vector_store.py +0 -0
- {hanzo_mcp-0.7.1 → hanzo_mcp-0.7.3}/tests/test_web3_integration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hanzo-mcp
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
|
|
5
5
|
Author-email: Hanzo Industries Inc <dev@hanzo.ai>
|
|
6
6
|
License: MIT
|
|
@@ -30,6 +30,7 @@ Requires-Dist: pydantic-settings>=2.7.0
|
|
|
30
30
|
Requires-Dist: typing-extensions>=4.13.0
|
|
31
31
|
Requires-Dist: watchdog>=6.0.0
|
|
32
32
|
Requires-Dist: keyring>=24.0.0
|
|
33
|
+
Requires-Dist: ffind>=1.3.0
|
|
33
34
|
Provides-Extra: dev
|
|
34
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
35
36
|
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
@@ -52,6 +53,8 @@ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
|
|
|
52
53
|
Requires-Dist: pytest-mock>=3.10.0; extra == "test"
|
|
53
54
|
Requires-Dist: pytest-asyncio>=0.25.3; extra == "test"
|
|
54
55
|
Requires-Dist: twisted; extra == "test"
|
|
56
|
+
Provides-Extra: agents
|
|
57
|
+
Requires-Dist: hanzo-agents>=0.1.0; extra == "agents"
|
|
55
58
|
Provides-Extra: performance
|
|
56
59
|
Requires-Dist: ujson>=5.7.0; extra == "performance"
|
|
57
60
|
Requires-Dist: orjson>=3.9.0; extra == "performance"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hanzo-mcp
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
|
|
5
5
|
Author-email: Hanzo Industries Inc <dev@hanzo.ai>
|
|
6
6
|
License: MIT
|
|
@@ -30,6 +30,7 @@ Requires-Dist: pydantic-settings>=2.7.0
|
|
|
30
30
|
Requires-Dist: typing-extensions>=4.13.0
|
|
31
31
|
Requires-Dist: watchdog>=6.0.0
|
|
32
32
|
Requires-Dist: keyring>=24.0.0
|
|
33
|
+
Requires-Dist: ffind>=1.3.0
|
|
33
34
|
Provides-Extra: dev
|
|
34
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
35
36
|
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
@@ -52,6 +53,8 @@ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
|
|
|
52
53
|
Requires-Dist: pytest-mock>=3.10.0; extra == "test"
|
|
53
54
|
Requires-Dist: pytest-asyncio>=0.25.3; extra == "test"
|
|
54
55
|
Requires-Dist: twisted; extra == "test"
|
|
56
|
+
Provides-Extra: agents
|
|
57
|
+
Requires-Dist: hanzo-agents>=0.1.0; extra == "agents"
|
|
55
58
|
Provides-Extra: performance
|
|
56
59
|
Requires-Dist: ujson>=5.7.0; extra == "performance"
|
|
57
60
|
Requires-Dist: orjson>=3.9.0; extra == "performance"
|
|
@@ -186,6 +186,9 @@ tests/test_batch_tool_edge_cases.py
|
|
|
186
186
|
tests/test_cli.py
|
|
187
187
|
tests/test_cli_agents.py
|
|
188
188
|
tests/test_failure_cases.py
|
|
189
|
+
tests/test_find_tool_ffind.py
|
|
190
|
+
tests/test_find_tool_integration.py
|
|
191
|
+
tests/test_find_tool_registration.py
|
|
189
192
|
tests/test_git_ingestion.py
|
|
190
193
|
tests/test_hanzo_mcp_integration.py
|
|
191
194
|
tests/test_hanzo_mcp_local.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hanzo-mcp"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.3"
|
|
8
8
|
description = "The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -34,6 +34,7 @@ dependencies = [
|
|
|
34
34
|
"typing-extensions>=4.13.0",
|
|
35
35
|
"watchdog>=6.0.0",
|
|
36
36
|
"keyring>=24.0.0",
|
|
37
|
+
"ffind>=1.3.0",
|
|
37
38
|
]
|
|
38
39
|
|
|
39
40
|
[project.urls]
|
|
@@ -52,6 +53,7 @@ test = [
|
|
|
52
53
|
"pytest-asyncio>=0.25.3",
|
|
53
54
|
"twisted",
|
|
54
55
|
]
|
|
56
|
+
agents = ["hanzo-agents>=0.1.0"]
|
|
55
57
|
performance = ["ujson>=5.7.0", "orjson>=3.9.0"]
|
|
56
58
|
publish = ["twine>=4.0.2", "build>=1.0.3"]
|
|
57
59
|
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"""Test FindTool with ffind for performance."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
import tempfile
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import time
|
|
8
|
+
import asyncio
|
|
9
|
+
|
|
10
|
+
from hanzo_mcp.tools.search.find_tool import FindTool, FFIND_AVAILABLE
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestFindToolFFind:
|
|
14
|
+
"""Test FindTool ffind functionality and performance."""
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def find_tool(self):
|
|
18
|
+
"""Create FindTool instance."""
|
|
19
|
+
return FindTool()
|
|
20
|
+
|
|
21
|
+
@pytest.fixture
|
|
22
|
+
def test_directory(self):
|
|
23
|
+
"""Create a test directory structure with many files."""
|
|
24
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
25
|
+
# Create a realistic directory structure
|
|
26
|
+
# src/
|
|
27
|
+
# ├── main.py
|
|
28
|
+
# ├── utils.py
|
|
29
|
+
# ├── config.json
|
|
30
|
+
# └── modules/
|
|
31
|
+
# ├── auth.py
|
|
32
|
+
# ├── database.py
|
|
33
|
+
# └── api/
|
|
34
|
+
# ├── routes.py
|
|
35
|
+
# ├── handlers.py
|
|
36
|
+
# └── middleware.py
|
|
37
|
+
# tests/
|
|
38
|
+
# ├── test_main.py
|
|
39
|
+
# ├── test_utils.py
|
|
40
|
+
# └── fixtures/
|
|
41
|
+
# └── data.json
|
|
42
|
+
# docs/
|
|
43
|
+
# ├── README.md
|
|
44
|
+
# ├── API.md
|
|
45
|
+
# └── images/
|
|
46
|
+
# ├── logo.png
|
|
47
|
+
# └── diagram.svg
|
|
48
|
+
# node_modules/ (should be ignored)
|
|
49
|
+
# └── package/
|
|
50
|
+
# └── index.js
|
|
51
|
+
# .git/ (should be ignored)
|
|
52
|
+
# └── config
|
|
53
|
+
|
|
54
|
+
# Create directories
|
|
55
|
+
dirs = [
|
|
56
|
+
"src", "src/modules", "src/modules/api",
|
|
57
|
+
"tests", "tests/fixtures",
|
|
58
|
+
"docs", "docs/images",
|
|
59
|
+
"node_modules", "node_modules/package",
|
|
60
|
+
".git", "__pycache__", ".venv"
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
for dir_name in dirs:
|
|
64
|
+
Path(tmpdir, dir_name).mkdir(parents=True, exist_ok=True)
|
|
65
|
+
|
|
66
|
+
# Create files with different sizes and content
|
|
67
|
+
files = {
|
|
68
|
+
"src/main.py": "# Main application\nimport sys\n\ndef main():\n pass\n" * 100,
|
|
69
|
+
"src/utils.py": "# Utilities\ndef helper():\n return 'TODO: implement'\n",
|
|
70
|
+
"src/config.json": '{"debug": true, "port": 8080}\n',
|
|
71
|
+
"src/modules/auth.py": "# Authentication module\nclass Auth:\n pass\n",
|
|
72
|
+
"src/modules/database.py": "# Database module\nimport sqlite3\n" * 50,
|
|
73
|
+
"src/modules/api/routes.py": "# API routes\nfrom flask import Flask\n",
|
|
74
|
+
"src/modules/api/handlers.py": "# Request handlers\ndef handle_request():\n pass\n",
|
|
75
|
+
"src/modules/api/middleware.py": "# Middleware\ndef auth_middleware():\n pass\n",
|
|
76
|
+
"tests/test_main.py": "# Test main\nimport pytest\ndef test_main():\n assert True\n",
|
|
77
|
+
"tests/test_utils.py": "# Test utils\ndef test_helper():\n pass\n",
|
|
78
|
+
"tests/fixtures/data.json": '{"test": "data"}\n',
|
|
79
|
+
"docs/README.md": "# Project README\n\nTODO: Write documentation\n",
|
|
80
|
+
"docs/API.md": "# API Documentation\n\n## Endpoints\n\n### GET /api/users\n",
|
|
81
|
+
"docs/images/logo.png": b"PNG fake image data" * 1000, # Binary file
|
|
82
|
+
"docs/images/diagram.svg": "<svg>TODO: Add diagram</svg>\n",
|
|
83
|
+
"node_modules/package/index.js": "module.exports = {};\n",
|
|
84
|
+
".git/config": "[core]\nrepositoryformatversion = 0\n",
|
|
85
|
+
"__pycache__/cache.pyc": b"Python bytecode",
|
|
86
|
+
".gitignore": "node_modules/\n__pycache__/\n*.pyc\n.venv/\n",
|
|
87
|
+
"large_file.dat": "x" * 1024 * 1024, # 1MB file
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for file_path, content in files.items():
|
|
91
|
+
full_path = Path(tmpdir, file_path)
|
|
92
|
+
if isinstance(content, bytes):
|
|
93
|
+
full_path.write_bytes(content)
|
|
94
|
+
else:
|
|
95
|
+
full_path.write_text(content)
|
|
96
|
+
|
|
97
|
+
yield tmpdir
|
|
98
|
+
|
|
99
|
+
def test_ffind_availability(self):
|
|
100
|
+
"""Test if ffind is available."""
|
|
101
|
+
print(f"\nffind available: {FFIND_AVAILABLE}")
|
|
102
|
+
# Don't fail if ffind is not installed, just report it
|
|
103
|
+
if not FFIND_AVAILABLE:
|
|
104
|
+
pytest.skip("ffind not installed - skipping performance tests")
|
|
105
|
+
|
|
106
|
+
@pytest.mark.asyncio
|
|
107
|
+
async def test_find_all_python_files(self, find_tool, test_directory):
|
|
108
|
+
"""Test finding all Python files."""
|
|
109
|
+
result = await find_tool.run(
|
|
110
|
+
pattern="*.py",
|
|
111
|
+
path=test_directory,
|
|
112
|
+
type="file"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Check results
|
|
116
|
+
assert "results" in result.data
|
|
117
|
+
results = result.data["results"]
|
|
118
|
+
|
|
119
|
+
# Should find Python files
|
|
120
|
+
py_files = [r["name"] for r in results]
|
|
121
|
+
assert "main.py" in py_files
|
|
122
|
+
assert "utils.py" in py_files
|
|
123
|
+
assert "auth.py" in py_files
|
|
124
|
+
assert "test_main.py" in py_files
|
|
125
|
+
|
|
126
|
+
# Should not find non-Python files
|
|
127
|
+
assert "config.json" not in py_files
|
|
128
|
+
assert "README.md" not in py_files
|
|
129
|
+
|
|
130
|
+
# Should respect gitignore (no __pycache__)
|
|
131
|
+
assert "cache.pyc" not in py_files
|
|
132
|
+
|
|
133
|
+
@pytest.mark.asyncio
|
|
134
|
+
async def test_find_with_size_filter(self, find_tool, test_directory):
|
|
135
|
+
"""Test finding files by size."""
|
|
136
|
+
# Find large files (> 500KB)
|
|
137
|
+
result = await find_tool.run(
|
|
138
|
+
pattern="*",
|
|
139
|
+
path=test_directory,
|
|
140
|
+
type="file",
|
|
141
|
+
min_size="500KB"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
results = result.data["results"]
|
|
145
|
+
# Should only find large_file.dat
|
|
146
|
+
assert len(results) == 1
|
|
147
|
+
assert results[0]["name"] == "large_file.dat"
|
|
148
|
+
|
|
149
|
+
@pytest.mark.asyncio
|
|
150
|
+
async def test_find_directories(self, find_tool, test_directory):
|
|
151
|
+
"""Test finding directories."""
|
|
152
|
+
result = await find_tool.run(
|
|
153
|
+
pattern="*",
|
|
154
|
+
path=test_directory,
|
|
155
|
+
type="dir",
|
|
156
|
+
max_depth=1
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
results = result.data["results"]
|
|
160
|
+
dir_names = [r["name"] for r in results]
|
|
161
|
+
|
|
162
|
+
# Should find top-level directories
|
|
163
|
+
assert "src" in dir_names
|
|
164
|
+
assert "tests" in dir_names
|
|
165
|
+
assert "docs" in dir_names
|
|
166
|
+
|
|
167
|
+
# Should not find nested directories (max_depth=1)
|
|
168
|
+
assert "modules" not in dir_names
|
|
169
|
+
assert "api" not in dir_names
|
|
170
|
+
|
|
171
|
+
@pytest.mark.asyncio
|
|
172
|
+
async def test_find_with_pattern_in_content(self, find_tool, test_directory):
|
|
173
|
+
"""Test finding files containing specific text."""
|
|
174
|
+
result = await find_tool.run(
|
|
175
|
+
pattern="TODO",
|
|
176
|
+
path=test_directory,
|
|
177
|
+
in_content=True,
|
|
178
|
+
type="file"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
results = result.data["results"]
|
|
182
|
+
file_names = [r["name"] for r in results]
|
|
183
|
+
|
|
184
|
+
# Should find files containing "TODO"
|
|
185
|
+
assert "utils.py" in file_names # Has TODO in content
|
|
186
|
+
assert "README.md" in file_names # Has TODO in content
|
|
187
|
+
assert "diagram.svg" in file_names # Has TODO in content
|
|
188
|
+
|
|
189
|
+
# Should not find files without TODO
|
|
190
|
+
assert "main.py" not in file_names
|
|
191
|
+
assert "auth.py" not in file_names
|
|
192
|
+
|
|
193
|
+
@pytest.mark.asyncio
|
|
194
|
+
async def test_pagination(self, find_tool, test_directory):
|
|
195
|
+
"""Test pagination functionality."""
|
|
196
|
+
# Get first page
|
|
197
|
+
result_page1 = await find_tool.run(
|
|
198
|
+
pattern="*",
|
|
199
|
+
path=test_directory,
|
|
200
|
+
type="file",
|
|
201
|
+
page_size=5,
|
|
202
|
+
page=1,
|
|
203
|
+
sort_by="name"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
page1_data = result_page1.data
|
|
207
|
+
assert len(page1_data["results"]) == 5
|
|
208
|
+
assert page1_data["pagination"]["page"] == 1
|
|
209
|
+
assert page1_data["pagination"]["has_next"] == True
|
|
210
|
+
|
|
211
|
+
# Get second page
|
|
212
|
+
result_page2 = await find_tool.run(
|
|
213
|
+
pattern="*",
|
|
214
|
+
path=test_directory,
|
|
215
|
+
type="file",
|
|
216
|
+
page_size=5,
|
|
217
|
+
page=2,
|
|
218
|
+
sort_by="name"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
page2_data = result_page2.data
|
|
222
|
+
assert page2_data["pagination"]["page"] == 2
|
|
223
|
+
|
|
224
|
+
# Results should be different
|
|
225
|
+
page1_names = [r["name"] for r in page1_data["results"]]
|
|
226
|
+
page2_names = [r["name"] for r in page2_data["results"]]
|
|
227
|
+
assert set(page1_names).isdisjoint(set(page2_names))
|
|
228
|
+
|
|
229
|
+
@pytest.mark.asyncio
|
|
230
|
+
async def test_performance_comparison(self, find_tool, test_directory):
|
|
231
|
+
"""Compare performance with and without ffind."""
|
|
232
|
+
# Force Python implementation
|
|
233
|
+
find_tool._available_backends = None
|
|
234
|
+
original_ffind = find_tool.__class__.__module__.FFIND_AVAILABLE
|
|
235
|
+
find_tool.__class__.__module__.FFIND_AVAILABLE = False
|
|
236
|
+
|
|
237
|
+
start_time = time.time()
|
|
238
|
+
result_python = await find_tool.run(
|
|
239
|
+
pattern="*.py",
|
|
240
|
+
path=test_directory,
|
|
241
|
+
type="file"
|
|
242
|
+
)
|
|
243
|
+
python_time = time.time() - start_time
|
|
244
|
+
|
|
245
|
+
# Restore ffind if available
|
|
246
|
+
find_tool.__class__.__module__.FFIND_AVAILABLE = original_ffind
|
|
247
|
+
find_tool._available_backends = None
|
|
248
|
+
|
|
249
|
+
if FFIND_AVAILABLE:
|
|
250
|
+
start_time = time.time()
|
|
251
|
+
result_ffind = await find_tool.run(
|
|
252
|
+
pattern="*.py",
|
|
253
|
+
path=test_directory,
|
|
254
|
+
type="file"
|
|
255
|
+
)
|
|
256
|
+
ffind_time = time.time() - start_time
|
|
257
|
+
|
|
258
|
+
print(f"\nPerformance comparison:")
|
|
259
|
+
print(f"Python implementation: {python_time:.3f}s")
|
|
260
|
+
print(f"ffind implementation: {ffind_time:.3f}s")
|
|
261
|
+
print(f"Speedup: {python_time/ffind_time:.1f}x")
|
|
262
|
+
|
|
263
|
+
# Results should be the same
|
|
264
|
+
assert len(result_python.data["results"]) == len(result_ffind.data["results"])
|
|
265
|
+
|
|
266
|
+
@pytest.mark.asyncio
|
|
267
|
+
async def test_fuzzy_search(self, find_tool, test_directory):
|
|
268
|
+
"""Test fuzzy pattern matching."""
|
|
269
|
+
result = await find_tool.run(
|
|
270
|
+
pattern="tst", # Fuzzy match for "test"
|
|
271
|
+
path=test_directory,
|
|
272
|
+
fuzzy=True,
|
|
273
|
+
type="file"
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
results = result.data["results"]
|
|
277
|
+
file_names = [r["name"] for r in results]
|
|
278
|
+
|
|
279
|
+
# Should find test files with fuzzy matching
|
|
280
|
+
assert any("test" in name for name in file_names)
|
|
281
|
+
|
|
282
|
+
@pytest.mark.asyncio
|
|
283
|
+
async def test_case_insensitive_search(self, find_tool, test_directory):
|
|
284
|
+
"""Test case-insensitive search."""
|
|
285
|
+
result = await find_tool.run(
|
|
286
|
+
pattern="*.MD", # Uppercase extension
|
|
287
|
+
path=test_directory,
|
|
288
|
+
case_sensitive=False,
|
|
289
|
+
type="file"
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
results = result.data["results"]
|
|
293
|
+
file_names = [r["name"] for r in results]
|
|
294
|
+
|
|
295
|
+
# Should find .md files despite case difference
|
|
296
|
+
assert "README.md" in file_names
|
|
297
|
+
assert "API.md" in file_names
|
|
298
|
+
|
|
299
|
+
@pytest.mark.asyncio
|
|
300
|
+
async def test_statistics(self, find_tool, test_directory):
|
|
301
|
+
"""Test that statistics are included in results."""
|
|
302
|
+
result = await find_tool.run(
|
|
303
|
+
pattern="*.py",
|
|
304
|
+
path=test_directory
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
stats = result.data.get("statistics")
|
|
308
|
+
assert stats is not None
|
|
309
|
+
assert "total_found" in stats
|
|
310
|
+
assert "search_time_ms" in stats
|
|
311
|
+
assert "search_method" in stats
|
|
312
|
+
assert stats["search_method"] in ["ffind", "python"]
|
|
313
|
+
assert stats["search_time_ms"] > 0
|
|
314
|
+
|
|
315
|
+
@pytest.mark.asyncio
|
|
316
|
+
async def test_gitignore_respect(self, find_tool, test_directory):
|
|
317
|
+
"""Test that .gitignore patterns are respected."""
|
|
318
|
+
result = await find_tool.run(
|
|
319
|
+
pattern="*",
|
|
320
|
+
path=test_directory,
|
|
321
|
+
respect_gitignore=True
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
results = result.data["results"]
|
|
325
|
+
file_paths = [r["path"] for r in results]
|
|
326
|
+
|
|
327
|
+
# Should not include gitignored files/dirs
|
|
328
|
+
assert not any("node_modules" in path for path in file_paths)
|
|
329
|
+
assert not any("__pycache__" in path for path in file_paths)
|
|
330
|
+
assert not any(".pyc" in path for path in file_paths)
|
|
331
|
+
|
|
332
|
+
# Test with gitignore disabled
|
|
333
|
+
result_no_ignore = await find_tool.run(
|
|
334
|
+
pattern="*",
|
|
335
|
+
path=test_directory,
|
|
336
|
+
respect_gitignore=False
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
results_no_ignore = result_no_ignore.data["results"]
|
|
340
|
+
file_paths_no_ignore = [r["path"] for r in results_no_ignore]
|
|
341
|
+
|
|
342
|
+
# Should include gitignored files when disabled
|
|
343
|
+
assert any("node_modules" in path for path in file_paths_no_ignore)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
if __name__ == "__main__":
|
|
347
|
+
# Run tests
|
|
348
|
+
pytest.main([__file__, "-v"])
|