massgen 0.1.0a3__py3-none-any.whl → 0.1.2__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.

Potentially problematic release.


This version of massgen might be problematic. Click here for more details.

Files changed (120) hide show
  1. massgen/__init__.py +1 -1
  2. massgen/agent_config.py +17 -0
  3. massgen/api_params_handler/_api_params_handler_base.py +1 -0
  4. massgen/api_params_handler/_chat_completions_api_params_handler.py +15 -2
  5. massgen/api_params_handler/_claude_api_params_handler.py +8 -1
  6. massgen/api_params_handler/_gemini_api_params_handler.py +73 -0
  7. massgen/api_params_handler/_response_api_params_handler.py +8 -1
  8. massgen/backend/base.py +83 -0
  9. massgen/backend/{base_with_mcp.py → base_with_custom_tool_and_mcp.py} +286 -15
  10. massgen/backend/capabilities.py +6 -6
  11. massgen/backend/chat_completions.py +200 -103
  12. massgen/backend/claude.py +115 -18
  13. massgen/backend/claude_code.py +378 -14
  14. massgen/backend/docs/CLAUDE_API_RESEARCH.md +3 -3
  15. massgen/backend/gemini.py +1333 -1629
  16. massgen/backend/gemini_mcp_manager.py +545 -0
  17. massgen/backend/gemini_trackers.py +344 -0
  18. massgen/backend/gemini_utils.py +43 -0
  19. massgen/backend/grok.py +39 -6
  20. massgen/backend/response.py +147 -81
  21. massgen/cli.py +605 -110
  22. massgen/config_builder.py +376 -27
  23. massgen/configs/README.md +123 -80
  24. massgen/configs/basic/multi/three_agents_default.yaml +3 -3
  25. massgen/configs/basic/single/single_agent.yaml +1 -1
  26. massgen/configs/providers/openai/gpt5_nano.yaml +3 -3
  27. massgen/configs/tools/custom_tools/claude_code_custom_tool_example.yaml +32 -0
  28. massgen/configs/tools/custom_tools/claude_code_custom_tool_example_no_path.yaml +28 -0
  29. massgen/configs/tools/custom_tools/claude_code_custom_tool_with_mcp_example.yaml +40 -0
  30. massgen/configs/tools/custom_tools/claude_code_custom_tool_with_wrong_mcp_example.yaml +38 -0
  31. massgen/configs/tools/custom_tools/claude_code_wrong_custom_tool_with_mcp_example.yaml +38 -0
  32. massgen/configs/tools/custom_tools/claude_custom_tool_example.yaml +24 -0
  33. massgen/configs/tools/custom_tools/claude_custom_tool_example_no_path.yaml +22 -0
  34. massgen/configs/tools/custom_tools/claude_custom_tool_with_mcp_example.yaml +35 -0
  35. massgen/configs/tools/custom_tools/claude_custom_tool_with_wrong_mcp_example.yaml +33 -0
  36. massgen/configs/tools/custom_tools/claude_wrong_custom_tool_with_mcp_example.yaml +33 -0
  37. massgen/configs/tools/custom_tools/gemini_custom_tool_example.yaml +24 -0
  38. massgen/configs/tools/custom_tools/gemini_custom_tool_example_no_path.yaml +22 -0
  39. massgen/configs/tools/custom_tools/gemini_custom_tool_with_mcp_example.yaml +35 -0
  40. massgen/configs/tools/custom_tools/gemini_custom_tool_with_wrong_mcp_example.yaml +33 -0
  41. massgen/configs/tools/custom_tools/gemini_wrong_custom_tool_with_mcp_example.yaml +33 -0
  42. massgen/configs/tools/custom_tools/github_issue_market_analysis.yaml +94 -0
  43. massgen/configs/tools/custom_tools/gpt5_nano_custom_tool_example.yaml +24 -0
  44. massgen/configs/tools/custom_tools/gpt5_nano_custom_tool_example_no_path.yaml +22 -0
  45. massgen/configs/tools/custom_tools/gpt5_nano_custom_tool_with_mcp_example.yaml +35 -0
  46. massgen/configs/tools/custom_tools/gpt5_nano_custom_tool_with_wrong_mcp_example.yaml +33 -0
  47. massgen/configs/tools/custom_tools/gpt5_nano_wrong_custom_tool_with_mcp_example.yaml +33 -0
  48. massgen/configs/tools/custom_tools/gpt_oss_custom_tool_example.yaml +25 -0
  49. massgen/configs/tools/custom_tools/gpt_oss_custom_tool_example_no_path.yaml +23 -0
  50. massgen/configs/tools/custom_tools/gpt_oss_custom_tool_with_mcp_example.yaml +34 -0
  51. massgen/configs/tools/custom_tools/gpt_oss_custom_tool_with_wrong_mcp_example.yaml +34 -0
  52. massgen/configs/tools/custom_tools/gpt_oss_wrong_custom_tool_with_mcp_example.yaml +34 -0
  53. massgen/configs/tools/custom_tools/grok3_mini_custom_tool_example.yaml +24 -0
  54. massgen/configs/tools/custom_tools/grok3_mini_custom_tool_example_no_path.yaml +22 -0
  55. massgen/configs/tools/custom_tools/grok3_mini_custom_tool_with_mcp_example.yaml +35 -0
  56. massgen/configs/tools/custom_tools/grok3_mini_custom_tool_with_wrong_mcp_example.yaml +33 -0
  57. massgen/configs/tools/custom_tools/grok3_mini_wrong_custom_tool_with_mcp_example.yaml +33 -0
  58. massgen/configs/tools/custom_tools/qwen_api_custom_tool_example.yaml +25 -0
  59. massgen/configs/tools/custom_tools/qwen_api_custom_tool_example_no_path.yaml +23 -0
  60. massgen/configs/tools/custom_tools/qwen_api_custom_tool_with_mcp_example.yaml +36 -0
  61. massgen/configs/tools/custom_tools/qwen_api_custom_tool_with_wrong_mcp_example.yaml +34 -0
  62. massgen/configs/tools/custom_tools/qwen_api_wrong_custom_tool_with_mcp_example.yaml +34 -0
  63. massgen/configs/tools/custom_tools/qwen_local_custom_tool_example.yaml +24 -0
  64. massgen/configs/tools/custom_tools/qwen_local_custom_tool_example_no_path.yaml +22 -0
  65. massgen/configs/tools/custom_tools/qwen_local_custom_tool_with_mcp_example.yaml +35 -0
  66. massgen/configs/tools/custom_tools/qwen_local_custom_tool_with_wrong_mcp_example.yaml +33 -0
  67. massgen/configs/tools/custom_tools/qwen_local_wrong_custom_tool_with_mcp_example.yaml +33 -0
  68. massgen/configs/tools/filesystem/claude_code_context_sharing.yaml +1 -1
  69. massgen/configs/tools/planning/five_agents_discord_mcp_planning_mode.yaml +7 -29
  70. massgen/configs/tools/planning/five_agents_filesystem_mcp_planning_mode.yaml +5 -6
  71. massgen/configs/tools/planning/five_agents_notion_mcp_planning_mode.yaml +4 -4
  72. massgen/configs/tools/planning/five_agents_twitter_mcp_planning_mode.yaml +4 -4
  73. massgen/configs/tools/planning/gpt5_mini_case_study_mcp_planning_mode.yaml +2 -2
  74. massgen/configs/voting/gemini_gpt_voting_sensitivity.yaml +67 -0
  75. massgen/formatter/_chat_completions_formatter.py +104 -0
  76. massgen/formatter/_claude_formatter.py +120 -0
  77. massgen/formatter/_gemini_formatter.py +448 -0
  78. massgen/formatter/_response_formatter.py +88 -0
  79. massgen/frontend/coordination_ui.py +4 -2
  80. massgen/logger_config.py +35 -3
  81. massgen/message_templates.py +56 -6
  82. massgen/orchestrator.py +512 -16
  83. massgen/stream_chunk/base.py +3 -0
  84. massgen/tests/custom_tools_example.py +392 -0
  85. massgen/tests/mcp_test_server.py +17 -7
  86. massgen/tests/test_config_builder.py +423 -0
  87. massgen/tests/test_custom_tools.py +401 -0
  88. massgen/tests/test_intelligent_planning_mode.py +643 -0
  89. massgen/tests/test_tools.py +127 -0
  90. massgen/token_manager/token_manager.py +13 -4
  91. massgen/tool/README.md +935 -0
  92. massgen/tool/__init__.py +39 -0
  93. massgen/tool/_async_helpers.py +70 -0
  94. massgen/tool/_basic/__init__.py +8 -0
  95. massgen/tool/_basic/_two_num_tool.py +24 -0
  96. massgen/tool/_code_executors/__init__.py +10 -0
  97. massgen/tool/_code_executors/_python_executor.py +74 -0
  98. massgen/tool/_code_executors/_shell_executor.py +61 -0
  99. massgen/tool/_exceptions.py +39 -0
  100. massgen/tool/_file_handlers/__init__.py +10 -0
  101. massgen/tool/_file_handlers/_file_operations.py +218 -0
  102. massgen/tool/_manager.py +634 -0
  103. massgen/tool/_registered_tool.py +88 -0
  104. massgen/tool/_result.py +66 -0
  105. massgen/tool/_self_evolution/_github_issue_analyzer.py +369 -0
  106. massgen/tool/docs/builtin_tools.md +681 -0
  107. massgen/tool/docs/exceptions.md +794 -0
  108. massgen/tool/docs/execution_results.md +691 -0
  109. massgen/tool/docs/manager.md +887 -0
  110. massgen/tool/docs/workflow_toolkits.md +529 -0
  111. massgen/tool/workflow_toolkits/__init__.py +57 -0
  112. massgen/tool/workflow_toolkits/base.py +55 -0
  113. massgen/tool/workflow_toolkits/new_answer.py +126 -0
  114. massgen/tool/workflow_toolkits/vote.py +167 -0
  115. {massgen-0.1.0a3.dist-info → massgen-0.1.2.dist-info}/METADATA +87 -129
  116. {massgen-0.1.0a3.dist-info → massgen-0.1.2.dist-info}/RECORD +120 -44
  117. {massgen-0.1.0a3.dist-info → massgen-0.1.2.dist-info}/WHEEL +0 -0
  118. {massgen-0.1.0a3.dist-info → massgen-0.1.2.dist-info}/entry_points.txt +0 -0
  119. {massgen-0.1.0a3.dist-info → massgen-0.1.2.dist-info}/licenses/LICENSE +0 -0
  120. {massgen-0.1.0a3.dist-info → massgen-0.1.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,681 @@
1
+ # Built-in Tools Guide
2
+
3
+ ## Overview
4
+
5
+ MassGen provides a comprehensive set of built-in tools that give AI agents capabilities for code execution, file operations, and multimedia processing. These tools are production-ready, well-tested, and designed to integrate seamlessly with the Tool System.
6
+
7
+ ## Tool Categories
8
+
9
+ Built-in tools are organized into several categories:
10
+
11
+ - **Code Executors**: Run Python and shell scripts safely
12
+ - **File Handlers**: Read, write, and modify files
13
+ - **Workflow Toolkits**: Specialized tools for agent coordination
14
+
15
+ ## Code Execution Tools
16
+
17
+ ### run_python_script
18
+
19
+ **What it does**: Executes Python code in an isolated subprocess environment. The code runs in a temporary file that's automatically cleaned up after execution.
20
+
21
+ **Why use it**: Allows agents to run Python code for calculations, data processing, or any task that requires Python. Isolation prevents interference with the main process.
22
+
23
+ **Location**: `massgen.tool._code_executors._python_executor`
24
+
25
+ #### Parameters
26
+
27
+ - `source_code` (required): Python code to execute as a string
28
+ - `max_duration` (optional): Maximum execution time in seconds (default: 300)
29
+ - `**extra_kwargs`: Additional keyword arguments (currently unused, reserved for future use)
30
+
31
+ #### Returns
32
+
33
+ ExecutionResult containing:
34
+ - `<exit_code>`: Process exit code (0 for success)
35
+ - `<stdout>`: Standard output from the script
36
+ - `<stderr>`: Standard error output
37
+
38
+ #### Security Features
39
+
40
+ - Runs in isolated subprocess
41
+ - Timeout protection (default 300 seconds)
42
+ - Temporary file cleanup
43
+ - No access to parent process environment
44
+
45
+ #### Examples
46
+
47
+ **Basic Calculation**:
48
+
49
+ ```python
50
+ from massgen.tool import run_python_script
51
+
52
+ # Simple calculation
53
+ code = """
54
+ result = 2 + 2
55
+ print(f"Result: {result}")
56
+ """
57
+
58
+ result = await run_python_script(source_code=code)
59
+ print(result.output_blocks[0].data)
60
+ # Output:
61
+ # <exit_code>0</exit_code>
62
+ # <stdout>Result: 4
63
+ # </stdout>
64
+ # <stderr></stderr>
65
+ ```
66
+
67
+ **Data Processing**:
68
+
69
+ ```python
70
+ # Process a list
71
+ code = """
72
+ data = [1, 2, 3, 4, 5]
73
+ squared = [x**2 for x in data]
74
+ print(f"Squared: {squared}")
75
+ print(f"Sum: {sum(squared)}")
76
+ """
77
+
78
+ result = await run_python_script(source_code=code)
79
+ # Output includes squared values and sum
80
+ ```
81
+
82
+ **With External Libraries**:
83
+
84
+ ```python
85
+ # Use installed packages
86
+ code = """
87
+ import json
88
+ import math
89
+
90
+ data = {"values": [1, 4, 9, 16, 25]}
91
+ sqrt_values = [math.sqrt(x) for x in data["values"]]
92
+
93
+ output = {"original": data["values"], "sqrt": sqrt_values}
94
+ print(json.dumps(output, indent=2))
95
+ """
96
+
97
+ result = await run_python_script(source_code=code)
98
+ ```
99
+
100
+ **File Operations in Script**:
101
+
102
+ ```python
103
+ # Create and read a file
104
+ code = """
105
+ # Write to file
106
+ with open('/tmp/test.txt', 'w') as f:
107
+ f.write('Hello from Python!')
108
+
109
+ # Read back
110
+ with open('/tmp/test.txt', 'r') as f:
111
+ content = f.read()
112
+ print(f"File content: {content}")
113
+ """
114
+
115
+ result = await run_python_script(source_code=code)
116
+ ```
117
+
118
+ **Error Handling**:
119
+
120
+ ```python
121
+ # Code with error
122
+ code = """
123
+ def divide(a, b):
124
+ return a / b
125
+
126
+ result = divide(10, 0) # Division by zero
127
+ print(f"Result: {result}")
128
+ """
129
+
130
+ result = await run_python_script(source_code=code)
131
+ print(result.output_blocks[0].data)
132
+ # Output includes:
133
+ # <exit_code>1</exit_code>
134
+ # <stderr>ZeroDivisionError: division by zero</stderr>
135
+ ```
136
+
137
+ **Timeout Example**:
138
+
139
+ ```python
140
+ # Long-running script with timeout
141
+ code = """
142
+ import time
143
+ for i in range(100):
144
+ time.sleep(1)
145
+ print(f"Second {i+1}")
146
+ """
147
+
148
+ result = await run_python_script(
149
+ source_code=code,
150
+ max_duration=5.0 # Stop after 5 seconds
151
+ )
152
+ # Will show timeout error in stderr
153
+ ```
154
+
155
+ #### Best Practices
156
+
157
+ 1. **Always Set Timeout**: Prevent runaway scripts
158
+ 2. **Print Results**: Use `print()` to capture output
159
+ 3. **Handle Errors**: Check exit_code and stderr
160
+ 4. **Clean Code**: Test code before running in production
161
+ 5. **Limit External Dependencies**: Not all packages may be available
162
+
163
+ #### Common Issues
164
+
165
+ **Import Errors**:
166
+ ```python
167
+ # Problem: Missing package
168
+ code = "import nonexistent_package"
169
+ # Solution: Check package is installed in environment
170
+ ```
171
+
172
+ **No Output**:
173
+ ```python
174
+ # Problem: Forgot to print
175
+ code = "result = 2 + 2" # No print statement
176
+ # Solution: Add print()
177
+ code = "result = 2 + 2; print(result)"
178
+ ```
179
+
180
+ **Timeout Too Short**:
181
+ ```python
182
+ # Problem: Complex operation needs more time
183
+ result = await run_python_script(code, max_duration=1.0) # Too short
184
+ # Solution: Increase timeout
185
+ result = await run_python_script(code, max_duration=60.0) # Better
186
+ ```
187
+
188
+ ---
189
+
190
+ ### run_shell_script
191
+
192
+ **What it does**: Executes shell commands in a subprocess. Similar to run_python_script but for shell commands.
193
+
194
+ **Why use it**: Allows agents to run system commands, scripts, or CLI tools.
195
+
196
+ **Location**: `massgen.tool._code_executors._shell_executor`
197
+
198
+ **Note**: Implementation details similar to run_python_script. Use with caution due to security implications of shell access.
199
+
200
+ ## File Operation Tools
201
+
202
+ ### read_file_content
203
+
204
+ **What it does**: Reads the contents of a file with optional line range specification. Can read entire files or specific line ranges, including negative indices for reading from the end.
205
+
206
+ **Why use it**: Essential for agents that need to examine files, load data, or read configuration. Supports partial reads for large files.
207
+
208
+ **Location**: `massgen.tool._file_handlers._file_operations`
209
+
210
+ #### Parameters
211
+
212
+ - `target_path` (required): Absolute or relative path to the file
213
+ - `line_range` (optional): `[start, end]` line numbers (1-based, inclusive)
214
+ - Positive numbers: Count from beginning (1 is first line)
215
+ - Negative numbers: Count from end (-1 is last line)
216
+
217
+ #### Returns
218
+
219
+ ExecutionResult containing:
220
+ - File content (with line numbers if range specified)
221
+ - Error message if file doesn't exist or isn't readable
222
+
223
+ #### Examples
224
+
225
+ **Read Entire File**:
226
+
227
+ ```python
228
+ from massgen.tool import read_file_content
229
+
230
+ # Read complete file
231
+ result = await read_file_content(target_path="config.json")
232
+ print(result.output_blocks[0].data)
233
+ # Output: Content of config.json:
234
+ # ```
235
+ # {
236
+ # "setting1": "value1",
237
+ # "setting2": "value2"
238
+ # }
239
+ # ```
240
+ ```
241
+
242
+ **Read Specific Lines**:
243
+
244
+ ```python
245
+ # Read lines 10-20
246
+ result = await read_file_content(
247
+ target_path="large_file.txt",
248
+ line_range=[10, 20]
249
+ )
250
+ # Output shows lines 10-20 with line numbers
251
+ # Content of large_file.txt (lines 10-20):
252
+ # ```
253
+ # 10│ Line 10 content
254
+ # 11│ Line 11 content
255
+ # ...
256
+ # 20│ Line 20 content
257
+ # ```
258
+ ```
259
+
260
+ **Read Last N Lines**:
261
+
262
+ ```python
263
+ # Read last 100 lines
264
+ result = await read_file_content(
265
+ target_path="app.log",
266
+ line_range=[-100, -1]
267
+ )
268
+ # Shows last 100 lines of the log file
269
+ ```
270
+
271
+ **Read First N Lines**:
272
+
273
+ ```python
274
+ # Read first 50 lines
275
+ result = await read_file_content(
276
+ target_path="data.csv",
277
+ line_range=[1, 50]
278
+ )
279
+ ```
280
+
281
+ **Error Handling**:
282
+
283
+ ```python
284
+ # File doesn't exist
285
+ result = await read_file_content(target_path="nonexistent.txt")
286
+ print(result.output_blocks[0].data)
287
+ # Output: Error: File 'nonexistent.txt' does not exist.
288
+
289
+ # Not a file (is a directory)
290
+ result = await read_file_content(target_path="/etc")
291
+ # Output: Error: Path '/etc' is not a file.
292
+
293
+ # Invalid line range
294
+ result = await read_file_content(
295
+ target_path="small_file.txt",
296
+ line_range=[100, 200] # File only has 50 lines
297
+ )
298
+ # Output: Error: Invalid line range [100, 200] for file with 50 lines.
299
+ ```
300
+
301
+ #### Best Practices
302
+
303
+ 1. **Check File Exists**: Handle error results gracefully
304
+ 2. **Use Line Ranges**: For large files, avoid reading entire content
305
+ 3. **Absolute Paths**: Use absolute paths when possible
306
+ 4. **UTF-8 Encoding**: Assumes UTF-8 encoding (most common)
307
+
308
+ ---
309
+
310
+ ### save_file_content
311
+
312
+ **What it does**: Writes content to a file, optionally creating parent directories. Overwrites existing files.
313
+
314
+ **Why use it**: Allows agents to create files, save results, write reports, or persist data.
315
+
316
+ **Location**: `massgen.tool._file_handlers._file_operations`
317
+
318
+ #### Parameters
319
+
320
+ - `target_path` (required): Path where file will be saved
321
+ - `file_content` (required): Content to write (string)
322
+ - `create_dirs` (optional): Create parent directories if they don't exist (default: True)
323
+
324
+ #### Returns
325
+
326
+ ExecutionResult containing:
327
+ - Success message with character count
328
+ - Error message if write fails
329
+
330
+ #### Examples
331
+
332
+ **Simple Write**:
333
+
334
+ ```python
335
+ from massgen.tool import save_file_content
336
+
337
+ # Write a text file
338
+ result = await save_file_content(
339
+ target_path="output.txt",
340
+ file_content="Hello, World!"
341
+ )
342
+ print(result.output_blocks[0].data)
343
+ # Output: Successfully wrote 13 characters to output.txt
344
+ ```
345
+
346
+ **Write JSON**:
347
+
348
+ ```python
349
+ import json
350
+
351
+ data = {"name": "Alice", "age": 30, "city": "NYC"}
352
+ content = json.dumps(data, indent=2)
353
+
354
+ result = await save_file_content(
355
+ target_path="data.json",
356
+ file_content=content
357
+ )
358
+ ```
359
+
360
+ **Write with Directory Creation**:
361
+
362
+ ```python
363
+ # Create nested directories automatically
364
+ result = await save_file_content(
365
+ target_path="reports/2024/march/summary.txt",
366
+ file_content="Monthly summary...",
367
+ create_dirs=True # Creates reports/2024/march/ if needed
368
+ )
369
+ ```
370
+
371
+ **Overwrite Existing File**:
372
+
373
+ ```python
374
+ # Overwrites without warning
375
+ result = await save_file_content(
376
+ target_path="existing.txt",
377
+ file_content="New content" # Old content is lost
378
+ )
379
+ ```
380
+
381
+ **Error Handling**:
382
+
383
+ ```python
384
+ # Permission denied
385
+ result = await save_file_content(
386
+ target_path="/root/protected.txt",
387
+ file_content="content"
388
+ )
389
+ # Output: Error writing file: Permission denied
390
+
391
+ # Cannot create directory
392
+ result = await save_file_content(
393
+ target_path="/readonly/file.txt",
394
+ file_content="content",
395
+ create_dirs=True
396
+ )
397
+ # Output: Error writing file: Cannot create directory
398
+ ```
399
+
400
+ #### Best Practices
401
+
402
+ 1. **Check Results**: Verify success message
403
+ 2. **Use create_dirs**: Usually want to create parent directories
404
+ 3. **Backup Important Files**: No confirmation before overwrite
405
+ 4. **Validate Content**: Ensure content is correct before writing
406
+ 5. **UTF-8 Safe**: Ensure content is UTF-8 compatible
407
+
408
+ #### Common Use Cases
409
+
410
+ **Save Analysis Results**:
411
+
412
+ ```python
413
+ results = analyze_data(dataset)
414
+ report = format_report(results)
415
+
416
+ await save_file_content(
417
+ target_path=f"reports/analysis_{datetime.now().date()}.txt",
418
+ file_content=report
419
+ )
420
+ ```
421
+
422
+ **Configuration Files**:
423
+
424
+ ```python
425
+ config = {
426
+ "api_key": "secret",
427
+ "endpoint": "https://api.example.com",
428
+ "timeout": 30
429
+ }
430
+
431
+ await save_file_content(
432
+ target_path="config.json",
433
+ file_content=json.dumps(config, indent=2)
434
+ )
435
+ ```
436
+
437
+ **Log Files**:
438
+
439
+ ```python
440
+ log_entry = f"[{datetime.now()}] Operation completed\n"
441
+
442
+ # Use append_file_content instead for logs
443
+ await append_file_content(
444
+ target_path="app.log",
445
+ additional_content=log_entry
446
+ )
447
+ ```
448
+
449
+ ---
450
+
451
+ ### append_file_content
452
+
453
+ **What it does**: Appends content to the end of a file, or inserts content at a specific line position. Does not overwrite existing content.
454
+
455
+ **Why use it**: Perfect for log files, incremental data collection, or adding to existing documents without losing original content.
456
+
457
+ **Location**: `massgen.tool._file_handlers._file_operations`
458
+
459
+ #### Parameters
460
+
461
+ - `target_path` (required): Path to the file
462
+ - `additional_content` (required): Content to append or insert
463
+ - `line_position` (optional): Line number to insert at (1-based). If None, appends to end
464
+
465
+ #### Returns
466
+
467
+ ExecutionResult containing:
468
+ - Success message with character count and operation type
469
+ - Error message if operation fails
470
+
471
+ #### Examples
472
+
473
+ **Append to End**:
474
+
475
+ ```python
476
+ from massgen.tool import append_file_content
477
+
478
+ # Append to log file
479
+ result = await append_file_content(
480
+ target_path="app.log",
481
+ additional_content="[2024-03-15] New log entry\n"
482
+ )
483
+ # Output: Successfully appended 30 characters to app.log
484
+ ```
485
+
486
+ **Insert at Specific Line**:
487
+
488
+ ```python
489
+ # Insert at line 5
490
+ result = await append_file_content(
491
+ target_path="document.txt",
492
+ additional_content="New paragraph here\n",
493
+ line_position=5
494
+ )
495
+ # Output: Successfully inserted content at line 5 in document.txt
496
+ ```
497
+
498
+ **Continuous Logging**:
499
+
500
+ ```python
501
+ # Log multiple entries
502
+ log_messages = [
503
+ "[INFO] Application started",
504
+ "[DEBUG] Loading configuration",
505
+ "[INFO] Server listening on port 8000"
506
+ ]
507
+
508
+ for msg in log_messages:
509
+ await append_file_content(
510
+ target_path="server.log",
511
+ additional_content=f"{msg}\n"
512
+ )
513
+ ```
514
+
515
+ **Insert Header**:
516
+
517
+ ```python
518
+ # Insert at beginning of file
519
+ header = "# Report Generated on 2024-03-15\n\n"
520
+
521
+ await append_file_content(
522
+ target_path="report.md",
523
+ additional_content=header,
524
+ line_position=1 # Insert at first line
525
+ )
526
+ ```
527
+
528
+ **Error Handling**:
529
+
530
+ ```python
531
+ # File doesn't exist
532
+ result = await append_file_content(
533
+ target_path="nonexistent.txt",
534
+ additional_content="content"
535
+ )
536
+ # Output: Error: File 'nonexistent.txt' does not exist.
537
+
538
+ # Invalid line position
539
+ result = await append_file_content(
540
+ target_path="small_file.txt", # 10 lines
541
+ additional_content="content",
542
+ line_position=100 # Too large
543
+ )
544
+ # Output: Error: Invalid line position 100 for file with 10 lines.
545
+ ```
546
+
547
+ #### Best Practices
548
+
549
+ 1. **Include Newlines**: Add `\n` to keep formatting correct
550
+ 2. **Timestamp Logs**: Include timestamps in log entries
551
+ 3. **Atomic Operations**: Each append is a separate file operation
552
+ 4. **Line Position Validation**: Check file length before inserting
553
+ 5. **Use for Logs**: Perfect for append-only log files
554
+
555
+ #### Common Use Cases
556
+
557
+ **Activity Logging**:
558
+
559
+ ```python
560
+ async def log_activity(activity: str):
561
+ timestamp = datetime.now().isoformat()
562
+ entry = f"[{timestamp}] {activity}\n"
563
+
564
+ await append_file_content(
565
+ target_path="activity.log",
566
+ additional_content=entry
567
+ )
568
+
569
+ # Usage
570
+ await log_activity("User logged in")
571
+ await log_activity("File uploaded")
572
+ await log_activity("Report generated")
573
+ ```
574
+
575
+ **Data Collection**:
576
+
577
+ ```python
578
+ # Collect measurements over time
579
+ async def record_measurement(value: float):
580
+ entry = f"{datetime.now()},{value}\n"
581
+
582
+ await append_file_content(
583
+ target_path="measurements.csv",
584
+ additional_content=entry
585
+ )
586
+ ```
587
+
588
+ **Document Building**:
589
+
590
+ ```python
591
+ # Build report incrementally
592
+ await save_file_content("report.md", "# Monthly Report\n\n")
593
+
594
+ await append_file_content("report.md", "## Sales Summary\n")
595
+ await append_file_content("report.md", sales_summary + "\n\n")
596
+
597
+ await append_file_content("report.md", "## User Statistics\n")
598
+ await append_file_content("report.md", user_stats + "\n\n")
599
+ ```
600
+
601
+ ## Integration with ToolManager
602
+
603
+ All built-in tools can be registered with ToolManager:
604
+
605
+ ```python
606
+ from massgen.tool import ToolManager
607
+
608
+ manager = ToolManager()
609
+
610
+ # Register by name (auto-discovery)
611
+ manager.add_tool_function(func="run_python_script")
612
+ manager.add_tool_function(func="read_file_content")
613
+ manager.add_tool_function(func="save_file_content")
614
+ manager.add_tool_function(func="append_file_content")
615
+
616
+ # Register with custom configuration
617
+ manager.add_tool_function(
618
+ func="run_python_script",
619
+ preset_args={"max_duration": 60.0}, # Custom timeout
620
+ description="Execute Python code with 60-second timeout"
621
+ )
622
+ ```
623
+
624
+ ## Security Considerations
625
+
626
+ ### Code Execution
627
+
628
+ 1. **Untrusted Code**: Never execute untrusted user code without review
629
+ 2. **Timeouts**: Always set reasonable timeouts
630
+ 3. **Resource Limits**: Consider memory and CPU limits
631
+ 4. **Sandboxing**: Code runs in subprocess but shares system access
632
+
633
+ ### File Operations
634
+
635
+ 1. **Path Validation**: Validate file paths before operations
636
+ 2. **Permission Checks**: Ensure agent has necessary permissions
637
+ 3. **Path Traversal**: Be careful with user-provided paths (../)
638
+ 4. **Overwrite Protection**: save_file_content overwrites without confirmation
639
+ 5. **Sensitive Data**: Don't write secrets or credentials to files
640
+
641
+ ### Best Practices
642
+
643
+ ```python
644
+ # Validate paths
645
+ import os
646
+
647
+ def is_safe_path(base_path: str, user_path: str) -> bool:
648
+ """Check if user_path is within base_path."""
649
+ abs_base = os.path.abspath(base_path)
650
+ abs_user = os.path.abspath(os.path.join(base_path, user_path))
651
+ return abs_user.startswith(abs_base)
652
+
653
+ # Use with file operations
654
+ if is_safe_path("/safe/directory", user_provided_path):
655
+ result = await read_file_content(user_provided_path)
656
+ else:
657
+ print("Error: Path outside allowed directory")
658
+ ```
659
+
660
+ ## Performance Tips
661
+
662
+ ### File Operations
663
+
664
+ 1. **Batch Writes**: Combine multiple writes into one
665
+ 2. **Line Ranges**: Use line_range for large files
666
+ 3. **Stream Large Files**: Process in chunks if possible
667
+ 4. **Cache Reads**: Cache frequently read files
668
+
669
+ ### Code Execution
670
+
671
+ 1. **Minimize Execution**: Cache results when possible
672
+ 2. **Optimize Code**: Profile and optimize Python scripts
673
+ 3. **Parallel Execution**: Use async for multiple operations
674
+ 4. **Resource Monitoring**: Monitor memory and CPU usage
675
+
676
+ ---
677
+
678
+ For more information, see:
679
+ - [ToolManager Documentation](manager.md)
680
+ - [ExecutionResult Documentation](execution_results.md)
681
+ - [Workflow Toolkits](workflow_toolkits.md)