toolplane-python-client 0.1.0__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.
- toolplane/__init__.py +106 -0
- toolplane/common/__init__.py +93 -0
- toolplane/common/base_config.py +129 -0
- toolplane/common/base_connection_manager.py +171 -0
- toolplane/common/base_session_manager.py +321 -0
- toolplane/common/base_tool_manager.py +347 -0
- toolplane/common/constants.py +47 -0
- toolplane/common/utils.py +310 -0
- toolplane/core/__init__.py +67 -0
- toolplane/core/config.py +107 -0
- toolplane/core/connection.py +285 -0
- toolplane/core/errors.py +298 -0
- toolplane/core/machine.py +480 -0
- toolplane/core/request.py +775 -0
- toolplane/core/session.py +332 -0
- toolplane/core/session_context.py +514 -0
- toolplane/core/task.py +130 -0
- toolplane/core/tool.py +329 -0
- toolplane/http_core/__init__.py +37 -0
- toolplane/http_core/http_config.py +97 -0
- toolplane/http_core/http_connection.py +409 -0
- toolplane/http_core/http_machine.py +298 -0
- toolplane/http_core/http_request.py +748 -0
- toolplane/http_core/http_session.py +348 -0
- toolplane/http_core/http_session_context.py +491 -0
- toolplane/http_core/http_task.py +101 -0
- toolplane/http_core/http_tool.py +400 -0
- toolplane/interfaces/__init__.py +27 -0
- toolplane/interfaces/client_interface.py +122 -0
- toolplane/interfaces/connection_interface.py +193 -0
- toolplane/interfaces/event_interface.py +290 -0
- toolplane/interfaces/request_interface.py +439 -0
- toolplane/interfaces/session_interface.py +288 -0
- toolplane/interfaces/tool_interface.py +441 -0
- toolplane/proto/__init__.py +0 -0
- toolplane/proto/service_pb2.py +315 -0
- toolplane/proto/service_pb2_grpc.py +2240 -0
- toolplane/provider_cli.py +268 -0
- toolplane/provider_registry.py +77 -0
- toolplane/provider_runtime.py +302 -0
- toolplane/toolkits/__init__.py +0 -0
- toolplane/toolkits/standalone_tools/__init__.py +0 -0
- toolplane/toolkits/standalone_tools/create_directory.py +94 -0
- toolplane/toolkits/standalone_tools/create_file.py +124 -0
- toolplane/toolkits/standalone_tools/file_search.py +229 -0
- toolplane/toolkits/standalone_tools/grep_search.py +372 -0
- toolplane/toolkits/standalone_tools/launcher.py +146 -0
- toolplane/toolkits/standalone_tools/list_dir.py +395 -0
- toolplane/toolkits/standalone_tools/read_file.py +346 -0
- toolplane/toolkits/standalone_tools/replace_string_in_file.py +407 -0
- toolplane/toolkits/standalone_tools/run_tests.py +66 -0
- toolplane/toolkits/standalone_tools/semantic_search.py +485 -0
- toolplane/toolkits/standalone_tools/standalone_toolkit.py +979 -0
- toolplane/toolkits/standalone_tools/test_failure_analysis.py +618 -0
- toolplane/toolkits/standalone_tools/test_standalone_toolkit.py +517 -0
- toolplane/toolkits/swe/__init__.py +35 -0
- toolplane/toolkits/swe/create_directory.py +15 -0
- toolplane/toolkits/swe/create_file.py +15 -0
- toolplane/toolkits/swe/descriptions.py +273 -0
- toolplane/toolkits/swe/execute_bash.py +93 -0
- toolplane/toolkits/swe/file_editor.py +775 -0
- toolplane/toolkits/swe/file_search.py +16 -0
- toolplane/toolkits/swe/finish.py +50 -0
- toolplane/toolkits/swe/grep_search.py +19 -0
- toolplane/toolkits/swe/list_dir.py +407 -0
- toolplane/toolkits/swe/read_file.py +18 -0
- toolplane/toolkits/swe/replace_string_in_file.py +17 -0
- toolplane/toolkits/swe/search.py +260 -0
- toolplane/toolkits/swe/semantic_search.py +20 -0
- toolplane/toolkits/swe/str_replace_editor.py +647 -0
- toolplane/toolkits/swe/submit.py +29 -0
- toolplane/toolkits/swe/swe_toolkit.py +1296 -0
- toolplane/toolplane_client.py +686 -0
- toolplane/toolplane_http_client.py +681 -0
- toolplane/utils/__init__.py +3 -0
- toolplane/utils/schema.py +146 -0
- toolplane_python_client-0.1.0.dist-info/METADATA +543 -0
- toolplane_python_client-0.1.0.dist-info/RECORD +81 -0
- toolplane_python_client-0.1.0.dist-info/WHEEL +5 -0
- toolplane_python_client-0.1.0.dist-info/entry_points.txt +2 -0
- toolplane_python_client-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Description: Read file contents with enhanced features and line range support.
|
|
4
|
+
|
|
5
|
+
This tool reads the contents of a file with support for line ranges,
|
|
6
|
+
encoding detection, and various output formats.
|
|
7
|
+
|
|
8
|
+
Parameters:
|
|
9
|
+
file_path (string, required): The absolute path of the file to read.
|
|
10
|
+
start_line (integer, required): The line number to start reading from (1-based).
|
|
11
|
+
end_line (integer, required): The inclusive line number to end reading at (1-based).
|
|
12
|
+
encoding (string, optional): The encoding to use for reading the file (default: auto-detect).
|
|
13
|
+
show_line_numbers (boolean, optional): Show line numbers in output (default: True).
|
|
14
|
+
highlight_syntax (boolean, optional): Attempt to highlight syntax if possible (default: False).
|
|
15
|
+
max_line_length (integer, optional): Maximum line length before truncation (default: 1000).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import os
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any, Dict, List, Optional
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def read_file(
|
|
26
|
+
file_path: str,
|
|
27
|
+
start_line: int,
|
|
28
|
+
end_line: int,
|
|
29
|
+
encoding: str = None,
|
|
30
|
+
show_line_numbers: bool = True,
|
|
31
|
+
highlight_syntax: bool = False,
|
|
32
|
+
max_line_length: int = 1000,
|
|
33
|
+
) -> Dict[str, Any]:
|
|
34
|
+
"""
|
|
35
|
+
Read file contents with enhanced features and line range support.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
file_path: The absolute path of the file to read
|
|
39
|
+
start_line: Line number to start reading from (1-based)
|
|
40
|
+
end_line: Line number to end reading at (1-based)
|
|
41
|
+
encoding: Encoding to use for reading the file
|
|
42
|
+
show_line_numbers: Show line numbers in output
|
|
43
|
+
highlight_syntax: Attempt to highlight syntax
|
|
44
|
+
max_line_length: Maximum line length before truncation
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Dictionary containing file content and metadata
|
|
48
|
+
"""
|
|
49
|
+
try:
|
|
50
|
+
path = Path(file_path)
|
|
51
|
+
|
|
52
|
+
if not path.exists():
|
|
53
|
+
return {
|
|
54
|
+
"success": False,
|
|
55
|
+
"error": f"File does not exist: {file_path}",
|
|
56
|
+
"content": None,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if not path.is_file():
|
|
60
|
+
return {
|
|
61
|
+
"success": False,
|
|
62
|
+
"error": f"Path is not a file: {file_path}",
|
|
63
|
+
"content": None,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Detect encoding if not specified
|
|
67
|
+
if encoding is None:
|
|
68
|
+
encoding = detect_encoding(path)
|
|
69
|
+
|
|
70
|
+
# Read the file
|
|
71
|
+
try:
|
|
72
|
+
with open(path, "r", encoding=encoding, errors="replace") as f:
|
|
73
|
+
all_lines = f.readlines()
|
|
74
|
+
except UnicodeDecodeError:
|
|
75
|
+
# Fallback to UTF-8 with error handling
|
|
76
|
+
with open(path, "r", encoding="utf-8", errors="replace") as f:
|
|
77
|
+
all_lines = f.readlines()
|
|
78
|
+
|
|
79
|
+
total_lines = len(all_lines)
|
|
80
|
+
|
|
81
|
+
# Validate line numbers
|
|
82
|
+
if start_line < 1:
|
|
83
|
+
start_line = 1
|
|
84
|
+
if end_line < 1:
|
|
85
|
+
end_line = total_lines
|
|
86
|
+
if end_line == -1:
|
|
87
|
+
end_line = total_lines
|
|
88
|
+
|
|
89
|
+
start_line = min(start_line, total_lines)
|
|
90
|
+
end_line = min(end_line, total_lines)
|
|
91
|
+
|
|
92
|
+
if start_line > end_line:
|
|
93
|
+
return {
|
|
94
|
+
"success": False,
|
|
95
|
+
"error": f"Start line ({start_line}) is greater than end line ({end_line})",
|
|
96
|
+
"content": None,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Extract the requested lines
|
|
100
|
+
selected_lines = all_lines[start_line - 1 : end_line]
|
|
101
|
+
|
|
102
|
+
# Process lines
|
|
103
|
+
processed_lines = []
|
|
104
|
+
for i, line in enumerate(selected_lines, start=start_line):
|
|
105
|
+
# Remove trailing newline
|
|
106
|
+
line = line.rstrip("\n\r")
|
|
107
|
+
|
|
108
|
+
# Truncate long lines
|
|
109
|
+
if len(line) > max_line_length:
|
|
110
|
+
line = line[:max_line_length] + "... [line truncated]"
|
|
111
|
+
|
|
112
|
+
processed_lines.append(
|
|
113
|
+
{
|
|
114
|
+
"line_number": i,
|
|
115
|
+
"content": line,
|
|
116
|
+
"original_length": len(all_lines[i - 1].rstrip("\n\r")),
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Get file metadata
|
|
121
|
+
stat_info = path.stat()
|
|
122
|
+
|
|
123
|
+
result = {
|
|
124
|
+
"success": True,
|
|
125
|
+
"file_path": str(path.resolve()),
|
|
126
|
+
"encoding": encoding,
|
|
127
|
+
"total_lines": total_lines,
|
|
128
|
+
"start_line": start_line,
|
|
129
|
+
"end_line": end_line,
|
|
130
|
+
"lines_returned": len(processed_lines),
|
|
131
|
+
"file_size": stat_info.st_size,
|
|
132
|
+
"content": processed_lines,
|
|
133
|
+
"show_line_numbers": show_line_numbers,
|
|
134
|
+
"highlight_syntax": highlight_syntax
|
|
135
|
+
and get_file_language(path) is not None,
|
|
136
|
+
"file_language": get_file_language(path),
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return result
|
|
140
|
+
|
|
141
|
+
except PermissionError:
|
|
142
|
+
return {
|
|
143
|
+
"success": False,
|
|
144
|
+
"error": f"Permission denied: {file_path}",
|
|
145
|
+
"content": None,
|
|
146
|
+
}
|
|
147
|
+
except Exception as e:
|
|
148
|
+
return {"success": False, "error": f"Error reading file: {e}", "content": None}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def detect_encoding(file_path: Path) -> str:
|
|
152
|
+
"""Detect file encoding using simple heuristics."""
|
|
153
|
+
try:
|
|
154
|
+
# Try common encodings in order
|
|
155
|
+
encodings = ["utf-8", "utf-16", "latin-1", "cp1252"]
|
|
156
|
+
|
|
157
|
+
for encoding in encodings:
|
|
158
|
+
try:
|
|
159
|
+
with open(file_path, "r", encoding=encoding) as f:
|
|
160
|
+
f.read(1024) # Try to read first 1KB
|
|
161
|
+
return encoding
|
|
162
|
+
except UnicodeDecodeError:
|
|
163
|
+
continue
|
|
164
|
+
|
|
165
|
+
# If all fail, return utf-8 as default
|
|
166
|
+
return "utf-8"
|
|
167
|
+
|
|
168
|
+
except Exception:
|
|
169
|
+
return "utf-8"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def get_file_language(file_path: Path) -> Optional[str]:
|
|
173
|
+
"""Determine the programming language based on file extension."""
|
|
174
|
+
extension_map = {
|
|
175
|
+
".py": "python",
|
|
176
|
+
".js": "javascript",
|
|
177
|
+
".ts": "typescript",
|
|
178
|
+
".jsx": "javascript",
|
|
179
|
+
".tsx": "typescript",
|
|
180
|
+
".java": "java",
|
|
181
|
+
".cpp": "cpp",
|
|
182
|
+
".c": "c",
|
|
183
|
+
".h": "c",
|
|
184
|
+
".hpp": "cpp",
|
|
185
|
+
".cs": "csharp",
|
|
186
|
+
".php": "php",
|
|
187
|
+
".rb": "ruby",
|
|
188
|
+
".go": "go",
|
|
189
|
+
".rs": "rust",
|
|
190
|
+
".swift": "swift",
|
|
191
|
+
".kt": "kotlin",
|
|
192
|
+
".scala": "scala",
|
|
193
|
+
".r": "r",
|
|
194
|
+
".sql": "sql",
|
|
195
|
+
".html": "html",
|
|
196
|
+
".htm": "html",
|
|
197
|
+
".css": "css",
|
|
198
|
+
".scss": "scss",
|
|
199
|
+
".sass": "sass",
|
|
200
|
+
".less": "less",
|
|
201
|
+
".xml": "xml",
|
|
202
|
+
".json": "json",
|
|
203
|
+
".yaml": "yaml",
|
|
204
|
+
".yml": "yaml",
|
|
205
|
+
".toml": "toml",
|
|
206
|
+
".ini": "ini",
|
|
207
|
+
".cfg": "ini",
|
|
208
|
+
".conf": "ini",
|
|
209
|
+
".md": "markdown",
|
|
210
|
+
".rst": "rst",
|
|
211
|
+
".tex": "latex",
|
|
212
|
+
".sh": "bash",
|
|
213
|
+
".bash": "bash",
|
|
214
|
+
".zsh": "zsh",
|
|
215
|
+
".fish": "fish",
|
|
216
|
+
".ps1": "powershell",
|
|
217
|
+
".bat": "batch",
|
|
218
|
+
".dockerfile": "dockerfile",
|
|
219
|
+
".makefile": "makefile",
|
|
220
|
+
".cmake": "cmake",
|
|
221
|
+
".gradle": "gradle",
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return extension_map.get(file_path.suffix.lower())
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def format_output(result: Dict[str, Any], output_format: str) -> str:
|
|
228
|
+
"""Format the output according to the specified format."""
|
|
229
|
+
if not result["success"]:
|
|
230
|
+
return f"Error: {result['error']}"
|
|
231
|
+
|
|
232
|
+
if output_format == "json":
|
|
233
|
+
import json
|
|
234
|
+
|
|
235
|
+
return json.dumps(result, indent=2)
|
|
236
|
+
|
|
237
|
+
elif output_format == "raw":
|
|
238
|
+
return "\n".join(line["content"] for line in result["content"])
|
|
239
|
+
|
|
240
|
+
else: # default format
|
|
241
|
+
lines = []
|
|
242
|
+
|
|
243
|
+
# Header
|
|
244
|
+
lines.append(f"File: {result['file_path']}")
|
|
245
|
+
lines.append(
|
|
246
|
+
f"Lines: {result['start_line']}-{result['end_line']} (of {result['total_lines']})"
|
|
247
|
+
)
|
|
248
|
+
lines.append(f"Encoding: {result['encoding']}")
|
|
249
|
+
if result["file_language"]:
|
|
250
|
+
lines.append(f"Language: {result['file_language']}")
|
|
251
|
+
lines.append("-" * 60)
|
|
252
|
+
|
|
253
|
+
# Content
|
|
254
|
+
for line_info in result["content"]:
|
|
255
|
+
if result["show_line_numbers"]:
|
|
256
|
+
line_num = f"{line_info['line_number']:4d}"
|
|
257
|
+
content = line_info["content"]
|
|
258
|
+
|
|
259
|
+
# Show truncation indicator
|
|
260
|
+
if line_info["original_length"] > len(content):
|
|
261
|
+
truncated = " [truncated]"
|
|
262
|
+
else:
|
|
263
|
+
truncated = ""
|
|
264
|
+
|
|
265
|
+
lines.append(f"{line_num}: {content}{truncated}")
|
|
266
|
+
else:
|
|
267
|
+
lines.append(line_info["content"])
|
|
268
|
+
|
|
269
|
+
return "\n".join(lines)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def main():
|
|
273
|
+
parser = argparse.ArgumentParser(
|
|
274
|
+
description="Read file contents with enhanced features and line range support."
|
|
275
|
+
)
|
|
276
|
+
parser.add_argument(
|
|
277
|
+
"file_path", type=str, help="The absolute path of the file to read"
|
|
278
|
+
)
|
|
279
|
+
parser.add_argument(
|
|
280
|
+
"start_line", type=int, help="The line number to start reading from (1-based)"
|
|
281
|
+
)
|
|
282
|
+
parser.add_argument(
|
|
283
|
+
"end_line",
|
|
284
|
+
type=int,
|
|
285
|
+
help="The inclusive line number to end reading at (1-based, use -1 for end of file)",
|
|
286
|
+
)
|
|
287
|
+
parser.add_argument(
|
|
288
|
+
"--encoding",
|
|
289
|
+
type=str,
|
|
290
|
+
help="The encoding to use for reading the file (default: auto-detect)",
|
|
291
|
+
)
|
|
292
|
+
parser.add_argument(
|
|
293
|
+
"--show_line_numbers",
|
|
294
|
+
action="store_true",
|
|
295
|
+
default=True,
|
|
296
|
+
help="Show line numbers in output (default: True)",
|
|
297
|
+
)
|
|
298
|
+
parser.add_argument(
|
|
299
|
+
"--no_line_numbers",
|
|
300
|
+
action="store_true",
|
|
301
|
+
default=False,
|
|
302
|
+
help="Hide line numbers in output",
|
|
303
|
+
)
|
|
304
|
+
parser.add_argument(
|
|
305
|
+
"--highlight_syntax",
|
|
306
|
+
action="store_true",
|
|
307
|
+
default=False,
|
|
308
|
+
help="Attempt to highlight syntax if possible (default: False)",
|
|
309
|
+
)
|
|
310
|
+
parser.add_argument(
|
|
311
|
+
"--max_line_length",
|
|
312
|
+
type=int,
|
|
313
|
+
default=1000,
|
|
314
|
+
help="Maximum line length before truncation (default: 1000)",
|
|
315
|
+
)
|
|
316
|
+
parser.add_argument(
|
|
317
|
+
"--output_format",
|
|
318
|
+
choices=["default", "json", "raw"],
|
|
319
|
+
default="default",
|
|
320
|
+
help="Output format (default: default)",
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
args = parser.parse_args()
|
|
324
|
+
|
|
325
|
+
# Handle line numbers flag
|
|
326
|
+
show_line_numbers = args.show_line_numbers and not args.no_line_numbers
|
|
327
|
+
|
|
328
|
+
result = read_file(
|
|
329
|
+
args.file_path,
|
|
330
|
+
args.start_line,
|
|
331
|
+
args.end_line,
|
|
332
|
+
encoding=args.encoding,
|
|
333
|
+
show_line_numbers=show_line_numbers,
|
|
334
|
+
highlight_syntax=args.highlight_syntax,
|
|
335
|
+
max_line_length=args.max_line_length,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
output = format_output(result, args.output_format)
|
|
339
|
+
print(output)
|
|
340
|
+
|
|
341
|
+
# Exit with error code if reading failed
|
|
342
|
+
sys.exit(0 if result["success"] else 1)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
if __name__ == "__main__":
|
|
346
|
+
main()
|