auto-coder 0.1.398__py3-none-any.whl → 0.1.399__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.399.dist-info/METADATA +396 -0
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.399.dist-info}/RECORD +62 -28
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.399.dist-info}/WHEEL +1 -1
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.399.dist-info}/entry_points.txt +2 -0
- autocoder/agent/base_agentic/base_agent.py +2 -2
- autocoder/agent/base_agentic/tools/replace_in_file_tool_resolver.py +1 -1
- autocoder/agent/entry_command_agent/__init__.py +29 -0
- autocoder/agent/entry_command_agent/auto_tool.py +61 -0
- autocoder/agent/entry_command_agent/chat.py +475 -0
- autocoder/agent/entry_command_agent/designer.py +53 -0
- autocoder/agent/entry_command_agent/generate_command.py +50 -0
- autocoder/agent/entry_command_agent/project_reader.py +58 -0
- autocoder/agent/entry_command_agent/voice2text.py +71 -0
- autocoder/auto_coder.py +23 -548
- autocoder/auto_coder_runner.py +510 -8
- autocoder/chat/rules_command.py +1 -1
- autocoder/chat_auto_coder.py +6 -1
- autocoder/common/ac_style_command_parser/__init__.py +15 -0
- autocoder/common/ac_style_command_parser/example.py +7 -0
- autocoder/{command_parser.py → common/ac_style_command_parser/parser.py} +1 -33
- autocoder/common/ac_style_command_parser/test_parser.py +516 -0
- autocoder/common/command_completer_v2.py +1 -1
- autocoder/common/command_file_manager/examples.py +22 -8
- autocoder/common/command_file_manager/manager.py +37 -6
- autocoder/common/conversations/get_conversation_manager.py +143 -0
- autocoder/common/conversations/manager.py +122 -11
- autocoder/common/conversations/storage/index_manager.py +89 -0
- autocoder/common/v2/agent/agentic_edit.py +131 -18
- autocoder/common/v2/agent/agentic_edit_types.py +10 -0
- autocoder/common/v2/code_auto_generate_editblock.py +10 -2
- autocoder/dispacher/__init__.py +10 -0
- autocoder/rags.py +0 -27
- autocoder/run_context.py +1 -0
- autocoder/sdk/__init__.py +188 -0
- autocoder/sdk/cli/__init__.py +15 -0
- autocoder/sdk/cli/__main__.py +26 -0
- autocoder/sdk/cli/completion_wrapper.py +38 -0
- autocoder/sdk/cli/formatters.py +211 -0
- autocoder/sdk/cli/handlers.py +174 -0
- autocoder/sdk/cli/install_completion.py +301 -0
- autocoder/sdk/cli/main.py +284 -0
- autocoder/sdk/cli/options.py +72 -0
- autocoder/sdk/constants.py +102 -0
- autocoder/sdk/core/__init__.py +20 -0
- autocoder/sdk/core/auto_coder_core.py +867 -0
- autocoder/sdk/core/bridge.py +497 -0
- autocoder/sdk/example.py +0 -0
- autocoder/sdk/exceptions.py +72 -0
- autocoder/sdk/models/__init__.py +19 -0
- autocoder/sdk/models/messages.py +209 -0
- autocoder/sdk/models/options.py +194 -0
- autocoder/sdk/models/responses.py +311 -0
- autocoder/sdk/session/__init__.py +32 -0
- autocoder/sdk/session/session.py +106 -0
- autocoder/sdk/session/session_manager.py +56 -0
- autocoder/sdk/utils/__init__.py +24 -0
- autocoder/sdk/utils/formatters.py +216 -0
- autocoder/sdk/utils/io_utils.py +302 -0
- autocoder/sdk/utils/validators.py +287 -0
- autocoder/version.py +2 -1
- auto_coder-0.1.398.dist-info/METADATA +0 -111
- autocoder/common/conversations/compatibility.py +0 -303
- autocoder/common/conversations/conversation_manager.py +0 -502
- autocoder/common/conversations/example.py +0 -152
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.399.dist-info/licenses}/LICENSE +0 -0
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.399.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import threading
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from .manager import PersistConversationManager
|
|
5
|
+
from .config import ConversationManagerConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ConversationManagerSingleton:
|
|
9
|
+
"""对话管理器的单例类,确保全局只有一个实例"""
|
|
10
|
+
|
|
11
|
+
_instance: Optional[PersistConversationManager] = None
|
|
12
|
+
_lock = threading.Lock()
|
|
13
|
+
_config: Optional[ConversationManagerConfig] = None
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def get_instance(cls, config: Optional[ConversationManagerConfig] = None) -> PersistConversationManager:
|
|
17
|
+
"""
|
|
18
|
+
获取对话管理器实例
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
config: 配置对象,如果为None则使用默认配置
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
PersistConversationManager实例
|
|
25
|
+
"""
|
|
26
|
+
if cls._instance is None:
|
|
27
|
+
with cls._lock:
|
|
28
|
+
if cls._instance is None:
|
|
29
|
+
if config is None:
|
|
30
|
+
config = cls._get_default_config()
|
|
31
|
+
cls._config = config
|
|
32
|
+
cls._instance = PersistConversationManager(config)
|
|
33
|
+
return cls._instance
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def reset_instance(cls, config: Optional[ConversationManagerConfig] = None):
|
|
37
|
+
"""
|
|
38
|
+
重置实例,用于测试或配置更改时
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
config: 新的配置对象
|
|
42
|
+
"""
|
|
43
|
+
with cls._lock:
|
|
44
|
+
cls._instance = None
|
|
45
|
+
cls._config = None
|
|
46
|
+
if config is not None:
|
|
47
|
+
cls._instance = PersistConversationManager(config)
|
|
48
|
+
cls._config = config
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def _get_default_config(cls) -> ConversationManagerConfig:
|
|
52
|
+
"""获取默认配置"""
|
|
53
|
+
# 默认存储路径为当前工作目录下的 .auto-coder/conversations
|
|
54
|
+
default_storage_path = os.path.join(os.getcwd(), ".auto-coder", "conversations")
|
|
55
|
+
|
|
56
|
+
return ConversationManagerConfig(
|
|
57
|
+
storage_path=default_storage_path,
|
|
58
|
+
max_cache_size=100,
|
|
59
|
+
cache_ttl=300.0,
|
|
60
|
+
lock_timeout=10.0,
|
|
61
|
+
backup_enabled=True,
|
|
62
|
+
backup_interval=3600.0,
|
|
63
|
+
max_backups=10
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def get_config(cls) -> Optional[ConversationManagerConfig]:
|
|
68
|
+
"""获取当前使用的配置"""
|
|
69
|
+
return cls._config
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_conversation_manager(config: Optional[ConversationManagerConfig] = None) -> PersistConversationManager:
|
|
73
|
+
"""
|
|
74
|
+
获取全局对话管理器实例
|
|
75
|
+
|
|
76
|
+
这是一个便捷函数,内部使用单例模式确保全局只有一个实例。
|
|
77
|
+
首次调用时会创建实例,后续调用会返回同一个实例。
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
config: 可选的配置对象。如果为None,将使用默认配置。
|
|
81
|
+
注意:只有在首次调用时,config参数才会生效。
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
PersistConversationManager: 对话管理器实例
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
```python
|
|
88
|
+
# 使用默认配置
|
|
89
|
+
manager = get_conversation_manager()
|
|
90
|
+
|
|
91
|
+
# 使用自定义配置(仅在首次调用时生效)
|
|
92
|
+
config = ConversationManagerConfig(
|
|
93
|
+
storage_path="./my_conversations",
|
|
94
|
+
max_cache_size=200
|
|
95
|
+
)
|
|
96
|
+
manager = get_conversation_manager(config)
|
|
97
|
+
|
|
98
|
+
# 创建对话
|
|
99
|
+
conv_id = manager.create_conversation(
|
|
100
|
+
name="测试对话",
|
|
101
|
+
description="这是一个测试对话"
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
"""
|
|
105
|
+
return ConversationManagerSingleton.get_instance(config)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def reset_conversation_manager(config: Optional[ConversationManagerConfig] = None):
|
|
109
|
+
"""
|
|
110
|
+
重置全局对话管理器实例
|
|
111
|
+
|
|
112
|
+
用于测试或需要更改配置时重置实例。
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
config: 新的配置对象,如果为None则在下次调用get_conversation_manager时使用默认配置
|
|
116
|
+
|
|
117
|
+
Example:
|
|
118
|
+
```python
|
|
119
|
+
# 重置为默认配置
|
|
120
|
+
reset_conversation_manager()
|
|
121
|
+
|
|
122
|
+
# 重置为新配置
|
|
123
|
+
new_config = ConversationManagerConfig(storage_path="./new_path")
|
|
124
|
+
reset_conversation_manager(new_config)
|
|
125
|
+
```
|
|
126
|
+
"""
|
|
127
|
+
ConversationManagerSingleton.reset_instance(config)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def get_conversation_manager_config() -> Optional[ConversationManagerConfig]:
|
|
131
|
+
"""
|
|
132
|
+
获取当前对话管理器使用的配置
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
当前配置对象,如果还未初始化则返回None
|
|
136
|
+
"""
|
|
137
|
+
return ConversationManagerSingleton.get_config()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# 便捷别名
|
|
141
|
+
get_manager = get_conversation_manager
|
|
142
|
+
reset_manager = reset_conversation_manager
|
|
143
|
+
get_manager_config = get_conversation_manager_config
|
|
@@ -331,21 +331,22 @@ class PersistConversationManager:
|
|
|
331
331
|
List of conversation data
|
|
332
332
|
"""
|
|
333
333
|
try:
|
|
334
|
-
#
|
|
335
|
-
|
|
334
|
+
# Convert sort_desc boolean to sort_order string
|
|
335
|
+
sort_order = 'desc' if sort_desc else 'asc'
|
|
336
|
+
|
|
337
|
+
# Get conversations from index with sorting and pagination
|
|
338
|
+
conversations = self.index_manager.list_conversations(
|
|
339
|
+
limit=limit,
|
|
340
|
+
offset=offset,
|
|
341
|
+
sort_by=sort_by,
|
|
342
|
+
sort_order=sort_order
|
|
343
|
+
)
|
|
336
344
|
|
|
337
345
|
# Apply filters if provided
|
|
338
346
|
if filters:
|
|
339
347
|
conversations = self.filter_manager.apply_filters(conversations, filters)
|
|
340
348
|
|
|
341
|
-
|
|
342
|
-
conversations = self.index_manager.sort_conversations(
|
|
343
|
-
conversations, sort_by, sort_desc
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
# Apply pagination
|
|
347
|
-
end_idx = offset + limit if limit else None
|
|
348
|
-
return conversations[offset:end_idx]
|
|
349
|
+
return conversations
|
|
349
350
|
|
|
350
351
|
except Exception as e:
|
|
351
352
|
raise ConversationManagerError(f"Failed to list conversations: {e}")
|
|
@@ -815,6 +816,7 @@ class PersistConversationManager:
|
|
|
815
816
|
**self._stats,
|
|
816
817
|
'cache_stats': cache_stats,
|
|
817
818
|
'total_conversations': len(self.index_manager.list_conversations()),
|
|
819
|
+
'current_conversation_id': self.get_current_conversation_id(),
|
|
818
820
|
'storage_path': self.config.storage_path
|
|
819
821
|
}
|
|
820
822
|
|
|
@@ -914,4 +916,113 @@ class PersistConversationManager:
|
|
|
914
916
|
try:
|
|
915
917
|
self.index_manager._save_index()
|
|
916
918
|
except Exception:
|
|
917
|
-
pass # Ignore errors during cleanup
|
|
919
|
+
pass # Ignore errors during cleanup
|
|
920
|
+
|
|
921
|
+
# Current Conversation Management Methods
|
|
922
|
+
|
|
923
|
+
def set_current_conversation(self, conversation_id: str) -> bool:
|
|
924
|
+
"""
|
|
925
|
+
设置当前对话。
|
|
926
|
+
|
|
927
|
+
Args:
|
|
928
|
+
conversation_id: 要设置为当前对话的ID
|
|
929
|
+
|
|
930
|
+
Returns:
|
|
931
|
+
True if setting was successful
|
|
932
|
+
|
|
933
|
+
Raises:
|
|
934
|
+
ConversationNotFoundError: 如果对话不存在
|
|
935
|
+
"""
|
|
936
|
+
try:
|
|
937
|
+
# 验证对话是否存在
|
|
938
|
+
conversation_data = self.get_conversation(conversation_id)
|
|
939
|
+
if not conversation_data:
|
|
940
|
+
raise ConversationNotFoundError(conversation_id)
|
|
941
|
+
|
|
942
|
+
# 设置当前对话
|
|
943
|
+
success = self.index_manager.set_current_conversation(conversation_id)
|
|
944
|
+
if not success:
|
|
945
|
+
raise ConversationManagerError(f"Failed to set current conversation: {conversation_id}")
|
|
946
|
+
|
|
947
|
+
return True
|
|
948
|
+
|
|
949
|
+
except ConversationNotFoundError:
|
|
950
|
+
raise
|
|
951
|
+
except Exception as e:
|
|
952
|
+
raise ConversationManagerError(f"Failed to set current conversation {conversation_id}: {e}")
|
|
953
|
+
|
|
954
|
+
def get_current_conversation_id(self) -> Optional[str]:
|
|
955
|
+
"""
|
|
956
|
+
获取当前对话ID。
|
|
957
|
+
|
|
958
|
+
Returns:
|
|
959
|
+
当前对话ID,如果未设置返回None
|
|
960
|
+
"""
|
|
961
|
+
try:
|
|
962
|
+
return self.index_manager.get_current_conversation_id()
|
|
963
|
+
except Exception as e:
|
|
964
|
+
raise ConversationManagerError(f"Failed to get current conversation ID: {e}")
|
|
965
|
+
|
|
966
|
+
def get_current_conversation(self) -> Optional[Dict[str, Any]]:
|
|
967
|
+
"""
|
|
968
|
+
获取当前对话的完整数据。
|
|
969
|
+
|
|
970
|
+
Returns:
|
|
971
|
+
当前对话的数据字典,如果未设置或对话不存在返回None
|
|
972
|
+
"""
|
|
973
|
+
try:
|
|
974
|
+
current_id = self.get_current_conversation_id()
|
|
975
|
+
if not current_id:
|
|
976
|
+
return None
|
|
977
|
+
|
|
978
|
+
return self.get_conversation(current_id)
|
|
979
|
+
|
|
980
|
+
except Exception as e:
|
|
981
|
+
raise ConversationManagerError(f"Failed to get current conversation: {e}")
|
|
982
|
+
|
|
983
|
+
def clear_current_conversation(self) -> bool:
|
|
984
|
+
"""
|
|
985
|
+
清除当前对话设置。
|
|
986
|
+
|
|
987
|
+
Returns:
|
|
988
|
+
True if clearing was successful
|
|
989
|
+
"""
|
|
990
|
+
try:
|
|
991
|
+
success = self.index_manager.clear_current_conversation()
|
|
992
|
+
if not success:
|
|
993
|
+
raise ConversationManagerError("Failed to clear current conversation")
|
|
994
|
+
|
|
995
|
+
return True
|
|
996
|
+
|
|
997
|
+
except Exception as e:
|
|
998
|
+
raise ConversationManagerError(f"Failed to clear current conversation: {e}")
|
|
999
|
+
|
|
1000
|
+
def append_message_to_current(
|
|
1001
|
+
self,
|
|
1002
|
+
role: str,
|
|
1003
|
+
content: Union[str, Dict[str, Any], List[Any]],
|
|
1004
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1005
|
+
) -> str:
|
|
1006
|
+
"""
|
|
1007
|
+
向当前对话添加消息。
|
|
1008
|
+
|
|
1009
|
+
Args:
|
|
1010
|
+
role: 消息角色
|
|
1011
|
+
content: 消息内容
|
|
1012
|
+
metadata: 可选的消息元数据
|
|
1013
|
+
|
|
1014
|
+
Returns:
|
|
1015
|
+
消息ID
|
|
1016
|
+
|
|
1017
|
+
Raises:
|
|
1018
|
+
ConversationManagerError: 如果没有设置当前对话或添加失败
|
|
1019
|
+
"""
|
|
1020
|
+
try:
|
|
1021
|
+
current_id = self.get_current_conversation_id()
|
|
1022
|
+
if not current_id:
|
|
1023
|
+
raise ConversationManagerError("No current conversation set")
|
|
1024
|
+
|
|
1025
|
+
return self.append_message(current_id, role, content, metadata)
|
|
1026
|
+
|
|
1027
|
+
except Exception as e:
|
|
1028
|
+
raise ConversationManagerError(f"Failed to append message to current conversation: {e}")
|
|
@@ -26,10 +26,12 @@ class IndexManager:
|
|
|
26
26
|
"""
|
|
27
27
|
self.index_path = Path(index_path)
|
|
28
28
|
self.index_file = self.index_path / "conversations.idx"
|
|
29
|
+
self.config_file = self.index_path / "config.json"
|
|
29
30
|
self.lock_file = self.index_path / "index.lock"
|
|
30
31
|
|
|
31
32
|
self._ensure_index_directory()
|
|
32
33
|
self._load_index()
|
|
34
|
+
self._load_config()
|
|
33
35
|
|
|
34
36
|
def _ensure_index_directory(self):
|
|
35
37
|
"""确保索引目录存在"""
|
|
@@ -47,6 +49,18 @@ class IndexManager:
|
|
|
47
49
|
# 如果索引损坏,重建空索引
|
|
48
50
|
self._index_data = {}
|
|
49
51
|
|
|
52
|
+
def _load_config(self):
|
|
53
|
+
"""加载配置数据"""
|
|
54
|
+
try:
|
|
55
|
+
if self.config_file.exists():
|
|
56
|
+
with open(self.config_file, 'r', encoding='utf-8') as f:
|
|
57
|
+
self._config_data = json.load(f)
|
|
58
|
+
else:
|
|
59
|
+
self._config_data = {}
|
|
60
|
+
except (json.JSONDecodeError, OSError, IOError):
|
|
61
|
+
# 如果配置损坏,重建空配置
|
|
62
|
+
self._config_data = {}
|
|
63
|
+
|
|
50
64
|
def _save_index(self) -> bool:
|
|
51
65
|
"""
|
|
52
66
|
保存索引数据
|
|
@@ -68,6 +82,81 @@ class IndexManager:
|
|
|
68
82
|
except (OSError, IOError):
|
|
69
83
|
return False
|
|
70
84
|
|
|
85
|
+
def _save_config(self) -> bool:
|
|
86
|
+
"""
|
|
87
|
+
保存配置数据
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
bool: 保存成功返回True
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
# 使用临时文件进行原子写入
|
|
94
|
+
temp_file = self.config_file.with_suffix('.tmp')
|
|
95
|
+
|
|
96
|
+
with open(temp_file, 'w', encoding='utf-8') as f:
|
|
97
|
+
json.dump(self._config_data, f, ensure_ascii=False, indent=2)
|
|
98
|
+
|
|
99
|
+
# 原子重命名
|
|
100
|
+
temp_file.replace(self.config_file)
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
except (OSError, IOError):
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
def set_current_conversation(self, conversation_id: Optional[str]) -> bool:
|
|
107
|
+
"""
|
|
108
|
+
设置当前对话ID
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
conversation_id: 对话ID,None表示清除当前对话
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
bool: 设置成功返回True
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
# 重新加载配置以获取最新数据
|
|
118
|
+
self._load_config()
|
|
119
|
+
|
|
120
|
+
# 设置或清除当前对话ID
|
|
121
|
+
if conversation_id is None:
|
|
122
|
+
self._config_data.pop('current_conversation_id', None)
|
|
123
|
+
else:
|
|
124
|
+
self._config_data['current_conversation_id'] = conversation_id
|
|
125
|
+
|
|
126
|
+
# 更新时间戳
|
|
127
|
+
self._config_data['last_updated'] = time.time()
|
|
128
|
+
|
|
129
|
+
# 保存配置
|
|
130
|
+
return self._save_config()
|
|
131
|
+
|
|
132
|
+
except Exception:
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
def get_current_conversation_id(self) -> Optional[str]:
|
|
136
|
+
"""
|
|
137
|
+
获取当前对话ID
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Optional[str]: 当前对话ID,未设置返回None
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
# 重新加载配置以获取最新数据
|
|
144
|
+
self._load_config()
|
|
145
|
+
|
|
146
|
+
return self._config_data.get('current_conversation_id')
|
|
147
|
+
|
|
148
|
+
except Exception:
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
def clear_current_conversation(self) -> bool:
|
|
152
|
+
"""
|
|
153
|
+
清除当前对话设置
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
bool: 清除成功返回True
|
|
157
|
+
"""
|
|
158
|
+
return self.set_current_conversation(None)
|
|
159
|
+
|
|
71
160
|
def add_conversation(self, conversation_metadata: Dict[str, Any]) -> bool:
|
|
72
161
|
"""
|
|
73
162
|
添加对话到索引
|