auto-coder 0.1.398__py3-none-any.whl → 0.1.400__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/METADATA +396 -0
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/RECORD +82 -29
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/WHEEL +1 -1
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.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 +511 -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} +28 -45
- autocoder/common/ac_style_command_parser/test_parser.py +516 -0
- autocoder/common/auto_coder_lang.py +78 -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/pull_requests/__init__.py +256 -0
- autocoder/common/pull_requests/base_provider.py +191 -0
- autocoder/common/pull_requests/config.py +66 -0
- autocoder/common/pull_requests/example.py +1 -0
- autocoder/common/pull_requests/exceptions.py +46 -0
- autocoder/common/pull_requests/manager.py +201 -0
- autocoder/common/pull_requests/models.py +164 -0
- autocoder/common/pull_requests/providers/__init__.py +23 -0
- autocoder/common/pull_requests/providers/gitcode_provider.py +19 -0
- autocoder/common/pull_requests/providers/gitee_provider.py +20 -0
- autocoder/common/pull_requests/providers/github_provider.py +214 -0
- autocoder/common/pull_requests/providers/gitlab_provider.py +29 -0
- autocoder/common/pull_requests/test_module.py +1 -0
- autocoder/common/pull_requests/utils.py +344 -0
- autocoder/common/tokens/__init__.py +62 -0
- autocoder/common/tokens/counter.py +211 -0
- autocoder/common/tokens/file_detector.py +105 -0
- autocoder/common/tokens/filters.py +111 -0
- autocoder/common/tokens/models.py +28 -0
- autocoder/common/v2/agent/agentic_edit.py +312 -85
- autocoder/common/v2/agent/agentic_edit_types.py +11 -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 +175 -0
- autocoder/sdk/cli/install_completion.py +301 -0
- autocoder/sdk/cli/main.py +286 -0
- autocoder/sdk/cli/options.py +73 -0
- autocoder/sdk/constants.py +102 -0
- autocoder/sdk/core/__init__.py +20 -0
- autocoder/sdk/core/auto_coder_core.py +880 -0
- autocoder/sdk/core/bridge.py +500 -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 +196 -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.400.dist-info/licenses}/LICENSE +0 -0
- {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auto-Coder SDK 桥接层
|
|
3
|
+
|
|
4
|
+
连接 SDK 和底层 auto_coder_runner 功能
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
from typing import Any, Dict, Optional, Iterator, Union
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import subprocess
|
|
12
|
+
|
|
13
|
+
from ..exceptions import BridgeError
|
|
14
|
+
from ..models.responses import StreamEvent
|
|
15
|
+
from autocoder.auto_coder_runner import run_auto_command,configure
|
|
16
|
+
from ..models.options import AutoCodeOptions
|
|
17
|
+
|
|
18
|
+
# 不导入事件类型,使用动态检查避免类型冲突
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AutoCoderBridge:
|
|
22
|
+
"""桥接层,连接现有功能"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, project_root: str,options:AutoCodeOptions):
|
|
25
|
+
"""
|
|
26
|
+
初始化桥接层
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
project_root: 项目根目录
|
|
30
|
+
"""
|
|
31
|
+
self.project_root = project_root or os.getcwd()
|
|
32
|
+
self.options = options
|
|
33
|
+
self._setup_environment()
|
|
34
|
+
|
|
35
|
+
def _setup_environment(self):
|
|
36
|
+
"""设置环境和内存"""
|
|
37
|
+
try:
|
|
38
|
+
# 切换到项目根目录
|
|
39
|
+
original_cwd = os.getcwd()
|
|
40
|
+
os.chdir(self.project_root)
|
|
41
|
+
|
|
42
|
+
# 尝试初始化 auto_coder_runner 环境
|
|
43
|
+
try:
|
|
44
|
+
self.init_project_if_required()
|
|
45
|
+
from autocoder.auto_coder_runner import start
|
|
46
|
+
start()
|
|
47
|
+
except ImportError:
|
|
48
|
+
# 如果无法导入,跳过初始化
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
# 恢复原始工作目录
|
|
52
|
+
os.chdir(original_cwd)
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
# 设置环境失败不应该阻止程序运行
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def init_project_if_required(self):
|
|
59
|
+
if not os.path.exists(".auto-coder") or not os.path.exists("actions"):
|
|
60
|
+
subprocess.run(
|
|
61
|
+
["auto-coder", "init", "--source_dir", "."], check=True
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def call_run_auto_command(
|
|
65
|
+
self,
|
|
66
|
+
query: str,
|
|
67
|
+
pre_commit: bool = False,
|
|
68
|
+
pr: bool = False,
|
|
69
|
+
extra_args: Optional[Dict[str, Any]] = None,
|
|
70
|
+
stream: bool = True
|
|
71
|
+
) -> Iterator[StreamEvent]:
|
|
72
|
+
"""
|
|
73
|
+
调用 run_auto_command 功能并返回事件流
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
query: 查询内容
|
|
77
|
+
pre_commit: 是否预提交
|
|
78
|
+
pr: 是否预提交
|
|
79
|
+
extra_args: 额外参数
|
|
80
|
+
stream: 是否流式返回
|
|
81
|
+
|
|
82
|
+
Yields:
|
|
83
|
+
StreamEvent: 事件流
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
BridgeError: 桥接层错误
|
|
87
|
+
"""
|
|
88
|
+
try:
|
|
89
|
+
# 切换到项目根目录
|
|
90
|
+
original_cwd = os.getcwd()
|
|
91
|
+
os.chdir(self.project_root)
|
|
92
|
+
|
|
93
|
+
# 准备参数
|
|
94
|
+
extra_args = extra_args or {}
|
|
95
|
+
|
|
96
|
+
# 发送开始事件
|
|
97
|
+
yield StreamEvent(
|
|
98
|
+
event_type="start",
|
|
99
|
+
data={"query": query, "pre_commit": pre_commit}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
|
|
104
|
+
configure(f"model:{self.options.model}")
|
|
105
|
+
events = run_auto_command(
|
|
106
|
+
query=query,
|
|
107
|
+
pre_commit=pre_commit,
|
|
108
|
+
pr=pr,
|
|
109
|
+
extra_args=extra_args
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# 如果返回的是生成器,逐个处理事件
|
|
113
|
+
if hasattr(events, '__iter__') and not isinstance(events, (str, bytes)):
|
|
114
|
+
for event in events:
|
|
115
|
+
# 转换事件格式
|
|
116
|
+
stream_event = self._convert_event_to_stream_event(
|
|
117
|
+
event)
|
|
118
|
+
if stream_event: # 只yield非None的事件
|
|
119
|
+
yield stream_event
|
|
120
|
+
else:
|
|
121
|
+
# 如果不是生成器,包装成单个事件
|
|
122
|
+
yield StreamEvent(
|
|
123
|
+
event_type="content",
|
|
124
|
+
data={"content": str(events)}
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
except (ImportError, FileNotFoundError, Exception) as e:
|
|
128
|
+
# import traceback
|
|
129
|
+
# traceback.print_exc()
|
|
130
|
+
# 如果无法导入或出现其他错误
|
|
131
|
+
raise BridgeError(
|
|
132
|
+
f"run_auto_command failed: {str(e)}", original_error=e)
|
|
133
|
+
|
|
134
|
+
# 发送完成事件
|
|
135
|
+
yield StreamEvent(
|
|
136
|
+
event_type="end",
|
|
137
|
+
data={"status": "completed"}
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
except Exception as e:
|
|
141
|
+
# 发送错误事件
|
|
142
|
+
yield StreamEvent(
|
|
143
|
+
event_type="error",
|
|
144
|
+
data={"error": str(e), "error_type": type(e).__name__}
|
|
145
|
+
)
|
|
146
|
+
raise BridgeError(
|
|
147
|
+
f"run_auto_command failed: {str(e)}", original_error=e)
|
|
148
|
+
finally:
|
|
149
|
+
# 恢复原始工作目录
|
|
150
|
+
os.chdir(original_cwd)
|
|
151
|
+
|
|
152
|
+
def _simulate_auto_command_response(self, query: str) -> Iterator[StreamEvent]:
|
|
153
|
+
"""
|
|
154
|
+
模拟 auto_command 响应
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
query: 查询内容
|
|
158
|
+
|
|
159
|
+
Yields:
|
|
160
|
+
StreamEvent: 模拟的事件流
|
|
161
|
+
"""
|
|
162
|
+
yield StreamEvent(
|
|
163
|
+
event_type="content",
|
|
164
|
+
data={"content": f"[模拟模式] 正在处理查询: {query}"}
|
|
165
|
+
)
|
|
166
|
+
yield StreamEvent(
|
|
167
|
+
event_type="content",
|
|
168
|
+
data={"content": f"[模拟模式] 这是对您查询的模拟响应。在真实环境中,Auto-Coder 会:"}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# 根据查询内容生成合适的模拟响应
|
|
172
|
+
if any(keyword in query.lower() for keyword in ["function", "函数", "write", "create", "写"]):
|
|
173
|
+
yield StreamEvent(
|
|
174
|
+
event_type="content",
|
|
175
|
+
data={"content": "1. 分析您的需求"}
|
|
176
|
+
)
|
|
177
|
+
yield StreamEvent(
|
|
178
|
+
event_type="content",
|
|
179
|
+
data={"content": "2. 生成相应的代码"}
|
|
180
|
+
)
|
|
181
|
+
yield StreamEvent(
|
|
182
|
+
event_type="content",
|
|
183
|
+
data={"content": "3. 添加适当的注释和文档"}
|
|
184
|
+
)
|
|
185
|
+
elif any(keyword in query.lower() for keyword in ["error", "错误", "handling", "处理"]):
|
|
186
|
+
yield StreamEvent(
|
|
187
|
+
event_type="content",
|
|
188
|
+
data={"content": "1. 识别潜在的错误点"}
|
|
189
|
+
)
|
|
190
|
+
yield StreamEvent(
|
|
191
|
+
event_type="content",
|
|
192
|
+
data={"content": "2. 添加 try-catch 块"}
|
|
193
|
+
)
|
|
194
|
+
yield StreamEvent(
|
|
195
|
+
event_type="content",
|
|
196
|
+
data={"content": "3. 添加适当的日志记录"}
|
|
197
|
+
)
|
|
198
|
+
elif any(keyword in query.lower() for keyword in ["explain", "解释", "how", "如何"]):
|
|
199
|
+
yield StreamEvent(
|
|
200
|
+
event_type="content",
|
|
201
|
+
data={"content": "1. 分析代码结构"}
|
|
202
|
+
)
|
|
203
|
+
yield StreamEvent(
|
|
204
|
+
event_type="content",
|
|
205
|
+
data={"content": "2. 提供详细的解释"}
|
|
206
|
+
)
|
|
207
|
+
yield StreamEvent(
|
|
208
|
+
event_type="content",
|
|
209
|
+
data={"content": "3. 给出使用示例"}
|
|
210
|
+
)
|
|
211
|
+
else:
|
|
212
|
+
yield StreamEvent(
|
|
213
|
+
event_type="content",
|
|
214
|
+
data={"content": "1. 理解您的请求"}
|
|
215
|
+
)
|
|
216
|
+
yield StreamEvent(
|
|
217
|
+
event_type="content",
|
|
218
|
+
data={"content": "2. 执行相应的操作"}
|
|
219
|
+
)
|
|
220
|
+
yield StreamEvent(
|
|
221
|
+
event_type="content",
|
|
222
|
+
data={"content": "3. 返回结果"}
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
yield StreamEvent(
|
|
226
|
+
event_type="content",
|
|
227
|
+
data={"content": "\n注意:当前运行在模拟模式下。要使用完整功能,请确保正确安装 Auto-Coder 核心组件。"}
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
def _convert_event_to_stream_event(self, event: Any) -> Optional[StreamEvent]:
|
|
231
|
+
"""
|
|
232
|
+
将 run_auto_command 的事件转换为 StreamEvent
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
event: 原始事件
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
StreamEvent: 转换后的事件,如果不需要转换则返回 None
|
|
239
|
+
"""
|
|
240
|
+
try:
|
|
241
|
+
# 获取事件类型名称
|
|
242
|
+
event_class_name = type(event).__name__
|
|
243
|
+
|
|
244
|
+
# 根据事件类型名称进行转换
|
|
245
|
+
if event_class_name == "LLMThinkingEvent":
|
|
246
|
+
return StreamEvent(
|
|
247
|
+
event_type="llm_thinking",
|
|
248
|
+
data={"text": getattr(event, 'text', '')}
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
elif event_class_name == "LLMOutputEvent":
|
|
252
|
+
return StreamEvent(
|
|
253
|
+
event_type="llm_output",
|
|
254
|
+
data={"text": getattr(event, 'text', '')}
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
elif event_class_name == "ToolCallEvent":
|
|
258
|
+
tool_name = "Unknown"
|
|
259
|
+
tool_args = {}
|
|
260
|
+
tool_xml = ""
|
|
261
|
+
|
|
262
|
+
if hasattr(event, 'tool'):
|
|
263
|
+
tool_name = type(event.tool).__name__ if hasattr(
|
|
264
|
+
event.tool, '__class__') else "Unknown"
|
|
265
|
+
if hasattr(event.tool, 'model_dump'):
|
|
266
|
+
try:
|
|
267
|
+
tool_args = event.tool.model_dump()
|
|
268
|
+
except:
|
|
269
|
+
tool_args = {}
|
|
270
|
+
elif hasattr(event.tool, '__dict__'):
|
|
271
|
+
tool_args = event.tool.__dict__
|
|
272
|
+
|
|
273
|
+
if hasattr(event, 'tool_xml'):
|
|
274
|
+
tool_xml = event.tool_xml
|
|
275
|
+
|
|
276
|
+
return StreamEvent(
|
|
277
|
+
event_type="tool_call",
|
|
278
|
+
data={
|
|
279
|
+
"tool_name": tool_name,
|
|
280
|
+
"args": tool_args,
|
|
281
|
+
"tool_xml": tool_xml
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
elif event_class_name == "ToolResultEvent":
|
|
286
|
+
result_data = {
|
|
287
|
+
"tool_name": getattr(event, 'tool_name', 'Unknown'),
|
|
288
|
+
"success": True,
|
|
289
|
+
"message": "",
|
|
290
|
+
"content": None
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if hasattr(event, 'result') and event.result:
|
|
294
|
+
if hasattr(event.result, 'success'):
|
|
295
|
+
result_data["success"] = event.result.success
|
|
296
|
+
if hasattr(event.result, 'message'):
|
|
297
|
+
result_data["message"] = event.result.message
|
|
298
|
+
if hasattr(event.result, 'content'):
|
|
299
|
+
result_data["content"] = event.result.content
|
|
300
|
+
|
|
301
|
+
return StreamEvent(
|
|
302
|
+
event_type="tool_result",
|
|
303
|
+
data=result_data
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
elif event_class_name == "CompletionEvent":
|
|
307
|
+
result = ""
|
|
308
|
+
if hasattr(event, 'completion'):
|
|
309
|
+
if hasattr(event.completion, 'result'):
|
|
310
|
+
result = event.completion.result
|
|
311
|
+
elif hasattr(event.completion, 'response'):
|
|
312
|
+
result = event.completion.response
|
|
313
|
+
|
|
314
|
+
return StreamEvent(
|
|
315
|
+
event_type="completion",
|
|
316
|
+
data={"result": result}
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
elif event_class_name == "ErrorEvent":
|
|
320
|
+
return StreamEvent(
|
|
321
|
+
event_type="error",
|
|
322
|
+
data={"error": getattr(
|
|
323
|
+
event, 'message', 'Unknown error'), "error_type": "AgenticError"}
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
elif event_class_name == "TokenUsageEvent":
|
|
327
|
+
return StreamEvent(
|
|
328
|
+
event_type="token_usage",
|
|
329
|
+
data={"usage": getattr(event, 'usage', {})}
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
elif event_class_name == "WindowLengthChangeEvent":
|
|
333
|
+
return StreamEvent(
|
|
334
|
+
event_type="window_change",
|
|
335
|
+
data={"tokens_used": getattr(event, 'tokens_used', 0)}
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
elif event_class_name == "ConversationIdEvent":
|
|
339
|
+
return StreamEvent(
|
|
340
|
+
event_type="conversation_id",
|
|
341
|
+
data={"conversation_id": getattr(
|
|
342
|
+
event, 'conversation_id', '')}
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
elif event_class_name == "PlanModeRespondEvent":
|
|
346
|
+
result = ""
|
|
347
|
+
if hasattr(event, 'completion'):
|
|
348
|
+
if hasattr(event.completion, 'response'):
|
|
349
|
+
result = event.completion.response
|
|
350
|
+
|
|
351
|
+
return StreamEvent(
|
|
352
|
+
event_type="plan_mode_respond",
|
|
353
|
+
data={"result": result}
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
# 处理简单字符串或其他类型
|
|
357
|
+
elif isinstance(event, str):
|
|
358
|
+
return StreamEvent(
|
|
359
|
+
event_type="content",
|
|
360
|
+
data={"content": event}
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
# 如果有event_type属性,尝试直接使用
|
|
364
|
+
elif hasattr(event, 'event_type'):
|
|
365
|
+
return StreamEvent(
|
|
366
|
+
event_type=event.event_type,
|
|
367
|
+
data=getattr(event, 'data', {}),
|
|
368
|
+
timestamp=getattr(event, 'timestamp', None)
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
# 未知事件类型,包装成内容事件
|
|
372
|
+
else:
|
|
373
|
+
return StreamEvent(
|
|
374
|
+
event_type="content",
|
|
375
|
+
data={"content": str(event)}
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
except Exception as e:
|
|
379
|
+
# 转换失败,返回错误事件
|
|
380
|
+
return StreamEvent(
|
|
381
|
+
event_type="content",
|
|
382
|
+
data={"content": f"[Event Conversion Error: {str(e)}]"}
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
def get_memory(self) -> Dict[str, Any]:
|
|
386
|
+
"""
|
|
387
|
+
获取当前内存状态
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
Dict[str, Any]: 内存数据
|
|
391
|
+
"""
|
|
392
|
+
try:
|
|
393
|
+
original_cwd = os.getcwd()
|
|
394
|
+
os.chdir(self.project_root)
|
|
395
|
+
|
|
396
|
+
try:
|
|
397
|
+
from autocoder.auto_coder_runner import get_memory
|
|
398
|
+
memory_data = get_memory()
|
|
399
|
+
return memory_data
|
|
400
|
+
except ImportError:
|
|
401
|
+
# 模拟内存数据
|
|
402
|
+
return {
|
|
403
|
+
"current_files": {"files": [], "groups": {}},
|
|
404
|
+
"conf": {},
|
|
405
|
+
"exclude_dirs": [],
|
|
406
|
+
"mode": "auto_detect"
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
except Exception as e:
|
|
410
|
+
raise BridgeError(
|
|
411
|
+
f"Failed to get memory: {str(e)}", original_error=e)
|
|
412
|
+
finally:
|
|
413
|
+
os.chdir(original_cwd)
|
|
414
|
+
|
|
415
|
+
def save_memory(self, memory_data: Dict[str, Any]) -> None:
|
|
416
|
+
"""
|
|
417
|
+
保存内存状态
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
memory_data: 要保存的内存数据
|
|
421
|
+
"""
|
|
422
|
+
try:
|
|
423
|
+
original_cwd = os.getcwd()
|
|
424
|
+
os.chdir(self.project_root)
|
|
425
|
+
|
|
426
|
+
try:
|
|
427
|
+
from autocoder.auto_coder_runner import save_memory, memory
|
|
428
|
+
# 更新全局 memory 变量
|
|
429
|
+
memory.update(memory_data)
|
|
430
|
+
save_memory()
|
|
431
|
+
except ImportError:
|
|
432
|
+
# 模拟保存
|
|
433
|
+
pass
|
|
434
|
+
|
|
435
|
+
except Exception as e:
|
|
436
|
+
raise BridgeError(
|
|
437
|
+
f"Failed to save memory: {str(e)}", original_error=e)
|
|
438
|
+
finally:
|
|
439
|
+
os.chdir(original_cwd)
|
|
440
|
+
|
|
441
|
+
def get_project_config(self) -> Dict[str, Any]:
|
|
442
|
+
"""
|
|
443
|
+
获取项目配置
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
Dict[str, Any]: 项目配置
|
|
447
|
+
"""
|
|
448
|
+
try:
|
|
449
|
+
original_cwd = os.getcwd()
|
|
450
|
+
os.chdir(self.project_root)
|
|
451
|
+
|
|
452
|
+
try:
|
|
453
|
+
from autocoder.auto_coder_runner import get_final_config
|
|
454
|
+
config = get_final_config()
|
|
455
|
+
return config.__dict__ if hasattr(config, '__dict__') else {}
|
|
456
|
+
except ImportError:
|
|
457
|
+
# 模拟配置
|
|
458
|
+
return {"mock_config": True}
|
|
459
|
+
|
|
460
|
+
except Exception as e:
|
|
461
|
+
raise BridgeError(
|
|
462
|
+
f"Failed to get project config: {str(e)}", original_error=e)
|
|
463
|
+
finally:
|
|
464
|
+
os.chdir(original_cwd)
|
|
465
|
+
|
|
466
|
+
def setup_project_context(self) -> None:
|
|
467
|
+
"""设置项目上下文"""
|
|
468
|
+
try:
|
|
469
|
+
# 确保项目环境已正确初始化
|
|
470
|
+
self._setup_environment()
|
|
471
|
+
except Exception as e:
|
|
472
|
+
raise BridgeError(
|
|
473
|
+
f"Failed to setup project context: {str(e)}", original_error=e)
|
|
474
|
+
|
|
475
|
+
def cleanup(self) -> None:
|
|
476
|
+
"""清理资源"""
|
|
477
|
+
try:
|
|
478
|
+
original_cwd = os.getcwd()
|
|
479
|
+
os.chdir(self.project_root)
|
|
480
|
+
|
|
481
|
+
try:
|
|
482
|
+
from autocoder.auto_coder_runner import stop
|
|
483
|
+
stop()
|
|
484
|
+
except ImportError:
|
|
485
|
+
pass
|
|
486
|
+
|
|
487
|
+
except Exception as e:
|
|
488
|
+
# 清理失败不应该阻止程序继续运行,只记录错误
|
|
489
|
+
print(f"Warning: Failed to cleanup resources: {str(e)}")
|
|
490
|
+
finally:
|
|
491
|
+
os.chdir(original_cwd)
|
|
492
|
+
|
|
493
|
+
def __enter__(self):
|
|
494
|
+
"""上下文管理器入口"""
|
|
495
|
+
self.setup_project_context()
|
|
496
|
+
return self
|
|
497
|
+
|
|
498
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
499
|
+
"""上下文管理器出口"""
|
|
500
|
+
self.cleanup()
|
autocoder/sdk/example.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
"""
|
|
3
|
+
Auto-Coder SDK 异常定义
|
|
4
|
+
|
|
5
|
+
定义所有自定义异常类,提供错误码和异常的映射关系,统一异常处理策略。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
class AutoCoderSDKError(Exception):
|
|
9
|
+
"""SDK基础异常类"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, message: str, error_code: str = None):
|
|
12
|
+
super().__init__(message)
|
|
13
|
+
self.message = message
|
|
14
|
+
self.error_code = error_code or "SDK_ERROR"
|
|
15
|
+
|
|
16
|
+
def __str__(self):
|
|
17
|
+
return f"[{self.error_code}] {self.message}"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SessionNotFoundError(AutoCoderSDKError):
|
|
21
|
+
"""会话未找到异常"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, session_id: str):
|
|
24
|
+
super().__init__(
|
|
25
|
+
f"Session '{session_id}' not found",
|
|
26
|
+
error_code="SESSION_NOT_FOUND"
|
|
27
|
+
)
|
|
28
|
+
self.session_id = session_id
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class InvalidOptionsError(AutoCoderSDKError):
|
|
32
|
+
"""无效选项异常"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, message: str):
|
|
35
|
+
super().__init__(
|
|
36
|
+
f"Invalid options: {message}",
|
|
37
|
+
error_code="INVALID_OPTIONS"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class BridgeError(AutoCoderSDKError):
|
|
42
|
+
"""桥接层异常"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, message: str, original_error: Exception = None):
|
|
45
|
+
super().__init__(
|
|
46
|
+
f"Bridge error: {message}",
|
|
47
|
+
error_code="BRIDGE_ERROR"
|
|
48
|
+
)
|
|
49
|
+
self.original_error = original_error
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class CLIError(AutoCoderSDKError):
|
|
53
|
+
"""CLI异常"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, message: str, exit_code: int = 1):
|
|
56
|
+
super().__init__(
|
|
57
|
+
f"CLI error: {message}",
|
|
58
|
+
error_code="CLI_ERROR"
|
|
59
|
+
)
|
|
60
|
+
self.exit_code = exit_code
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ValidationError(AutoCoderSDKError):
|
|
64
|
+
"""验证错误异常"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, field: str, message: str):
|
|
67
|
+
super().__init__(
|
|
68
|
+
f"Validation error for '{field}': {message}",
|
|
69
|
+
error_code="VALIDATION_ERROR"
|
|
70
|
+
)
|
|
71
|
+
self.field = field
|
|
72
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Auto-Coder SDK 数据模型
|
|
5
|
+
|
|
6
|
+
包含所有数据结构定义,提供类型安全的接口。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .options import AutoCodeOptions
|
|
10
|
+
from .messages import Message
|
|
11
|
+
from .responses import CLIResult, SessionInfo
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"AutoCodeOptions",
|
|
15
|
+
"Message",
|
|
16
|
+
"CLIResult",
|
|
17
|
+
"SessionInfo"
|
|
18
|
+
]
|
|
19
|
+
|