auto-coder 0.1.375__py3-none-any.whl → 0.1.377__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 (52) hide show
  1. {auto_coder-0.1.375.dist-info → auto_coder-0.1.377.dist-info}/METADATA +1 -1
  2. {auto_coder-0.1.375.dist-info → auto_coder-0.1.377.dist-info}/RECORD +18 -52
  3. autocoder/agent/base_agentic/base_agent.py +9 -8
  4. autocoder/auto_coder_rag.py +12 -0
  5. autocoder/models.py +2 -2
  6. autocoder/rag/agentic_rag.py +7 -20
  7. autocoder/rag/cache/local_duckdb_storage_cache.py +63 -33
  8. autocoder/rag/conversation_to_queries.py +37 -5
  9. autocoder/rag/long_context_rag.py +161 -41
  10. autocoder/rag/tools/recall_tool.py +2 -1
  11. autocoder/rag/tools/search_tool.py +2 -1
  12. autocoder/rag/types.py +36 -0
  13. autocoder/utils/_markitdown.py +59 -13
  14. autocoder/version.py +1 -1
  15. autocoder/agent/agentic_edit.py +0 -833
  16. autocoder/agent/agentic_edit_tools/__init__.py +0 -28
  17. autocoder/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +0 -32
  18. autocoder/agent/agentic_edit_tools/attempt_completion_tool_resolver.py +0 -29
  19. autocoder/agent/agentic_edit_tools/base_tool_resolver.py +0 -29
  20. autocoder/agent/agentic_edit_tools/execute_command_tool_resolver.py +0 -84
  21. autocoder/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py +0 -75
  22. autocoder/agent/agentic_edit_tools/list_files_tool_resolver.py +0 -62
  23. autocoder/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py +0 -30
  24. autocoder/agent/agentic_edit_tools/read_file_tool_resolver.py +0 -36
  25. autocoder/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +0 -95
  26. autocoder/agent/agentic_edit_tools/search_files_tool_resolver.py +0 -70
  27. autocoder/agent/agentic_edit_tools/use_mcp_tool_resolver.py +0 -55
  28. autocoder/agent/agentic_edit_tools/write_to_file_tool_resolver.py +0 -98
  29. autocoder/agent/agentic_edit_types.py +0 -124
  30. autocoder/auto_coder_lang.py +0 -60
  31. autocoder/auto_coder_rag_client_mcp.py +0 -170
  32. autocoder/auto_coder_rag_mcp.py +0 -193
  33. autocoder/common/llm_rerank.py +0 -84
  34. autocoder/common/model_speed_test.py +0 -392
  35. autocoder/common/v2/agent/agentic_edit_conversation.py +0 -188
  36. autocoder/common/v2/agent/ignore_utils.py +0 -50
  37. autocoder/dispacher/actions/plugins/action_translate.py +0 -214
  38. autocoder/ignorefiles/__init__.py +0 -4
  39. autocoder/ignorefiles/ignore_file_utils.py +0 -63
  40. autocoder/ignorefiles/test_ignore_file_utils.py +0 -91
  41. autocoder/linters/code_linter.py +0 -588
  42. autocoder/rag/loaders/test_image_loader.py +0 -209
  43. autocoder/rag/raw_rag.py +0 -96
  44. autocoder/rag/simple_directory_reader.py +0 -646
  45. autocoder/rag/simple_rag.py +0 -404
  46. autocoder/regex_project/__init__.py +0 -162
  47. autocoder/utils/coder.py +0 -125
  48. autocoder/utils/tests.py +0 -37
  49. {auto_coder-0.1.375.dist-info → auto_coder-0.1.377.dist-info}/LICENSE +0 -0
  50. {auto_coder-0.1.375.dist-info → auto_coder-0.1.377.dist-info}/WHEEL +0 -0
  51. {auto_coder-0.1.375.dist-info → auto_coder-0.1.377.dist-info}/entry_points.txt +0 -0
  52. {auto_coder-0.1.375.dist-info → auto_coder-0.1.377.dist-info}/top_level.txt +0 -0
