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.

Files changed (86) hide show
  1. auto_coder-0.1.400.dist-info/METADATA +396 -0
  2. {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/RECORD +82 -29
  3. {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/WHEEL +1 -1
  4. {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/entry_points.txt +2 -0
  5. autocoder/agent/base_agentic/base_agent.py +2 -2
  6. autocoder/agent/base_agentic/tools/replace_in_file_tool_resolver.py +1 -1
  7. autocoder/agent/entry_command_agent/__init__.py +29 -0
  8. autocoder/agent/entry_command_agent/auto_tool.py +61 -0
  9. autocoder/agent/entry_command_agent/chat.py +475 -0
  10. autocoder/agent/entry_command_agent/designer.py +53 -0
  11. autocoder/agent/entry_command_agent/generate_command.py +50 -0
  12. autocoder/agent/entry_command_agent/project_reader.py +58 -0
  13. autocoder/agent/entry_command_agent/voice2text.py +71 -0
  14. autocoder/auto_coder.py +23 -548
  15. autocoder/auto_coder_runner.py +511 -8
  16. autocoder/chat/rules_command.py +1 -1
  17. autocoder/chat_auto_coder.py +6 -1
  18. autocoder/common/ac_style_command_parser/__init__.py +15 -0
  19. autocoder/common/ac_style_command_parser/example.py +7 -0
  20. autocoder/{command_parser.py → common/ac_style_command_parser/parser.py} +28 -45
  21. autocoder/common/ac_style_command_parser/test_parser.py +516 -0
  22. autocoder/common/auto_coder_lang.py +78 -0
  23. autocoder/common/command_completer_v2.py +1 -1
  24. autocoder/common/command_file_manager/examples.py +22 -8
  25. autocoder/common/command_file_manager/manager.py +37 -6
  26. autocoder/common/conversations/get_conversation_manager.py +143 -0
  27. autocoder/common/conversations/manager.py +122 -11
  28. autocoder/common/conversations/storage/index_manager.py +89 -0
  29. autocoder/common/pull_requests/__init__.py +256 -0
  30. autocoder/common/pull_requests/base_provider.py +191 -0
  31. autocoder/common/pull_requests/config.py +66 -0
  32. autocoder/common/pull_requests/example.py +1 -0
  33. autocoder/common/pull_requests/exceptions.py +46 -0
  34. autocoder/common/pull_requests/manager.py +201 -0
  35. autocoder/common/pull_requests/models.py +164 -0
  36. autocoder/common/pull_requests/providers/__init__.py +23 -0
  37. autocoder/common/pull_requests/providers/gitcode_provider.py +19 -0
  38. autocoder/common/pull_requests/providers/gitee_provider.py +20 -0
  39. autocoder/common/pull_requests/providers/github_provider.py +214 -0
  40. autocoder/common/pull_requests/providers/gitlab_provider.py +29 -0
  41. autocoder/common/pull_requests/test_module.py +1 -0
  42. autocoder/common/pull_requests/utils.py +344 -0
  43. autocoder/common/tokens/__init__.py +62 -0
  44. autocoder/common/tokens/counter.py +211 -0
  45. autocoder/common/tokens/file_detector.py +105 -0
  46. autocoder/common/tokens/filters.py +111 -0
  47. autocoder/common/tokens/models.py +28 -0
  48. autocoder/common/v2/agent/agentic_edit.py +312 -85
  49. autocoder/common/v2/agent/agentic_edit_types.py +11 -0
  50. autocoder/common/v2/code_auto_generate_editblock.py +10 -2
  51. autocoder/dispacher/__init__.py +10 -0
  52. autocoder/rags.py +0 -27
  53. autocoder/run_context.py +1 -0
  54. autocoder/sdk/__init__.py +188 -0
  55. autocoder/sdk/cli/__init__.py +15 -0
  56. autocoder/sdk/cli/__main__.py +26 -0
  57. autocoder/sdk/cli/completion_wrapper.py +38 -0
  58. autocoder/sdk/cli/formatters.py +211 -0
  59. autocoder/sdk/cli/handlers.py +175 -0
  60. autocoder/sdk/cli/install_completion.py +301 -0
  61. autocoder/sdk/cli/main.py +286 -0
  62. autocoder/sdk/cli/options.py +73 -0
  63. autocoder/sdk/constants.py +102 -0
  64. autocoder/sdk/core/__init__.py +20 -0
  65. autocoder/sdk/core/auto_coder_core.py +880 -0
  66. autocoder/sdk/core/bridge.py +500 -0
  67. autocoder/sdk/example.py +0 -0
  68. autocoder/sdk/exceptions.py +72 -0
  69. autocoder/sdk/models/__init__.py +19 -0
  70. autocoder/sdk/models/messages.py +209 -0
  71. autocoder/sdk/models/options.py +196 -0
  72. autocoder/sdk/models/responses.py +311 -0
  73. autocoder/sdk/session/__init__.py +32 -0
  74. autocoder/sdk/session/session.py +106 -0
  75. autocoder/sdk/session/session_manager.py +56 -0
  76. autocoder/sdk/utils/__init__.py +24 -0
  77. autocoder/sdk/utils/formatters.py +216 -0
  78. autocoder/sdk/utils/io_utils.py +302 -0
  79. autocoder/sdk/utils/validators.py +287 -0
  80. autocoder/version.py +2 -1
  81. auto_coder-0.1.398.dist-info/METADATA +0 -111
  82. autocoder/common/conversations/compatibility.py +0 -303
  83. autocoder/common/conversations/conversation_manager.py +0 -502
  84. autocoder/common/conversations/example.py +0 -152
  85. {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info/licenses}/LICENSE +0 -0
  86. {auto_coder-0.1.398.dist-info → auto_coder-0.1.400.dist-info}/top_level.txt +0 -0
autocoder/rags.py CHANGED
@@ -369,30 +369,3 @@ def update_rag_status(name: str, status: str, **kwargs) -> bool:
369
369
  return rag_manager.update_status(name, status, **kwargs)
370
370
 
371
371
 
372
- # 使用示例
373
- if __name__ == "__main__":
374
- # 创建配置
375
- config = {
376
- "model": "deepseek_chat",
377
- "tokenizer_path": "/Users/allwefantasy/Downloads/tokenizer.json",
378
- "doc_dir": "/path/to/docs",
379
- "rag_doc_filter_relevance": 2.0,
380
- "host": "0.0.0.0",
381
- "port": 8000,
382
- "enable_hybrid_index": False,
383
- "required_exts": ".md,.rst",
384
- "disable_inference_enhance": True
385
- }
386
-
387
- # 创建
388
- create_rag_config("test_rag", config)
389
-
390
- # 读取
391
- all_configs = get_rag_config()
392
- specific_config = get_rag_config("test_rag")
393
-
394
- # 更新
395
- update_rag_config("test_rag", {"status": "running", "port": 8001})
396
-
397
- # 删除
398
- delete_rag_config("test_rag")
autocoder/run_context.py CHANGED
@@ -9,6 +9,7 @@ class RunMode(Enum):
9
9
  """Enum representing different run modes for Auto-Coder."""
10
10
  TERMINAL = auto()
11
11
  WEB = auto()
12
+ API = auto()
12
13
 
13
14
 
14
15
  class RunContext:
@@ -0,0 +1,188 @@
1
+ """
2
+ Auto-Coder SDK
3
+
4
+ 为第三方开发者提供的 Python SDK,允许通过命令行工具和 Python API 两种方式使用 Auto-Coder 的核心功能。
5
+ """
6
+
7
+ from typing import AsyncIterator, Optional, Dict, Any
8
+
9
+ from .core.auto_coder_core import AutoCoderCore
10
+ from .models.options import AutoCodeOptions
11
+ from .models.messages import Message
12
+ from .models.responses import StreamEvent, CodeModificationResult
13
+ from .session.session import Session
14
+ from .session.session_manager import SessionManager
15
+ from .exceptions import (
16
+ AutoCoderSDKError,
17
+ SessionNotFoundError,
18
+ InvalidOptionsError,
19
+ BridgeError,
20
+ ValidationError
21
+ )
22
+
23
+ __version__ = "1.0.0"
24
+ __all__ = [
25
+ # 核心功能
26
+ "query",
27
+ "query_sync",
28
+ "modify_code",
29
+ "modify_code_stream",
30
+
31
+ # 数据模型
32
+ "AutoCodeOptions",
33
+ "Message",
34
+ "StreamEvent",
35
+ "CodeModificationResult",
36
+
37
+ # 会话管理
38
+ "Session",
39
+ "SessionManager",
40
+
41
+ # 异常
42
+ "AutoCoderSDKError",
43
+ "SessionNotFoundError",
44
+ "InvalidOptionsError",
45
+ "BridgeError",
46
+ "ValidationError",
47
+ ]
48
+
49
+
50
+ async def query(
51
+ prompt: str,
52
+ options: Optional[AutoCodeOptions] = None,
53
+ show_terminal: bool = True
54
+ ) -> AsyncIterator[Message]:
55
+ """
56
+ 异步流式查询接口
57
+
58
+ Args:
59
+ prompt: 查询提示
60
+ options: 配置选项
61
+ show_terminal: 是否在终端显示友好的渲染输出
62
+
63
+ Yields:
64
+ Message: 响应消息流
65
+
66
+ Example:
67
+ >>> import asyncio
68
+ >>> from autocoder.sdk import query, AutoCodeOptions
69
+ >>>
70
+ >>> async def main():
71
+ ... options = AutoCodeOptions(max_turns=3)
72
+ ... async for message in query("Write a hello world function", options):
73
+ ... print(f"[{message.role}] {message.content}")
74
+ >>>
75
+ >>> asyncio.run(main())
76
+ """
77
+ if options is None:
78
+ options = AutoCodeOptions()
79
+ core = AutoCoderCore(options)
80
+ async for message in core.query_stream(f"/new {prompt}", show_terminal):
81
+ yield message
82
+
83
+
84
+ def query_sync(
85
+ prompt: str,
86
+ options: Optional[AutoCodeOptions] = None,
87
+ show_terminal: bool = True
88
+ ) -> str:
89
+ """
90
+ 同步查询接口
91
+
92
+ Args:
93
+ prompt: 查询提示
94
+ options: 配置选项
95
+ show_terminal: 是否在终端显示友好的渲染输出
96
+
97
+ Returns:
98
+ str: 响应内容
99
+
100
+ Example:
101
+ >>> from autocoder.sdk import query_sync, AutoCodeOptions
102
+ >>>
103
+ >>> options = AutoCodeOptions(max_turns=1)
104
+ >>> response = query_sync("Write a simple calculator function", options)
105
+ >>> print(response)
106
+ """
107
+ if options is None:
108
+ options = AutoCodeOptions()
109
+ core = AutoCoderCore(options)
110
+ return core.query_sync(f"/new {prompt}", show_terminal)
111
+
112
+
113
+ def modify_code(
114
+ prompt: str,
115
+ pre_commit: bool = False,
116
+ extra_args: Optional[Dict[str, Any]] = None,
117
+ options: Optional[AutoCodeOptions] = None,
118
+ show_terminal: bool = True
119
+ ) -> CodeModificationResult:
120
+ """
121
+ 代码修改接口
122
+
123
+ Args:
124
+ prompt: 修改提示
125
+ pre_commit: 是否预提交
126
+ extra_args: 额外参数
127
+ options: 配置选项
128
+ show_terminal: 是否在终端显示友好的渲染输出
129
+
130
+ Returns:
131
+ CodeModificationResult: 修改结果
132
+
133
+ Example:
134
+ >>> from autocoder.sdk import modify_code, AutoCodeOptions
135
+ >>>
136
+ >>> options = AutoCodeOptions(cwd="/path/to/project")
137
+ >>> result = modify_code(
138
+ ... "Add error handling to the main function",
139
+ ... pre_commit=False,
140
+ ... options=options
141
+ ... )
142
+ >>>
143
+ >>> if result.success:
144
+ ... print(f"Modified files: {result.modified_files}")
145
+ ... else:
146
+ ... print(f"Error: {result.error_details}")
147
+ """
148
+ core = AutoCoderCore(options or AutoCodeOptions())
149
+ return core.modify_code(prompt, pre_commit, extra_args, show_terminal)
150
+
151
+
152
+ async def modify_code_stream(
153
+ prompt: str,
154
+ pre_commit: bool = False,
155
+ extra_args: Optional[Dict[str, Any]] = None,
156
+ options: Optional[AutoCodeOptions] = None,
157
+ show_terminal: bool = True
158
+ ) -> AsyncIterator[StreamEvent]:
159
+ """
160
+ 异步流式代码修改接口
161
+
162
+ Args:
163
+ prompt: 修改提示
164
+ pre_commit: 是否预提交
165
+ extra_args: 额外参数
166
+ options: 配置选项
167
+ show_terminal: 是否在终端显示友好的渲染输出
168
+
169
+ Yields:
170
+ StreamEvent: 修改事件流
171
+
172
+ Example:
173
+ >>> import asyncio
174
+ >>> from autocoder.sdk import modify_code_stream, AutoCodeOptions
175
+ >>>
176
+ >>> async def main():
177
+ ... options = AutoCodeOptions(cwd="/path/to/project")
178
+ ... async for event in modify_code_stream(
179
+ ... "Refactor the user authentication module",
180
+ ... options=options
181
+ ... ):
182
+ ... print(f"[{event.event_type}] {event.data}")
183
+ >>>
184
+ >>> asyncio.run(main())
185
+ """
186
+ core = AutoCoderCore(options or AutoCodeOptions())
187
+ async for event in core.modify_code_stream(prompt, pre_commit, extra_args, show_terminal):
188
+ yield event
@@ -0,0 +1,15 @@
1
+ """
2
+ Auto-Coder CLI 模块
3
+
4
+ 提供命令行接口,允许用户通过终端使用 Auto-Coder 的核心功能。
5
+ """
6
+
7
+ from .main import AutoCoderCLI
8
+ from .options import CLIOptions, CLIResult
9
+
10
+ # 导出main函数作为入口点
11
+ def main():
12
+ """CLI主入口点函数"""
13
+ return AutoCoderCLI.main()
14
+
15
+ __all__ = ["AutoCoderCLI", "CLIOptions", "CLIResult", "main"]
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CLI 模块主入口点
4
+ """
5
+
6
+ import sys
7
+ import argparse
8
+ from pathlib import Path
9
+
10
+ def main():
11
+ """主入口点,路由到不同的 CLI 功能"""
12
+
13
+ # 检查是否是自动补全相关的命令
14
+ if len(sys.argv) > 1 and sys.argv[1] in ["install", "uninstall", "test"]:
15
+ # 路由到自动补全安装工具
16
+ from .install_completion import main as install_main
17
+ install_main()
18
+ return
19
+
20
+ # 默认显示自动补全工具的帮助
21
+ from .install_completion import main as install_main
22
+ install_main()
23
+
24
+ if __name__ == "__main__":
25
+ main()
26
+
@@ -0,0 +1,38 @@
1
+
2
+
3
+ #!/usr/bin/env python3
4
+ """
5
+ Auto-Coder CLI 自动补全包装器
6
+
7
+ 提供一个独立的补全脚本,不依赖于特定的 shell 环境
8
+ """
9
+
10
+ import sys
11
+ import os
12
+
13
+ def main():
14
+ """主函数,处理自动补全请求"""
15
+ try:
16
+ # 设置环境变量以启用 argcomplete
17
+ os.environ.setdefault('_ARGCOMPLETE_COMPLETE', 'complete')
18
+
19
+ # 导入并运行 CLI
20
+ from autocoder.sdk.cli.main import AutoCoderCLI
21
+
22
+ # 模拟 auto-coder.run 命令
23
+ sys.argv[0] = 'auto-coder.run'
24
+
25
+ # 解析参数(这会触发自动补全)
26
+ AutoCoderCLI.parse_args()
27
+
28
+ except SystemExit:
29
+ # argcomplete 会调用 sys.exit,这是正常的
30
+ pass
31
+ except Exception as e:
32
+ # 在补全过程中出现错误,静默处理
33
+ pass
34
+
35
+ if __name__ == '__main__':
36
+ main()
37
+
38
+
@@ -0,0 +1,211 @@
1
+ """
2
+ 输出格式化器模块
3
+
4
+ 提供不同格式的输出处理,支持文本、JSON和流式JSON格式。
5
+ """
6
+
7
+ import json
8
+ import asyncio
9
+ from typing import Any, Dict, AsyncIterator, Union, Optional
10
+
11
+
12
+ class OutputFormatter:
13
+ """输出格式化器,处理不同格式的输出。"""
14
+
15
+ def __init__(self, verbose: bool = False):
16
+ """
17
+ 初始化输出格式化器。
18
+
19
+ Args:
20
+ verbose: 是否输出详细信息
21
+ """
22
+ self.verbose = verbose
23
+
24
+ def format_text(self, content: Union[str, Dict[str, Any]]) -> str:
25
+ """
26
+ 格式化为文本输出。
27
+
28
+ Args:
29
+ content: 要格式化的内容,可以是字符串或字典
30
+
31
+ Returns:
32
+ 格式化后的文本
33
+ """
34
+ if isinstance(content, dict):
35
+ # 如果是字典,提取主要内容
36
+ if "content" in content:
37
+ result = content["content"]
38
+ else:
39
+ result = str(content)
40
+ else:
41
+ result = str(content)
42
+
43
+ if self.verbose:
44
+ # 在详细模式下添加调试信息
45
+ debug_info = self._get_debug_info(content)
46
+ if debug_info:
47
+ result += f"\n\n[DEBUG]\n{debug_info}"
48
+
49
+ return result
50
+
51
+ def format_json(self, content: Any) -> str:
52
+ """
53
+ 格式化为JSON输出。
54
+
55
+ Args:
56
+ content: 要格式化的内容
57
+
58
+ Returns:
59
+ JSON格式的字符串
60
+ """
61
+ # 确保内容可以被序列化为JSON
62
+ if isinstance(content, str):
63
+ try:
64
+ # 尝试解析为JSON
65
+ parsed = json.loads(content)
66
+ content = parsed
67
+ except json.JSONDecodeError:
68
+ # 如果不是有效的JSON,则包装为字典
69
+ content = {"content": content}
70
+
71
+ # 添加调试信息(如果启用详细模式)
72
+ if self.verbose and isinstance(content, dict):
73
+ content["debug"] = self._get_debug_info_dict(content)
74
+
75
+ return json.dumps(content, ensure_ascii=False, indent=2)
76
+
77
+ async def format_stream_json(self, stream: AsyncIterator[Any]) -> AsyncIterator[str]:
78
+ """
79
+ 格式化为流式JSON输出。
80
+
81
+ Args:
82
+ stream: 异步迭代器,提供流式内容
83
+
84
+ Yields:
85
+ JSON格式的字符串,每行一个JSON对象
86
+ """
87
+ async for item in stream:
88
+ # 处理不同类型的项
89
+ if isinstance(item, dict):
90
+ output = item
91
+ elif isinstance(item, str):
92
+ try:
93
+ output = json.loads(item)
94
+ except json.JSONDecodeError:
95
+ output = {"content": item, "type": "text"}
96
+ else:
97
+ output = {"content": str(item), "type": "text"}
98
+
99
+ # 添加调试信息(如果启用详细模式)
100
+ if self.verbose:
101
+ output["debug"] = self._get_debug_info_dict(output)
102
+
103
+ yield json.dumps(output, ensure_ascii=False)
104
+
105
+ def _get_debug_info(self, content: Any) -> str:
106
+ """
107
+ 获取调试信息的文本表示。
108
+
109
+ Args:
110
+ content: 内容对象
111
+
112
+ Returns:
113
+ 调试信息文本
114
+ """
115
+ debug_dict = self._get_debug_info_dict(content)
116
+ if debug_dict:
117
+ return json.dumps(debug_dict, ensure_ascii=False, indent=2)
118
+ return ""
119
+
120
+ def _get_debug_info_dict(self, content: Any) -> Dict[str, Any]:
121
+ """
122
+ 获取调试信息的字典表示。
123
+
124
+ Args:
125
+ content: 内容对象
126
+
127
+ Returns:
128
+ 调试信息字典
129
+ """
130
+ debug_info = {}
131
+
132
+ # 从内容中提取元数据
133
+ if isinstance(content, dict):
134
+ if "metadata" in content:
135
+ debug_info["metadata"] = content["metadata"]
136
+
137
+ # 提取令牌计数信息
138
+ if "tokens" in content:
139
+ debug_info["tokens"] = content["tokens"]
140
+ elif "metadata" in content and "tokens" in content["metadata"]:
141
+ debug_info["tokens"] = content["metadata"]["tokens"]
142
+
143
+ # 提取模型信息
144
+ if "model" in content:
145
+ debug_info["model"] = content["model"]
146
+ elif "metadata" in content and "model" in content["metadata"]:
147
+ debug_info["model"] = content["metadata"]["model"]
148
+
149
+ # 提取时间信息
150
+ if "timestamp" in content:
151
+ debug_info["timestamp"] = content["timestamp"]
152
+ elif "metadata" in content and "timestamp" in content["metadata"]:
153
+ debug_info["timestamp"] = content["metadata"]["timestamp"]
154
+
155
+ return debug_info
156
+
157
+
158
+ class InputFormatter:
159
+ """输入格式化器,处理不同格式的输入。"""
160
+
161
+ def format_text(self, content: str) -> str:
162
+ """
163
+ 格式化文本输入。
164
+
165
+ Args:
166
+ content: 输入文本
167
+
168
+ Returns:
169
+ 格式化后的文本
170
+ """
171
+ return content.strip()
172
+
173
+ def format_json(self, content: str) -> Dict[str, Any]:
174
+ """
175
+ 格式化JSON输入。
176
+
177
+ Args:
178
+ content: JSON格式的输入字符串
179
+
180
+ Returns:
181
+ 解析后的字典
182
+
183
+ Raises:
184
+ ValueError: 如果输入不是有效的JSON
185
+ """
186
+ try:
187
+ return json.loads(content)
188
+ except json.JSONDecodeError as e:
189
+ raise ValueError(f"无效的JSON输入: {str(e)}")
190
+
191
+ async def format_stream_json(self, content: str) -> AsyncIterator[Dict[str, Any]]:
192
+ """
193
+ 格式化流式JSON输入。
194
+
195
+ Args:
196
+ content: 包含多行JSON对象的字符串
197
+
198
+ Yields:
199
+ 解析后的字典
200
+
201
+ Raises:
202
+ ValueError: 如果某行不是有效的JSON
203
+ """
204
+ for line in content.strip().split("\n"):
205
+ if not line.strip():
206
+ continue
207
+
208
+ try:
209
+ yield json.loads(line)
210
+ except json.JSONDecodeError as e:
211
+ raise ValueError(f"无效的JSON行: {line}, 错误: {str(e)}")
@@ -0,0 +1,175 @@
1
+ """
2
+ 命令处理器模块
3
+
4
+ 提供统一的命令处理器,支持单次运行和会话复用功能。
5
+ """
6
+
7
+ import sys
8
+ import asyncio
9
+ from pathlib import Path
10
+ from typing import Optional, Dict, Any, List, Union
11
+
12
+ from ..core import AutoCoderCore
13
+ from ..models import AutoCodeOptions, Message
14
+ from ..exceptions import AutoCoderSDKError
15
+ from .options import CLIOptions, CLIResult
16
+ from .formatters import OutputFormatter, InputFormatter
17
+
18
+
19
+ class CommandHandler:
20
+ """命令处理器基类,提供通用功能。"""
21
+
22
+ def __init__(self, options: CLIOptions, cwd: Optional[str] = None):
23
+ """
24
+ 初始化命令处理器。
25
+
26
+ Args:
27
+ options: CLI选项
28
+ cwd: 当前工作目录,如果为None则使用系统当前目录
29
+ """
30
+ self.options = options
31
+ self.cwd = Path(cwd) if cwd else Path.cwd()
32
+ self.output_formatter = OutputFormatter(verbose=options.verbose)
33
+ self.input_formatter = InputFormatter()
34
+
35
+ def _create_core_options(self) -> AutoCodeOptions:
36
+ """
37
+ 创建核心选项。
38
+
39
+ Returns:
40
+ AutoCodeOptions实例
41
+ """
42
+ return AutoCodeOptions(
43
+ max_turns=self.options.max_turns,
44
+ system_prompt=self.options.system_prompt,
45
+ cwd=str(self.cwd),
46
+ allowed_tools=self.options.allowed_tools,
47
+ permission_mode=self.options.permission_mode,
48
+ output_format=self.options.output_format,
49
+ stream=self.options.output_format.startswith("stream"),
50
+ session_id=self.options.resume_session,
51
+ continue_session=self.options.continue_session,
52
+ model=self.options.model,
53
+ pr=self.options.pr
54
+ )
55
+
56
+ def _get_prompt(self) -> str:
57
+ """
58
+ 获取提示内容,如果未提供则从stdin读取。
59
+
60
+ Returns:
61
+ 提示内容
62
+
63
+ Raises:
64
+ ValueError: 如果未提供提示且stdin为空
65
+ """
66
+ if self.options.prompt:
67
+ return self.options.prompt
68
+
69
+ # 从stdin读取
70
+ if not sys.stdin.isatty():
71
+ content = sys.stdin.read()
72
+ if not content.strip():
73
+ raise ValueError("未提供提示内容且标准输入为空")
74
+
75
+ # 根据输入格式处理
76
+ if self.options.input_format == "text":
77
+ return self.input_formatter.format_text(content)
78
+ elif self.options.input_format == "json":
79
+ result = self.input_formatter.format_json(content)
80
+ # 尝试提取提示内容
81
+ if isinstance(result, dict):
82
+ if "prompt" in result:
83
+ return result["prompt"]
84
+ elif "message" in result:
85
+ message = result["message"]
86
+ if isinstance(message, dict) and "content" in message:
87
+ return message["content"]
88
+ elif isinstance(message, str):
89
+ return message
90
+ return content # 如果无法提取,则返回原始内容
91
+ else:
92
+ # 对于流式输入,暂时只支持直接传递
93
+ return content
94
+ else:
95
+ raise ValueError("未提供提示内容且没有标准输入")
96
+
97
+
98
+ class PrintModeHandler(CommandHandler):
99
+ """统一的命令处理器,支持单次运行和会话复用。"""
100
+
101
+ def handle(self) -> CLIResult:
102
+ """
103
+ 处理命令,支持会话复用。
104
+
105
+ Returns:
106
+ 命令执行结果
107
+ """
108
+ try:
109
+ prompt = self._get_prompt()
110
+ core_options = self._create_core_options()
111
+ core = AutoCoderCore(core_options)
112
+
113
+ # 根据会话参数构建完整的 prompt
114
+ final_prompt = self._build_prompt_with_session_context(prompt)
115
+
116
+ # 根据输出格式选择不同的处理方式
117
+ if self.options.output_format == "stream-json":
118
+ # 流式JSON输出
119
+ result = asyncio.run(self._handle_stream(core, final_prompt))
120
+ else:
121
+ # 同步查询
122
+ response = core.query_sync(final_prompt)
123
+
124
+ # 格式化输出
125
+ if self.options.output_format == "json":
126
+ result = self.output_formatter.format_json(response)
127
+ else:
128
+ result = self.output_formatter.format_text(response)
129
+
130
+ return CLIResult(success=True, output=result)
131
+
132
+ except Exception as e:
133
+ return CLIResult(success=False, error=str(e))
134
+
135
+ def _build_prompt_with_session_context(self, prompt: str) -> str:
136
+ """
137
+ 根据会话参数构建完整的 prompt。
138
+
139
+ Args:
140
+ prompt: 原始提示内容
141
+
142
+ Returns:
143
+ str: 构建后的完整提示
144
+ """
145
+ if self.options.continue_session:
146
+ # 继续当前对话
147
+ return f"{prompt}" if prompt else ""
148
+ elif self.options.resume_session:
149
+ # 恢复特定会话
150
+ return f"/resume {self.options.resume_session} {prompt}" if prompt else f"/resume {self.options.resume_session}"
151
+ else:
152
+ # 创建新对话
153
+ return f"/new {prompt}"
154
+
155
+ async def _handle_stream(self, core: AutoCoderCore, prompt: str) -> str:
156
+ """
157
+ 处理流式输出。
158
+
159
+ Args:
160
+ core: AutoCoderCore实例
161
+ prompt: 提示内容
162
+
163
+ Returns:
164
+ 处理结果
165
+ """
166
+ result = []
167
+ async for message in core.query_stream(prompt):
168
+ formatted = await anext(self.output_formatter.format_stream_json([message]))
169
+ result.append(formatted)
170
+ # 实时输出到stdout
171
+ print(formatted, flush=True)
172
+
173
+ return "\n".join(result)
174
+
175
+