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,517 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Comprehensive test suite for standalone tools.
4
+
5
+ This test suite validates all standalone tools functionality including:
6
+ - Basic functionality tests
7
+ - Error handling
8
+ - Edge cases
9
+ - Output format validation
10
+ - Integration tests
11
+ """
12
+
13
+ import json
14
+ import os
15
+ import subprocess
16
+ import sys
17
+ import tempfile
18
+ from pathlib import Path
19
+ from typing import Any, Dict, List
20
+
21
+ import pytest
22
+
23
+
24
+ class TestStandaloneTools:
25
+ """Test suite for all standalone tools."""
26
+
27
+ @pytest.fixture(autouse=True)
28
+ def setup(self):
29
+ """Set up test environment for each test."""
30
+ self.tools_dir = Path(__file__).parent
31
+ self.temp_dir = None
32
+ self.test_files = {}
33
+
34
+ def teardown_method(self):
35
+ """Clean up after each test."""
36
+ if self.temp_dir and self.temp_dir.exists():
37
+ import shutil
38
+
39
+ shutil.rmtree(self.temp_dir, ignore_errors=True)
40
+
41
+ def create_temp_dir(self) -> Path:
42
+ """Create a temporary directory for testing."""
43
+ if not self.temp_dir:
44
+ self.temp_dir = Path(tempfile.mkdtemp())
45
+ return self.temp_dir
46
+
47
+ def create_test_file(self, name: str, content: str) -> Path:
48
+ """Create a test file with given content."""
49
+ temp_dir = self.create_temp_dir()
50
+ file_path = temp_dir / name
51
+ file_path.write_text(content, encoding="utf-8")
52
+ self.test_files[name] = file_path
53
+ return file_path
54
+
55
+ def run_tool(self, tool_name: str, args: List[str]) -> subprocess.CompletedProcess:
56
+ """Run a standalone tool with given arguments."""
57
+ tool_path = self.tools_dir / tool_name
58
+ cmd = [sys.executable, str(tool_path)] + args
59
+ return subprocess.run(cmd, capture_output=True, text=True)
60
+
61
+ def test_create_directory_basic(self):
62
+ """Test create_directory.py basic functionality."""
63
+ temp_dir = self.create_temp_dir()
64
+ test_dir = temp_dir / "test_directory"
65
+
66
+ result = self.run_tool("create_directory.py", [str(test_dir)])
67
+
68
+ assert result.returncode == 0
69
+ assert test_dir.exists()
70
+ assert test_dir.is_dir()
71
+ assert "Directory created successfully" in result.stdout
72
+
73
+ def test_create_directory_existing(self):
74
+ """Test create_directory.py with existing directory."""
75
+ temp_dir = self.create_temp_dir()
76
+ test_dir = temp_dir / "existing_dir"
77
+ test_dir.mkdir()
78
+
79
+ result = self.run_tool("create_directory.py", [str(test_dir)])
80
+
81
+ assert result.returncode == 0
82
+ assert "Directory created successfully" in result.stdout
83
+
84
+ def test_create_directory_nested(self):
85
+ """Test create_directory.py with nested directories."""
86
+ temp_dir = self.create_temp_dir()
87
+ test_dir = temp_dir / "level1" / "level2" / "level3"
88
+
89
+ result = self.run_tool("create_directory.py", [str(test_dir)])
90
+
91
+ assert result.returncode == 0
92
+ assert test_dir.exists()
93
+ assert test_dir.is_dir()
94
+
95
+ def test_create_file_basic(self):
96
+ """Test create_file.py basic functionality."""
97
+ temp_dir = self.create_temp_dir()
98
+ test_file = temp_dir / "test.txt"
99
+ content = "Hello, World!"
100
+
101
+ result = self.run_tool("create_file.py", [str(test_file), content])
102
+
103
+ assert result.returncode == 0
104
+ assert test_file.exists()
105
+ assert test_file.read_text() == content
106
+ assert "File created successfully" in result.stdout
107
+
108
+ def test_create_file_with_dirs(self):
109
+ """Test create_file.py with automatic directory creation."""
110
+ temp_dir = self.create_temp_dir()
111
+ test_file = temp_dir / "subdir" / "test.txt"
112
+ content = "Test content"
113
+
114
+ result = self.run_tool("create_file.py", [str(test_file), content])
115
+
116
+ assert result.returncode == 0
117
+ assert test_file.exists()
118
+ assert test_file.read_text() == content
119
+
120
+ def test_create_file_overwrite(self):
121
+ """Test create_file.py overwrite functionality."""
122
+ temp_dir = self.create_temp_dir()
123
+ test_file = temp_dir / "test.txt"
124
+ test_file.write_text("Original content")
125
+
126
+ new_content = "New content"
127
+ result = self.run_tool(
128
+ "create_file.py", [str(test_file), new_content, "--overwrite"]
129
+ )
130
+
131
+ assert result.returncode == 0
132
+ assert test_file.read_text() == new_content
133
+
134
+ def test_file_search_basic(self):
135
+ """Test file_search.py basic functionality."""
136
+ temp_dir = self.create_temp_dir()
137
+
138
+ # Create test files
139
+ (temp_dir / "test1.py").write_text("print('hello')")
140
+ (temp_dir / "test2.py").write_text("print('world')")
141
+ (temp_dir / "test.txt").write_text("text file")
142
+
143
+ result = self.run_tool("file_search.py", ["*.py", "--base_path", str(temp_dir)])
144
+
145
+ assert result.returncode == 0
146
+ assert "test1.py" in result.stdout
147
+ assert "test2.py" in result.stdout
148
+ assert "test.txt" not in result.stdout
149
+
150
+ def test_file_search_json_output(self):
151
+ """Test file_search.py JSON output format."""
152
+ temp_dir = self.create_temp_dir()
153
+ (temp_dir / "test.py").write_text("test")
154
+
155
+ result = self.run_tool(
156
+ "file_search.py",
157
+ ["*.py", "--base_path", str(temp_dir), "--output_format", "json"],
158
+ )
159
+
160
+ assert result.returncode == 0
161
+ data = json.loads(result.stdout)
162
+ assert isinstance(data, list)
163
+ assert len(data) > 0
164
+ assert "test.py" in data[0]["path"]
165
+
166
+ def test_file_search_max_results(self):
167
+ """Test file_search.py max_results parameter."""
168
+ temp_dir = self.create_temp_dir()
169
+
170
+ # Create multiple test files
171
+ for i in range(5):
172
+ (temp_dir / f"test{i}.py").write_text(f"test {i}")
173
+
174
+ result = self.run_tool(
175
+ "file_search.py",
176
+ ["*.py", "--base_path", str(temp_dir), "--max_results", "2"],
177
+ )
178
+
179
+ assert result.returncode == 0
180
+ # Should find exactly 2 files
181
+ lines = [
182
+ line
183
+ for line in result.stdout.split("\n")
184
+ if "test" in line and ".py" in line
185
+ ]
186
+ assert len(lines) == 2
187
+
188
+ def test_grep_search_basic(self):
189
+ """Test grep_search.py basic functionality."""
190
+ temp_dir = self.create_temp_dir()
191
+ test_file = temp_dir / "test.py"
192
+ test_file.write_text(
193
+ "def hello():\n print('Hello, World!')\n return 'hello'"
194
+ )
195
+
196
+ result = self.run_tool(
197
+ "grep_search.py", ["hello", "--base_path", str(temp_dir)]
198
+ )
199
+
200
+ assert result.returncode == 0
201
+ assert "def hello" in result.stdout
202
+ assert "return 'hello'" in result.stdout
203
+
204
+ def test_grep_search_regex(self):
205
+ """Test grep_search.py regex functionality."""
206
+ temp_dir = self.create_temp_dir()
207
+ test_file = temp_dir / "test.py"
208
+ test_file.write_text("def function1():\n pass\ndef function2():\n pass")
209
+
210
+ result = self.run_tool(
211
+ "grep_search.py",
212
+ ["def function\\d", "--is_regexp", "--base_path", str(temp_dir)],
213
+ )
214
+
215
+ assert result.returncode == 0
216
+ assert "function1" in result.stdout
217
+ assert "function2" in result.stdout
218
+
219
+ def test_grep_search_context(self):
220
+ """Test grep_search.py context lines."""
221
+ temp_dir = self.create_temp_dir()
222
+ test_file = temp_dir / "test.py"
223
+ test_file.write_text("line1\nline2\ntarget_line\nline4\nline5")
224
+
225
+ result = self.run_tool(
226
+ "grep_search.py",
227
+ ["target_line", "--context_lines", "1", "--base_path", str(temp_dir)],
228
+ )
229
+
230
+ assert result.returncode == 0
231
+ assert "line2" in result.stdout
232
+ assert "target_line" in result.stdout
233
+ assert "line4" in result.stdout
234
+
235
+ def test_grep_search_json_output(self):
236
+ """Test grep_search.py JSON output format."""
237
+ temp_dir = self.create_temp_dir()
238
+ test_file = temp_dir / "test.py"
239
+ test_file.write_text("hello world")
240
+
241
+ result = self.run_tool(
242
+ "grep_search.py",
243
+ ["hello", "--base_path", str(temp_dir), "--output_format", "json"],
244
+ )
245
+
246
+ assert result.returncode == 0
247
+ data = json.loads(result.stdout)
248
+ assert isinstance(data, list)
249
+ assert len(data) > 0
250
+ assert "matches" in data[0]
251
+
252
+ def test_list_dir_basic(self):
253
+ """Test list_dir.py basic functionality."""
254
+ temp_dir = self.create_temp_dir()
255
+
256
+ # Create test files and directories
257
+ (temp_dir / "file1.txt").write_text("test")
258
+ (temp_dir / "file2.py").write_text("test")
259
+ (temp_dir / "subdir").mkdir()
260
+
261
+ result = self.run_tool("list_dir.py", [str(temp_dir)])
262
+
263
+ assert result.returncode == 0
264
+ assert "file1.txt" in result.stdout
265
+ assert "file2.py" in result.stdout
266
+ assert "subdir" in result.stdout
267
+
268
+ def test_list_dir_details(self):
269
+ """Test list_dir.py with details."""
270
+ temp_dir = self.create_temp_dir()
271
+ (temp_dir / "test.txt").write_text("test content")
272
+
273
+ result = self.run_tool("list_dir.py", [str(temp_dir), "--show_details"])
274
+
275
+ assert result.returncode == 0
276
+ assert "test.txt" in result.stdout
277
+ # Since --show_details might not be fully implemented, just check basic functionality
278
+
279
+ def test_read_file_basic(self):
280
+ """Test read_file.py basic functionality."""
281
+ content = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5"
282
+ test_file = self.create_test_file("test.txt", content)
283
+
284
+ result = self.run_tool("read_file.py", [str(test_file), "2", "4"])
285
+
286
+ assert result.returncode == 0
287
+ assert "Line 2" in result.stdout
288
+ assert "Line 3" in result.stdout
289
+ assert "Line 4" in result.stdout
290
+ assert "Line 1" not in result.stdout
291
+ assert "Line 5" not in result.stdout
292
+
293
+ def test_read_file_all_lines(self):
294
+ """Test read_file.py reading all lines."""
295
+ content = "Line 1\nLine 2\nLine 3"
296
+ test_file = self.create_test_file("test.txt", content)
297
+
298
+ result = self.run_tool("read_file.py", [str(test_file), "1", "-1"])
299
+
300
+ assert result.returncode == 0
301
+ assert "Line 1" in result.stdout
302
+ assert "Line 2" in result.stdout
303
+ assert "Line 3" in result.stdout
304
+
305
+ def test_read_file_json_output(self):
306
+ """Test read_file.py JSON output format."""
307
+ content = "Line 1\nLine 2"
308
+ test_file = self.create_test_file("test.txt", content)
309
+
310
+ result = self.run_tool(
311
+ "read_file.py", [str(test_file), "1", "2", "--output_format", "json"]
312
+ )
313
+
314
+ assert result.returncode == 0
315
+ data = json.loads(result.stdout)
316
+ assert data["success"] is True
317
+ assert len(data["content"]) == 2
318
+ assert data["content"][0]["content"] == "Line 1"
319
+
320
+ def test_read_file_nonexistent(self):
321
+ """Test read_file.py with nonexistent file."""
322
+ result = self.run_tool("read_file.py", ["/nonexistent/file.txt", "1", "5"])
323
+
324
+ assert result.returncode != 0 or "does not exist" in result.stdout
325
+
326
+ def test_replace_string_basic(self):
327
+ """Test replace_string_in_file.py basic functionality."""
328
+ content = "Hello, World!\nGoodbye, World!"
329
+ test_file = self.create_test_file("test.txt", content)
330
+
331
+ result = self.run_tool(
332
+ "replace_string_in_file.py",
333
+ [str(test_file), "World", "Universe", "--no_backup"],
334
+ )
335
+
336
+ assert result.returncode == 0
337
+ new_content = test_file.read_text()
338
+ assert "Hello, Universe!" in new_content
339
+ assert "Goodbye, Universe!" in new_content
340
+ assert "World" not in new_content
341
+
342
+ def test_replace_string_dry_run(self):
343
+ """Test replace_string_in_file.py dry run."""
344
+ content = "Hello, World!"
345
+ test_file = self.create_test_file("test.txt", content)
346
+
347
+ result = self.run_tool(
348
+ "replace_string_in_file.py",
349
+ [str(test_file), "World", "Universe", "--dry_run"],
350
+ )
351
+
352
+ assert result.returncode == 0
353
+ assert (
354
+ "would be replaced" in result.stdout.lower()
355
+ or "dry run" in result.stdout.lower()
356
+ )
357
+ # File should remain unchanged
358
+ assert test_file.read_text() == content
359
+
360
+ def test_replace_string_backup(self):
361
+ """Test replace_string_in_file.py backup creation."""
362
+ content = "Hello, World!"
363
+ test_file = self.create_test_file("test.txt", content)
364
+
365
+ result = self.run_tool(
366
+ "replace_string_in_file.py", [str(test_file), "World", "Universe"]
367
+ )
368
+
369
+ assert result.returncode == 0
370
+ # Check if backup was created (should have backup in name)
371
+ backup_files = list(test_file.parent.glob(f"*backup*"))
372
+ assert len(backup_files) > 0
373
+
374
+ def test_semantic_search_basic(self):
375
+ """Test semantic_search.py basic functionality."""
376
+ temp_dir = self.create_temp_dir()
377
+
378
+ # Create test files with different content
379
+ (temp_dir / "auth.py").write_text(
380
+ "def authenticate_user(username, password):\n return True"
381
+ )
382
+ (temp_dir / "math.py").write_text("def calculate_sum(a, b):\n return a + b")
383
+
384
+ result = self.run_tool(
385
+ "semantic_search.py",
386
+ [
387
+ "authentication function",
388
+ "--search_path",
389
+ str(temp_dir),
390
+ "--max_results",
391
+ "5",
392
+ ],
393
+ )
394
+
395
+ assert result.returncode == 0
396
+ # Should find the authentication-related content
397
+ assert (
398
+ "auth" in result.stdout.lower() or "authenticate" in result.stdout.lower()
399
+ )
400
+
401
+ def test_semantic_search_file_types(self):
402
+ """Test semantic_search.py file type filtering."""
403
+ temp_dir = self.create_temp_dir()
404
+
405
+ (temp_dir / "test.py").write_text("python code")
406
+ (temp_dir / "test.txt").write_text("text file")
407
+
408
+ result = self.run_tool(
409
+ "semantic_search.py",
410
+ ["code", "--search_path", str(temp_dir), "--file_types", ".py"],
411
+ )
412
+
413
+ assert result.returncode == 0
414
+ # Should only search Python files
415
+
416
+ def test_test_failure_analysis_basic(self):
417
+ """Test test_failure_analysis.py basic functionality."""
418
+ # Create a mock test output
419
+ test_output = """
420
+ FAILED test_example.py::test_function - AssertionError: Expected 5, got 3
421
+ FAILED test_another.py::test_method - ValueError: Invalid input
422
+ """
423
+
424
+ result = self.run_tool(
425
+ "test_failure_analysis.py", ["--test_output", test_output]
426
+ )
427
+
428
+ assert result.returncode == 0
429
+ assert "AssertionError" in result.stdout or "ValueError" in result.stdout
430
+
431
+ def test_launcher_list(self):
432
+ """Test launcher.py list functionality."""
433
+ result = self.run_tool("launcher.py", ["list"])
434
+
435
+ assert result.returncode == 0
436
+ assert "create_directory.py" in result.stdout
437
+ assert "create_file.py" in result.stdout
438
+ assert "grep_search.py" in result.stdout
439
+
440
+ def test_launcher_search(self):
441
+ """Test launcher.py search functionality."""
442
+ result = self.run_tool("launcher.py", ["search", "file"])
443
+
444
+ assert result.returncode == 0
445
+ assert "file_search.py" in result.stdout or "read_file.py" in result.stdout
446
+
447
+ def test_launcher_run_help(self):
448
+ """Test launcher.py run functionality with help."""
449
+ result = self.run_tool("launcher.py", ["run", "create_directory.py", "--help"])
450
+
451
+ assert result.returncode == 0
452
+ assert "usage:" in result.stdout.lower()
453
+
454
+ def test_all_tools_help(self):
455
+ """Test that all tools provide help information."""
456
+ tools = [
457
+ "create_directory.py",
458
+ "create_file.py",
459
+ "file_search.py",
460
+ "grep_search.py",
461
+ "list_dir.py",
462
+ "read_file.py",
463
+ "replace_string_in_file.py",
464
+ "semantic_search.py",
465
+ "test_failure_analysis.py",
466
+ "launcher.py",
467
+ ]
468
+
469
+ for tool in tools:
470
+ result = self.run_tool(tool, ["--help"])
471
+ assert result.returncode == 0, f"Tool {tool} failed help test"
472
+ assert "usage:" in result.stdout.lower(), f"Tool {tool} doesn't show usage"
473
+
474
+ def test_error_handling(self):
475
+ """Test error handling for various tools."""
476
+ # Test create_directory with invalid path (if applicable)
477
+ result = self.run_tool("create_directory.py", ["/invalid:/path"])
478
+ # Should handle gracefully (either succeed or fail with proper message)
479
+
480
+ # Test read_file with invalid line numbers
481
+ temp_file = self.create_test_file("small.txt", "line1\nline2")
482
+ result = self.run_tool("read_file.py", [str(temp_file), "10", "20"])
483
+ # Tool handles this gracefully by adjusting range to available lines
484
+ assert result.returncode == 0
485
+
486
+ def test_json_output_validity(self):
487
+ """Test that all tools produce valid JSON when requested."""
488
+ temp_dir = self.create_temp_dir()
489
+ (temp_dir / "test.py").write_text("test content")
490
+
491
+ tools_with_json = [
492
+ (
493
+ "file_search.py",
494
+ ["*.py", "--base_path", str(temp_dir), "--output_format", "json"],
495
+ ),
496
+ (
497
+ "grep_search.py",
498
+ ["test", "--base_path", str(temp_dir), "--output_format", "json"],
499
+ ),
500
+ (
501
+ "read_file.py",
502
+ [str(temp_dir / "test.py"), "1", "1", "--output_format", "json"],
503
+ ),
504
+ ]
505
+
506
+ for tool, args in tools_with_json:
507
+ result = self.run_tool(tool, args)
508
+ if result.returncode == 0:
509
+ try:
510
+ json.loads(result.stdout)
511
+ except json.JSONDecodeError:
512
+ pytest.fail(f"Tool {tool} produced invalid JSON: {result.stdout}")
513
+
514
+
515
+ if __name__ == "__main__":
516
+ # Run tests directly
517
+ pytest.main([__file__, "-v"])
@@ -0,0 +1,35 @@
1
+ from .swe_toolkit import (
2
+ SWE_TOOL_SELECTION_GUIDE,
3
+ BashInput,
4
+ BashTool,
5
+ FileEditorInput,
6
+ FileEditorTool,
7
+ FinishInput,
8
+ FinishTool,
9
+ SearchDirInput,
10
+ SearchDirTool,
11
+ SearchInput,
12
+ SearchTool,
13
+ SubmitTool,
14
+ get_file_editor_only,
15
+ get_search_tools_only,
16
+ get_swe_toolkit,
17
+ )
18
+
19
+ __all__ = [
20
+ "FileEditorInput",
21
+ "SearchInput",
22
+ "SearchDirInput",
23
+ "BashInput",
24
+ "FinishInput",
25
+ "FileEditorTool",
26
+ "SearchTool",
27
+ "SearchDirTool",
28
+ "BashTool",
29
+ "FinishTool",
30
+ "SubmitTool",
31
+ "get_swe_toolkit",
32
+ "get_file_editor_only",
33
+ "get_search_tools_only",
34
+ "SWE_TOOL_SELECTION_GUIDE",
35
+ ]
@@ -0,0 +1,15 @@
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.create_directory import ( # noqa: F401
7
+ create_directory,
8
+ main,
9
+ )
10
+
11
+ if __name__ == "__main__":
12
+ main()
13
+
14
+ if __name__ == "__main__":
15
+ main()
@@ -0,0 +1,15 @@
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.create_file import ( # noqa: F401
7
+ create_file,
8
+ main,
9
+ )
10
+
11
+ if __name__ == "__main__":
12
+ main()
13
+
14
+ if __name__ == "__main__":
15
+ main()