auto-coder 0.1.221__py3-none-any.whl → 0.1.223__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.221.dist-info → auto_coder-0.1.223.dist-info}/METADATA +1 -1
- {auto_coder-0.1.221.dist-info → auto_coder-0.1.223.dist-info}/RECORD +15 -13
- autocoder/auto_coder.py +27 -7
- autocoder/auto_coder_rag_client_mcp.py +170 -0
- autocoder/auto_coder_rag_mcp.py +193 -0
- autocoder/chat_auto_coder.py +35 -4
- autocoder/common/__init__.py +2 -0
- autocoder/common/command_completer.py +1 -1
- autocoder/common/mcp_servers/mcp_server_perplexity.py +2 -2
- autocoder/rag/long_context_rag.py +3 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.221.dist-info → auto_coder-0.1.223.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.221.dist-info → auto_coder-0.1.223.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.221.dist-info → auto_coder-0.1.223.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.221.dist-info → auto_coder-0.1.223.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
autocoder/auto_coder.py,sha256=
|
|
2
|
+
autocoder/auto_coder.py,sha256=BQvCwOc-4XgOtpwQWHCTvcx97XEejdwRordyrCYSf0s,43554
|
|
3
3
|
autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,3229
|
|
4
4
|
autocoder/auto_coder_rag.py,sha256=illKgzP2bv-Tq50ujsofJnOHdI4pzr0ALtfR8NHHWdQ,22351
|
|
5
|
+
autocoder/auto_coder_rag_client_mcp.py,sha256=WU8WzwuRbJE-W_r94S8PYKOQ32FEv2WPJzCgZII7dBc,6277
|
|
6
|
+
autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
|
|
5
7
|
autocoder/auto_coder_server.py,sha256=XU9b4SBH7zjPPXaTWWHV4_zJm-XYa6njuLQaplYJH_c,20290
|
|
6
8
|
autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
|
|
7
|
-
autocoder/chat_auto_coder.py,sha256=
|
|
9
|
+
autocoder/chat_auto_coder.py,sha256=x98afu7PCzYtf2545tIdJP13tI3lixFJg4sSSFtRjeM,95346
|
|
8
10
|
autocoder/chat_auto_coder_lang.py,sha256=ReWukXKVvuzVvpbYk5O9kc1ev7XNmAv3DnuQhmpLmnc,8717
|
|
9
11
|
autocoder/command_args.py,sha256=9aYJ-AmPxP1sQh6ciw04FWHjSn31f2W9afXFwo8wgx4,30441
|
|
10
12
|
autocoder/lang.py,sha256=U6AjVV8Rs1uLyjFCZ8sT6WWuNUxMBqkXXIOs4S120uk,14511
|
|
11
|
-
autocoder/version.py,sha256=
|
|
13
|
+
autocoder/version.py,sha256=hA-WuAig1V69eSYfuZJjxnT6-tLr5fGDFA1I86siMMg,24
|
|
12
14
|
autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
15
|
autocoder/agent/auto_demand_organizer.py,sha256=NWSAEsEk94vT3lGjfo25kKLMwYdPcpy9e-i21txPasQ,6942
|
|
14
16
|
autocoder/agent/auto_filegroup.py,sha256=CW7bqp0FW1GIEMnl-blyAc2UGT7O9Mom0q66ITz1ckM,6635
|
|
@@ -21,7 +23,7 @@ autocoder/agent/project_reader.py,sha256=tWLaPoLw1gI6kO_NzivQj28KbobU2ceOLuppHMb
|
|
|
21
23
|
autocoder/chat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
24
|
autocoder/common/JupyterClient.py,sha256=O-wi6pXeAEYhAY24kDa0BINrLYvKS6rKyWe98pDClS0,2816
|
|
23
25
|
autocoder/common/ShellClient.py,sha256=fM1q8t_XMSbLBl2zkCNC2J9xuyKN3eXzGm6hHhqL2WY,2286
|
|
24
|
-
autocoder/common/__init__.py,sha256=
|
|
26
|
+
autocoder/common/__init__.py,sha256=jwjsx9qT_5fJmdlbNt3I5UiDtDKcdeLqQ8s_Tw_sT0U,11492
|
|
25
27
|
autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
|
|
26
28
|
autocoder/common/anything2img.py,sha256=4TREa-sOA-iargieUy7MpyCYVUE-9Mmq0wJtwomPqnE,7662
|
|
27
29
|
autocoder/common/audio.py,sha256=Kn9nWKQddWnUrAz0a_ZUgjcu4VUU_IcZBigT7n3N3qc,7439
|
|
@@ -38,7 +40,7 @@ autocoder/common/code_auto_merge_diff.py,sha256=5SI6ggklJ0QDHvsS0cpNXFuIkFRQxp1i
|
|
|
38
40
|
autocoder/common/code_auto_merge_editblock.py,sha256=l6yEiZqXyIlUNIIPXvkHOnLCIInXR78TzSjF-jtJkkg,17035
|
|
39
41
|
autocoder/common/code_auto_merge_strict_diff.py,sha256=ABYOTDUQYA4Bn4BwT1Rw812y49cHW3UH_JSpM9uJ6ig,9399
|
|
40
42
|
autocoder/common/code_modification_ranker.py,sha256=DFlbwgdg8GK47zVcvfZSzkyniEKmTVLTOWejjcVIgaw,5121
|
|
41
|
-
autocoder/common/command_completer.py,sha256=
|
|
43
|
+
autocoder/common/command_completer.py,sha256=xXDatBOkjV78jsgG1eF8pcMFC0glTm1poesjd_Q6kSw,9169
|
|
42
44
|
autocoder/common/command_generator.py,sha256=v4LmU7sO-P7jEZIXCWHUC6P-vT7AvBi_x_PTwCqBAE8,1323
|
|
43
45
|
autocoder/common/command_templates.py,sha256=3G-pCNbL6iHbnkG6v1JZpbIK3Mc9d373_RYGmCcDPMY,8548
|
|
44
46
|
autocoder/common/const.py,sha256=eTjhjh4Aj4CUzviJ81jaf3Y5cwqsLATySn2wJxaS6RQ,2911
|
|
@@ -57,7 +59,7 @@ autocoder/common/sys_prompt.py,sha256=JlexfjZt554faqbgkCmzOJqYUzDHfbnxly5ugFfHfE
|
|
|
57
59
|
autocoder/common/text.py,sha256=KGRQq314GHBmY4MWG8ossRoQi1_DTotvhxchpn78c-k,1003
|
|
58
60
|
autocoder/common/types.py,sha256=oQKPE1TG0O7DQQLaBSMp6CP3Bbvg0K8elFdidlV52Lg,631
|
|
59
61
|
autocoder/common/mcp_servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
|
-
autocoder/common/mcp_servers/mcp_server_perplexity.py,sha256=
|
|
62
|
+
autocoder/common/mcp_servers/mcp_server_perplexity.py,sha256=jz0LkCgZcqKkNdLZ9swNOu9Besoba4JOyHDedoZnWHo,5546
|
|
61
63
|
autocoder/data/tokenizer.json,sha256=QfO_ZCE9qMAS2L0IcaWKH99wRj6PCPEQ3bsQgvUp9mk,4607451
|
|
62
64
|
autocoder/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
65
|
autocoder/db/store.py,sha256=tFT66bP2ZKIqZip-uhLkHRSLaaOAUUDZfozJwcqix3c,1908
|
|
@@ -78,7 +80,7 @@ autocoder/rag/api_server.py,sha256=dRbhAZVRAOlZ64Cnxf4_rKb4iJwHnrWS9Zr67IVORw0,7
|
|
|
78
80
|
autocoder/rag/doc_filter.py,sha256=B99Qcy3tcNLuSz2kWbpgfBj2_Igme91zWKOJ2Niq2UY,6652
|
|
79
81
|
autocoder/rag/document_retriever.py,sha256=5oThtxukGuRFF96o3pHKsk306a8diXbhgSrbqyU2BvM,8894
|
|
80
82
|
autocoder/rag/llm_wrapper.py,sha256=sbDxCANiZyWb_ocqNgqu2oy3c2t8orPNRGleEs-Uwl8,2649
|
|
81
|
-
autocoder/rag/long_context_rag.py,sha256=
|
|
83
|
+
autocoder/rag/long_context_rag.py,sha256=F-ulTwSZ9ogIGL9jTXDUnI44zStH02EjrztZgRkW9-g,25246
|
|
82
84
|
autocoder/rag/rag_config.py,sha256=8LwFcTd8OJWWwi1_WY4IzjqgtT6RyE2j4PjxS5cCTDE,802
|
|
83
85
|
autocoder/rag/rag_entry.py,sha256=6TKtErZ0Us9XSV6HgRKXA6yR3SiZGPHpynOKSaR1wgE,2463
|
|
84
86
|
autocoder/rag/raw_rag.py,sha256=yS2Ur6kG0IRjhCj2_VonwxjY_xls_E62jO5Gz5j2nqE,2952
|
|
@@ -122,9 +124,9 @@ autocoder/utils/request_event_queue.py,sha256=r3lo5qGsB1dIjzVQ05dnr0z_9Z3zOkBdP1
|
|
|
122
124
|
autocoder/utils/request_queue.py,sha256=nwp6PMtgTCiuwJI24p8OLNZjUiprC-TsefQrhMI-yPE,3889
|
|
123
125
|
autocoder/utils/rest.py,sha256=HawagAap3wMIDROGhY1730zSZrJR_EycODAA5qOj83c,8807
|
|
124
126
|
autocoder/utils/tests.py,sha256=BqphrwyycGAvs-5mhH8pKtMZdObwhFtJ5MC_ZAOiLq8,1340
|
|
125
|
-
auto_coder-0.1.
|
|
126
|
-
auto_coder-0.1.
|
|
127
|
-
auto_coder-0.1.
|
|
128
|
-
auto_coder-0.1.
|
|
129
|
-
auto_coder-0.1.
|
|
130
|
-
auto_coder-0.1.
|
|
127
|
+
auto_coder-0.1.223.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
128
|
+
auto_coder-0.1.223.dist-info/METADATA,sha256=wma3ZSYec0V5FYUoLcbVDuWamEWG0ClOEoOInJkGnCQ,2615
|
|
129
|
+
auto_coder-0.1.223.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
130
|
+
auto_coder-0.1.223.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
|
|
131
|
+
auto_coder-0.1.223.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
|
|
132
|
+
auto_coder-0.1.223.dist-info/RECORD,,
|
autocoder/auto_coder.py
CHANGED
|
@@ -577,6 +577,9 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
577
577
|
with Live(
|
|
578
578
|
Panel("", title="Response", border_style="green", expand=False),
|
|
579
579
|
refresh_per_second=4,
|
|
580
|
+
auto_refresh=True,
|
|
581
|
+
vertical_overflow="visible",
|
|
582
|
+
console=Console(force_terminal=True, color_system="auto", height=None)
|
|
580
583
|
) as live:
|
|
581
584
|
live.update(
|
|
582
585
|
Panel(
|
|
@@ -689,6 +692,9 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
689
692
|
with Live(
|
|
690
693
|
Panel("", title="Response", border_style="green", expand=False),
|
|
691
694
|
refresh_per_second=4,
|
|
695
|
+
auto_refresh=True,
|
|
696
|
+
vertical_overflow="visible",
|
|
697
|
+
console=Console(force_terminal=True, color_system="auto", height=None)
|
|
692
698
|
) as live:
|
|
693
699
|
live.update(
|
|
694
700
|
Panel(
|
|
@@ -698,8 +704,8 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
698
704
|
expand=False,
|
|
699
705
|
)
|
|
700
706
|
)
|
|
701
|
-
return
|
|
702
707
|
|
|
708
|
+
return
|
|
703
709
|
elif raw_args.agent_command == "designer":
|
|
704
710
|
from autocoder.agent.designer import SVGDesigner, SDDesigner, LogoDesigner
|
|
705
711
|
|
|
@@ -938,11 +944,24 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
938
944
|
|
|
939
945
|
return {}
|
|
940
946
|
|
|
941
|
-
if args.
|
|
947
|
+
if args.action == "rag":
|
|
948
|
+
args.enable_rag_search = True
|
|
949
|
+
args.enable_rag_context = False
|
|
942
950
|
rag = RAGFactory.get_rag(llm=chat_llm, args=args, path="")
|
|
943
951
|
response = rag.stream_chat_oai(
|
|
944
|
-
conversations=
|
|
952
|
+
conversations=[{"role": "user", "content": args.query}])[0]
|
|
945
953
|
v = ([item, None] for item in response)
|
|
954
|
+
|
|
955
|
+
elif args.action == "mcp":
|
|
956
|
+
from autocoder.common.mcp_server import get_mcp_server, McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest, McpListRunningRequest, McpRefreshRequest
|
|
957
|
+
mcp_server = get_mcp_server()
|
|
958
|
+
response = mcp_server.send_request(
|
|
959
|
+
McpRequest(
|
|
960
|
+
query=args.query,
|
|
961
|
+
model=args.inference_model or args.model
|
|
962
|
+
)
|
|
963
|
+
)
|
|
964
|
+
v = [[response.result,None]]
|
|
946
965
|
else:
|
|
947
966
|
v = chat_llm.stream_chat_oai(
|
|
948
967
|
conversations=loaded_conversations, delta_mode=True
|
|
@@ -953,10 +972,11 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
953
972
|
|
|
954
973
|
try:
|
|
955
974
|
with Live(
|
|
956
|
-
Panel("", title="Response"),
|
|
975
|
+
Panel("", title="Response", border_style="green", expand=False),
|
|
957
976
|
refresh_per_second=4,
|
|
958
977
|
auto_refresh=True,
|
|
959
|
-
vertical_overflow="visible"
|
|
978
|
+
vertical_overflow="visible",
|
|
979
|
+
console=Console(force_terminal=True, color_system="auto", height=None)
|
|
960
980
|
) as live:
|
|
961
981
|
for res in v:
|
|
962
982
|
markdown_content += res[0]
|
|
@@ -977,7 +997,7 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
977
997
|
expand=False,
|
|
978
998
|
)
|
|
979
999
|
)
|
|
980
|
-
|
|
1000
|
+
live.update(
|
|
981
1001
|
Panel(
|
|
982
1002
|
Markdown(markdown_content),
|
|
983
1003
|
title="Response",
|
|
@@ -999,7 +1019,7 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
999
1019
|
value=StreamValue(value=[""]), status=RequestOption.COMPLETED
|
|
1000
1020
|
),
|
|
1001
1021
|
)
|
|
1002
|
-
|
|
1022
|
+
|
|
1003
1023
|
chat_history["ask_conversation"].append(
|
|
1004
1024
|
{"role": "assistant", "content": assistant_response}
|
|
1005
1025
|
)
|
|
@@ -0,0 +1,170 @@
|
|
|
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": False
|
|
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="deepseek_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())
|
|
@@ -0,0 +1,193 @@
|
|
|
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())
|
autocoder/chat_auto_coder.py
CHANGED
|
@@ -38,6 +38,7 @@ from rich.table import Table
|
|
|
38
38
|
from rich.live import Live
|
|
39
39
|
from rich.text import Text
|
|
40
40
|
from rich.live import Live
|
|
41
|
+
from rich.markdown import Markdown
|
|
41
42
|
from byzerllm.utils.nontext import Image
|
|
42
43
|
import git
|
|
43
44
|
from autocoder.common import git_utils
|
|
@@ -46,6 +47,7 @@ from autocoder.utils import operate_config_api
|
|
|
46
47
|
from autocoder.agent.auto_guess_query import AutoGuessQuery
|
|
47
48
|
from autocoder.common.mcp_server import get_mcp_server, McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest, McpListRunningRequest, McpRefreshRequest
|
|
48
49
|
import byzerllm
|
|
50
|
+
from byzerllm.utils import format_str_jinja2
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
class SymbolItem(BaseModel):
|
|
@@ -1499,11 +1501,32 @@ def mcp(query: str):
|
|
|
1499
1501
|
model=args.inference_model or args.model
|
|
1500
1502
|
)
|
|
1501
1503
|
)
|
|
1502
|
-
|
|
1504
|
+
console = Console()
|
|
1503
1505
|
if response.error:
|
|
1504
|
-
print(
|
|
1506
|
+
console.print(Panel(
|
|
1507
|
+
f"Error from MCP server: {response.error}",
|
|
1508
|
+
title="Error",
|
|
1509
|
+
border_style="red"
|
|
1510
|
+
))
|
|
1505
1511
|
else:
|
|
1506
|
-
|
|
1512
|
+
# Save conversation
|
|
1513
|
+
mcp_dir = os.path.join(".auto-coder", "mcp", "conversations")
|
|
1514
|
+
os.makedirs(mcp_dir, exist_ok=True)
|
|
1515
|
+
timestamp = str(int(time.time()))
|
|
1516
|
+
file_path = os.path.join(mcp_dir, f"{timestamp}.md")
|
|
1517
|
+
|
|
1518
|
+
# Format response as markdown
|
|
1519
|
+
markdown_content = f"# MCP Response\n\n{response.result}"
|
|
1520
|
+
|
|
1521
|
+
# Save to file
|
|
1522
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
1523
|
+
f.write(markdown_content)
|
|
1524
|
+
|
|
1525
|
+
# Print with markdown formatting
|
|
1526
|
+
console.print(Panel(
|
|
1527
|
+
Markdown(markdown_content),
|
|
1528
|
+
border_style="green"
|
|
1529
|
+
))
|
|
1507
1530
|
|
|
1508
1531
|
|
|
1509
1532
|
def code_next(query: str):
|
|
@@ -1837,10 +1860,18 @@ def chat(query: str):
|
|
|
1837
1860
|
if "emb_model" in conf:
|
|
1838
1861
|
yaml_config["emb_model"] = conf["emb_model"]
|
|
1839
1862
|
|
|
1840
|
-
is_new =
|
|
1863
|
+
is_new = "/new" in query
|
|
1841
1864
|
if is_new:
|
|
1842
1865
|
query = query.replace("/new", "", 1).strip()
|
|
1843
1866
|
|
|
1867
|
+
if "/mcp " in query:
|
|
1868
|
+
yaml_config["action"] = "mcp"
|
|
1869
|
+
query = query.replace("/mcp ", "", 1).strip()
|
|
1870
|
+
|
|
1871
|
+
if "/rag " in query:
|
|
1872
|
+
yaml_config["action"] = "rag"
|
|
1873
|
+
query = query.replace("/rag ", "", 1).strip()
|
|
1874
|
+
|
|
1844
1875
|
is_review = query.strip().startswith("/review")
|
|
1845
1876
|
if is_review:
|
|
1846
1877
|
query = query.replace("/review", "", 1).strip()
|
autocoder/common/__init__.py
CHANGED
|
@@ -13,7 +13,7 @@ COMMANDS = {
|
|
|
13
13
|
"/sd": {},
|
|
14
14
|
},
|
|
15
15
|
"/coding": {"/apply": {}, "/next": {}},
|
|
16
|
-
"/chat": {"/new": {}, "/review": {}, "/no_context": {}},
|
|
16
|
+
"/chat": {"/new": {}, "/mcp": {}, "/rag": {}, "/review": {}, "/no_context": {}},
|
|
17
17
|
"/mcp": {
|
|
18
18
|
"/add": "",
|
|
19
19
|
"/remove": "",
|
|
@@ -51,11 +51,11 @@ async def handle_list_tools() -> list[types.Tool]:
|
|
|
51
51
|
"type": "string",
|
|
52
52
|
"description": "The name of the model that will complete your prompt.",
|
|
53
53
|
"enum": [
|
|
54
|
-
"llama-3.1-sonar-small-128k-online",
|
|
54
|
+
# "llama-3.1-sonar-small-128k-online",
|
|
55
55
|
# Commenting out larger models,which have higher risks of timing out,
|
|
56
56
|
# until Claude Desktop can handle long-running tasks effectively.
|
|
57
57
|
# "llama-3.1-sonar-large-128k-online",
|
|
58
|
-
|
|
58
|
+
"llama-3.1-sonar-huge-128k-online",
|
|
59
59
|
],
|
|
60
60
|
},
|
|
61
61
|
"messages": {
|
|
@@ -104,6 +104,8 @@ class LongContextRAG:
|
|
|
104
104
|
raise ValueError(
|
|
105
105
|
"You are in client mode, please provide the RAG token. e.g. rag_token: your_token_here"
|
|
106
106
|
)
|
|
107
|
+
if not args.rag_url.endswith("/v1"):
|
|
108
|
+
args.rag_url = args.rag_url.rstrip("/") + "/v1"
|
|
107
109
|
self.client = OpenAI(api_key=args.rag_token, base_url=args.rag_url)
|
|
108
110
|
else:
|
|
109
111
|
self.client = None
|
|
@@ -340,6 +342,7 @@ class LongContextRAG:
|
|
|
340
342
|
model=model,
|
|
341
343
|
messages=conversations,
|
|
342
344
|
stream=True,
|
|
345
|
+
max_tokens=self.args.rag_params_max_tokens
|
|
343
346
|
)
|
|
344
347
|
|
|
345
348
|
def response_generator():
|
autocoder/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.223"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|