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.
Files changed (81) hide show
  1. toolplane/__init__.py +106 -0
  2. toolplane/common/__init__.py +93 -0
  3. toolplane/common/base_config.py +129 -0
  4. toolplane/common/base_connection_manager.py +171 -0
  5. toolplane/common/base_session_manager.py +321 -0
  6. toolplane/common/base_tool_manager.py +347 -0
  7. toolplane/common/constants.py +47 -0
  8. toolplane/common/utils.py +310 -0
  9. toolplane/core/__init__.py +67 -0
  10. toolplane/core/config.py +107 -0
  11. toolplane/core/connection.py +285 -0
  12. toolplane/core/errors.py +298 -0
  13. toolplane/core/machine.py +480 -0
  14. toolplane/core/request.py +775 -0
  15. toolplane/core/session.py +332 -0
  16. toolplane/core/session_context.py +514 -0
  17. toolplane/core/task.py +130 -0
  18. toolplane/core/tool.py +329 -0
  19. toolplane/http_core/__init__.py +37 -0
  20. toolplane/http_core/http_config.py +97 -0
  21. toolplane/http_core/http_connection.py +409 -0
  22. toolplane/http_core/http_machine.py +298 -0
  23. toolplane/http_core/http_request.py +748 -0
  24. toolplane/http_core/http_session.py +348 -0
  25. toolplane/http_core/http_session_context.py +491 -0
  26. toolplane/http_core/http_task.py +101 -0
  27. toolplane/http_core/http_tool.py +400 -0
  28. toolplane/interfaces/__init__.py +27 -0
  29. toolplane/interfaces/client_interface.py +122 -0
  30. toolplane/interfaces/connection_interface.py +193 -0
  31. toolplane/interfaces/event_interface.py +290 -0
  32. toolplane/interfaces/request_interface.py +439 -0
  33. toolplane/interfaces/session_interface.py +288 -0
  34. toolplane/interfaces/tool_interface.py +441 -0
  35. toolplane/proto/__init__.py +0 -0
  36. toolplane/proto/service_pb2.py +315 -0
  37. toolplane/proto/service_pb2_grpc.py +2240 -0
  38. toolplane/provider_cli.py +268 -0
  39. toolplane/provider_registry.py +77 -0
  40. toolplane/provider_runtime.py +302 -0
  41. toolplane/toolkits/__init__.py +0 -0
  42. toolplane/toolkits/standalone_tools/__init__.py +0 -0
  43. toolplane/toolkits/standalone_tools/create_directory.py +94 -0
  44. toolplane/toolkits/standalone_tools/create_file.py +124 -0
  45. toolplane/toolkits/standalone_tools/file_search.py +229 -0
  46. toolplane/toolkits/standalone_tools/grep_search.py +372 -0
  47. toolplane/toolkits/standalone_tools/launcher.py +146 -0
  48. toolplane/toolkits/standalone_tools/list_dir.py +395 -0
  49. toolplane/toolkits/standalone_tools/read_file.py +346 -0
  50. toolplane/toolkits/standalone_tools/replace_string_in_file.py +407 -0
  51. toolplane/toolkits/standalone_tools/run_tests.py +66 -0
  52. toolplane/toolkits/standalone_tools/semantic_search.py +485 -0
  53. toolplane/toolkits/standalone_tools/standalone_toolkit.py +979 -0
  54. toolplane/toolkits/standalone_tools/test_failure_analysis.py +618 -0
  55. toolplane/toolkits/standalone_tools/test_standalone_toolkit.py +517 -0
  56. toolplane/toolkits/swe/__init__.py +35 -0
  57. toolplane/toolkits/swe/create_directory.py +15 -0
  58. toolplane/toolkits/swe/create_file.py +15 -0
  59. toolplane/toolkits/swe/descriptions.py +273 -0
  60. toolplane/toolkits/swe/execute_bash.py +93 -0
  61. toolplane/toolkits/swe/file_editor.py +775 -0
  62. toolplane/toolkits/swe/file_search.py +16 -0
  63. toolplane/toolkits/swe/finish.py +50 -0
  64. toolplane/toolkits/swe/grep_search.py +19 -0
  65. toolplane/toolkits/swe/list_dir.py +407 -0
  66. toolplane/toolkits/swe/read_file.py +18 -0
  67. toolplane/toolkits/swe/replace_string_in_file.py +17 -0
  68. toolplane/toolkits/swe/search.py +260 -0
  69. toolplane/toolkits/swe/semantic_search.py +20 -0
  70. toolplane/toolkits/swe/str_replace_editor.py +647 -0
  71. toolplane/toolkits/swe/submit.py +29 -0
  72. toolplane/toolkits/swe/swe_toolkit.py +1296 -0
  73. toolplane/toolplane_client.py +686 -0
  74. toolplane/toolplane_http_client.py +681 -0
  75. toolplane/utils/__init__.py +3 -0
  76. toolplane/utils/schema.py +146 -0
  77. toolplane_python_client-0.1.0.dist-info/METADATA +543 -0
  78. toolplane_python_client-0.1.0.dist-info/RECORD +81 -0
  79. toolplane_python_client-0.1.0.dist-info/WHEEL +5 -0
  80. toolplane_python_client-0.1.0.dist-info/entry_points.txt +2 -0
  81. toolplane_python_client-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,395 @@
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
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: 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
+ if recursive:
68
+ results = _list_recursive(
69
+ dir_path, show_hidden, max_depth, file_filter, current_depth=0
70
+ )
71
+ else:
72
+ results = _list_single_dir(dir_path, show_hidden, file_filter)
73
+
74
+ # Add detailed information if requested
75
+ if show_details:
76
+ for result in results:
77
+ _add_detailed_info(result)
78
+
79
+ # Sort results
80
+ results = _sort_results(results, sort_by, reverse_sort)
81
+
82
+ return results
83
+
84
+ except PermissionError:
85
+ print(f"Error: Permission denied accessing '{path}'.", file=sys.stderr)
86
+ return []
87
+ except Exception as e:
88
+ print(f"Error listing directory '{path}': {e}", file=sys.stderr)
89
+ return []
90
+
91
+
92
+ def _list_single_dir(
93
+ dir_path: Path, show_hidden: bool, file_filter: str
94
+ ) -> List[Dict[str, Any]]:
95
+ """List contents of a single directory."""
96
+ results = []
97
+
98
+ try:
99
+ for item in dir_path.iterdir():
100
+ # Skip hidden files if not requested
101
+ if not show_hidden and item.name.startswith("."):
102
+ continue
103
+
104
+ # Apply file filter
105
+ if file_filter and item.is_file() and not item.name.endswith(file_filter):
106
+ continue
107
+
108
+ try:
109
+ stat_info = item.stat()
110
+
111
+ result = {
112
+ "name": item.name,
113
+ "path": str(item.resolve()),
114
+ "relative_path": str(item.relative_to(dir_path.parent)),
115
+ "is_file": item.is_file(),
116
+ "is_dir": item.is_dir(),
117
+ "is_symlink": item.is_symlink(),
118
+ "size": stat_info.st_size if item.is_file() else 0,
119
+ "modified": stat_info.st_mtime,
120
+ "modified_readable": time.strftime(
121
+ "%Y-%m-%d %H:%M:%S", time.localtime(stat_info.st_mtime)
122
+ ),
123
+ "permissions": stat.filemode(stat_info.st_mode),
124
+ "depth": 0,
125
+ }
126
+
127
+ results.append(result)
128
+
129
+ except (OSError, PermissionError):
130
+ # Skip items that can't be accessed
131
+ continue
132
+
133
+ except PermissionError:
134
+ pass
135
+
136
+ return results
137
+
138
+
139
+ def _list_recursive(
140
+ dir_path: Path,
141
+ show_hidden: bool,
142
+ max_depth: int,
143
+ file_filter: str,
144
+ current_depth: int = 0,
145
+ ) -> List[Dict[str, Any]]:
146
+ """List directory contents recursively."""
147
+ results = []
148
+
149
+ if current_depth >= max_depth:
150
+ return results
151
+
152
+ try:
153
+ for item in dir_path.iterdir():
154
+ # Skip hidden files if not requested
155
+ if not show_hidden and item.name.startswith("."):
156
+ continue
157
+
158
+ # Apply file filter
159
+ if file_filter and item.is_file() and not item.name.endswith(file_filter):
160
+ continue
161
+
162
+ try:
163
+ stat_info = item.stat()
164
+
165
+ result = {
166
+ "name": item.name,
167
+ "path": str(item.resolve()),
168
+ "relative_path": str(item.relative_to(dir_path.parent)),
169
+ "is_file": item.is_file(),
170
+ "is_dir": item.is_dir(),
171
+ "is_symlink": item.is_symlink(),
172
+ "size": stat_info.st_size if item.is_file() else 0,
173
+ "modified": stat_info.st_mtime,
174
+ "modified_readable": time.strftime(
175
+ "%Y-%m-%d %H:%M:%S", time.localtime(stat_info.st_mtime)
176
+ ),
177
+ "permissions": stat.filemode(stat_info.st_mode),
178
+ "depth": current_depth,
179
+ }
180
+
181
+ results.append(result)
182
+
183
+ # Recurse into subdirectories
184
+ if item.is_dir() and not item.is_symlink():
185
+ sub_results = _list_recursive(
186
+ item, show_hidden, max_depth, file_filter, current_depth + 1
187
+ )
188
+ results.extend(sub_results)
189
+
190
+ except (OSError, PermissionError):
191
+ # Skip items that can't be accessed
192
+ continue
193
+
194
+ except PermissionError:
195
+ pass
196
+
197
+ return results
198
+
199
+
200
+ def _add_detailed_info(result: Dict[str, Any]) -> None:
201
+ """Add detailed information to a result entry."""
202
+ try:
203
+ path = Path(result["path"])
204
+ stat_info = path.stat()
205
+
206
+ result.update(
207
+ {
208
+ "owner_readable": bool(stat_info.st_mode & stat.S_IRUSR),
209
+ "owner_writable": bool(stat_info.st_mode & stat.S_IWUSR),
210
+ "owner_executable": bool(stat_info.st_mode & stat.S_IXUSR),
211
+ "group_readable": bool(stat_info.st_mode & stat.S_IRGRP),
212
+ "group_writable": bool(stat_info.st_mode & stat.S_IWGRP),
213
+ "group_executable": bool(stat_info.st_mode & stat.S_IXGRP),
214
+ "other_readable": bool(stat_info.st_mode & stat.S_IROTH),
215
+ "other_writable": bool(stat_info.st_mode & stat.S_IWOTH),
216
+ "other_executable": bool(stat_info.st_mode & stat.S_IXOTH),
217
+ "inode": stat_info.st_ino,
218
+ "device": stat_info.st_dev,
219
+ "nlink": stat_info.st_nlink,
220
+ "uid": stat_info.st_uid,
221
+ "gid": stat_info.st_gid,
222
+ "accessed": stat_info.st_atime,
223
+ "accessed_readable": time.strftime(
224
+ "%Y-%m-%d %H:%M:%S", time.localtime(stat_info.st_atime)
225
+ ),
226
+ "created": getattr(stat_info, "st_birthtime", stat_info.st_ctime),
227
+ "created_readable": time.strftime(
228
+ "%Y-%m-%d %H:%M:%S",
229
+ time.localtime(
230
+ getattr(stat_info, "st_birthtime", stat_info.st_ctime)
231
+ ),
232
+ ),
233
+ }
234
+ )
235
+ except (OSError, PermissionError):
236
+ pass
237
+
238
+
239
+ def _sort_results(
240
+ results: List[Dict[str, Any]], sort_by: str, reverse_sort: bool
241
+ ) -> List[Dict[str, Any]]:
242
+ """Sort results by the specified criteria."""
243
+ if sort_by == "name":
244
+ results.sort(key=lambda x: x["name"].lower(), reverse=reverse_sort)
245
+ elif sort_by == "size":
246
+ results.sort(key=lambda x: x["size"], reverse=reverse_sort)
247
+ elif sort_by == "modified":
248
+ results.sort(key=lambda x: x["modified"], reverse=reverse_sort)
249
+ elif sort_by == "type":
250
+ # Sort by type (directories first, then files)
251
+ results.sort(
252
+ key=lambda x: (not x["is_dir"], x["name"].lower()), reverse=reverse_sort
253
+ )
254
+
255
+ return results
256
+
257
+
258
+ def format_size(size_bytes: int) -> str:
259
+ """Format file size in human-readable format."""
260
+ if size_bytes == 0:
261
+ return "0 B"
262
+
263
+ units = ["B", "KB", "MB", "GB", "TB"]
264
+ i = 0
265
+ while size_bytes >= 1024 and i < len(units) - 1:
266
+ size_bytes /= 1024
267
+ i += 1
268
+
269
+ return f"{size_bytes:.1f} {units[i]}"
270
+
271
+
272
+ def main():
273
+ parser = argparse.ArgumentParser(
274
+ description="List directory contents with enhanced features."
275
+ )
276
+ parser.add_argument(
277
+ "path", type=str, help="The absolute path to the directory to list"
278
+ )
279
+ parser.add_argument(
280
+ "--show_hidden",
281
+ action="store_true",
282
+ default=False,
283
+ help="Show hidden files and directories (default: False)",
284
+ )
285
+ parser.add_argument(
286
+ "--show_details",
287
+ action="store_true",
288
+ default=False,
289
+ help="Show detailed information like size and permissions (default: False)",
290
+ )
291
+ parser.add_argument(
292
+ "--sort_by",
293
+ choices=["name", "size", "modified", "type"],
294
+ default="name",
295
+ help="Sort by 'name', 'size', 'modified', or 'type' (default: name)",
296
+ )
297
+ parser.add_argument(
298
+ "--reverse_sort",
299
+ action="store_true",
300
+ default=False,
301
+ help="Reverse the sort order (default: False)",
302
+ )
303
+ parser.add_argument(
304
+ "--recursive",
305
+ action="store_true",
306
+ default=False,
307
+ help="List contents recursively (default: False)",
308
+ )
309
+ parser.add_argument(
310
+ "--max_depth",
311
+ type=int,
312
+ default=3,
313
+ help="Maximum depth for recursive listing (default: 3)",
314
+ )
315
+ parser.add_argument(
316
+ "--file_filter",
317
+ type=str,
318
+ help="Filter files by extension (e.g., '.py', '.txt')",
319
+ )
320
+ parser.add_argument(
321
+ "--output_format",
322
+ choices=["list", "table", "json", "tree"],
323
+ default="list",
324
+ help="Output format (default: list)",
325
+ )
326
+
327
+ args = parser.parse_args()
328
+
329
+ results = list_dir(
330
+ args.path,
331
+ show_hidden=args.show_hidden,
332
+ show_details=args.show_details,
333
+ sort_by=args.sort_by,
334
+ reverse_sort=args.reverse_sort,
335
+ recursive=args.recursive,
336
+ max_depth=args.max_depth,
337
+ file_filter=args.file_filter,
338
+ )
339
+
340
+ if not results:
341
+ sys.exit(1)
342
+
343
+ if args.output_format == "json":
344
+ import json
345
+
346
+ print(json.dumps(results, indent=2))
347
+
348
+ elif args.output_format == "table":
349
+ if args.show_details:
350
+ print(
351
+ f"{'Name':<30} {'Type':<5} {'Size':<10} {'Permissions':<12} {'Modified':<20}"
352
+ )
353
+ print("-" * 90)
354
+
355
+ for result in results:
356
+ file_type = "DIR" if result["is_dir"] else "FILE"
357
+ if result["is_symlink"]:
358
+ file_type = "LINK"
359
+
360
+ size_str = format_size(result["size"]) if result["is_file"] else "-"
361
+ indent = " " * result.get("depth", 0)
362
+
363
+ print(
364
+ f"{indent}{result['name']:<30} {file_type:<5} {size_str:<10} {result['permissions']:<12} {result['modified_readable']:<20}"
365
+ )
366
+ else:
367
+ print(f"{'Name':<40} {'Type':<5} {'Size':<10}")
368
+ print("-" * 60)
369
+
370
+ for result in results:
371
+ file_type = "DIR" if result["is_dir"] else "FILE"
372
+ if result["is_symlink"]:
373
+ file_type = "LINK"
374
+
375
+ size_str = format_size(result["size"]) if result["is_file"] else "-"
376
+ indent = " " * result.get("depth", 0)
377
+
378
+ print(f"{indent}{result['name']:<40} {file_type:<5} {size_str:<10}")
379
+
380
+ elif args.output_format == "tree":
381
+ for result in results:
382
+ indent = " " * result.get("depth", 0)
383
+ marker = "├── " if result.get("depth", 0) > 0 else ""
384
+ suffix = "/" if result["is_dir"] else ""
385
+
386
+ print(f"{indent}{marker}{result['name']}{suffix}")
387
+
388
+ else: # list format
389
+ for result in results:
390
+ suffix = "/" if result["is_dir"] else ""
391
+ print(f"{result['name']}{suffix}")
392
+
393
+
394
+ if __name__ == "__main__":
395
+ main()