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,16 @@
|
|
|
1
|
+
"""Re-exported from toolplane.toolkits.standalone_tools — the single
|
|
2
|
+
maintained copy of this tool. The SWE toolkit composes these safe
|
|
3
|
+
file tools with its own unsafe ones (execute_bash, file_editor).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from toolplane.toolkits.standalone_tools.file_search import ( # noqa: F401
|
|
7
|
+
file_search,
|
|
8
|
+
format_size,
|
|
9
|
+
main,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
if __name__ == "__main__":
|
|
13
|
+
main()
|
|
14
|
+
|
|
15
|
+
if __name__ == "__main__":
|
|
16
|
+
main()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Description: A simple finish tool with a "submit" command.
|
|
4
|
+
|
|
5
|
+
Notes about the `submit` command:
|
|
6
|
+
* When invoked with `--result`, the provided string is used for submitting required task results (e.g., localization files).
|
|
7
|
+
* If no `--result` is provided, it defaults to an empty string.
|
|
8
|
+
|
|
9
|
+
**Parameters:**
|
|
10
|
+
1. **command** (`string`, required): The command to run. Currently allowed option is: `submit`.
|
|
11
|
+
- Allowed value: [`submit`]
|
|
12
|
+
2. **result** (`string`, optional): The result text to submit. Defaults to an empty string.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def submit(result: str = ""):
|
|
20
|
+
"""
|
|
21
|
+
Submits a final result, printing a message that includes the result.
|
|
22
|
+
"""
|
|
23
|
+
print("<<<Finished>>>")
|
|
24
|
+
# if result:
|
|
25
|
+
# print(f"Final result submitted: {result}")
|
|
26
|
+
# else:
|
|
27
|
+
# print("No result provided.")
|
|
28
|
+
# You can add more logic here as needed
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main():
|
|
32
|
+
parser = argparse.ArgumentParser(
|
|
33
|
+
description="submit tool: run the `submit` command with an optional `--result` argument."
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument("command", help="Subcommand to run (currently only `submit`).")
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--result", help="The result text to submit (optional).", default=""
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
args = parser.parse_args()
|
|
41
|
+
|
|
42
|
+
if args.command == "submit":
|
|
43
|
+
submit(args.result)
|
|
44
|
+
else:
|
|
45
|
+
print(f"Unknown command '{args.command}'. Only `submit` is supported.")
|
|
46
|
+
sys.exit(1)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
main()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Re-exported from toolplane.toolkits.standalone_tools — the single
|
|
2
|
+
maintained copy of this tool. The SWE toolkit composes these safe
|
|
3
|
+
file tools with its own unsafe ones (execute_bash, file_editor).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from toolplane.toolkits.standalone_tools.grep_search import ( # noqa: F401
|
|
7
|
+
get_all_text_files,
|
|
8
|
+
get_files_by_pattern,
|
|
9
|
+
grep_search,
|
|
10
|
+
is_text_file,
|
|
11
|
+
main,
|
|
12
|
+
search_file,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
if __name__ == "__main__":
|
|
16
|
+
main()
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Description: List directory contents with enhanced features.
|
|
4
|
+
|
|
5
|
+
This tool lists the contents of a directory with various display options,
|
|
6
|
+
sorting capabilities, and filtering features.
|
|
7
|
+
|
|
8
|
+
Parameters:
|
|
9
|
+
path (string, required): The absolute path to the directory to list.
|
|
10
|
+
show_hidden (boolean, optional): Show hidden files and directories (default: False).
|
|
11
|
+
show_details (boolean, optional): Show detailed information like size and permissions (default: False).
|
|
12
|
+
sort_by (string, optional): Sort by 'name', 'size', 'modified', 'type' (default: 'name').
|
|
13
|
+
reverse_sort (boolean, optional): Reverse the sort order (default: False).
|
|
14
|
+
recursive (boolean, optional): List contents recursively (default: False).
|
|
15
|
+
max_depth (integer, optional): Maximum depth for recursive listing (default: 3).
|
|
16
|
+
file_filter (string, optional): Filter files by extension (e.g., '.py', '.txt').
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import os
|
|
21
|
+
import stat
|
|
22
|
+
import sys
|
|
23
|
+
import time
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Any, Dict, List, Optional
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def list_dir(
|
|
29
|
+
path: str,
|
|
30
|
+
show_hidden: bool = False,
|
|
31
|
+
show_details: bool = False,
|
|
32
|
+
sort_by: str = "name",
|
|
33
|
+
reverse_sort: bool = False,
|
|
34
|
+
recursive: bool = False,
|
|
35
|
+
max_depth: int = 3,
|
|
36
|
+
file_filter: Optional[str] = None,
|
|
37
|
+
) -> List[Dict[str, Any]]:
|
|
38
|
+
"""
|
|
39
|
+
List directory contents with enhanced features.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
path: The directory path to list
|
|
43
|
+
show_hidden: Show hidden files and directories
|
|
44
|
+
show_details: Show detailed information
|
|
45
|
+
sort_by: Sort by 'name', 'size', 'modified', 'type'
|
|
46
|
+
reverse_sort: Reverse the sort order
|
|
47
|
+
recursive: List contents recursively
|
|
48
|
+
max_depth: Maximum depth for recursive listing
|
|
49
|
+
file_filter: Filter files by extension
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
List of dictionaries containing file/directory information
|
|
53
|
+
"""
|
|
54
|
+
try:
|
|
55
|
+
dir_path = Path(path)
|
|
56
|
+
|
|
57
|
+
if not dir_path.exists():
|
|
58
|
+
print(f"Error: Directory '{path}' does not exist.", file=sys.stderr)
|
|
59
|
+
return []
|
|
60
|
+
|
|
61
|
+
if not dir_path.is_dir():
|
|
62
|
+
print(f"Error: '{path}' is not a directory.", file=sys.stderr)
|
|
63
|
+
return []
|
|
64
|
+
|
|
65
|
+
results = []
|
|
66
|
+
|
|
67
|
+
base_dir = dir_path.resolve()
|
|
68
|
+
if recursive:
|
|
69
|
+
results = _list_recursive(
|
|
70
|
+
dir_path, base_dir, show_hidden, max_depth, file_filter, current_depth=0
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
results = _list_single_dir(dir_path, base_dir, show_hidden, file_filter)
|
|
74
|
+
|
|
75
|
+
# Add detailed information if requested
|
|
76
|
+
if show_details:
|
|
77
|
+
for result in results:
|
|
78
|
+
_add_detailed_info(result)
|
|
79
|
+
|
|
80
|
+
# Sort results
|
|
81
|
+
results = _sort_results(results, sort_by, reverse_sort)
|
|
82
|
+
|
|
83
|
+
return results
|
|
84
|
+
|
|
85
|
+
except PermissionError:
|
|
86
|
+
print(f"Error: Permission denied accessing '{path}'.", file=sys.stderr)
|
|
87
|
+
return []
|
|
88
|
+
except Exception as e:
|
|
89
|
+
print(f"Error listing directory '{path}': {e}", file=sys.stderr)
|
|
90
|
+
return []
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _list_single_dir(
|
|
94
|
+
dir_path: Path, base_dir: Path, show_hidden: bool, file_filter: Optional[str]
|
|
95
|
+
) -> List[Dict[str, Any]]:
|
|
96
|
+
"""List contents of a single directory."""
|
|
97
|
+
results = []
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
for item in dir_path.iterdir():
|
|
101
|
+
# Skip hidden files if not requested
|
|
102
|
+
if not show_hidden and item.name.startswith("."):
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
# Apply file filter
|
|
106
|
+
if file_filter and item.is_file() and not item.name.endswith(file_filter):
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
stat_info = item.stat()
|
|
111
|
+
|
|
112
|
+
result = {
|
|
113
|
+
"name": item.name,
|
|
114
|
+
"path": str(item.resolve()),
|
|
115
|
+
"relative_path": str(item.resolve().relative_to(base_dir)),
|
|
116
|
+
"is_file": item.is_file(),
|
|
117
|
+
"is_dir": item.is_dir(),
|
|
118
|
+
"is_symlink": item.is_symlink(),
|
|
119
|
+
"size": stat_info.st_size if item.is_file() else 0,
|
|
120
|
+
"modified": stat_info.st_mtime,
|
|
121
|
+
"modified_readable": time.strftime(
|
|
122
|
+
"%Y-%m-%d %H:%M:%S", time.localtime(stat_info.st_mtime)
|
|
123
|
+
),
|
|
124
|
+
"permissions": stat.filemode(stat_info.st_mode),
|
|
125
|
+
"depth": 0,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
results.append(result)
|
|
129
|
+
|
|
130
|
+
except (OSError, PermissionError):
|
|
131
|
+
# Skip items that can't be accessed
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
except PermissionError:
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
return results
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _list_recursive(
|
|
141
|
+
dir_path: Path,
|
|
142
|
+
base_dir: Path,
|
|
143
|
+
show_hidden: bool,
|
|
144
|
+
max_depth: int,
|
|
145
|
+
file_filter: Optional[str],
|
|
146
|
+
current_depth: int = 0,
|
|
147
|
+
) -> List[Dict[str, Any]]:
|
|
148
|
+
"""List directory contents recursively.
|
|
149
|
+
|
|
150
|
+
Includes items at depth == max_depth but does not recurse deeper.
|
|
151
|
+
"""
|
|
152
|
+
results = []
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
for item in dir_path.iterdir():
|
|
156
|
+
# Skip hidden files if not requested
|
|
157
|
+
if not show_hidden and item.name.startswith("."):
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
# Apply file filter
|
|
161
|
+
if file_filter and item.is_file() and not item.name.endswith(file_filter):
|
|
162
|
+
continue
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
stat_info = item.stat()
|
|
166
|
+
|
|
167
|
+
result = {
|
|
168
|
+
"name": item.name,
|
|
169
|
+
"path": str(item.resolve()),
|
|
170
|
+
"relative_path": str(item.resolve().relative_to(base_dir)),
|
|
171
|
+
"is_file": item.is_file(),
|
|
172
|
+
"is_dir": item.is_dir(),
|
|
173
|
+
"is_symlink": item.is_symlink(),
|
|
174
|
+
"size": stat_info.st_size if item.is_file() else 0,
|
|
175
|
+
"modified": stat_info.st_mtime,
|
|
176
|
+
"modified_readable": time.strftime(
|
|
177
|
+
"%Y-%m-%d %H:%M:%S", time.localtime(stat_info.st_mtime)
|
|
178
|
+
),
|
|
179
|
+
"permissions": stat.filemode(stat_info.st_mode),
|
|
180
|
+
"depth": current_depth,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
results.append(result)
|
|
184
|
+
|
|
185
|
+
# Recurse into subdirectories if we haven't reached max_depth
|
|
186
|
+
if (
|
|
187
|
+
item.is_dir()
|
|
188
|
+
and not item.is_symlink()
|
|
189
|
+
and current_depth < max_depth
|
|
190
|
+
):
|
|
191
|
+
sub_results = _list_recursive(
|
|
192
|
+
item,
|
|
193
|
+
base_dir,
|
|
194
|
+
show_hidden,
|
|
195
|
+
max_depth,
|
|
196
|
+
file_filter,
|
|
197
|
+
current_depth + 1,
|
|
198
|
+
)
|
|
199
|
+
results.extend(sub_results)
|
|
200
|
+
|
|
201
|
+
except (OSError, PermissionError):
|
|
202
|
+
# Skip items that can't be accessed
|
|
203
|
+
continue
|
|
204
|
+
|
|
205
|
+
except PermissionError:
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
return results
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _add_detailed_info(result: Dict[str, Any]) -> None:
|
|
212
|
+
"""Add detailed information to a result entry."""
|
|
213
|
+
try:
|
|
214
|
+
path = Path(result["path"])
|
|
215
|
+
stat_info = path.stat()
|
|
216
|
+
|
|
217
|
+
result.update(
|
|
218
|
+
{
|
|
219
|
+
"owner_readable": bool(stat_info.st_mode & stat.S_IRUSR),
|
|
220
|
+
"owner_writable": bool(stat_info.st_mode & stat.S_IWUSR),
|
|
221
|
+
"owner_executable": bool(stat_info.st_mode & stat.S_IXUSR),
|
|
222
|
+
"group_readable": bool(stat_info.st_mode & stat.S_IRGRP),
|
|
223
|
+
"group_writable": bool(stat_info.st_mode & stat.S_IWGRP),
|
|
224
|
+
"group_executable": bool(stat_info.st_mode & stat.S_IXGRP),
|
|
225
|
+
"other_readable": bool(stat_info.st_mode & stat.S_IROTH),
|
|
226
|
+
"other_writable": bool(stat_info.st_mode & stat.S_IWOTH),
|
|
227
|
+
"other_executable": bool(stat_info.st_mode & stat.S_IXOTH),
|
|
228
|
+
"inode": stat_info.st_ino,
|
|
229
|
+
"device": stat_info.st_dev,
|
|
230
|
+
"nlink": stat_info.st_nlink,
|
|
231
|
+
"uid": stat_info.st_uid,
|
|
232
|
+
"gid": stat_info.st_gid,
|
|
233
|
+
"accessed": stat_info.st_atime,
|
|
234
|
+
"accessed_readable": time.strftime(
|
|
235
|
+
"%Y-%m-%d %H:%M:%S", time.localtime(stat_info.st_atime)
|
|
236
|
+
),
|
|
237
|
+
"created": getattr(stat_info, "st_birthtime", stat_info.st_ctime),
|
|
238
|
+
"created_readable": time.strftime(
|
|
239
|
+
"%Y-%m-%d %H:%M:%S",
|
|
240
|
+
time.localtime(
|
|
241
|
+
getattr(stat_info, "st_birthtime", stat_info.st_ctime)
|
|
242
|
+
),
|
|
243
|
+
),
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
except (OSError, PermissionError):
|
|
247
|
+
pass
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _sort_results(
|
|
251
|
+
results: List[Dict[str, Any]], sort_by: str, reverse_sort: bool
|
|
252
|
+
) -> List[Dict[str, Any]]:
|
|
253
|
+
"""Sort results by the specified criteria."""
|
|
254
|
+
if sort_by == "name":
|
|
255
|
+
results.sort(key=lambda x: x["name"].lower(), reverse=reverse_sort)
|
|
256
|
+
elif sort_by == "size":
|
|
257
|
+
results.sort(key=lambda x: x["size"], reverse=reverse_sort)
|
|
258
|
+
elif sort_by == "modified":
|
|
259
|
+
results.sort(key=lambda x: x["modified"], reverse=reverse_sort)
|
|
260
|
+
elif sort_by == "type":
|
|
261
|
+
# Sort by type (directories first, then files)
|
|
262
|
+
results.sort(
|
|
263
|
+
key=lambda x: (not x["is_dir"], x["name"].lower()), reverse=reverse_sort
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
return results
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def format_size(size_bytes: int) -> str:
|
|
270
|
+
"""Format file size in human-readable format."""
|
|
271
|
+
if size_bytes == 0:
|
|
272
|
+
return "0 B"
|
|
273
|
+
|
|
274
|
+
units = ["B", "KB", "MB", "GB", "TB"]
|
|
275
|
+
i = 0
|
|
276
|
+
size = float(size_bytes)
|
|
277
|
+
while size >= 1024.0 and i < len(units) - 1:
|
|
278
|
+
size /= 1024.0
|
|
279
|
+
i += 1
|
|
280
|
+
|
|
281
|
+
return f"{size:.1f} {units[i]}"
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def main():
|
|
285
|
+
parser = argparse.ArgumentParser(
|
|
286
|
+
description="List directory contents with enhanced features."
|
|
287
|
+
)
|
|
288
|
+
parser.add_argument(
|
|
289
|
+
"path", type=str, help="The absolute path to the directory to list"
|
|
290
|
+
)
|
|
291
|
+
parser.add_argument(
|
|
292
|
+
"--show_hidden",
|
|
293
|
+
action="store_true",
|
|
294
|
+
default=False,
|
|
295
|
+
help="Show hidden files and directories (default: False)",
|
|
296
|
+
)
|
|
297
|
+
parser.add_argument(
|
|
298
|
+
"--show_details",
|
|
299
|
+
action="store_true",
|
|
300
|
+
default=False,
|
|
301
|
+
help="Show detailed information like size and permissions (default: False)",
|
|
302
|
+
)
|
|
303
|
+
parser.add_argument(
|
|
304
|
+
"--sort_by",
|
|
305
|
+
choices=["name", "size", "modified", "type"],
|
|
306
|
+
default="name",
|
|
307
|
+
help="Sort by 'name', 'size', 'modified', or 'type' (default: name)",
|
|
308
|
+
)
|
|
309
|
+
parser.add_argument(
|
|
310
|
+
"--reverse_sort",
|
|
311
|
+
action="store_true",
|
|
312
|
+
default=False,
|
|
313
|
+
help="Reverse the sort order (default: False)",
|
|
314
|
+
)
|
|
315
|
+
parser.add_argument(
|
|
316
|
+
"--recursive",
|
|
317
|
+
action="store_true",
|
|
318
|
+
default=False,
|
|
319
|
+
help="List contents recursively (default: False)",
|
|
320
|
+
)
|
|
321
|
+
parser.add_argument(
|
|
322
|
+
"--max_depth",
|
|
323
|
+
type=int,
|
|
324
|
+
default=3,
|
|
325
|
+
help="Maximum depth for recursive listing (default: 3)",
|
|
326
|
+
)
|
|
327
|
+
parser.add_argument(
|
|
328
|
+
"--file_filter",
|
|
329
|
+
type=str,
|
|
330
|
+
help="Filter files by extension (e.g., '.py', '.txt')",
|
|
331
|
+
)
|
|
332
|
+
parser.add_argument(
|
|
333
|
+
"--output_format",
|
|
334
|
+
choices=["list", "table", "json", "tree"],
|
|
335
|
+
default="list",
|
|
336
|
+
help="Output format (default: list)",
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
args = parser.parse_args()
|
|
340
|
+
|
|
341
|
+
results = list_dir(
|
|
342
|
+
args.path,
|
|
343
|
+
show_hidden=args.show_hidden,
|
|
344
|
+
show_details=args.show_details,
|
|
345
|
+
sort_by=args.sort_by,
|
|
346
|
+
reverse_sort=args.reverse_sort,
|
|
347
|
+
recursive=args.recursive,
|
|
348
|
+
max_depth=args.max_depth,
|
|
349
|
+
file_filter=args.file_filter,
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
if not results:
|
|
353
|
+
sys.exit(1)
|
|
354
|
+
|
|
355
|
+
if args.output_format == "json":
|
|
356
|
+
import json
|
|
357
|
+
|
|
358
|
+
print(json.dumps(results, indent=2))
|
|
359
|
+
|
|
360
|
+
elif args.output_format == "table":
|
|
361
|
+
if args.show_details:
|
|
362
|
+
print(
|
|
363
|
+
f"{'Name':<30} {'Type':<5} {'Size':<10} {'Permissions':<12} {'Modified':<20}"
|
|
364
|
+
)
|
|
365
|
+
print("-" * 90)
|
|
366
|
+
|
|
367
|
+
for result in results:
|
|
368
|
+
file_type = "DIR" if result["is_dir"] else "FILE"
|
|
369
|
+
if result["is_symlink"]:
|
|
370
|
+
file_type = "LINK"
|
|
371
|
+
|
|
372
|
+
size_str = format_size(result["size"]) if result["is_file"] else "-"
|
|
373
|
+
indent = " " * result.get("depth", 0)
|
|
374
|
+
|
|
375
|
+
print(
|
|
376
|
+
f"{indent}{result['name']:<30} {file_type:<5} {size_str:<10} {result['permissions']:<12} {result['modified_readable']:<20}"
|
|
377
|
+
)
|
|
378
|
+
else:
|
|
379
|
+
print(f"{'Name':<40} {'Type':<5} {'Size':<10}")
|
|
380
|
+
print("-" * 60)
|
|
381
|
+
|
|
382
|
+
for result in results:
|
|
383
|
+
file_type = "DIR" if result["is_dir"] else "FILE"
|
|
384
|
+
if result["is_symlink"]:
|
|
385
|
+
file_type = "LINK"
|
|
386
|
+
|
|
387
|
+
size_str = format_size(result["size"]) if result["is_file"] else "-"
|
|
388
|
+
indent = " " * result.get("depth", 0)
|
|
389
|
+
|
|
390
|
+
print(f"{indent}{result['name']:<40} {file_type:<5} {size_str:<10}")
|
|
391
|
+
|
|
392
|
+
elif args.output_format == "tree":
|
|
393
|
+
for result in results:
|
|
394
|
+
indent = " " * result.get("depth", 0)
|
|
395
|
+
marker = "├── " if result.get("depth", 0) > 0 else ""
|
|
396
|
+
suffix = "/" if result["is_dir"] else ""
|
|
397
|
+
|
|
398
|
+
print(f"{indent}{marker}{result['name']}{suffix}")
|
|
399
|
+
|
|
400
|
+
else: # list format
|
|
401
|
+
for result in results:
|
|
402
|
+
suffix = "/" if result["is_dir"] else ""
|
|
403
|
+
print(f"{result['name']}{suffix}")
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
if __name__ == "__main__":
|
|
407
|
+
main()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Re-exported from toolplane.toolkits.standalone_tools — the single
|
|
2
|
+
maintained copy of this tool. The SWE toolkit composes these safe
|
|
3
|
+
file tools with its own unsafe ones (execute_bash, file_editor).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from toolplane.toolkits.standalone_tools.read_file import ( # noqa: F401
|
|
7
|
+
detect_encoding,
|
|
8
|
+
format_output,
|
|
9
|
+
get_file_language,
|
|
10
|
+
main,
|
|
11
|
+
read_file,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
main()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Re-exported from toolplane.toolkits.standalone_tools — the single
|
|
2
|
+
maintained copy of this tool. The SWE toolkit composes these safe
|
|
3
|
+
file tools with its own unsafe ones (execute_bash, file_editor).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from toolplane.toolkits.standalone_tools.replace_string_in_file import ( # noqa: F401
|
|
7
|
+
create_file_backup,
|
|
8
|
+
main,
|
|
9
|
+
replace_string_in_file,
|
|
10
|
+
validate_old_string_uniqueness,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
main()
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
main()
|