siada-cli 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_config.yaml +34 -0
- siada/__init__.py +13 -0
- siada/agent_hub/__init__.py +10 -0
- siada/agent_hub/coder/bug_fix_agent.py +398 -0
- siada/agent_hub/coder/code_gen_agent.py +235 -0
- siada/agent_hub/coder/fe_gen_agent.py +37 -0
- siada/agent_hub/coder/issue_review_agent.py +68 -0
- siada/agent_hub/coder/prompt/__init__.py +0 -0
- siada/agent_hub/coder/prompt/base/__init__.py +0 -0
- siada/agent_hub/coder/prompt/base/capabilities.py +18 -0
- siada/agent_hub/coder/prompt/base/non_interactive.py +14 -0
- siada/agent_hub/coder/prompt/base/prompt_builder.py +33 -0
- siada/agent_hub/coder/prompt/base/rules.py +40 -0
- siada/agent_hub/coder/prompt/base/tool_use.py +14 -0
- siada/agent_hub/coder/prompt/bug_prompt/bug_fix_prompt.py +51 -0
- siada/agent_hub/coder/prompt/bug_prompt/rules.py +53 -0
- siada/agent_hub/coder/prompt/code_gen_prompt.py +45 -0
- siada/agent_hub/coder/prompt/fe_gen_prompt.py +45 -0
- siada/agent_hub/coder/prompt/issue_review_prompt.py +121 -0
- siada/agent_hub/coder/tracing/__init__.py +22 -0
- siada/agent_hub/coder/tracing/logger_tracing_processor.py +458 -0
- siada/agent_hub/hooks/__init__.py +0 -0
- siada/agent_hub/hooks/io_hooks.py +30 -0
- siada/agent_hub/siada_agent.py +214 -0
- siada/config/__init__.py +0 -0
- siada/config/config_loader.py +67 -0
- siada/entrypoint/__init__.py +3 -0
- siada/entrypoint/args_parser/__init__.py +0 -0
- siada/entrypoint/args_parser/args.py +195 -0
- siada/entrypoint/interaction/__init__.py +0 -0
- siada/entrypoint/interaction/base_turn.py +107 -0
- siada/entrypoint/interaction/config.py +30 -0
- siada/entrypoint/interaction/controller.py +122 -0
- siada/entrypoint/interaction/nointeractive_controller.py +27 -0
- siada/entrypoint/interaction/turn/interface.py +116 -0
- siada/entrypoint/interaction/turn/models.py +34 -0
- siada/entrypoint/interaction/turn/run_turn.py +641 -0
- siada/entrypoint/interaction/turn_factory.py +35 -0
- siada/entrypoint/interaction/turn_models.py +28 -0
- siada/entrypoint/siadahub.py +413 -0
- siada/foundation/__init__.py +0 -0
- siada/foundation/code_agent_context.py +48 -0
- siada/foundation/config.py +59 -0
- siada/foundation/constants.py +2 -0
- siada/foundation/context.py +76 -0
- siada/foundation/logging.py +341 -0
- siada/foundation/tools/__init__.py +0 -0
- siada/foundation/tools/get_git_diff.py +105 -0
- siada/io/__init__.py +0 -0
- siada/io/banner.py +148 -0
- siada/io/color_settings.py +207 -0
- siada/io/color_utils.py +16 -0
- siada/io/components/__init__.py +0 -0
- siada/io/components/mdstream.py +204 -0
- siada/io/console_printer.py +68 -0
- siada/io/io.py +661 -0
- siada/io/key_bindings.py +129 -0
- siada/io/notification_command.py +40 -0
- siada/io/test_banner.py +64 -0
- siada/models/__init__.py +0 -0
- siada/models/agent.py +47 -0
- siada/models/coder/__init__.py +0 -0
- siada/models/converter.py +27 -0
- siada/models/model_base_config.py +121 -0
- siada/models/model_run_config.py +153 -0
- siada/provider/__init__.py +0 -0
- siada/provider/client_factory.py +112 -0
- siada/provider/llm_client.py +11 -0
- siada/provider/openrouter/__init__.py +0 -0
- siada/provider/openrouter/coverter.py +17 -0
- siada/provider/openrouter/openroute_provider.py +33 -0
- siada/provider/provider_factory.py +53 -0
- siada/queries/tree-sitter-language-pack/README.md +7 -0
- siada/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
- siada/queries/tree-sitter-language-pack/c-tags.scm +9 -0
- siada/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
- siada/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
- siada/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
- siada/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
- siada/queries/tree-sitter-language-pack/d-tags.scm +26 -0
- siada/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
- siada/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
- siada/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
- siada/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
- siada/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
- siada/queries/tree-sitter-language-pack/go-tags.scm +42 -0
- siada/queries/tree-sitter-language-pack/java-tags.scm +20 -0
- siada/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
- siada/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
- siada/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
- siada/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
- siada/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
- siada/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
- siada/queries/tree-sitter-language-pack/python-tags.scm +14 -0
- siada/queries/tree-sitter-language-pack/r-tags.scm +21 -0
- siada/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
- siada/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
- siada/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
- siada/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
- siada/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
- siada/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
- siada/queries/tree-sitter-languages/README.md +23 -0
- siada/queries/tree-sitter-languages/c-tags.scm +9 -0
- siada/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
- siada/queries/tree-sitter-languages/cpp-tags.scm +15 -0
- siada/queries/tree-sitter-languages/dart-tags.scm +91 -0
- siada/queries/tree-sitter-languages/elisp-tags.scm +8 -0
- siada/queries/tree-sitter-languages/elixir-tags.scm +54 -0
- siada/queries/tree-sitter-languages/elm-tags.scm +19 -0
- siada/queries/tree-sitter-languages/go-tags.scm +30 -0
- siada/queries/tree-sitter-languages/hcl-tags.scm +77 -0
- siada/queries/tree-sitter-languages/java-tags.scm +20 -0
- siada/queries/tree-sitter-languages/javascript-tags.scm +88 -0
- siada/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
- siada/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
- siada/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
- siada/queries/tree-sitter-languages/php-tags.scm +26 -0
- siada/queries/tree-sitter-languages/python-tags.scm +12 -0
- siada/queries/tree-sitter-languages/ql-tags.scm +26 -0
- siada/queries/tree-sitter-languages/ruby-tags.scm +64 -0
- siada/queries/tree-sitter-languages/rust-tags.scm +60 -0
- siada/queries/tree-sitter-languages/scala-tags.scm +65 -0
- siada/queries/tree-sitter-languages/typescript-tags.scm +41 -0
- siada/services/__init__.py +30 -0
- siada/services/at_file_recommendation_design_document.md +1213 -0
- siada/services/code_context_manager.py +136 -0
- siada/services/enhanced_fix_result_check.py +546 -0
- siada/services/execution_trace_collector.py +207 -0
- siada/services/file_recommendation/__init__.py +136 -0
- siada/services/file_recommendation/core/__init__.py +17 -0
- siada/services/file_recommendation/core/completion_engine.py +351 -0
- siada/services/file_recommendation/core/config.py +62 -0
- siada/services/file_recommendation/core/file_discovery.py +353 -0
- siada/services/file_recommendation/core/suggestion.py +110 -0
- siada/services/file_recommendation/utils/__init__.py +22 -0
- siada/services/file_recommendation/utils/path_utils.py +138 -0
- siada/services/file_recommendation/utils/text_utils.py +253 -0
- siada/services/fix_result_check.py +377 -0
- siada/services/handle_at_command/README.md +247 -0
- siada/services/handle_at_command/__init__.py +115 -0
- siada/services/handle_at_command/exceptions.py +46 -0
- siada/services/handle_at_command/models.py +92 -0
- siada/services/handle_at_command/parser.py +189 -0
- siada/services/handle_at_command/processor.py +321 -0
- siada/services/handle_at_command/resolver.py +318 -0
- siada/services/handle_at_command/utils.py +345 -0
- siada/services/model_info_service.py +103 -0
- siada/services/siada_runner.py +170 -0
- siada/session/__init__.py +29 -0
- siada/session/session_manager.py +66 -0
- siada/session/session_models.py +43 -0
- siada/support/__init__.py +0 -0
- siada/support/completer.py +204 -0
- siada/support/editor.py +146 -0
- siada/support/envprocessor.py +54 -0
- siada/support/repo.py +51 -0
- siada/support/slash_commands.py +410 -0
- siada/support/spinner.py +320 -0
- siada/tools/__init__.py +0 -0
- siada/tools/ast/README.md +345 -0
- siada/tools/ast/ast_tool.py +341 -0
- siada/tools/ast/models.py +11 -0
- siada/tools/coder/__init__.py +0 -0
- siada/tools/coder/ask_followup_question.py +70 -0
- siada/tools/coder/cmd_runner.py +132 -0
- siada/tools/coder/file_operator.py +284 -0
- siada/tools/coder/file_search/README.md +223 -0
- siada/tools/coder/file_search/__init__.py +10 -0
- siada/tools/coder/file_search/bin/rg-linux-arm64 +0 -0
- siada/tools/coder/file_search/bin/rg-linux-x64 +0 -0
- siada/tools/coder/file_search/bin/rg-macos-arm64 +0 -0
- siada/tools/coder/file_search/bin/rg-macos-x64 +0 -0
- siada/tools/coder/file_search/bin/rg.exe +0 -0
- siada/tools/coder/file_search/search.py +437 -0
- siada/tools/coder/file_search/setup_package.py +150 -0
- siada/tools/coder/file_search/test_search.py +142 -0
- siada/tools/coder/files.py +147 -0
- siada/tools/coder/fix_attempt_completion.py +58 -0
- siada/tools/coder/issue_review_completion.py +29 -0
- siada/tools/coder/observation/__init__.py +0 -0
- siada/tools/coder/observation/error.py +22 -0
- siada/tools/coder/observation/file_observation.py +216 -0
- siada/tools/coder/observation/observation.py +71 -0
- siada/tools/coder/repo_map/__init__.py +157 -0
- siada/tools/coder/repo_map/dump.py +29 -0
- siada/tools/coder/repo_map/io.py +226 -0
- siada/tools/coder/repo_map/repo_map.py +881 -0
- siada/tools/coder/repo_map/special.py +203 -0
- siada/tools/coder/repo_map/token_counter.py +154 -0
- siada/tools/coder/repo_map/waiting.py +221 -0
- siada/tools/coder/reproduce_completion.py +39 -0
- siada/tools/coder/run_cmd.py +60 -0
- siada/tools/coder/test_completion.py +25 -0
- siada/tools/coder/tool_docs.py +44 -0
- siada/tools/compression_tool.py +200 -0
- siada/tools/read_many_files/README.md +220 -0
- siada/tools/read_many_files/__init__.py +25 -0
- siada/tools/read_many_files/file_processor.py +486 -0
- siada/tools/read_many_files/filters.py +326 -0
- siada/tools/read_many_files/formatters.py +204 -0
- siada/tools/read_many_files/models.py +189 -0
- siada/tools/read_many_files_tool.py +233 -0
- siada/tools/tool_call_format/__init__.py +55 -0
- siada/tools/tool_call_format/file_to_language.py +231 -0
- siada/tools/tool_call_format/formatter_factory.py +80 -0
- siada/tools/tool_call_format/formatters.py +282 -0
- siada/tools/tool_call_format/tool_call_formatter.py +54 -0
- siada/tools/web/__init__.py +0 -0
- siada/tools/web/web_crawl.py +208 -0
- siada/utils.py +194 -0
- siada_cli-0.0.1.dist-info/LICENSE +201 -0
- siada_cli-0.0.1.dist-info/METADATA +457 -0
- siada_cli-0.0.1.dist-info/RECORD +215 -0
- siada_cli-0.0.1.dist-info/WHEEL +4 -0
- siada_cli-0.0.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ReadManyFiles tool data models and structures.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import List, Dict, Optional, Union, Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class ReadManyFilesParams:
|
|
11
|
+
"""ReadManyFiles tool input parameters"""
|
|
12
|
+
|
|
13
|
+
# Required parameters
|
|
14
|
+
paths: List[str] # File paths or directory paths array, relative to tool config target directory
|
|
15
|
+
# Can directly use glob patterns
|
|
16
|
+
# Example: ['src/**/*.py', 'docs/*.md']
|
|
17
|
+
|
|
18
|
+
# Optional parameters
|
|
19
|
+
include: Optional[List[str]] = None # Additional include glob patterns
|
|
20
|
+
# Example: ["*.test.ts"]
|
|
21
|
+
|
|
22
|
+
exclude: Optional[List[str]] = None # Exclude glob patterns
|
|
23
|
+
# Example: ["*.log", "dist/**"]
|
|
24
|
+
|
|
25
|
+
recursive: bool = True # Whether to search recursively
|
|
26
|
+
# Mainly controlled by "**" in glob patterns
|
|
27
|
+
|
|
28
|
+
useDefaultExcludes: bool = True # Whether to apply default exclude patterns
|
|
29
|
+
|
|
30
|
+
file_filtering_options: Optional[Dict[str, bool]] = None
|
|
31
|
+
# File filtering options
|
|
32
|
+
# {
|
|
33
|
+
# 'respect_git_ignore': bool, # Default: True
|
|
34
|
+
# }
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class ToolResult:
|
|
39
|
+
"""Tool execution result"""
|
|
40
|
+
|
|
41
|
+
llmContent: Union[List[str], List[Any], List[Union[str, Any]]]
|
|
42
|
+
# Content returned to LLM
|
|
43
|
+
# - For text files: formatted string array
|
|
44
|
+
# - For images/PDF: Part object array
|
|
45
|
+
# - Mixed content: mixed array of strings and Part objects
|
|
46
|
+
|
|
47
|
+
returnDisplay: str
|
|
48
|
+
# Content returned to user interface display
|
|
49
|
+
# Contains detailed summary information of processing results
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class FileProcessResult:
|
|
54
|
+
"""Single file processing result"""
|
|
55
|
+
|
|
56
|
+
success: bool
|
|
57
|
+
path: str
|
|
58
|
+
content: Optional[Any] = None
|
|
59
|
+
reason: Optional[str] = None
|
|
60
|
+
file_type: Optional[str] = None
|
|
61
|
+
size: Optional[int] = None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class ProcessingStats:
|
|
66
|
+
"""File processing statistics"""
|
|
67
|
+
|
|
68
|
+
total_files_found: int = 0
|
|
69
|
+
processed_files: int = 0
|
|
70
|
+
skipped_files: int = 0
|
|
71
|
+
text_files: int = 0
|
|
72
|
+
image_files: int = 0
|
|
73
|
+
pdf_files: int = 0
|
|
74
|
+
binary_files: int = 0
|
|
75
|
+
error_files: int = 0
|
|
76
|
+
total_size: int = 0
|
|
77
|
+
processing_time: float = 0.0
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Default exclude patterns
|
|
81
|
+
DEFAULT_EXCLUDES = [
|
|
82
|
+
# Dependency directories
|
|
83
|
+
'**/node_modules/**',
|
|
84
|
+
'**/__pycache__/**',
|
|
85
|
+
'**/venv/**',
|
|
86
|
+
'**/env/**',
|
|
87
|
+
'**/.env/**',
|
|
88
|
+
|
|
89
|
+
# Version control
|
|
90
|
+
'**/.git/**',
|
|
91
|
+
'**/.svn/**',
|
|
92
|
+
'**/.hg/**',
|
|
93
|
+
|
|
94
|
+
# IDE configuration
|
|
95
|
+
'**/.vscode/**',
|
|
96
|
+
'**/.idea/**',
|
|
97
|
+
'**/.eclipse/**',
|
|
98
|
+
|
|
99
|
+
# Build output
|
|
100
|
+
'**/dist/**',
|
|
101
|
+
'**/build/**',
|
|
102
|
+
'**/target/**',
|
|
103
|
+
'**/coverage/**',
|
|
104
|
+
'**/out/**',
|
|
105
|
+
|
|
106
|
+
# Compiled files
|
|
107
|
+
'**/*.pyc',
|
|
108
|
+
'**/*.pyo',
|
|
109
|
+
'**/*.class',
|
|
110
|
+
'**/*.jar',
|
|
111
|
+
'**/*.war',
|
|
112
|
+
'**/*.o',
|
|
113
|
+
'**/*.obj',
|
|
114
|
+
|
|
115
|
+
# Binary files
|
|
116
|
+
'**/*.bin',
|
|
117
|
+
'**/*.exe',
|
|
118
|
+
'**/*.dll',
|
|
119
|
+
'**/*.so',
|
|
120
|
+
'**/*.dylib',
|
|
121
|
+
|
|
122
|
+
# Compressed files
|
|
123
|
+
'**/*.zip',
|
|
124
|
+
'**/*.tar',
|
|
125
|
+
'**/*.gz',
|
|
126
|
+
'**/*.bz2',
|
|
127
|
+
'**/*.rar',
|
|
128
|
+
'**/*.7z',
|
|
129
|
+
|
|
130
|
+
# Office documents (unless explicitly requested)
|
|
131
|
+
'**/*.doc',
|
|
132
|
+
'**/*.docx',
|
|
133
|
+
'**/*.xls',
|
|
134
|
+
'**/*.xlsx',
|
|
135
|
+
'**/*.ppt',
|
|
136
|
+
'**/*.pptx',
|
|
137
|
+
'**/*.odt',
|
|
138
|
+
'**/*.ods',
|
|
139
|
+
'**/*.odp',
|
|
140
|
+
|
|
141
|
+
# System files
|
|
142
|
+
'**/.DS_Store',
|
|
143
|
+
'**/Thumbs.db',
|
|
144
|
+
'**/.env',
|
|
145
|
+
'**/.env.local',
|
|
146
|
+
'**/.env.*.local',
|
|
147
|
+
|
|
148
|
+
# Log files
|
|
149
|
+
'**/*.log',
|
|
150
|
+
'**/logs/**',
|
|
151
|
+
|
|
152
|
+
# Cache directories
|
|
153
|
+
'**/.cache/**',
|
|
154
|
+
'**/cache/**',
|
|
155
|
+
'**/.tmp/**',
|
|
156
|
+
'**/tmp/**',
|
|
157
|
+
|
|
158
|
+
# Package manager files
|
|
159
|
+
'**/package-lock.json',
|
|
160
|
+
'**/yarn.lock',
|
|
161
|
+
'**/poetry.lock',
|
|
162
|
+
'**/Pipfile.lock',
|
|
163
|
+
|
|
164
|
+
# Gemini history files
|
|
165
|
+
'**/GEMINI.md',
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
# Supported text file extensions
|
|
169
|
+
TEXT_FILE_EXTENSIONS = {
|
|
170
|
+
'.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.c', '.cpp', '.cc', '.cxx',
|
|
171
|
+
'.h', '.hpp', '.cs', '.php', '.rb', '.go', '.rs', '.swift', '.kt', '.scala',
|
|
172
|
+
'.clj', '.hs', '.ml', '.fs', '.vb', '.pl', '.sh', '.bash', '.zsh', '.fish',
|
|
173
|
+
'.ps1', '.bat', '.cmd', '.html', '.htm', '.xml', '.css', '.scss', '.sass',
|
|
174
|
+
'.less', '.json', '.yaml', '.yml', '.toml', '.ini', '.cfg', '.conf',
|
|
175
|
+
'.properties', '.env', '.md', '.rst', '.txt', '.log', '.sql', '.r',
|
|
176
|
+
'.m', '.mm', '.dart', '.lua', '.vim', '.dockerfile', '.makefile',
|
|
177
|
+
'.cmake', '.gradle', '.maven', '.ant', '.sbt', '.cabal', '.nix'
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Supported image file extensions
|
|
181
|
+
IMAGE_FILE_EXTENSIONS = {
|
|
182
|
+
'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.svg', '.ico',
|
|
183
|
+
'.tiff', '.tif', '.psd', '.ai', '.eps'
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Supported PDF file extensions
|
|
187
|
+
PDF_FILE_EXTENSIONS = {
|
|
188
|
+
'.pdf'
|
|
189
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ReadManyFiles tool - Batch read multiple files with intelligent filtering.
|
|
3
|
+
|
|
4
|
+
This tool provides functionality to read multiple files based on glob patterns,
|
|
5
|
+
with support for text files, images, and PDFs. It includes intelligent filtering
|
|
6
|
+
using .gitignore rules and default exclusion patterns.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import time
|
|
11
|
+
import asyncio
|
|
12
|
+
from typing import Dict, Any, Optional
|
|
13
|
+
|
|
14
|
+
from .read_many_files.models import ReadManyFilesParams, ToolResult
|
|
15
|
+
from .read_many_files.file_processor import FileProcessor
|
|
16
|
+
from .read_many_files.filters import FileFilter
|
|
17
|
+
from .read_many_files.formatters import ResultFormatter
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ReadManyFilesTool:
|
|
21
|
+
"""ReadManyFiles tool implementation"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, target_dir: Optional[str] = None):
|
|
24
|
+
"""
|
|
25
|
+
Initialize ReadManyFiles tool
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
target_dir: Target directory for file operations (defaults to current working directory)
|
|
29
|
+
"""
|
|
30
|
+
self.target_dir = target_dir or os.getcwd()
|
|
31
|
+
self.file_processor = FileProcessor(self.target_dir)
|
|
32
|
+
self.file_filter = FileFilter(self.target_dir)
|
|
33
|
+
self.formatter = ResultFormatter(self.target_dir)
|
|
34
|
+
|
|
35
|
+
def validate_params(self, params: ReadManyFilesParams) -> Optional[str]:
|
|
36
|
+
"""
|
|
37
|
+
Validate input parameters
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
params: ReadManyFilesParams object
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Error message if validation fails, None if valid
|
|
44
|
+
"""
|
|
45
|
+
if not params.paths:
|
|
46
|
+
return "Parameter 'paths' is required and cannot be empty"
|
|
47
|
+
|
|
48
|
+
if not isinstance(params.paths, list):
|
|
49
|
+
return "Parameter 'paths' must be a list"
|
|
50
|
+
|
|
51
|
+
if any(not isinstance(path, str) for path in params.paths):
|
|
52
|
+
return "All items in 'paths' must be strings"
|
|
53
|
+
|
|
54
|
+
if params.include and not isinstance(params.include, list):
|
|
55
|
+
return "Parameter 'include' must be a list if provided"
|
|
56
|
+
|
|
57
|
+
if params.exclude and not isinstance(params.exclude, list):
|
|
58
|
+
return "Parameter 'exclude' must be a list if provided"
|
|
59
|
+
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
def merge_filtering_options(self, params: ReadManyFilesParams) -> Dict[str, bool]:
|
|
63
|
+
"""
|
|
64
|
+
Merge filtering options with defaults
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
params: ReadManyFilesParams object
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Dictionary of filtering options
|
|
71
|
+
"""
|
|
72
|
+
default_options = {
|
|
73
|
+
'respect_git_ignore': True
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if params.file_filtering_options:
|
|
77
|
+
default_options.update(params.file_filtering_options)
|
|
78
|
+
|
|
79
|
+
return default_options
|
|
80
|
+
|
|
81
|
+
async def execute(self, params: ReadManyFilesParams, signal=None) -> ToolResult:
|
|
82
|
+
"""
|
|
83
|
+
Execute the ReadManyFiles tool
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
params: ReadManyFilesParams object with tool parameters
|
|
87
|
+
signal: Cancellation signal (optional)
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
ToolResult object with processing results
|
|
91
|
+
"""
|
|
92
|
+
start_time = time.time()
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
# 1. Parameter validation
|
|
96
|
+
validation_error = self.validate_params(params)
|
|
97
|
+
if validation_error:
|
|
98
|
+
return ToolResult(**self.formatter.create_error_result(validation_error))
|
|
99
|
+
|
|
100
|
+
# 2. Configuration initialization
|
|
101
|
+
file_filtering_options = self.merge_filtering_options(params)
|
|
102
|
+
|
|
103
|
+
# 3. Build search patterns
|
|
104
|
+
search_patterns = params.paths + (params.include or [])
|
|
105
|
+
if not search_patterns:
|
|
106
|
+
return ToolResult(**self.formatter.create_info_result("No search patterns provided"))
|
|
107
|
+
|
|
108
|
+
exclusion_patterns = self.file_filter.build_exclusion_patterns(params)
|
|
109
|
+
|
|
110
|
+
# 4. Execute file search
|
|
111
|
+
all_files = await self.file_processor.search_files_with_glob(
|
|
112
|
+
search_patterns, exclusion_patterns, signal
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if not all_files:
|
|
116
|
+
return ToolResult(**self.formatter.create_info_result(
|
|
117
|
+
"No files found matching the specified patterns"
|
|
118
|
+
))
|
|
119
|
+
|
|
120
|
+
# 5. Apply ignore filters
|
|
121
|
+
filtered_files, filter_counts = self.file_filter.apply_gitignore_filters(
|
|
122
|
+
all_files, file_filtering_options
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# 6. Security validation
|
|
126
|
+
validated_files = self.file_filter.validate_workspace_security(filtered_files)
|
|
127
|
+
|
|
128
|
+
if not validated_files:
|
|
129
|
+
return ToolResult(**self.formatter.create_info_result(
|
|
130
|
+
"No files remain after filtering and security validation"
|
|
131
|
+
))
|
|
132
|
+
|
|
133
|
+
# 7. Read file contents
|
|
134
|
+
content_parts, processed_files, skipped_files = await self.file_processor.process_files(
|
|
135
|
+
validated_files, params.paths
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# 8. Add filter statistics to skipped files
|
|
139
|
+
filter_skip_info = self.formatter.build_filter_skip_info(filter_counts)
|
|
140
|
+
skipped_files.extend(filter_skip_info)
|
|
141
|
+
|
|
142
|
+
# 9. Update processing time
|
|
143
|
+
end_time = time.time()
|
|
144
|
+
self.file_processor.stats.processing_time = end_time - start_time
|
|
145
|
+
|
|
146
|
+
# 10. Build and return result
|
|
147
|
+
result_dict = self.formatter.build_result(
|
|
148
|
+
content_parts, processed_files, skipped_files, self.file_processor.stats
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return ToolResult(**result_dict)
|
|
152
|
+
|
|
153
|
+
except Exception as error:
|
|
154
|
+
return ToolResult(**self.formatter.create_error_result(
|
|
155
|
+
f"Unexpected error during file processing: {str(error)}"
|
|
156
|
+
))
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# Main function for tool execution
|
|
160
|
+
async def read_many_files(params: ReadManyFilesParams,
|
|
161
|
+
target_dir: Optional[str] = None,
|
|
162
|
+
signal=None) -> ToolResult:
|
|
163
|
+
"""
|
|
164
|
+
Read multiple files based on glob patterns
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
params: ReadManyFilesParams object with tool parameters
|
|
168
|
+
target_dir: Target directory for file operations (optional)
|
|
169
|
+
signal: Cancellation signal (optional)
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
ToolResult object with processing results
|
|
173
|
+
"""
|
|
174
|
+
tool = ReadManyFilesTool(target_dir)
|
|
175
|
+
return await tool.execute(params, signal)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# Convenience function for direct usage
|
|
179
|
+
async def read_files_by_patterns(paths: list,
|
|
180
|
+
include: Optional[list] = None,
|
|
181
|
+
exclude: Optional[list] = None,
|
|
182
|
+
target_dir: Optional[str] = None,
|
|
183
|
+
use_default_excludes: bool = True,
|
|
184
|
+
respect_git_ignore: bool = True) -> ToolResult:
|
|
185
|
+
"""
|
|
186
|
+
Convenience function to read files by patterns
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
paths: List of file paths or glob patterns
|
|
190
|
+
include: Additional include patterns (optional)
|
|
191
|
+
exclude: Exclude patterns (optional)
|
|
192
|
+
target_dir: Target directory (optional)
|
|
193
|
+
use_default_excludes: Whether to use default exclusion patterns
|
|
194
|
+
respect_git_ignore: Whether to respect .gitignore rules
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
ToolResult object with processing results
|
|
198
|
+
"""
|
|
199
|
+
params = ReadManyFilesParams(
|
|
200
|
+
paths=paths,
|
|
201
|
+
include=include,
|
|
202
|
+
exclude=exclude,
|
|
203
|
+
useDefaultExcludes=use_default_excludes,
|
|
204
|
+
file_filtering_options={
|
|
205
|
+
'respect_git_ignore': respect_git_ignore
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
return await read_many_files(params, target_dir)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
if __name__ == "__main__":
|
|
213
|
+
# Example usage
|
|
214
|
+
import asyncio
|
|
215
|
+
|
|
216
|
+
async def main():
|
|
217
|
+
# Example: Read all Python files in current directory
|
|
218
|
+
result = await read_files_by_patterns(
|
|
219
|
+
paths=["**/*.py"],
|
|
220
|
+
exclude=["**/test_*.py", "**/__pycache__/**"]
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
print("LLM Content:")
|
|
224
|
+
for content in result.llmContent:
|
|
225
|
+
if isinstance(content, str):
|
|
226
|
+
print(content[:200] + "..." if len(content) > 200 else content)
|
|
227
|
+
else:
|
|
228
|
+
print(f"[Binary content: {content.get('type', 'unknown')}]")
|
|
229
|
+
|
|
230
|
+
print("\nDisplay Message:")
|
|
231
|
+
print(result.returnDisplay)
|
|
232
|
+
|
|
233
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tool Call Formatter 模块
|
|
3
|
+
|
|
4
|
+
提供工具调用参数格式化功能,包括:
|
|
5
|
+
- ToolCallFormatter 抽象基类接口
|
|
6
|
+
- ToolCallFormatterFactory 工厂类
|
|
7
|
+
- 各种具体的 formatter 实现
|
|
8
|
+
- ParameterInterceptor 参数拦截装饰器
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .tool_call_formatter import ToolCallFormatter
|
|
12
|
+
from .formatter_factory import ToolCallFormatterFactory
|
|
13
|
+
from .formatters import (
|
|
14
|
+
DefaultFormatter,
|
|
15
|
+
ListCodeDefinitionNamesFormatter,
|
|
16
|
+
SearchFormatter,
|
|
17
|
+
CommandFormatter,
|
|
18
|
+
FixAttemptCompletionFormatter,
|
|
19
|
+
ReproduceCompletionFormatter,
|
|
20
|
+
FileEditFormatter,
|
|
21
|
+
AskFollowupQuestionFormatter,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# 自动注册所有formatter
|
|
25
|
+
def _register_all_formatters():
|
|
26
|
+
"""自动注册所有可用的formatter"""
|
|
27
|
+
formatters = [
|
|
28
|
+
DefaultFormatter,
|
|
29
|
+
SearchFormatter,
|
|
30
|
+
CommandFormatter,
|
|
31
|
+
FixAttemptCompletionFormatter,
|
|
32
|
+
ReproduceCompletionFormatter,
|
|
33
|
+
FileEditFormatter,
|
|
34
|
+
AskFollowupQuestionFormatter,
|
|
35
|
+
ListCodeDefinitionNamesFormatter,
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
for formatter_class in formatters:
|
|
39
|
+
ToolCallFormatterFactory.register_formatter(formatter_class)
|
|
40
|
+
|
|
41
|
+
# 在模块导入时自动注册
|
|
42
|
+
_register_all_formatters()
|
|
43
|
+
|
|
44
|
+
# 导出的公共接口
|
|
45
|
+
__all__ = [
|
|
46
|
+
'ToolCallFormatter',
|
|
47
|
+
'ToolCallFormatterFactory',
|
|
48
|
+
'DefaultFormatter',
|
|
49
|
+
'FileReadFormatter',
|
|
50
|
+
'SearchFormatter',
|
|
51
|
+
'CommandFormatter',
|
|
52
|
+
'ParameterInterceptor',
|
|
53
|
+
'parameter_interceptor',
|
|
54
|
+
'simple_interceptor',
|
|
55
|
+
]
|