@@ -1,98 +0,0 @@
1
- import os
2
- import re
3
- from typing import Dict, Any, Optional, List, Tuple
4
- from .base_tool_resolver import BaseToolResolver
5
- from autocoder.agent.agentic_edit_types import WriteToFileTool, ToolResult # Import ToolResult from types
6
- from loguru import logger
7
-
8
-
9
- class WriteToFileToolResolver(BaseToolResolver):
10
- def __init__(self, agent: Optional[Any], tool: WriteToFileTool, args: Dict[str, Any]):
11
- super().__init__(agent, tool, args)
12
- self.tool: WriteToFileTool = tool # For type hinting
13
-
14
- def parse_diff(self, diff_content: str) -> List[Tuple[str, str]]:
15
- """
16
- Parses the diff content into a list of (search_block, replace_block) tuples.
17
- """
18
- blocks = []
19
- # Regex to find SEARCH/REPLACE blocks, handling potential variations in line endings
20
- pattern = re.compile(r"<<<<<<< SEARCH\r?\n(.*?)\r?\n=======\r?\n(.*?)\r?\n>>>>>>> REPLACE", re.DOTALL)
21
- matches = pattern.findall(diff_content)
22
- for search_block, replace_block in matches:
23
- blocks.append((search_block, replace_block))
24
- if not matches and diff_content.strip():
25
- logger.warning(f"Could not parse any SEARCH/REPLACE blocks from diff: {diff_content}")
26
- return blocks
27
-
28
- def resolve(self) -> ToolResult:
29
- file_path = self.tool.path
30
- content = self.tool.content
31
- source_dir = self.args.source_dir or "."
32
- absolute_path = os.path.abspath(os.path.join(source_dir, file_path))
33
-
34
- # Security check: ensure the path is within the source directory
35
- if not absolute_path.startswith(os.path.abspath(source_dir)):
36
- return ToolResult(success=False, message=f"Error: Access denied. Attempted to write file outside the project directory: {file_path}")
37
-
38
- try:
39
- # Create directories if they don't exist
40
- os.makedirs(os.path.dirname(absolute_path), exist_ok=True)
41
-
42
- # Check if the content contains SEARCH/REPLACE blocks
43
- parsed_blocks = self.parse_diff(content)
44
- if parsed_blocks:
45
- # If file exists, read its current content
46
- if os.path.exists(absolute_path):
47
- try:
48
- with open(absolute_path, 'r', encoding='utf-8', errors='replace') as f:
49
- original_content = f.read()
50
- except Exception as e:
51
- logger.error(f"Error reading existing file '{file_path}' for diff apply: {str(e)}")
52
- return ToolResult(success=False, message=f"An error occurred while reading the existing file: {str(e)}")
53
- else:
54
- # If file does not exist, start with empty content
55
- original_content = ""
56
-
57
- current_content = original_content
58
- applied_count = 0
59
- errors = []
60
-
61
- for i, (search_block, replace_block) in enumerate(parsed_blocks):
62
- start_index = current_content.find(search_block)
63
- if start_index != -1:
64
- current_content = (
65
- current_content[:start_index]
66
- + replace_block
67
- + current_content[start_index + len(search_block):]
68
- )
69
- applied_count += 1
70
- logger.info(f"Applied SEARCH/REPLACE block {i+1} in file {file_path}")
71
- else:
72
- error_message = f"SEARCH block {i+1} not found in current content. Search block:\n---\n{search_block}\n---"
73
- logger.warning(error_message)
74
- errors.append(error_message)
75
- # Continue with next block
76
-
77
- try:
78
- with open(absolute_path, 'w', encoding='utf-8') as f:
79
- f.write(current_content)
80
- message = f"Successfully applied {applied_count}/{len(parsed_blocks)} changes to file: {file_path}."
81
- if errors:
82
- message += "\nWarnings:\n" + "\n".join(errors)
83
- logger.info(message)
84
- return ToolResult(success=True, message=message, content=current_content)
85
- except Exception as e:
86
- logger.error(f"Error writing replaced content to file '{file_path}': {str(e)}")
87
- return ToolResult(success=False, message=f"An error occurred while writing the modified file: {str(e)}")
88
- else:
89
- # No diff blocks detected, treat as full content overwrite
90
- with open(absolute_path, 'w', encoding='utf-8') as f:
91
- f.write(content)
92
-
93
- logger.info(f"Successfully wrote to file: {file_path}")
94
- return ToolResult(success=True, message=f"Successfully wrote to file: {file_path}", content=content)
95
-
96
- except Exception as e:
97
- logger.error(f"Error writing to file '{file_path}': {str(e)}")
98
- return ToolResult(success=False, message=f"An error occurred while writing to the file: {str(e)}")
@@ -1,124 +0,0 @@
1
- from pydantic import BaseModel
2
- from typing import List, Dict, Any, Callable, Optional, Type
3
- from pydantic import SkipValidation
4
-
5
-
6
- # Result class used by Tool Resolvers
7
- class ToolResult(BaseModel):
8
- success: bool
9
- message: str
10
- content: Any = None # Can store file content, command output, etc.
11
-
12
- # Pydantic Models for Tools
13
- class BaseTool(BaseModel):
14
- pass
15
-
16
- class ExecuteCommandTool(BaseTool):
17
- command: str
18
- requires_approval: bool
19
-
20
- class ReadFileTool(BaseTool):
21
- path: str
22
-
23
- class WriteToFileTool(BaseTool):
24
- path: str
25
- content: str
26
-
27
- class ReplaceInFileTool(BaseTool):
28
- path: str
29
- diff: str
30
-
31
- class SearchFilesTool(BaseTool):
32
- path: str
33
- regex: str
34
- file_pattern: Optional[str] = None
35
-
36
- class ListFilesTool(BaseTool):
37
- path: str
38
- recursive: Optional[bool] = False
39
-
40
- class ListCodeDefinitionNamesTool(BaseTool):
41
- path: str
42
-
43
- class AskFollowupQuestionTool(BaseTool):
44
- question: str
45
- options: Optional[List[str]] = None
46
-
47
- class AttemptCompletionTool(BaseTool):
48
- result: str
49
- command: Optional[str] = None
50
-
51
- class PlanModeRespondTool(BaseTool):
52
- response: str
53
- options: Optional[List[str]] = None
54
-
55
- class UseMcpTool(BaseTool):
56
- server_name: str
57
- tool_name: str
58
- arguments: Dict[str, Any]
59
-
60
- class PlainTextOutput(BaseModel):
61
- text: str
62
-
63
-
64
- # Mapping from tool tag names to Pydantic models
65
- TOOL_MODEL_MAP: Dict[str, Type[BaseTool]] = {
66
- "execute_command": ExecuteCommandTool,
67
- "read_file": ReadFileTool,
68
- "write_to_file": WriteToFileTool,
69
- "replace_in_file": ReplaceInFileTool,
70
- "search_files": SearchFilesTool,
71
- "list_files": ListFilesTool,
72
- "list_code_definition_names": ListCodeDefinitionNamesTool,
73
- "ask_followup_question": AskFollowupQuestionTool,
74
- "attempt_completion": AttemptCompletionTool,
75
- "plan_mode_respond": PlanModeRespondTool,
76
- "use_mcp_tool": UseMcpTool,
77
- }
78
-
79
-
80
- class AgenticEditRequest(BaseModel):
81
- user_input: str
82
-
83
-
84
- class FileOperation(BaseModel):
85
- path: str
86
- operation: str # e.g., "MODIFY", "REFERENCE", "ADD", "REMOVE"
87
- class MemoryConfig(BaseModel):
88
- """
89
- A model to encapsulate memory configuration and operations.
90
- """
91
-
92
- memory: Dict[str, Any]
93
- save_memory_func: SkipValidation[Callable]
94
-
95
- class Config:
96
- arbitrary_types_allowed = True
97
-
98
-
99
- class CommandConfig(BaseModel):
100
- coding: SkipValidation[Callable]
101
- chat: SkipValidation[Callable]
102
- add_files: SkipValidation[Callable]
103
- remove_files: SkipValidation[Callable]
104
- index_build: SkipValidation[Callable]
105
- index_query: SkipValidation[Callable]
106
- list_files: SkipValidation[Callable]
107
- ask: SkipValidation[Callable]
108
- revert: SkipValidation[Callable]
109
- commit: SkipValidation[Callable]
110
- help: SkipValidation[Callable]
111
- exclude_dirs: SkipValidation[Callable]
112
- summon: SkipValidation[Callable]
113
- design: SkipValidation[Callable]
114
- mcp: SkipValidation[Callable]
115
- models: SkipValidation[Callable]
116
- lib: SkipValidation[Callable]
117
- execute_shell_command: SkipValidation[Callable]
118
- generate_shell_command: SkipValidation[Callable]
119
- conf_export: SkipValidation[Callable]
120
- conf_import: SkipValidation[Callable]
121
- index_export: SkipValidation[Callable]
122
- index_import: SkipValidation[Callable]
123
- exclude_files: SkipValidation[Callable]
124
-
@@ -1,60 +0,0 @@
1
- import locale
2
-
3
- MESSAGES = {
4
- "en": {
5
- "human_as_model_instructions": (
6
- "You are now in Human as Model mode. The content has been copied to your clipboard.\n"
7
- "The system is waiting for your input. When finished, enter 'EOF' on a new line to submit.\n"
8
- "Use '/break' to exit this mode. If you have issues with copy-paste, use '/clear' to clean and paste again."
9
- ),
10
- "clipboard_not_supported": (
11
- "pyperclip not installed or clipboard is not supported, instruction will not be copied to clipboard."
12
- ),
13
- "human_as_model_instructions_no_clipboard": (
14
- "You are now in Human as Model mode. [bold red]The content could not be copied to your clipboard.[/bold red]\n"
15
- "but you can copy prompt from output.txt file.\n"
16
- "The system is waiting for your input. When finished, enter 'EOF' on a new line to submit.\n"
17
- "Use '/break' to exit this mode. If you have issues with copy-paste, use '/clear' to clean and paste again."
18
- ),
19
- "chat_human_as_model_instructions": (
20
- "Chat is now in Human as Model mode.\n"
21
- "The question has been copied to your clipboard.\n"
22
- "Please use Web version model to get the answer.\n"
23
- "Or use /conf human_as_model:false to close this mode and get the answer in terminal directly."
24
- "Paste the answer to the input box below, use '/break' to exit, '/clear' to clear the screen, '/eof' to submit."
25
- )
26
- },
27
- "zh": {
28
- "human_as_model_instructions": (
29
- "您现在处于人类作为模型模式。内容已复制到您的剪贴板。\n"
30
- "系统正在等待您的输入。完成后,在新行输入'EOF'提交。\n"
31
- "使用'/break'退出此模式。如果复制粘贴有问题,使用'/clear'清理并重新粘贴。"
32
- ),
33
- "clipboard_not_supported": (
34
- "未安装pyperclip或不支持剪贴板,指令将不会被复制到剪贴板。"
35
- ),
36
- "human_as_model_instructions_no_clipboard": (
37
- "您现在处于人类作为模型模式。[bold red]内容无法复制到您的剪贴板。[/bold red]\n"
38
- "但您可以从output.txt文件复制提示。\n"
39
- "系统正在等待您的输入。完成后,在新行输入'EOF'提交。\n"
40
- "使用'/break'退出此模式。如果复制粘贴有问题,使用'/clear'清理并重新粘贴。"
41
- ),
42
- "chat_human_as_model_instructions": (
43
- "\n============= Chat 处于 Human as Model 模式 =============\n"
44
- "问题已复制到剪贴板\n"
45
- "请使用Web版本模型获取答案\n"
46
- "或者使用 /conf human_as_model:false 关闭该模式直接在终端获得答案。"
47
- "将获得答案黏贴到下面的输入框,换行后,使用 '/break' 退出,'/clear' 清屏,'/eof' 提交。"
48
- ),
49
- }
50
- }
51
-
52
- def get_system_language():
53
- try:
54
- return locale.getdefaultlocale()[0][:2]
55
- except:
56
- return 'en'
57
-
58
- def get_message(key):
59
- lang = get_system_language()
60
- return MESSAGES.get(lang, MESSAGES['en']).get(key, MESSAGES['en'][key])
@@ -1,170 +0,0 @@
1
- from typing import Any, List, Dict, Generator, Optional
2
- import asyncio
3
- import httpx
4
- import argparse
5
- from mcp.server.models import InitializationOptions
6
- import mcp.types as types
7
- from mcp.server import NotificationOptions, Server
8
- import mcp.server.stdio
9
- from autocoder.common import AutoCoderArgs
10
- from byzerllm import ByzerLLM
11
- from autocoder.lang import lang_desc
12
- import locale
13
- import pkg_resources
14
- from openai import OpenAI
15
-
16
- class AutoCoderRAGClientMCP:
17
- def __init__(self, llm: ByzerLLM, args: AutoCoderArgs):
18
- self.llm = llm
19
- self.args = args
20
-
21
- if not args.rag_url:
22
- raise ValueError("rag_url is required for RAG client mode")
23
-
24
- if not args.rag_url.startswith("http://"):
25
- args.rag_url = f"http://{args.rag_url}"
26
-
27
- if not args.rag_url.endswith("/v1"):
28
- args.rag_url = args.rag_url.rstrip("/") + "/v1"
29
-
30
- if not args.rag_token:
31
- raise ValueError("rag_token is required for RAG client mode")
32
-
33
- self.client = OpenAI(api_key=args.rag_token, base_url=args.rag_url)
34
-
35
- self.server = Server("auto_coder_rag_client")
36
-
37
- async def setup_server(self):
38
- @self.server.list_tools()
39
- async def handle_list_tools() -> List[types.Tool]:
40
- return [
41
- types.Tool(
42
- name="rag-search",
43
- description="Search documents using RAG",
44
- inputSchema={
45
- "type": "object",
46
- "properties": {
47
- "query": {
48
- "type": "string",
49
- "description": "Search query",
50
- },
51
- },
52
- "required": ["query"],
53
- },
54
- ),
55
- types.Tool(
56
- name="rag-chat",
57
- description="Chat with documents using RAG",
58
- inputSchema={
59
- "type": "object",
60
- "properties": {
61
- "query": {
62
- "type": "string",
63
- "description": "Chat query",
64
- },
65
- },
66
- "required": ["query"],
67
- },
68
- ),
69
- ]
70
-
71
- @self.server.call_tool()
72
- async def handle_call_tool(
73
- name: str, arguments: Dict[str, Any] | None
74
- ) -> List[types.TextContent | types.ImageContent | types.EmbeddedResource]:
75
- if not arguments:
76
- raise ValueError("Missing arguments")
77
-
78
- if name == "rag-search":
79
- query = arguments.get("query")
80
- if not query:
81
- raise ValueError("Missing query parameter")
82
-
83
- response = self.client.chat.completions.create(
84
- messages=[{"role": "user", "content": json.dumps({
85
- "query": query,
86
- "only_contexts": True
87
- })}],
88
- model=self.args.model,
89
- max_tokens=self.args.rag_params_max_tokens,
90
- )
91
- result = response.choices[0].message.content
92
-
93
- return [
94
- types.TextContent(
95
- type="text",
96
- text=f"Search results for '{query}':\n\n{result}"
97
- )
98
- ]
99
-
100
- elif name == "rag-chat":
101
- query = arguments.get("query")
102
- if not query:
103
- raise ValueError("Missing query parameter")
104
-
105
- response = self.client.chat.completions.create(
106
- messages=[{"role": "user", "content": query}],
107
- model=self.args.model,
108
- stream=True,
109
- max_tokens=self.args.rag_params_max_tokens
110
- )
111
-
112
- full_response = ""
113
- for chunk in response:
114
- if chunk.choices[0].delta.content is not None:
115
- full_response += chunk.choices[0].delta.content
116
-
117
- return [
118
- types.TextContent(
119
- type="text",
120
- text=f"Chat response for '{query}':\n\n{full_response}"
121
- )
122
- ]
123
-
124
- else:
125
- raise ValueError(f"Unknown tool: {name}")
126
-
127
- async def run(self):
128
- async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
129
- await self.server.run(
130
- read_stream,
131
- write_stream,
132
- InitializationOptions(
133
- server_name="auto_coder_rag_client",
134
- server_version="0.1.0",
135
- capabilities=self.server.get_capabilities(
136
- notification_options=NotificationOptions(),
137
- experimental_capabilities={},
138
- ),
139
- ),
140
- )
141
-
142
- def parse_args(input_args: Optional[List[str]] = None) -> AutoCoderArgs:
143
- system_lang, _ = locale.getdefaultlocale()
144
- lang = "zh" if system_lang and system_lang.startswith("zh") else "en"
145
- desc = lang_desc[lang]
146
-
147
- parser = argparse.ArgumentParser(description="Auto Coder RAG Client MCP Server")
148
- parser.add_argument("--rag_url", required=True, help="RAG server URL")
149
- parser.add_argument("--rag_token", required=True, help="RAG server token")
150
- parser.add_argument("--model", default="v3_chat", help=desc["model"])
151
- parser.add_argument("--rag_params_max_tokens", type=int, default=4096, help="Max tokens for RAG response")
152
-
153
- args = parser.parse_args(input_args)
154
- return AutoCoderArgs(**vars(args))
155
-
156
- async def main():
157
- # Parse command line arguments
158
- args = parse_args()
159
-
160
- # Initialize LLM
161
- llm = ByzerLLM()
162
- llm.setup_default_model_name(args.model)
163
-
164
- # Initialize and run server
165
- server = AutoCoderRAGClientMCP(llm=llm, args=args)
166
- await server.setup_server()
167
- await server.run()
168
-
169
- if __name__ == "__main__":
170
- asyncio.run(main())
@@ -1,193 +0,0 @@
1
- from typing import Any, List, Dict, Generator, Optional
2
- import asyncio
3
- import httpx
4
- import argparse
5
- from mcp.server.models import InitializationOptions
6
- import mcp.types as types
7
- from mcp.server import NotificationOptions, Server
8
- import mcp.server.stdio
9
- from autocoder.rag.long_context_rag import LongContextRAG
10
- from autocoder.common import AutoCoderArgs
11
- from byzerllm import ByzerLLM
12
- from autocoder.lang import lang_desc
13
- import locale
14
- import pkg_resources
15
-
16
- class AutoCoderRAGMCP:
17
- def __init__(self, llm: ByzerLLM, args: AutoCoderArgs):
18
- self.llm = llm
19
- self.args = args
20
- self.rag = LongContextRAG(
21
- llm=llm,
22
- args=args,
23
- path=args.source_dir,
24
- tokenizer_path=args.tokenizer_path
25
- )
26
- self.server = Server("auto_coder_rag")
27
-
28
- async def setup_server(self):
29
- @self.server.list_tools()
30
- async def handle_list_tools() -> List[types.Tool]:
31
- return [
32
- types.Tool(
33
- name="rag-search",
34
- description="Search documents using RAG",
35
- inputSchema={
36
- "type": "object",
37
- "properties": {
38
- "query": {
39
- "type": "string",
40
- "description": "Search query",
41
- },
42
- },
43
- "required": ["query"],
44
- },
45
- ),
46
- types.Tool(
47
- name="rag-chat",
48
- description="Chat with documents using RAG",
49
- inputSchema={
50
- "type": "object",
51
- "properties": {
52
- "query": {
53
- "type": "string",
54
- "description": "Chat query",
55
- },
56
- },
57
- "required": ["query"],
58
- },
59
- ),
60
- ]
61
-
62
- @self.server.call_tool()
63
- async def handle_call_tool(
64
- name: str, arguments: Dict[str, Any] | None
65
- ) -> List[types.TextContent | types.ImageContent | types.EmbeddedResource]:
66
- if not arguments:
67
- raise ValueError("Missing arguments")
68
-
69
- if name == "rag-search":
70
- query = arguments.get("query")
71
- if not query:
72
- raise ValueError("Missing query parameter")
73
-
74
- results = self.rag.search(query)
75
- return [
76
- types.TextContent(
77
- type="text",
78
- text=f"Search results for '{query}':\n\n" +
79
- "\n".join([f"- {result.module_name}: {result.source_code[:200]}..."
80
- for result in results])
81
- )
82
- ]
83
-
84
- elif name == "rag-chat":
85
- query = arguments.get("query")
86
- if not query:
87
- raise ValueError("Missing query parameter")
88
-
89
- response, _ = self.rag.stream_chat_oai(
90
- conversations=[{"role": "user", "content": query}]
91
- )
92
- full_response = "".join([chunk for chunk in response])
93
-
94
- return [
95
- types.TextContent(
96
- type="text",
97
- text=f"Chat response for '{query}':\n\n{full_response}"
98
- )
99
- ]
100
-
101
- else:
102
- raise ValueError(f"Unknown tool: {name}")
103
-
104
- async def run(self):
105
- async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
106
- await self.server.run(
107
- read_stream,
108
- write_stream,
109
- InitializationOptions(
110
- server_name="auto_coder_rag",
111
- server_version="0.1.0",
112
- capabilities=self.server.get_capabilities(
113
- notification_options=NotificationOptions(),
114
- experimental_capabilities={},
115
- ),
116
- ),
117
- )
118
-
119
- def parse_args(input_args: Optional[List[str]] = None) -> AutoCoderArgs:
120
- try:
121
- tokenizer_path = pkg_resources.resource_filename(
122
- "autocoder", "data/tokenizer.json"
123
- )
124
- except FileNotFoundError:
125
- tokenizer_path = None
126
-
127
- system_lang, _ = locale.getdefaultlocale()
128
- lang = "zh" if system_lang and system_lang.startswith("zh") else "en"
129
- desc = lang_desc[lang]
130
-
131
- parser = argparse.ArgumentParser(description="Auto Coder RAG MCP Server")
132
- parser.add_argument("--source_dir", default=".", help="Source directory path")
133
- parser.add_argument("--tokenizer_path", default=tokenizer_path, help="Path to tokenizer file")
134
- parser.add_argument("--model", default="deepseek_chat", help=desc["model"])
135
- parser.add_argument("--index_model", default="", help=desc["index_model"])
136
- parser.add_argument("--emb_model", default="", help=desc["emb_model"])
137
- parser.add_argument("--ray_address", default="auto", help=desc["ray_address"])
138
- parser.add_argument("--required_exts", default="", help=desc["doc_build_parse_required_exts"])
139
- parser.add_argument("--rag_doc_filter_relevance", type=int, default=5, help="Relevance score threshold for document filtering")
140
- parser.add_argument("--rag_context_window_limit", type=int, default=56000, help="Context window limit for RAG")
141
- parser.add_argument("--full_text_ratio", type=float, default=0.7, help="Ratio of full text area in context window")
142
- parser.add_argument("--segment_ratio", type=float, default=0.2, help="Ratio of segment area in context window")
143
- parser.add_argument("--index_filter_workers", type=int, default=5, help="Number of workers for document filtering")
144
- parser.add_argument("--index_filter_file_num", type=int, default=3, help="Maximum number of files to filter")
145
- parser.add_argument("--host", default="", help="Server host address")
146
- parser.add_argument("--port", type=int, default=8000, help="Server port")
147
- parser.add_argument("--monitor_mode", action="store_true", help="Enable document monitoring mode")
148
- parser.add_argument("--enable_hybrid_index", action="store_true", help="Enable hybrid index")
149
- parser.add_argument("--disable_auto_window", action="store_true", help="Disable automatic window adaptation")
150
- parser.add_argument("--disable_segment_reorder", action="store_true", help="Disable segment reordering")
151
- parser.add_argument("--disable_inference_enhance", action="store_true", help="Disable inference enhancement")
152
- parser.add_argument("--inference_deep_thought", action="store_true", help="Enable deep thought in inference")
153
- parser.add_argument("--inference_slow_without_deep_thought", action="store_true", help="Enable slow inference without deep thought")
154
- parser.add_argument("--inference_compute_precision", type=int, default=64, help="Inference compute precision")
155
- parser.add_argument("--data_cells_max_num", type=int, default=2000, help="Maximum number of data cells to process")
156
- parser.add_argument("--recall_model", default="", help="Model used for document recall")
157
- parser.add_argument("--chunk_model", default="", help="Model used for document chunking")
158
- parser.add_argument("--qa_model", default="", help="Model used for question answering")
159
-
160
- args = parser.parse_args(input_args)
161
- return AutoCoderArgs(**vars(args)),args
162
-
163
- async def main():
164
- # Parse command line arguments
165
- args,raw_rags = parse_args()
166
-
167
- # Initialize LLM
168
- llm = ByzerLLM()
169
- llm.setup_default_model_name(args.model)
170
-
171
- # Setup sub models if specified
172
- if raw_rags.recall_model:
173
- recall_model = ByzerLLM()
174
- recall_model.setup_default_model_name(args.recall_model)
175
- llm.setup_sub_client("recall_model", recall_model)
176
-
177
- if raw_rags.chunk_model:
178
- chunk_model = ByzerLLM()
179
- chunk_model.setup_default_model_name(args.chunk_model)
180
- llm.setup_sub_client("chunk_model", chunk_model)
181
-
182
- if raw_rags.qa_model:
183
- qa_model = ByzerLLM()
184
- qa_model.setup_default_model_name(args.qa_model)
185
- llm.setup_sub_client("qa_model", qa_model)
186
-
187
- # Initialize and run server
188
- server = AutoCoderRAGMCP(llm=llm, args=args)
189
- await server.setup_server()
190
- await server.run()
191
-
192
- if __name__ == "__main__":
193
- asyncio.run(main())