auto-coder 0.1.400__py3-none-any.whl → 1.0.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.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.400.dist-info → auto_coder-1.0.0.dist-info}/METADATA +1 -1
- {auto_coder-0.1.400.dist-info → auto_coder-1.0.0.dist-info}/RECORD +48 -31
- autocoder/agent/agentic_filter.py +1 -1
- autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +1 -1
- autocoder/auto_coder_runner.py +120 -26
- autocoder/chat_auto_coder.py +81 -22
- autocoder/commands/auto_command.py +1 -1
- autocoder/common/__init__.py +2 -2
- autocoder/common/file_monitor/test_file_monitor.py +307 -0
- autocoder/common/git_utils.py +7 -2
- autocoder/common/pruner/__init__.py +0 -0
- autocoder/common/pruner/agentic_conversation_pruner.py +197 -0
- autocoder/common/pruner/context_pruner.py +574 -0
- autocoder/common/pruner/conversation_pruner.py +132 -0
- autocoder/common/pruner/test_agentic_conversation_pruner.py +342 -0
- autocoder/common/pruner/test_context_pruner.py +546 -0
- autocoder/common/tokens/__init__.py +15 -0
- autocoder/common/tokens/counter.py +20 -0
- autocoder/common/v2/agent/agentic_edit.py +372 -538
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +8 -1
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +43 -0
- autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
- autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +1 -1
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +1 -1
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +33 -88
- autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +8 -8
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +118 -0
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +324 -0
- autocoder/common/v2/agent/agentic_edit_types.py +46 -4
- autocoder/common/v2/agent/runner/__init__.py +31 -0
- autocoder/common/v2/agent/runner/base_runner.py +106 -0
- autocoder/common/v2/agent/runner/event_runner.py +216 -0
- autocoder/common/v2/agent/runner/sdk_runner.py +40 -0
- autocoder/common/v2/agent/runner/terminal_runner.py +283 -0
- autocoder/common/v2/agent/runner/tool_display.py +191 -0
- autocoder/index/entry.py +1 -1
- autocoder/plugins/token_helper_plugin.py +107 -7
- autocoder/run_context.py +9 -0
- autocoder/sdk/__init__.py +114 -81
- autocoder/sdk/cli/main.py +5 -0
- autocoder/sdk/core/auto_coder_core.py +0 -158
- autocoder/sdk/core/bridge.py +2 -4
- autocoder/version.py +1 -1
- {auto_coder-0.1.400.dist-info → auto_coder-1.0.0.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.400.dist-info → auto_coder-1.0.0.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.400.dist-info → auto_coder-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {auto_coder-0.1.400.dist-info → auto_coder-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,56 +1,34 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
3
|
import time
|
|
4
|
-
from pydantic import BaseModel, Field
|
|
5
4
|
import byzerllm
|
|
6
|
-
from typing import List, Dict, Any, Union,
|
|
5
|
+
from typing import List, Dict, Any, Union, Optional, Tuple
|
|
7
6
|
from autocoder.common.printer import Printer
|
|
8
|
-
from rich.console import Console
|
|
9
|
-
from rich.panel import Panel
|
|
10
|
-
from pydantic import SkipValidation
|
|
11
|
-
from byzerllm.utils.types import SingleOutputMeta
|
|
12
7
|
|
|
13
|
-
from
|
|
14
|
-
format_str_jinja2
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
from autocoder.common import AutoCoderArgs, git_utils, SourceCodeList, SourceCode
|
|
8
|
+
from autocoder.common import AutoCoderArgs, git_utils, SourceCodeList
|
|
18
9
|
from autocoder.common.global_cancel import global_cancel
|
|
19
10
|
from autocoder.common import detect_env
|
|
20
11
|
from autocoder.common import shells
|
|
21
12
|
from loguru import logger
|
|
22
|
-
from autocoder.utils import llms as llms_utils
|
|
23
|
-
from autocoder.common.auto_configure import config_readme
|
|
24
13
|
from autocoder.utils.auto_project_type import ProjectTypeAnalyzer
|
|
25
|
-
|
|
14
|
+
|
|
26
15
|
from autocoder.common.mcp_server import get_mcp_server, McpServerInfoRequest
|
|
27
16
|
from autocoder.common import SourceCodeList
|
|
28
17
|
from autocoder.common.utils_code_auto_generate import stream_chat_with_continue # Added import
|
|
29
18
|
import re
|
|
30
19
|
import xml.sax.saxutils
|
|
31
20
|
import time # Added for sleep
|
|
32
|
-
from typing import
|
|
33
|
-
from xml.etree import ElementTree as ET
|
|
34
|
-
from rich.console import Console # Added
|
|
35
|
-
from rich.panel import Panel # Added
|
|
36
|
-
from rich.syntax import Syntax # Added
|
|
37
|
-
from rich.markdown import Markdown # Added
|
|
21
|
+
from typing import Union, Type, Generator
|
|
38
22
|
from autocoder.events.event_manager_singleton import get_event_manager
|
|
39
|
-
from autocoder.events.event_types import
|
|
23
|
+
from autocoder.events.event_types import EventMetadata
|
|
40
24
|
from autocoder.memory.active_context_manager import ActiveContextManager
|
|
41
25
|
from autocoder.events import event_content as EventContentCreator
|
|
42
|
-
from autocoder.shadows.shadow_manager import ShadowManager
|
|
43
|
-
from autocoder.linters.shadow_linter import ShadowLinter
|
|
44
|
-
from autocoder.compilers.shadow_compiler import ShadowCompiler
|
|
45
26
|
from autocoder.common.action_yml_file_manager import ActionYmlFileManager
|
|
46
27
|
from autocoder.common.auto_coder_lang import get_message
|
|
47
28
|
from autocoder.common.save_formatted_log import save_formatted_log
|
|
48
|
-
# Import the new display function
|
|
49
|
-
from autocoder.common.v2.agent.agentic_tool_display import get_tool_display_message
|
|
50
29
|
from autocoder.common.v2.agent.agentic_edit_types import FileChangeEntry
|
|
51
30
|
from autocoder.utils.llms import get_single_llm
|
|
52
31
|
|
|
53
|
-
from autocoder.common.file_checkpoint.models import FileChange as CheckpointFileChange
|
|
54
32
|
from autocoder.common.file_checkpoint.manager import FileChangeManager as CheckpointFileChangeManager
|
|
55
33
|
from autocoder.linters.normal_linter import NormalLinter
|
|
56
34
|
from autocoder.compilers.normal_compiler import NormalCompiler
|
|
@@ -60,7 +38,8 @@ from autocoder.common.v2.agent.agentic_edit_tools import ( # Import specific re
|
|
|
60
38
|
ReplaceInFileToolResolver, SearchFilesToolResolver, ListFilesToolResolver,
|
|
61
39
|
ListCodeDefinitionNamesToolResolver, AskFollowupQuestionToolResolver,
|
|
62
40
|
AttemptCompletionToolResolver, PlanModeRespondToolResolver, UseMcpToolResolver,
|
|
63
|
-
UseRAGToolResolver,
|
|
41
|
+
UseRAGToolResolver, ACModReadToolResolver, ACModWriteToolResolver, TodoReadToolResolver,
|
|
42
|
+
TodoWriteToolResolver
|
|
64
43
|
)
|
|
65
44
|
from autocoder.common.llm_friendly_package import LLMFriendlyPackageManager
|
|
66
45
|
from autocoder.common.rulefiles.autocoderrules_utils import get_rules,auto_select_rules,get_required_and_index_rules
|
|
@@ -73,7 +52,8 @@ from autocoder.common.v2.agent.agentic_edit_types import (AgenticEditRequest, To
|
|
|
73
52
|
ListFilesTool,
|
|
74
53
|
ListCodeDefinitionNamesTool, AskFollowupQuestionTool,
|
|
75
54
|
AttemptCompletionTool, PlanModeRespondTool, UseMcpTool,
|
|
76
|
-
UseRAGTool,
|
|
55
|
+
UseRAGTool, ACModReadTool, ACModWriteTool, TodoReadTool,
|
|
56
|
+
TodoWriteTool,
|
|
77
57
|
TOOL_MODEL_MAP,
|
|
78
58
|
# Event Types
|
|
79
59
|
LLMOutputEvent, LLMThinkingEvent, ToolCallEvent,
|
|
@@ -98,21 +78,21 @@ TOOL_RESOLVER_MAP: Dict[Type[BaseTool], Type[BaseToolResolver]] = {
|
|
|
98
78
|
SearchFilesTool: SearchFilesToolResolver,
|
|
99
79
|
ListFilesTool: ListFilesToolResolver,
|
|
100
80
|
ListCodeDefinitionNamesTool: ListCodeDefinitionNamesToolResolver,
|
|
101
|
-
|
|
81
|
+
ACModReadTool: ACModReadToolResolver,
|
|
82
|
+
ACModWriteTool: ACModWriteToolResolver,
|
|
102
83
|
AskFollowupQuestionTool: AskFollowupQuestionToolResolver,
|
|
103
84
|
AttemptCompletionTool: AttemptCompletionToolResolver, # Will stop the loop anyway
|
|
104
85
|
PlanModeRespondTool: PlanModeRespondToolResolver,
|
|
105
86
|
UseMcpTool: UseMcpToolResolver,
|
|
106
|
-
UseRAGTool: UseRAGToolResolver
|
|
87
|
+
UseRAGTool: UseRAGToolResolver,
|
|
88
|
+
TodoReadTool: TodoReadToolResolver,
|
|
89
|
+
TodoWriteTool: TodoWriteToolResolver
|
|
107
90
|
}
|
|
108
|
-
from autocoder.common.conversations.get_conversation_manager import
|
|
109
|
-
|
|
110
|
-
get_conversation_manager_config,
|
|
111
|
-
reset_conversation_manager
|
|
112
|
-
)
|
|
113
|
-
from autocoder.common.conversations import ConversationManagerConfig
|
|
114
|
-
from autocoder.common.pull_requests import create_pull_request, detect_platform_from_repo
|
|
91
|
+
from autocoder.common.conversations.get_conversation_manager import get_conversation_manager
|
|
92
|
+
from autocoder.common.pull_requests import create_pull_request
|
|
115
93
|
from autocoder.common.auto_coder_lang import get_message, get_message_with_format
|
|
94
|
+
from autocoder.common.pruner.agentic_conversation_pruner import AgenticConversationPruner
|
|
95
|
+
from copy import deepcopy
|
|
116
96
|
|
|
117
97
|
|
|
118
98
|
# --- Tool Display Customization is now handled by agentic_tool_display.py ---
|
|
@@ -197,6 +177,9 @@ class AgenticEdit:
|
|
|
197
177
|
# 对话管理器
|
|
198
178
|
self.conversation_config =conversation_config
|
|
199
179
|
self.conversation_manager = get_conversation_manager()
|
|
180
|
+
|
|
181
|
+
# Agentic 对话修剪器
|
|
182
|
+
self.agentic_pruner = AgenticConversationPruner(args=args, llm=self.context_prune_llm)
|
|
200
183
|
|
|
201
184
|
if self.conversation_config.action == "new":
|
|
202
185
|
conversation_id = self.conversation_manager.create_conversation(name=self.conversation_config.query or "New Conversation",
|
|
@@ -344,14 +327,37 @@ class AgenticEdit:
|
|
|
344
327
|
<requires_approval>true or false</requires_approval>
|
|
345
328
|
</execute_command>
|
|
346
329
|
|
|
347
|
-
##
|
|
348
|
-
Description: Request to retrieve information about a
|
|
330
|
+
## ac_mod_read
|
|
331
|
+
Description: Request to retrieve information about an AC Module - a language-agnostic module containing a .ac.mod.md file that provides complete functionality and can be used as an API. The .ac.mod.md file contains usage examples, core components, component dependencies, references to other AC modules, and testing information. It accepts a directory path (absolute or relative to the current project).
|
|
349
332
|
Parameters:
|
|
350
|
-
- path: (required) The
|
|
333
|
+
- path: (required) The AC Module directory path (directory containing .ac.mod.md file).
|
|
351
334
|
Usage:
|
|
352
|
-
<
|
|
353
|
-
<path>relative/or/absolute/
|
|
354
|
-
</
|
|
335
|
+
<ac_mod_read>
|
|
336
|
+
<path>relative/or/absolute/ac/module/path</path>
|
|
337
|
+
</ac_mod_read>
|
|
338
|
+
|
|
339
|
+
## ac_mod_write
|
|
340
|
+
Description: Request to create or update an AC Module's .ac.mod.md file. This tool allows you to define a new AC Module or modify an existing one by writing to its .ac.mod.md file. The file contains usage examples, core components, component dependencies, references to other AC modules, and testing information.
|
|
341
|
+
Parameters:
|
|
342
|
+
- path: (required) The AC Module directory path (directory where .ac.mod.md file should be created or updated).
|
|
343
|
+
- diff: (required) One or more SEARCH/REPLACE blocks following this exact format:
|
|
344
|
+
```
|
|
345
|
+
<<<<<<< SEARCH
|
|
346
|
+
[exact content to find]
|
|
347
|
+
=======
|
|
348
|
+
[new content to replace with]
|
|
349
|
+
>>>>>>> REPLACE
|
|
350
|
+
|
|
351
|
+
This tool have the same usage as the replace_in_file tool, but it is used to update the AC Module's .ac.mod.md file.
|
|
352
|
+
|
|
353
|
+
Usage:
|
|
354
|
+
|
|
355
|
+
<ac_mod_write>
|
|
356
|
+
<path>relative/or/absolute/ac/module/path</path>
|
|
357
|
+
<diff>
|
|
358
|
+
Search and replace blocks here
|
|
359
|
+
</diff>
|
|
360
|
+
</ac_mod_write>
|
|
355
361
|
|
|
356
362
|
## read_file
|
|
357
363
|
Description: Request to read the contents of a file at the specified path. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. Automatically extracts raw text from PDF and DOCX files. May not be suitable for other types of binary files, as it returns the raw content as a string.
|
|
@@ -455,7 +461,36 @@ class AgenticEdit:
|
|
|
455
461
|
<options>
|
|
456
462
|
Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]
|
|
457
463
|
</options>
|
|
458
|
-
</ask_followup_question>
|
|
464
|
+
</ask_followup_question>
|
|
465
|
+
|
|
466
|
+
## todo_read
|
|
467
|
+
Description: Request to read the current todo list for the session. This tool helps you track progress, organize complex tasks, and understand the current status of ongoing work. Use this tool proactively to stay aware of task progress and demonstrate thoroughness.
|
|
468
|
+
Parameters:
|
|
469
|
+
- No parameters required
|
|
470
|
+
Usage:
|
|
471
|
+
<todo_read>
|
|
472
|
+
</todo_read>
|
|
473
|
+
|
|
474
|
+
## todo_write
|
|
475
|
+
Description: Request to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user. It also helps the user understand the progress of the task and overall progress of their request. Use this tool proactively for complex multi-step tasks, when explicitly requested by the user, or when you need to organize multiple operations.
|
|
476
|
+
Parameters:
|
|
477
|
+
- action: (required) The action to perform: 'create' (create new todo list), 'add_task' (add single task), 'update' (update existing task), 'mark_progress' (mark task as in progress), 'mark_completed' (mark task as completed)
|
|
478
|
+
- task_id: (optional) The ID of the task to update (required for update, mark_progress, mark_completed actions)
|
|
479
|
+
- content: (optional) The task content or description (required for create, add_task actions)
|
|
480
|
+
- priority: (optional) Task priority level: 'high', 'medium', 'low' (default: 'medium')
|
|
481
|
+
- status: (optional) Task status: 'pending', 'in_progress', 'completed' (default: 'pending')
|
|
482
|
+
- notes: (optional) Additional notes or details about the task
|
|
483
|
+
Usage:
|
|
484
|
+
<todo_write>
|
|
485
|
+
<action>create</action>
|
|
486
|
+
<content>
|
|
487
|
+
<task>Read the configuration file</task>
|
|
488
|
+
<task>Update the database settings</task>
|
|
489
|
+
<task>Test the connection</task>
|
|
490
|
+
<task>Deploy the changes</task>
|
|
491
|
+
</content>
|
|
492
|
+
<priority>high</priority>
|
|
493
|
+
</todo_write>
|
|
459
494
|
|
|
460
495
|
## attempt_completion
|
|
461
496
|
Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again.
|
|
@@ -505,7 +540,7 @@ class AgenticEdit:
|
|
|
505
540
|
{%if rag_server_info %}
|
|
506
541
|
### RAG_SERVER_LIST
|
|
507
542
|
{{rag_server_info}}
|
|
508
|
-
{%endif%}
|
|
543
|
+
{%endif%}
|
|
509
544
|
|
|
510
545
|
# Tool Use Examples
|
|
511
546
|
|
|
@@ -579,7 +614,35 @@ class AgenticEdit:
|
|
|
579
614
|
<server_name>github</server_name>
|
|
580
615
|
<tool_name>create_issue</tool_name>
|
|
581
616
|
<query>ower is octocat, repo is hello-world, title is Found a bug, body is I'm having a problem with this. labels is "bug" and "help wanted",assignees is "octocat"</query>
|
|
582
|
-
</use_mcp_tool>
|
|
617
|
+
</use_mcp_tool>
|
|
618
|
+
|
|
619
|
+
## Example 5: Reading the current todo list
|
|
620
|
+
|
|
621
|
+
<todo_read>
|
|
622
|
+
</todo_read>
|
|
623
|
+
|
|
624
|
+
## Example 6: Creating a new todo list for a complex task
|
|
625
|
+
|
|
626
|
+
<todo_write>
|
|
627
|
+
<action>create</action>
|
|
628
|
+
<content>
|
|
629
|
+
<task>Analyze the existing codebase structure</task>
|
|
630
|
+
<task>Design the new feature architecture</task>
|
|
631
|
+
<task>Implement the core functionality</task>
|
|
632
|
+
<task>Add comprehensive tests</task>
|
|
633
|
+
<task>Update documentation</task>
|
|
634
|
+
<task>Review and refactor code</task>
|
|
635
|
+
</content>
|
|
636
|
+
<priority>high</priority>
|
|
637
|
+
</todo_write>
|
|
638
|
+
|
|
639
|
+
## Example 7: Marking a specific task as completed
|
|
640
|
+
|
|
641
|
+
<todo_write>
|
|
642
|
+
<action>mark_completed</action>
|
|
643
|
+
<task_id>task_123</task_id>
|
|
644
|
+
<notes>Successfully implemented with 95% test coverage</notes>
|
|
645
|
+
</todo_write>
|
|
583
646
|
|
|
584
647
|
# Tool Use Guidelines
|
|
585
648
|
0. **ALWAYS START WITH THOROUGH SEARCH AND EXPLORATION.** Before making any code changes, use search tools (list_files, grep commands) to fully understand the codebase structure, existing patterns, and dependencies. This prevents errors and ensures your changes align with project conventions.
|
|
@@ -740,10 +803,10 @@ class AgenticEdit:
|
|
|
740
803
|
- **Combine multiple approaches** for comprehensive understanding
|
|
741
804
|
|
|
742
805
|
**Default workflow:**
|
|
743
|
-
1. `list_files` → understand structure
|
|
806
|
+
1. `list_files`(without recursively) → understand structure (if needed)
|
|
744
807
|
2. `grep` → find specific patterns/symbols
|
|
745
808
|
3. `read_file` → examine details
|
|
746
|
-
4.
|
|
809
|
+
4. Implement changes
|
|
747
810
|
5. `grep` → verify changes
|
|
748
811
|
|
|
749
812
|
# Comprehensive Workflow
|
|
@@ -809,13 +872,7 @@ class AgenticEdit:
|
|
|
809
872
|
|
|
810
873
|
More detail is on the EDITING FILES PART.
|
|
811
874
|
|
|
812
|
-
## Phase 5: Comprehensive Verification
|
|
813
|
-
|
|
814
|
-
**File System Verification**
|
|
815
|
-
<execute_command>
|
|
816
|
-
<command>ls -la newfile.* 2>/dev/null || echo "Expected new files not found"</command>
|
|
817
|
-
<requires_approval>false</requires_approval>
|
|
818
|
-
</execute_command>
|
|
875
|
+
## Phase 5: Comprehensive Verification
|
|
819
876
|
|
|
820
877
|
**Code Integration Verification**
|
|
821
878
|
<execute_command>
|
|
@@ -832,17 +889,7 @@ class AgenticEdit:
|
|
|
832
889
|
<execute_command>
|
|
833
890
|
<command>npm run lint 2>/dev/null || echo "Linting not configured"</command>
|
|
834
891
|
<requires_approval>false</requires_approval>
|
|
835
|
-
</execute_command>
|
|
836
|
-
|
|
837
|
-
<execute_command>
|
|
838
|
-
<command>npm test 2>/dev/null || echo "Testing not configured"</command>
|
|
839
|
-
<requires_approval>false</requires_approval>
|
|
840
|
-
</execute_command>
|
|
841
|
-
|
|
842
|
-
<execute_command>
|
|
843
|
-
<command>npm run build 2>/dev/null || echo "Build not configured"</command>
|
|
844
|
-
<requires_approval>false</requires_approval>
|
|
845
|
-
</execute_command>
|
|
892
|
+
</execute_command>
|
|
846
893
|
|
|
847
894
|
**Documentation & Comments**
|
|
848
895
|
- Verify that new functions/classes have appropriate documentation
|
|
@@ -880,6 +927,118 @@ class AgenticEdit:
|
|
|
880
927
|
|
|
881
928
|
====
|
|
882
929
|
|
|
930
|
+
TODO FILE TOOLS
|
|
931
|
+
|
|
932
|
+
The TODO tools help you manage and track task progress during complex coding sessions. They provide structured task management capabilities that enhance productivity and demonstrate thoroughness to users.
|
|
933
|
+
|
|
934
|
+
# todo_read
|
|
935
|
+
|
|
936
|
+
## Purpose
|
|
937
|
+
|
|
938
|
+
- Read and display the current session's todo list to understand task progress
|
|
939
|
+
- Get an overview of all pending, in-progress, and completed tasks
|
|
940
|
+
- Track the status of complex multi-step operations
|
|
941
|
+
|
|
942
|
+
## When to Use
|
|
943
|
+
|
|
944
|
+
Use this tool proactively and frequently to ensure awareness of current task status:
|
|
945
|
+
|
|
946
|
+
- **At the beginning of conversations** to see what's pending
|
|
947
|
+
- **Before starting new tasks** to prioritize work appropriately
|
|
948
|
+
- **When the user asks about previous tasks** or plans
|
|
949
|
+
- **Whenever you're uncertain about what to do next**
|
|
950
|
+
- **After completing tasks** to update understanding of remaining work
|
|
951
|
+
- **After every few messages** to ensure you're staying on track
|
|
952
|
+
- **Periodically during long sessions** to review progress and stay organized
|
|
953
|
+
|
|
954
|
+
## Important Considerations
|
|
955
|
+
|
|
956
|
+
- This tool takes **no parameters** - leave the input completely blank or empty
|
|
957
|
+
- **DO NOT** include dummy objects, placeholder strings, or keys like "input" or "empty"
|
|
958
|
+
- **LEAVE IT BLANK** - the tool will automatically read the current session's todo list
|
|
959
|
+
- Returns formatted output showing tasks grouped by status (In Progress, Pending, Completed)
|
|
960
|
+
- Provides summary statistics about task completion rates
|
|
961
|
+
|
|
962
|
+
## Benefits
|
|
963
|
+
|
|
964
|
+
- Helps maintain context and continuity across complex tasks
|
|
965
|
+
- Provides clear visibility into what has been accomplished and what remains
|
|
966
|
+
- Demonstrates organized approach to problem-solving
|
|
967
|
+
- Helps prioritize next steps based on current task status
|
|
968
|
+
|
|
969
|
+
# todo_write
|
|
970
|
+
|
|
971
|
+
## Purpose
|
|
972
|
+
|
|
973
|
+
- Create and manage structured task lists for complex coding sessions
|
|
974
|
+
- Track progress on multi-step operations with status updates
|
|
975
|
+
- Organize work into manageable, prioritized tasks
|
|
976
|
+
- Provide clear progress visibility to users
|
|
977
|
+
|
|
978
|
+
## When to Use
|
|
979
|
+
|
|
980
|
+
Use this tool proactively in these scenarios:
|
|
981
|
+
|
|
982
|
+
- **Complex multi-step tasks**: When a task requires 3 or more distinct steps or actions
|
|
983
|
+
- **Non-trivial and complex tasks**: Tasks that require careful planning or multiple operations
|
|
984
|
+
- **User explicitly requests todo list**: When the user directly asks you to use the todo list
|
|
985
|
+
- **User provides multiple tasks**: When users provide a list of things to be done (numbered or comma-separated)
|
|
986
|
+
- **After receiving new instructions**: Immediately capture user requirements as todos
|
|
987
|
+
- **When you start working on a task**: Mark it as in_progress BEFORE beginning work (ideally only one task should be in_progress at a time)
|
|
988
|
+
- **After completing a task**: Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
989
|
+
|
|
990
|
+
## When NOT to Use
|
|
991
|
+
|
|
992
|
+
Skip using this tool when:
|
|
993
|
+
|
|
994
|
+
- There is only a **single, straightforward task**
|
|
995
|
+
- The task is **trivial** and tracking it provides no organizational benefit
|
|
996
|
+
- The task can be completed in **less than 3 trivial steps**
|
|
997
|
+
- The task is **purely conversational or informational**
|
|
998
|
+
|
|
999
|
+
**NOTE**: Do not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly.
|
|
1000
|
+
|
|
1001
|
+
## Important Considerations
|
|
1002
|
+
|
|
1003
|
+
- Each task gets a unique ID that can be used for future updates
|
|
1004
|
+
- Task content for 'create' action should be formatted as a numbered list for multiple tasks
|
|
1005
|
+
- The system automatically tracks task creation and modification timestamps
|
|
1006
|
+
- Todo lists persist across tool calls within the same session
|
|
1007
|
+
- Use descriptive task names that clearly indicate what needs to be accomplished
|
|
1008
|
+
|
|
1009
|
+
## Example Usage Scenario
|
|
1010
|
+
|
|
1011
|
+
```
|
|
1012
|
+
User: I want to add a dark mode toggle to the application settings. Make sure you run the tests and build when you're done!
|
|
1013
|
+
|
|
1014
|
+
Assistant: I'll help add a dark mode toggle to your application settings. Let me create a todo list to track this implementation.
|
|
1015
|
+
|
|
1016
|
+
Creates todo list with the following items:
|
|
1017
|
+
1. Create dark mode toggle component in Settings page
|
|
1018
|
+
2. Add dark mode state management (context/store)
|
|
1019
|
+
3. Implement CSS-in-JS styles for dark theme
|
|
1020
|
+
4. Update existing components to support theme switching
|
|
1021
|
+
5. Run tests and build process, addressing any failures or errors that occur
|
|
1022
|
+
|
|
1023
|
+
Thinking: The assistant used the todo list because:
|
|
1024
|
+
1. Adding dark mode is a multi-step feature requiring UI, state management, and styling changes
|
|
1025
|
+
2. The user explicitly requested tests and build be run afterward
|
|
1026
|
+
3. The assistant inferred that tests and build need to pass by adding "Ensure tests and build succeed" as the final task
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
## Workflow Tips
|
|
1030
|
+
|
|
1031
|
+
1. **Start with creation**: Use 'create' action to establish the initial task list for complex projects
|
|
1032
|
+
2. **Add tasks incrementally**: Use 'add_task' as new requirements emerge during implementation
|
|
1033
|
+
3. **Track progress actively**: Use 'mark_progress' when starting work on a task
|
|
1034
|
+
4. **Complete tasks promptly**: Use 'mark_completed' when tasks are finished
|
|
1035
|
+
5. **Add context**: Use 'notes' parameter to record important decisions or challenges
|
|
1036
|
+
6. **Review regularly**: Use todo_read to maintain awareness of overall progress
|
|
1037
|
+
|
|
1038
|
+
By using these TODO tools effectively, you can maintain better organization, provide clear progress visibility, and demonstrate a systematic approach to complex coding tasks.
|
|
1039
|
+
|
|
1040
|
+
====
|
|
1041
|
+
|
|
883
1042
|
EDITING FILES
|
|
884
1043
|
|
|
885
1044
|
Before applying the editing techniques below, ensure you have followed the SEARCHING FILES methodology to fully understand the codebase context.
|
|
@@ -956,41 +1115,158 @@ class AgenticEdit:
|
|
|
956
1115
|
|
|
957
1116
|
====
|
|
958
1117
|
|
|
959
|
-
|
|
1118
|
+
AC MOD FILES
|
|
960
1119
|
|
|
961
|
-
#
|
|
1120
|
+
# AC Modules (.ac.mod.md)
|
|
962
1121
|
|
|
963
|
-
##
|
|
1122
|
+
## What is an AC Module?
|
|
964
1123
|
|
|
965
|
-
-
|
|
966
|
-
- This includes recent changes, important files, and their purposes
|
|
967
|
-
- This contextual information helps you understand the role of the directory and the files in the directory
|
|
1124
|
+
Any directory containing a `.ac.mod.md` file is considered an AC Module - a language-agnostic module that provides complete functionality and can be used as an API. These modules are self-contained units with well-defined interfaces and comprehensive documentation.
|
|
968
1125
|
|
|
969
|
-
##
|
|
1126
|
+
## AC Module Structure
|
|
1127
|
+
- .ac.mod.md contains detailed information about:
|
|
1128
|
+
- Usage examples and quick start guides
|
|
1129
|
+
- Core components and their relationships
|
|
1130
|
+
- Dependencies between components
|
|
1131
|
+
- References to other AC modules it depends on
|
|
1132
|
+
- Testing instructions and examples
|
|
970
1133
|
|
|
971
|
-
|
|
972
|
-
- Do NOT use other tools like list_files to view this specialized context information
|
|
1134
|
+
## When to Use AC Modules
|
|
973
1135
|
|
|
974
|
-
|
|
1136
|
+
1. **Avoid duplicate implementation**: Check if functionality already exists in project AC modules before implementing new features
|
|
1137
|
+
2. **Project understanding**: Review multiple AC modules to gain comprehensive knowledge of the entire project architecture
|
|
1138
|
+
3. **File modification context**: When modifying files in a directory, check if it's an AC module or contains AC modules to understand the full impact
|
|
1139
|
+
|
|
1140
|
+
## ac_mod_read
|
|
1141
|
+
|
|
1142
|
+
When to use:
|
|
1143
|
+
- Use the this tool to retrieve comprehensive information about an AC module
|
|
1144
|
+
- The tool reads the `.ac.mod.md` file and provides structured information about the module
|
|
1145
|
+
|
|
1146
|
+
Example:
|
|
1147
|
+
|
|
1148
|
+
<ac_mod_read>
|
|
1149
|
+
<path>src/autocoder/agent</path>
|
|
1150
|
+
</ac_mod_read>
|
|
1151
|
+
|
|
975
1152
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1153
|
+
## ac_mod_write
|
|
1154
|
+
|
|
1155
|
+
When to use:
|
|
1156
|
+
- When we edit files in an AC module, we should update the `.ac.mod.md` file to reflect the changes.
|
|
1157
|
+
- When the user directly asks you to create or update an AC module
|
|
1158
|
+
|
|
1159
|
+
Example:
|
|
1160
|
+
|
|
1161
|
+
<ac_mod_write>
|
|
1162
|
+
<path>src/autocoder/agent</path>
|
|
1163
|
+
<diff>
|
|
1164
|
+
search and replace blocks here
|
|
1165
|
+
</diff>
|
|
1166
|
+
</ac_mod_write>
|
|
979
1167
|
|
|
980
|
-
|
|
1168
|
+
The content of the `.ac.mod.md` file should be ***strictly following*** the structure of the example as follows:
|
|
1169
|
+
|
|
1170
|
+
<ac_mod_md_example>
|
|
1171
|
+
# [Module Name]
|
|
981
1172
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1173
|
+
[One-sentence description of the module's core functionality and its role in the project]
|
|
1174
|
+
|
|
1175
|
+
## Directory Structure
|
|
1176
|
+
|
|
1177
|
+
```
|
|
1178
|
+
[module_path]/
|
|
1179
|
+
├── [main_file1] # [Detailed function description]
|
|
1180
|
+
├── [main_file2] # [Detailed function description]
|
|
1181
|
+
├── [subdirectory]/ # [Subdirectory function description]
|
|
1182
|
+
│ └── [subfile] # [Subfile function description]
|
|
1183
|
+
└── .ac.mod.md # This document
|
|
986
1184
|
```
|
|
987
1185
|
|
|
988
|
-
|
|
1186
|
+
## Quick Start
|
|
1187
|
+
|
|
1188
|
+
### Basic Usage
|
|
1189
|
+
|
|
1190
|
+
```python
|
|
1191
|
+
# Import necessary modules
|
|
1192
|
+
from [module_path] import [MainClassName], [HelperClassName]
|
|
1193
|
+
|
|
1194
|
+
# 1. Initialize configuration
|
|
1195
|
+
[Specific initialization code example]
|
|
1196
|
+
|
|
1197
|
+
# 2. Create instance
|
|
1198
|
+
[Instance creation code example]
|
|
1199
|
+
|
|
1200
|
+
# 3. Basic usage
|
|
1201
|
+
[Basic usage code example]
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
### Helper Functions
|
|
1205
|
+
|
|
1206
|
+
[Detailed explanation of helper functions provided by the module]
|
|
1207
|
+
|
|
1208
|
+
### Configuration Management
|
|
1209
|
+
|
|
1210
|
+
[Explanation of configuration options and management methods]
|
|
1211
|
+
|
|
1212
|
+
## Core Components
|
|
1213
|
+
|
|
1214
|
+
### 1. [MainClassName] Main Class
|
|
1215
|
+
[YOU SHOULD KEEP THIS PART AS SIMPLIFIED AS POSSIBLE]
|
|
1216
|
+
**Core Features:**
|
|
1217
|
+
- [Feature1]: [Detailed description]
|
|
1218
|
+
- [Feature2]: [Detailed description]
|
|
1219
|
+
|
|
1220
|
+
**Main Methods:**
|
|
1221
|
+
- `[method1]()`: [Method functionality and parameter description]
|
|
1222
|
+
- `[method2]()`: [Method functionality and parameter description]
|
|
1223
|
+
|
|
1224
|
+
### 2. [Module] Architecture
|
|
1225
|
+
|
|
1226
|
+
[Detailed explanation of the module's design and implementation]
|
|
989
1227
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
- Helps prioritize which files to examine in detail with tools like read_file, shell commands, or list_code_definition_names
|
|
1228
|
+
## Mermaid File Dependency Graph
|
|
1229
|
+
[Main description of dependencies within the module]
|
|
993
1230
|
|
|
1231
|
+
```mermaid
|
|
1232
|
+
graph TB
|
|
1233
|
+
%% Core module definition
|
|
1234
|
+
[MainModule][MainModule<br/>Core functionality description]
|
|
1235
|
+
[SubModule1][SubModule1<br/>Functionality description]
|
|
1236
|
+
|
|
1237
|
+
%% Dependency relationships
|
|
1238
|
+
[MainModule] --> [SubModule1]
|
|
1239
|
+
|
|
1240
|
+
%% Style definitions
|
|
1241
|
+
classDef coreClass fill:#e1f5fe,stroke:#0277bd,stroke-width:2px
|
|
1242
|
+
classDef subClass fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1px
|
|
1243
|
+
|
|
1244
|
+
class [MainModule] coreClass
|
|
1245
|
+
class [SubModule1] subClass
|
|
1246
|
+
```
|
|
1247
|
+
|
|
1248
|
+
## Dependency Relationships
|
|
1249
|
+
Dependencies on other modules with .ac.mod.md files, simply shown as a relative path list, for example:
|
|
1250
|
+
|
|
1251
|
+
- ../a/.ac.mod.md
|
|
1252
|
+
- ../../b/.ac.mod.md
|
|
1253
|
+
|
|
1254
|
+
## Commands to Verify Module Functionality
|
|
1255
|
+
|
|
1256
|
+
Usually an executable command that can run a script or execute tests, for example:
|
|
1257
|
+
|
|
1258
|
+
```
|
|
1259
|
+
node --experimental-transform-types ./a/b/c.ts
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
Or test execution commands:
|
|
1263
|
+
|
|
1264
|
+
```
|
|
1265
|
+
pytest path/to/your/module/tests -v
|
|
1266
|
+
```
|
|
1267
|
+
</ac_mod_md_example>
|
|
1268
|
+
|
|
1269
|
+
|
|
994
1270
|
====
|
|
995
1271
|
|
|
996
1272
|
CAPABILITIES
|
|
@@ -1257,9 +1533,9 @@ class AgenticEdit:
|
|
|
1257
1533
|
|
|
1258
1534
|
self.current_conversations = conversations
|
|
1259
1535
|
|
|
1260
|
-
#
|
|
1536
|
+
# 计算初始对话窗口长度
|
|
1261
1537
|
conversation_str = json.dumps(conversations, ensure_ascii=False)
|
|
1262
|
-
current_tokens = count_tokens(conversation_str)
|
|
1538
|
+
current_tokens = count_tokens(conversation_str)
|
|
1263
1539
|
yield WindowLengthChangeEvent(tokens_used=current_tokens)
|
|
1264
1540
|
|
|
1265
1541
|
logger.info(
|
|
@@ -1291,12 +1567,12 @@ class AgenticEdit:
|
|
|
1291
1567
|
f"Starting LLM interaction cycle. History size: {len(conversations)}")
|
|
1292
1568
|
|
|
1293
1569
|
assistant_buffer = ""
|
|
1294
|
-
logger.info("Initializing stream chat with LLM")
|
|
1570
|
+
logger.info("Initializing stream chat with LLM")
|
|
1295
1571
|
|
|
1296
|
-
# ##
|
|
1572
|
+
# ## 实际请求大模型,并且我们会裁剪对话窗口长度
|
|
1297
1573
|
llm_response_gen = stream_chat_with_continue(
|
|
1298
1574
|
llm=self.llm,
|
|
1299
|
-
conversations=conversations,
|
|
1575
|
+
conversations=self.agentic_pruner.prune_conversations(deepcopy(conversations)),
|
|
1300
1576
|
llm_config={}, # Placeholder for future LLM configs
|
|
1301
1577
|
args=self.args
|
|
1302
1578
|
)
|
|
@@ -1996,7 +2272,7 @@ class AgenticEdit:
|
|
|
1996
2272
|
|
|
1997
2273
|
# 准备 PR 标题和描述
|
|
1998
2274
|
query = self.args.query or get_message("/agent/edit/pull_request/default_query")
|
|
1999
|
-
pr_title = get_message_with_format("/agent/edit/pull_request/title", query=query[0:40])
|
|
2275
|
+
pr_title = get_message_with_format("/agent/edit/pull_request/title", query="{query[0:40]}...")
|
|
2000
2276
|
|
|
2001
2277
|
# 构建 PR 描述
|
|
2002
2278
|
file_list = ""
|
|
@@ -2101,446 +2377,4 @@ class AgenticEdit:
|
|
|
2101
2377
|
path="/agent/edit/pull_request_exception",
|
|
2102
2378
|
stream_out_type="/agent/edit"
|
|
2103
2379
|
).to_dict()
|
|
2104
|
-
)
|
|
2105
|
-
|
|
2106
|
-
def run_in_terminal(self, request: AgenticEditRequest):
|
|
2107
|
-
"""
|
|
2108
|
-
Runs the agentic edit process based on the request and displays
|
|
2109
|
-
the interaction streamingly in the terminal using Rich.
|
|
2110
|
-
"""
|
|
2111
|
-
import json
|
|
2112
|
-
console = Console()
|
|
2113
|
-
project_name = os.path.basename(os.path.abspath(self.args.source_dir))
|
|
2114
|
-
|
|
2115
|
-
if self.conversation_config.action == "list":
|
|
2116
|
-
conversations = self.conversation_manager.list_conversations()
|
|
2117
|
-
# 只保留 conversation_id 和 name 字段
|
|
2118
|
-
filtered_conversations = []
|
|
2119
|
-
for conv in conversations:
|
|
2120
|
-
filtered_conv = {
|
|
2121
|
-
"conversation_id": conv.get("conversation_id"),
|
|
2122
|
-
"name": conv.get("name")
|
|
2123
|
-
}
|
|
2124
|
-
filtered_conversations.append(filtered_conv)
|
|
2125
|
-
|
|
2126
|
-
# 格式化 JSON 输出,使用 JSON 格式渲染而不是 Markdown
|
|
2127
|
-
json_str = json.dumps(filtered_conversations, ensure_ascii=False, indent=4)
|
|
2128
|
-
console.print(Panel(json_str,
|
|
2129
|
-
title="🏁 Task Completion", border_style="green", title_align="left"))
|
|
2130
|
-
return
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
if self.conversation_config.action == "new" and not request.user_input.strip():
|
|
2134
|
-
console.print(Panel(Markdown(f"New conversation created: {self.conversation_manager.get_current_conversation_id()}"),
|
|
2135
|
-
title="🏁 Task Completion", border_style="green", title_align="left"))
|
|
2136
|
-
return
|
|
2137
|
-
|
|
2138
|
-
console.rule(f"[bold cyan]Starting Agentic Edit: {project_name}[/]")
|
|
2139
|
-
console.print(Panel(
|
|
2140
|
-
f"[bold]{get_message('/agent/edit/user_query')}:[/bold]\n{request.user_input}", title=get_message("/agent/edit/objective"), border_style="blue"))
|
|
2141
|
-
|
|
2142
|
-
# 用于累计TokenUsageEvent数据
|
|
2143
|
-
accumulated_token_usage = {
|
|
2144
|
-
"model_name": "",
|
|
2145
|
-
"input_tokens": 0,
|
|
2146
|
-
"output_tokens": 0,
|
|
2147
|
-
"input_cost": 0.0,
|
|
2148
|
-
"output_cost": 0.0
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
try:
|
|
2152
|
-
self.apply_pre_changes()
|
|
2153
|
-
event_stream = self.analyze(request)
|
|
2154
|
-
for event in event_stream:
|
|
2155
|
-
if isinstance(event, ConversationIdEvent):
|
|
2156
|
-
console.print(f"[dim]Conversation ID: {event.conversation_id}[/dim]")
|
|
2157
|
-
continue
|
|
2158
|
-
if isinstance(event, TokenUsageEvent):
|
|
2159
|
-
last_meta: SingleOutputMeta = event.usage
|
|
2160
|
-
# Get model info for pricing
|
|
2161
|
-
from autocoder.utils import llms as llm_utils
|
|
2162
|
-
model_name = ",".join(llm_utils.get_llm_names(self.llm))
|
|
2163
|
-
model_info = llm_utils.get_model_info(
|
|
2164
|
-
model_name, self.args.product_mode) or {}
|
|
2165
|
-
input_price = model_info.get(
|
|
2166
|
-
"input_price", 0.0) if model_info else 0.0
|
|
2167
|
-
output_price = model_info.get(
|
|
2168
|
-
"output_price", 0.0) if model_info else 0.0
|
|
2169
|
-
|
|
2170
|
-
# Calculate costs
|
|
2171
|
-
input_cost = (last_meta.input_tokens_count *
|
|
2172
|
-
input_price) / 1000000 # Convert to millions
|
|
2173
|
-
# Convert to millions
|
|
2174
|
-
output_cost = (
|
|
2175
|
-
last_meta.generated_tokens_count * output_price) / 1000000
|
|
2176
|
-
|
|
2177
|
-
# 添加日志记录
|
|
2178
|
-
logger.info(f"Token Usage: Model={model_name}, Input Tokens={last_meta.input_tokens_count}, Output Tokens={last_meta.generated_tokens_count}, Input Cost=${input_cost:.6f}, Output Cost=${output_cost:.6f}")
|
|
2179
|
-
|
|
2180
|
-
# 累计token使用情况
|
|
2181
|
-
accumulated_token_usage["model_name"] = model_name
|
|
2182
|
-
accumulated_token_usage["input_tokens"] += last_meta.input_tokens_count
|
|
2183
|
-
accumulated_token_usage["output_tokens"] += last_meta.generated_tokens_count
|
|
2184
|
-
accumulated_token_usage["input_cost"] += input_cost
|
|
2185
|
-
accumulated_token_usage["output_cost"] += output_cost
|
|
2186
|
-
|
|
2187
|
-
elif isinstance(event, WindowLengthChangeEvent):
|
|
2188
|
-
# 显示当前会话的token数量
|
|
2189
|
-
logger.info(f"当前会话总 tokens: {event.tokens_used}")
|
|
2190
|
-
console.print(f"[dim]当前会话总 tokens: {event.tokens_used}[/dim]")
|
|
2191
|
-
|
|
2192
|
-
elif isinstance(event, LLMThinkingEvent):
|
|
2193
|
-
# Render thinking within a less prominent style, maybe grey?
|
|
2194
|
-
console.print(f"[grey50]{event.text}[/grey50]", end="")
|
|
2195
|
-
elif isinstance(event, LLMOutputEvent):
|
|
2196
|
-
# Print regular LLM output, potentially as markdown if needed later
|
|
2197
|
-
console.print(event.text, end="")
|
|
2198
|
-
elif isinstance(event, ToolCallEvent):
|
|
2199
|
-
# Skip displaying AttemptCompletionTool's tool call
|
|
2200
|
-
if isinstance(event.tool, AttemptCompletionTool):
|
|
2201
|
-
continue # Do not display AttemptCompletionTool tool call
|
|
2202
|
-
|
|
2203
|
-
tool_name = type(event.tool).__name__
|
|
2204
|
-
# Use the new internationalized display function
|
|
2205
|
-
display_content = get_tool_display_message(event.tool)
|
|
2206
|
-
console.print(Panel(
|
|
2207
|
-
display_content, title=f"🛠️ Action: {tool_name}", border_style="blue", title_align="left"))
|
|
2208
|
-
|
|
2209
|
-
elif isinstance(event, ToolResultEvent):
|
|
2210
|
-
# Skip displaying AttemptCompletionTool's result
|
|
2211
|
-
if event.tool_name == "AttemptCompletionTool":
|
|
2212
|
-
continue # Do not display AttemptCompletionTool result
|
|
2213
|
-
|
|
2214
|
-
if event.tool_name == "PlanModeRespondTool":
|
|
2215
|
-
continue
|
|
2216
|
-
|
|
2217
|
-
result = event.result
|
|
2218
|
-
title = f"✅ Tool Result: {event.tool_name}" if result.success else f"❌ Tool Result: {event.tool_name}"
|
|
2219
|
-
border_style = "green" if result.success else "red"
|
|
2220
|
-
base_content = f"[bold]Status:[/bold] {'Success' if result.success else 'Failure'}\n"
|
|
2221
|
-
base_content += f"[bold]Message:[/bold] {result.message}\n"
|
|
2222
|
-
|
|
2223
|
-
def _format_content(content):
|
|
2224
|
-
if len(content) > 200:
|
|
2225
|
-
return f"{content[:100]}\n...\n{content[-100:]}"
|
|
2226
|
-
else:
|
|
2227
|
-
return content
|
|
2228
|
-
|
|
2229
|
-
# Prepare panel for base info first
|
|
2230
|
-
panel_content = [base_content]
|
|
2231
|
-
syntax_content = None
|
|
2232
|
-
|
|
2233
|
-
if result.content is not None:
|
|
2234
|
-
content_str = ""
|
|
2235
|
-
try:
|
|
2236
|
-
if isinstance(result.content, (dict, list)):
|
|
2237
|
-
import json
|
|
2238
|
-
content_str = json.dumps(
|
|
2239
|
-
result.content, indent=2, ensure_ascii=False)
|
|
2240
|
-
syntax_content = Syntax(
|
|
2241
|
-
content_str, "json", theme="default", line_numbers=False)
|
|
2242
|
-
elif isinstance(result.content, str) and ('\n' in result.content or result.content.strip().startswith('<')):
|
|
2243
|
-
# Heuristic for code or XML/HTML
|
|
2244
|
-
lexer = "python" # Default guess
|
|
2245
|
-
if event.tool_name == "ReadFileTool" and isinstance(event.result.message, str):
|
|
2246
|
-
# Try to guess lexer from file extension in message
|
|
2247
|
-
if ".py" in event.result.message:
|
|
2248
|
-
lexer = "python"
|
|
2249
|
-
elif ".js" in event.result.message:
|
|
2250
|
-
lexer = "javascript"
|
|
2251
|
-
elif ".ts" in event.result.message:
|
|
2252
|
-
lexer = "typescript"
|
|
2253
|
-
elif ".html" in event.result.message:
|
|
2254
|
-
lexer = "html"
|
|
2255
|
-
elif ".css" in event.result.message:
|
|
2256
|
-
lexer = "css"
|
|
2257
|
-
elif ".json" in event.result.message:
|
|
2258
|
-
lexer = "json"
|
|
2259
|
-
elif ".xml" in event.result.message:
|
|
2260
|
-
lexer = "xml"
|
|
2261
|
-
elif ".md" in event.result.message:
|
|
2262
|
-
lexer = "markdown"
|
|
2263
|
-
else:
|
|
2264
|
-
lexer = "text" # Fallback lexer
|
|
2265
|
-
elif event.tool_name == "ExecuteCommandTool":
|
|
2266
|
-
lexer = "shell"
|
|
2267
|
-
else:
|
|
2268
|
-
lexer = "text"
|
|
2269
|
-
|
|
2270
|
-
syntax_content = Syntax(
|
|
2271
|
-
_format_content(result.content), lexer, theme="default", line_numbers=True)
|
|
2272
|
-
else:
|
|
2273
|
-
content_str = str(result.content)
|
|
2274
|
-
# Append simple string content directly
|
|
2275
|
-
panel_content.append(
|
|
2276
|
-
_format_content(content_str))
|
|
2277
|
-
except Exception as e:
|
|
2278
|
-
logger.warning(
|
|
2279
|
-
f"Error formatting tool result content: {e}")
|
|
2280
|
-
panel_content.append(
|
|
2281
|
-
# Fallback
|
|
2282
|
-
_format_content(str(result.content)))
|
|
2283
|
-
|
|
2284
|
-
# Print the base info panel
|
|
2285
|
-
console.print(Panel("\n".join(
|
|
2286
|
-
panel_content), title=title, border_style=border_style, title_align="left"))
|
|
2287
|
-
# Print syntax highlighted content separately if it exists
|
|
2288
|
-
if syntax_content:
|
|
2289
|
-
console.print(syntax_content)
|
|
2290
|
-
elif isinstance(event, PlanModeRespondEvent):
|
|
2291
|
-
console.print(Panel(Markdown(event.completion.response),
|
|
2292
|
-
title="🏁 Task Completion", border_style="green", title_align="left"))
|
|
2293
|
-
|
|
2294
|
-
elif isinstance(event, CompletionEvent):
|
|
2295
|
-
# 在这里完成实际合并
|
|
2296
|
-
try:
|
|
2297
|
-
self.apply_changes()
|
|
2298
|
-
except Exception as e:
|
|
2299
|
-
logger.exception(
|
|
2300
|
-
f"Error merging shadow changes to project: {e}")
|
|
2301
|
-
|
|
2302
|
-
console.print(Panel(Markdown(event.completion.result),
|
|
2303
|
-
title="🏁 Task Completion", border_style="green", title_align="left"))
|
|
2304
|
-
if event.completion.command:
|
|
2305
|
-
console.print(
|
|
2306
|
-
f"[dim]Suggested command:[/dim] [bold cyan]{event.completion.command}[/]")
|
|
2307
|
-
elif isinstance(event, ErrorEvent):
|
|
2308
|
-
console.print(Panel(
|
|
2309
|
-
f"[bold red]Error:[/bold red] {event.message}", title="🔥 Error", border_style="red", title_align="left"))
|
|
2310
|
-
|
|
2311
|
-
time.sleep(0.1) # Small delay for better visual flow
|
|
2312
|
-
|
|
2313
|
-
# 在处理完所有事件后打印累计的token使用情况
|
|
2314
|
-
if accumulated_token_usage["input_tokens"] > 0:
|
|
2315
|
-
self.printer.print_in_terminal(
|
|
2316
|
-
"code_generation_complete",
|
|
2317
|
-
duration=0.0,
|
|
2318
|
-
input_tokens=accumulated_token_usage["input_tokens"],
|
|
2319
|
-
output_tokens=accumulated_token_usage["output_tokens"],
|
|
2320
|
-
input_cost=accumulated_token_usage["input_cost"],
|
|
2321
|
-
output_cost=accumulated_token_usage["output_cost"],
|
|
2322
|
-
speed=0.0,
|
|
2323
|
-
model_names=accumulated_token_usage["model_name"],
|
|
2324
|
-
sampling_count=1
|
|
2325
|
-
)
|
|
2326
|
-
|
|
2327
|
-
except Exception as e:
|
|
2328
|
-
# 在处理异常时也打印累计的token使用情况
|
|
2329
|
-
if accumulated_token_usage["input_tokens"] > 0:
|
|
2330
|
-
self.printer.print_in_terminal(
|
|
2331
|
-
"code_generation_complete",
|
|
2332
|
-
duration=0.0,
|
|
2333
|
-
input_tokens=accumulated_token_usage["input_tokens"],
|
|
2334
|
-
output_tokens=accumulated_token_usage["output_tokens"],
|
|
2335
|
-
input_cost=accumulated_token_usage["input_cost"],
|
|
2336
|
-
output_cost=accumulated_token_usage["output_cost"],
|
|
2337
|
-
speed=0.0,
|
|
2338
|
-
model_names=accumulated_token_usage["model_name"],
|
|
2339
|
-
sampling_count=1
|
|
2340
|
-
)
|
|
2341
|
-
|
|
2342
|
-
logger.exception(
|
|
2343
|
-
"An unexpected error occurred during agent execution:")
|
|
2344
|
-
console.print(Panel(
|
|
2345
|
-
f"[bold red]FATAL ERROR:[/bold red]\n{str(e)}", title="🔥 System Error", border_style="red"))
|
|
2346
|
-
raise e
|
|
2347
|
-
finally:
|
|
2348
|
-
console.rule("[bold cyan]Agentic Edit Finished[/]")
|
|
2349
|
-
|
|
2350
|
-
def run(self, request: AgenticEditRequest):
|
|
2351
|
-
try:
|
|
2352
|
-
event_stream = self.analyze(request)
|
|
2353
|
-
for agent_event in event_stream:
|
|
2354
|
-
if isinstance(agent_event, CompletionEvent):
|
|
2355
|
-
self.apply_changes()
|
|
2356
|
-
yield agent_event
|
|
2357
|
-
|
|
2358
|
-
except Exception as e:
|
|
2359
|
-
logger.exception(
|
|
2360
|
-
"An unexpected error occurred during agent execution: {e}")
|
|
2361
|
-
raise e
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
def run_with_events(self, request: AgenticEditRequest):
|
|
2365
|
-
"""
|
|
2366
|
-
Runs the agentic edit process, converting internal events to the
|
|
2367
|
-
standard event system format and writing them using the event manager.
|
|
2368
|
-
"""
|
|
2369
|
-
event_manager = get_event_manager(self.args.event_file)
|
|
2370
|
-
self.apply_pre_changes()
|
|
2371
|
-
|
|
2372
|
-
try:
|
|
2373
|
-
event_stream = self.analyze(request)
|
|
2374
|
-
for agent_event in event_stream:
|
|
2375
|
-
content = None
|
|
2376
|
-
metadata = EventMetadata(
|
|
2377
|
-
action_file=self.args.file,
|
|
2378
|
-
is_streaming=False,
|
|
2379
|
-
stream_out_type="/agent/edit")
|
|
2380
|
-
|
|
2381
|
-
if isinstance(agent_event, LLMThinkingEvent):
|
|
2382
|
-
content = EventContentCreator.create_stream_thinking(
|
|
2383
|
-
content=agent_event.text)
|
|
2384
|
-
metadata.is_streaming = True
|
|
2385
|
-
metadata.path = "/agent/edit/thinking"
|
|
2386
|
-
event_manager.write_stream(
|
|
2387
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2388
|
-
elif isinstance(agent_event, LLMOutputEvent):
|
|
2389
|
-
content = EventContentCreator.create_stream_content(
|
|
2390
|
-
content=agent_event.text)
|
|
2391
|
-
metadata.is_streaming = True
|
|
2392
|
-
metadata.path = "/agent/edit/output"
|
|
2393
|
-
event_manager.write_stream(content=content.to_dict(),
|
|
2394
|
-
metadata=metadata.to_dict())
|
|
2395
|
-
elif isinstance(agent_event, ToolCallEvent):
|
|
2396
|
-
tool_name = type(agent_event.tool).__name__
|
|
2397
|
-
metadata.path = "/agent/edit/tool/call"
|
|
2398
|
-
content = EventContentCreator.create_result(
|
|
2399
|
-
content={
|
|
2400
|
-
"tool_name": tool_name,
|
|
2401
|
-
**agent_event.tool.model_dump()
|
|
2402
|
-
},
|
|
2403
|
-
metadata={}
|
|
2404
|
-
)
|
|
2405
|
-
event_manager.write_result(
|
|
2406
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2407
|
-
elif isinstance(agent_event, ToolResultEvent):
|
|
2408
|
-
metadata.path = "/agent/edit/tool/result"
|
|
2409
|
-
content = EventContentCreator.create_result(
|
|
2410
|
-
content={
|
|
2411
|
-
"tool_name": agent_event.tool_name,
|
|
2412
|
-
**agent_event.result.model_dump()
|
|
2413
|
-
},
|
|
2414
|
-
metadata={}
|
|
2415
|
-
)
|
|
2416
|
-
event_manager.write_result(
|
|
2417
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2418
|
-
elif isinstance(agent_event, PlanModeRespondEvent):
|
|
2419
|
-
metadata.path = "/agent/edit/plan_mode_respond"
|
|
2420
|
-
content = EventContentCreator.create_markdown_result(
|
|
2421
|
-
content=agent_event.completion.response,
|
|
2422
|
-
metadata={}
|
|
2423
|
-
)
|
|
2424
|
-
event_manager.write_result(
|
|
2425
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2426
|
-
|
|
2427
|
-
elif isinstance(agent_event, TokenUsageEvent):
|
|
2428
|
-
last_meta: SingleOutputMeta = agent_event.usage
|
|
2429
|
-
# Get model info for pricing
|
|
2430
|
-
from autocoder.utils import llms as llm_utils
|
|
2431
|
-
model_name = ",".join(llm_utils.get_llm_names(self.llm))
|
|
2432
|
-
model_info = llm_utils.get_model_info(
|
|
2433
|
-
model_name, self.args.product_mode) or {}
|
|
2434
|
-
input_price = model_info.get(
|
|
2435
|
-
"input_price", 0.0) if model_info else 0.0
|
|
2436
|
-
output_price = model_info.get(
|
|
2437
|
-
"output_price", 0.0) if model_info else 0.0
|
|
2438
|
-
|
|
2439
|
-
# Calculate costs
|
|
2440
|
-
input_cost = (last_meta.input_tokens_count *
|
|
2441
|
-
input_price) / 1000000 # Convert to millions
|
|
2442
|
-
# Convert to millions
|
|
2443
|
-
output_cost = (
|
|
2444
|
-
last_meta.generated_tokens_count * output_price) / 1000000
|
|
2445
|
-
|
|
2446
|
-
# 添加日志记录
|
|
2447
|
-
logger.info(f"Token Usage Details: Model={model_name}, Input Tokens={last_meta.input_tokens_count}, Output Tokens={last_meta.generated_tokens_count}, Input Cost=${input_cost:.6f}, Output Cost=${output_cost:.6f}")
|
|
2448
|
-
|
|
2449
|
-
# 直接将每次的 TokenUsageEvent 写入到事件中
|
|
2450
|
-
metadata.path = "/agent/edit/token_usage"
|
|
2451
|
-
content = EventContentCreator.create_result(content=EventContentCreator.ResultTokenStatContent(
|
|
2452
|
-
model_name=model_name,
|
|
2453
|
-
elapsed_time=0.0,
|
|
2454
|
-
first_token_time=last_meta.first_token_time,
|
|
2455
|
-
input_tokens=last_meta.input_tokens_count,
|
|
2456
|
-
output_tokens=last_meta.generated_tokens_count,
|
|
2457
|
-
input_cost=input_cost,
|
|
2458
|
-
output_cost=output_cost
|
|
2459
|
-
).to_dict())
|
|
2460
|
-
event_manager.write_result(content=content.to_dict(), metadata=metadata.to_dict())
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
elif isinstance(agent_event, CompletionEvent):
|
|
2464
|
-
# 在这里完成实际合并
|
|
2465
|
-
try:
|
|
2466
|
-
self.apply_changes()
|
|
2467
|
-
except Exception as e:
|
|
2468
|
-
logger.exception(
|
|
2469
|
-
f"Error merging shadow changes to project: {e}")
|
|
2470
|
-
|
|
2471
|
-
metadata.path = "/agent/edit/completion"
|
|
2472
|
-
content = EventContentCreator.create_completion(
|
|
2473
|
-
success_code="AGENT_COMPLETE",
|
|
2474
|
-
success_message="Agent attempted task completion.",
|
|
2475
|
-
result={
|
|
2476
|
-
"response": agent_event.completion.result
|
|
2477
|
-
}
|
|
2478
|
-
)
|
|
2479
|
-
event_manager.write_completion(
|
|
2480
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2481
|
-
elif isinstance(agent_event, WindowLengthChangeEvent):
|
|
2482
|
-
# 处理窗口长度变化事件
|
|
2483
|
-
metadata.path = "/agent/edit/window_length_change"
|
|
2484
|
-
content = EventContentCreator.create_result(
|
|
2485
|
-
content={
|
|
2486
|
-
"tokens_used": agent_event.tokens_used
|
|
2487
|
-
},
|
|
2488
|
-
metadata={}
|
|
2489
|
-
)
|
|
2490
|
-
event_manager.write_result(
|
|
2491
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2492
|
-
|
|
2493
|
-
# 记录日志
|
|
2494
|
-
logger.info(f"当前会话总 tokens: {agent_event.tokens_used}")
|
|
2495
|
-
|
|
2496
|
-
elif isinstance(agent_event, ConversationIdEvent):
|
|
2497
|
-
metadata.path = "/agent/edit/conversation_id"
|
|
2498
|
-
content = EventContentCreator.create_result(
|
|
2499
|
-
content={
|
|
2500
|
-
"conversation_id": agent_event.conversation_id
|
|
2501
|
-
},
|
|
2502
|
-
metadata={}
|
|
2503
|
-
)
|
|
2504
|
-
event_manager.write_result(content=content.to_dict(), metadata=metadata.to_dict())
|
|
2505
|
-
|
|
2506
|
-
elif isinstance(agent_event, ErrorEvent):
|
|
2507
|
-
metadata.path = "/agent/edit/error"
|
|
2508
|
-
content = EventContentCreator.create_error(
|
|
2509
|
-
error_code="AGENT_ERROR",
|
|
2510
|
-
error_message=agent_event.message,
|
|
2511
|
-
details={"agent_event_type": "ErrorEvent"}
|
|
2512
|
-
)
|
|
2513
|
-
event_manager.write_error(
|
|
2514
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2515
|
-
else:
|
|
2516
|
-
metadata.path = "/agent/edit/error"
|
|
2517
|
-
logger.warning(
|
|
2518
|
-
f"Unhandled agent event type: {type(agent_event)}")
|
|
2519
|
-
content = EventContentCreator.create_error(
|
|
2520
|
-
error_code="AGENT_ERROR",
|
|
2521
|
-
error_message=f"Unhandled agent event type: {type(agent_event)}",
|
|
2522
|
-
details={"agent_event_type": type(
|
|
2523
|
-
agent_event).__name__}
|
|
2524
|
-
)
|
|
2525
|
-
event_manager.write_error(
|
|
2526
|
-
content=content.to_dict(), metadata=metadata.to_dict())
|
|
2527
|
-
|
|
2528
|
-
except Exception as e:
|
|
2529
|
-
logger.exception(
|
|
2530
|
-
"An unexpected error occurred during agent execution:")
|
|
2531
|
-
metadata = EventMetadata(
|
|
2532
|
-
action_file=self.args.file,
|
|
2533
|
-
is_streaming=False,
|
|
2534
|
-
stream_out_type="/agent/edit/error")
|
|
2535
|
-
|
|
2536
|
-
# 发送累计的TokenUsageEvent数据(在错误情况下也需要发送)
|
|
2537
|
-
|
|
2538
|
-
error_content = EventContentCreator.create_error(
|
|
2539
|
-
error_code="AGENT_FATAL_ERROR",
|
|
2540
|
-
error_message=f"An unexpected error occurred: {str(e)}",
|
|
2541
|
-
details={"exception_type": type(e).__name__}
|
|
2542
|
-
)
|
|
2543
|
-
event_manager.write_error(
|
|
2544
|
-
content=error_content.to_dict(), metadata=metadata.to_dict())
|
|
2545
|
-
# Re-raise the exception if needed, or handle appropriately
|
|
2546
|
-
raise e
|
|
2380
|
+
)
|