auto-coder 0.1.248__py3-none-any.whl → 0.1.250__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.248
3
+ Version: 0.1.250
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -1,22 +1,22 @@
1
1
  autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- autocoder/auto_coder.py,sha256=tElv9VAvv1hfb9qt8R9EFbXqhYs6pm89cy4mPIFFUQE,63127
2
+ autocoder/auto_coder.py,sha256=iysR5Bd2IREUKkGkfcmuoLlqn76L70iNKcG-Y-BQvY0,62918
3
3
  autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,3229
4
4
  autocoder/auto_coder_rag.py,sha256=illKgzP2bv-Tq50ujsofJnOHdI4pzr0ALtfR8NHHWdQ,22351
5
5
  autocoder/auto_coder_rag_client_mcp.py,sha256=WV7j5JUiQge0x4-B7Hp5-pSAFXLbvLpzQMcCovbauIM,6276
6
6
  autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
7
7
  autocoder/auto_coder_server.py,sha256=XU9b4SBH7zjPPXaTWWHV4_zJm-XYa6njuLQaplYJH_c,20290
8
8
  autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
9
- autocoder/chat_auto_coder.py,sha256=OUpoT-kUNoDS5VlO-Tui9zztd2ACyVa_kYQueBhb294,106724
10
- autocoder/chat_auto_coder_lang.py,sha256=C0QJkyIhW-9aksHznrcATf0JdI1uKqOr46zW4RZ2ljA,15759
9
+ autocoder/chat_auto_coder.py,sha256=H83C0FW5q51-Iq0MBAO-9xbr2tCfbF-LVRZddFhmOhM,104869
10
+ autocoder/chat_auto_coder_lang.py,sha256=ffLIVhOrODHamiy4csir-1TD7q7P9NeuZoZ9VaHeuic,15880
11
11
  autocoder/command_args.py,sha256=9aYJ-AmPxP1sQh6ciw04FWHjSn31f2W9afXFwo8wgx4,30441
12
12
  autocoder/lang.py,sha256=U6AjVV8Rs1uLyjFCZ8sT6WWuNUxMBqkXXIOs4S120uk,14511
13
13
  autocoder/models.py,sha256=_9Kc8oS_tnnqKzRGnybgOfn1NOey7OXZ8y9qhBmgiB4,5517
14
- autocoder/version.py,sha256=gz_qiXdNgWHsUB0K0UK2gM2GACFJe2vl6xhS3UW_9Sc,23
14
+ autocoder/version.py,sha256=wNwxrmLzoMunbZEL7IU7ZAvpehOc0XEYZBzjCnolPhU,23
15
15
  autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  autocoder/agent/auto_demand_organizer.py,sha256=NWSAEsEk94vT3lGjfo25kKLMwYdPcpy9e-i21txPasQ,6942
17
17
  autocoder/agent/auto_filegroup.py,sha256=CW7bqp0FW1GIEMnl-blyAc2UGT7O9Mom0q66ITz1ckM,6635
18
18
  autocoder/agent/auto_guess_query.py,sha256=rDSdhpPHcOGE5MuDXvIrhCXAPR4ARS1LqpyoLsx2Jhw,11374
19
- autocoder/agent/auto_review_commit.py,sha256=3_XgcOGNbpOnwq9WMj66rceZFEa4lEQvs9OZdKQi7co,7663
19
+ autocoder/agent/auto_review_commit.py,sha256=7na6LiMg9jxtdX5hplJ2m-9tx2HzRBAEZ6h8lcsmasw,7591
20
20
  autocoder/agent/auto_tool.py,sha256=DBzip-P_T6ZtT2eHexPcusmKYD0h7ufzp7TLwXAY10E,11554
21
21
  autocoder/agent/coder.py,sha256=x6bdJwDuETGg9ebQnYlUWCxCtQcDGg73LtI6McpWslQ,72034
22
22
  autocoder/agent/designer.py,sha256=EpRbzO58Xym3GrnppIT1Z8ZFAlnNfgzHbIzZ3PX-Yv8,27037
@@ -25,11 +25,11 @@ autocoder/agent/project_reader.py,sha256=tWLaPoLw1gI6kO_NzivQj28KbobU2ceOLuppHMb
25
25
  autocoder/chat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  autocoder/common/JupyterClient.py,sha256=O-wi6pXeAEYhAY24kDa0BINrLYvKS6rKyWe98pDClS0,2816
27
27
  autocoder/common/ShellClient.py,sha256=fM1q8t_XMSbLBl2zkCNC2J9xuyKN3eXzGm6hHhqL2WY,2286
28
- autocoder/common/__init__.py,sha256=fdXgU4PPTmb6enpLOOowMaU6gNmLgy2f6ViXO6jmBm8,11839
28
+ autocoder/common/__init__.py,sha256=xkPcT6OixAN7JLOXcvvXn23Oon0FOmzNXoysxzj6p3k,11890
29
29
  autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
30
30
  autocoder/common/anything2img.py,sha256=4TREa-sOA-iargieUy7MpyCYVUE-9Mmq0wJtwomPqnE,7662
31
31
  autocoder/common/audio.py,sha256=Kn9nWKQddWnUrAz0a_ZUgjcu4VUU_IcZBigT7n3N3qc,7439
32
- autocoder/common/auto_coder_lang.py,sha256=jnrKGze7xAhGj5Qo9yJ4wIgdSBMNwWw1cM8Y-IzMMCI,15399
32
+ autocoder/common/auto_coder_lang.py,sha256=ljREsdH6VuAeV9cPHPFsQWGxDKIVW8-oFLb8yC4lMQ0,15525
33
33
  autocoder/common/buildin_tokenizer.py,sha256=L7d5t39ZFvUd6EoMPXUhYK1toD0FHlRH1jtjKRGokWU,1236
34
34
  autocoder/common/chunk_validation.py,sha256=BrR_ZWavW8IANuueEE7hS8NFAwEvm8TX34WnPx_1hs8,3030
35
35
  autocoder/common/cleaner.py,sha256=NU72i8C6o9m0vXExab7nao5bstBUsfJFcj11cXa9l4U,1089
@@ -44,7 +44,7 @@ autocoder/common/code_auto_merge_editblock.py,sha256=sp7C0fZJMVcNgI8uWy43CKDk7gG
44
44
  autocoder/common/code_auto_merge_strict_diff.py,sha256=9rm0NJ_n6M3LohEX7xl1Jym0xmm8UEYqj_ZTSO3oSlM,9519
45
45
  autocoder/common/code_modification_ranker.py,sha256=TycYdtxfNfde2N9-9jEB-9IL2Q3PoHS-k-r9JqZYD6s,6545
46
46
  autocoder/common/command_completer.py,sha256=SSeb8MDH0JPvfdyW-S2uaHnui4VBDfSQvQPLbv3ORPA,9314
47
- autocoder/common/command_generator.py,sha256=v4LmU7sO-P7jEZIXCWHUC6P-vT7AvBi_x_PTwCqBAE8,1323
47
+ autocoder/common/command_generator.py,sha256=-hmbD_AnCa5HxL4BznuEfYAf_l8AxU5fAG5F0sM_fuE,2116
48
48
  autocoder/common/command_templates.py,sha256=mnB3n8i0yjH1mqzyClEg8Wpr9VbZV44kxky66Zu6OJY,8557
49
49
  autocoder/common/const.py,sha256=eTjhjh4Aj4CUzviJ81jaf3Y5cwqsLATySn2wJxaS6RQ,2911
50
50
  autocoder/common/files.py,sha256=CguxG9digkWBJpRaILErZmL_G5ryPRahPmPFWGB7X18,1973
@@ -61,6 +61,7 @@ autocoder/common/recall_validation.py,sha256=Avt9Q9dX3kG6Pf2zsdlOHmsjd-OeSj7U1PF
61
61
  autocoder/common/screenshots.py,sha256=_gA-z1HxGjPShBrtgkdideq58MG6rqFB2qMUJKjrycs,3769
62
62
  autocoder/common/search.py,sha256=245iPFgWhMldoUK3CqCP89ltaxZiNPK73evoG6Fp1h8,16518
63
63
  autocoder/common/search_replace.py,sha256=GphFkc57Hb673CAwmbiocqTbw8vrV7TrZxtOhD0332g,22147
64
+ autocoder/common/shells.py,sha256=zOUkGNB0MLLH9FXZfkhyAEoO0h7ZPyY35vjKou5PXf0,6937
64
65
  autocoder/common/sys_prompt.py,sha256=JlexfjZt554faqbgkCmzOJqYUzDHfbnxly5ugFfHfEE,26403
65
66
  autocoder/common/text.py,sha256=KGRQq314GHBmY4MWG8ossRoQi1_DTotvhxchpn78c-k,1003
66
67
  autocoder/common/types.py,sha256=PXTETrsTvhLE49jqAeUKGySvxBN9pjeyCgRHLDYdd9U,664
@@ -85,7 +86,7 @@ autocoder/index/symbols_utils.py,sha256=CjcjUVajmJZB75Ty3a7kMv1BZphrm-tIBAdOJv6u
85
86
  autocoder/index/types.py,sha256=a2s_KV5FJlq7jqA2ELSo9E1sjuLwDB-JJYMhSpzBAhU,596
86
87
  autocoder/index/filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
88
  autocoder/index/filter/normal_filter.py,sha256=APu34iSvWhtlLtWgkj8N3Vo4oW1TegtZQq2bwDX_cs4,8031
88
- autocoder/index/filter/quick_filter.py,sha256=7bE_-Vii04GXTd4W7wYHBag2gFViIRTEUv84yomnLhM,9496
89
+ autocoder/index/filter/quick_filter.py,sha256=rkRmDOxT2ZF2f2d-xOPtpzVxkSYiw2KWW7g7FY40A0E,9522
89
90
  autocoder/pyproject/__init__.py,sha256=dQ2_7YZ7guybT9BhfxSGn43eLQJGQN2zgeKa6--JlaQ,14403
90
91
  autocoder/rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
92
  autocoder/rag/api_server.py,sha256=dRbhAZVRAOlZ64Cnxf4_rKb4iJwHnrWS9Zr67IVORw0,7288
@@ -139,11 +140,11 @@ autocoder/utils/rest.py,sha256=hLBhr78y-WVnV0oQf9Rxc22EwqF78KINkScvYa1MuYA,6435
139
140
  autocoder/utils/tests.py,sha256=BqphrwyycGAvs-5mhH8pKtMZdObwhFtJ5MC_ZAOiLq8,1340
140
141
  autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
142
  autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
- autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=5MCtQwQDttvr0pRcYlYERFQpQAdi1Yvyf5Hm6F-_jvQ,9433
143
+ autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=5kKOrPy1GWZ6qHjni-YNJJb2x0rD7_3Idl2M9sWxVfU,10481
143
144
  autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
144
- auto_coder-0.1.248.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
145
- auto_coder-0.1.248.dist-info/METADATA,sha256=P9xWuIkH9_AVM1y1UWhGrfkvhlH2-HQmbRpilf6BUwA,2616
146
- auto_coder-0.1.248.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
147
- auto_coder-0.1.248.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
148
- auto_coder-0.1.248.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
149
- auto_coder-0.1.248.dist-info/RECORD,,
145
+ auto_coder-0.1.250.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
146
+ auto_coder-0.1.250.dist-info/METADATA,sha256=ZAZ-ZHjFf6PUo8PYcj62mgVAEO2CXzJBRSA1z-bppc8,2616
147
+ auto_coder-0.1.250.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
148
+ auto_coder-0.1.250.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
149
+ auto_coder-0.1.250.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
150
+ auto_coder-0.1.250.dist-info/RECORD,,
@@ -5,7 +5,6 @@ import byzerllm
5
5
  import pydantic
6
6
  import git
7
7
  from rich.console import Console
8
- from autocoder.utils.auto_coder_utils.chat_stream_out import stream_out
9
8
  from autocoder.common.printer import Printer
10
9
  from autocoder.common import AutoCoderArgs
11
10
  from autocoder.common.utils_code_auto_generate import stream_chat_with_continue
autocoder/auto_coder.py CHANGED
@@ -1002,15 +1002,7 @@ def main(input_args: Optional[List[str]] = None):
1002
1002
  elif raw_args.agent_command == "generate_command":
1003
1003
  from autocoder.common.command_generator import generate_shell_script
1004
1004
 
1005
- console = Console()
1006
-
1007
- console.print(
1008
- Panel(
1009
- f"Generating shell script from user input {args.query}...",
1010
- title="Command Generator",
1011
- border_style="green",
1012
- )
1013
- )
1005
+ console = Console()
1014
1006
 
1015
1007
  shell_script = generate_shell_script(args.query, llm)
1016
1008
 
@@ -1356,7 +1348,8 @@ def main(input_args: Optional[List[str]] = None):
1356
1348
  v,
1357
1349
  request_id=args.request_id,
1358
1350
  console=console,
1359
- model_name=model_name
1351
+ model_name=model_name,
1352
+ args=args
1360
1353
  )
1361
1354
 
1362
1355
  # 打印耗时和token统计
@@ -2385,64 +2385,8 @@ def list_files():
2385
2385
 
2386
2386
  @run_in_raw_thread()
2387
2387
  def execute_shell_command(command: str):
2388
- console = Console()
2389
- try:
2390
- # Use shell=True to support shell mode
2391
- process = subprocess.Popen(
2392
- command,
2393
- stdout=subprocess.PIPE,
2394
- stderr=subprocess.PIPE,
2395
- text=True,
2396
- bufsize=1,
2397
- universal_newlines=True,
2398
- shell=True,
2399
- )
2400
-
2401
- output = []
2402
- with Live(console=console, refresh_per_second=4) as live:
2403
- while True:
2404
- output_line = process.stdout.readline()
2405
- error_line = process.stderr.readline()
2406
-
2407
- if output_line:
2408
- output.append(output_line.strip())
2409
- live.update(
2410
- Panel(
2411
- Text("\n".join(output[-20:])),
2412
- title="Shell Output",
2413
- border_style="green",
2414
- )
2415
- )
2416
- if error_line:
2417
- output.append(f"ERROR: {error_line.strip()}")
2418
- live.update(
2419
- Panel(
2420
- Text("\n".join(output[-20:])),
2421
- title="Shell Output",
2422
- border_style="red",
2423
- )
2424
- )
2425
-
2426
- if (
2427
- output_line == ""
2428
- and error_line == ""
2429
- and process.poll() is not None
2430
- ):
2431
- break
2432
-
2433
- if process.returncode != 0:
2434
- console.print(
2435
- f"[bold red]Command failed with return code {process.returncode}[/bold red]"
2436
- )
2437
-
2438
- except FileNotFoundError:
2439
- console.print(
2440
- f"[bold red]Command not found:[/bold red] [yellow]{command}[/yellow]"
2441
- )
2442
- except subprocess.SubprocessError as e:
2443
- console.print(
2444
- f"[bold red]Error executing command:[/bold red] [yellow]{str(e)}[/yellow]"
2445
- )
2388
+ from autocoder.common.shells import execute_shell_command as shell_exec
2389
+ shell_exec(command)
2446
2390
 
2447
2391
 
2448
2392
  def lib_command(args: List[str]):
@@ -2723,13 +2667,13 @@ def main():
2723
2667
  if temp_user_input.startswith('/'):
2724
2668
  user_input = temp_user_input
2725
2669
 
2726
- if (
2727
- memory["mode"] == "auto_detect"
2670
+ if (
2671
+ memory["mode"] == "auto_detect"
2728
2672
  and user_input
2729
2673
  and not user_input.startswith("/")
2730
2674
  ):
2731
2675
  shell_script = generate_shell_command(user_input)
2732
- if confirm("Do you want to execute this script?"):
2676
+ if confirm(get_message("confirm_execute")):
2733
2677
  execute_shell_command(shell_script)
2734
2678
  else:
2735
2679
  continue
@@ -2850,8 +2794,8 @@ def main():
2850
2794
  command = user_input
2851
2795
  if user_input.startswith("/shell"):
2852
2796
  command = user_input[len("/shell"):].strip()
2853
- if not command:
2854
- print("Please enter a shell command to execute.")
2797
+ if not command:
2798
+ print("Please enter a shell command to execute.")
2855
2799
  else:
2856
2800
  execute_shell_command(command)
2857
2801
 
@@ -116,6 +116,7 @@ MESSAGES = {
116
116
  "commit_generating": "{{ model_name }} Generating commit message...",
117
117
  "commit_message": "{{ model_name }} Generated commit message: {{ message }}",
118
118
  "commit_failed": "{{ model_name }} Failed to generate commit message: {{ error }}",
119
+ "confirm_execute": "Do you want to execute this script?",
119
120
  },
120
121
  "zh": {
121
122
  "commit_generating": "{{ model_name }} 正在生成提交信息...",
@@ -231,6 +232,7 @@ MESSAGES = {
231
232
  "remove_files_none": "没有文件被移除。",
232
233
  "files_removed": "移除的文件",
233
234
  "models_api_key_empty": "警告: {{name}} API key 为空。请设置一个有效的 API key。",
235
+ "confirm_execute": "是否执行此脚本?",
234
236
  }
235
237
  }
236
238
 
@@ -357,6 +357,8 @@ class AutoCoderArgs(pydantic.BaseModel):
357
357
  enable_global_memory: Optional[bool] = True
358
358
  product_mode: Optional[str] = "lite"
359
359
 
360
+ keep_reasoning_content: Optional[bool] = True
361
+
360
362
  in_code_apply: bool = False
361
363
 
362
364
  class Config:
@@ -4,6 +4,7 @@ from byzerllm.utils import format_str_jinja2
4
4
  MESSAGES = {
5
5
  "en": {
6
6
  "model_not_found": "Model {{model_name}} not found",
7
+ "generating_shell_script": "Generating Shell Script",
7
8
  "new_session_started": "New session started. Previous chat history has been archived.",
8
9
  "memory_save_success": "✅ Saved to your memory",
9
10
  "file_decode_error": "Failed to decode file: {{file_path}}. Tried encodings: {{encodings}}",
@@ -89,6 +90,7 @@ MESSAGES = {
89
90
  },
90
91
  "zh": {
91
92
  "model_not_found": "未找到模型: {{model_name}}",
93
+ "generating_shell_script": "正在生成 Shell 脚本",
92
94
  "new_session_started": "新会话已开始。之前的聊天历史已存档。",
93
95
  "memory_save_success": "✅ 已保存到您的记忆中",
94
96
  "file_decode_error": "无法解码文件: {{file_path}}。尝试的编码: {{encodings}}",
@@ -1,7 +1,9 @@
1
1
  import byzerllm
2
2
  from byzerllm.utils.client import code_utils
3
+ from autocoder.utils.auto_coder_utils.chat_stream_out import stream_out
3
4
  from autocoder.common import detect_env
4
-
5
+ from autocoder.common import shells
6
+ from autocoder.common.printer import Printer
5
7
 
6
8
  @byzerllm.prompt()
7
9
  def _generate_shell_script(user_input: str) -> str:
@@ -10,36 +12,51 @@ def _generate_shell_script(user_input: str) -> str:
10
12
 
11
13
  操作系统: {{ env_info.os_name }} {{ env_info.os_version }}
12
14
  Python版本: {{ env_info.python_version }}
15
+ 终端类型: {{ env_info.shell_type }}
16
+ 终端编码: {{ env_info.shell_encoding }}
13
17
  {%- if env_info.conda_env %}
14
18
  Conda环境: {{ env_info.conda_env }}
15
19
  {%- endif %}
16
20
  {%- if env_info.virtualenv %}
17
21
  虚拟环境: {{ env_info.virtualenv }}
18
- {%- endif %}
19
- {%- if env_info.has_bash %}
20
- 支持Bash
21
- {%- else %}
22
- 不支持Bash
23
- {%- endif %}
22
+ {%- endif %}
24
23
 
25
- 根据用户的输入以及当前的操作系统生成合适的 shell 脚本。
24
+ 根据用户的输入以及当前的操作系统和Shell类型生成合适的 shell 脚本,注意只能生成一个shell脚本,不要生成多个。
26
25
 
27
26
  用户输入: {{ user_input }}
28
27
 
29
- 请生成一个适当的 shell 脚本来执行用户的请求。确保脚本是安全的,并且可以在操作系统支持的 shell 中运行。
28
+ 请生成一个适当的 shell 脚本来执行用户的请求。确保脚本是安全的,并且可以在当前Shell环境中运行。
30
29
  脚本应该包含必要的注释来解释每个步骤。
31
- 脚本内容请用如下方式返回:
30
+ 脚本内容请用如下方式返回:
32
31
 
33
32
  ```shell
34
33
  # 你的 shell 脚本内容
35
34
  ```
36
35
  """
36
+ env_info = detect_env()
37
37
  return {
38
- "env_info": detect_env()
38
+ "env_info": env_info,
39
+ "shell_type": shells.get_terminal_name(),
40
+ "shell_encoding": shells.get_terminal_encoding()
39
41
  }
40
42
 
41
43
 
42
44
  def generate_shell_script(user_input: str, llm: byzerllm.ByzerLLM) -> str:
43
- result = _generate_shell_script.with_llm(llm).run(user_input=user_input)
44
- code = code_utils.extract_code(result)[0][1]
45
+ # 获取 prompt 内容
46
+ prompt = _generate_shell_script.prompt(user_input=user_input)
47
+
48
+ # 构造对话上下文
49
+ conversations = [{"role": "user", "content": prompt}]
50
+
51
+ # 使用 stream_out 进行输出
52
+ printer = Printer()
53
+ title = printer.get_message_from_key("generating_shell_script")
54
+ result, _ = stream_out(
55
+ llm.stream_chat_oai(conversations=conversations, delta_mode=True),
56
+ model_name=llm.default_model_name,
57
+ title=title
58
+ )
59
+
60
+ # 提取代码块
61
+ code = code_utils.extract_code(result)[-1][1]
45
62
  return code
@@ -0,0 +1,225 @@
1
+
2
+ import sys
3
+ import os
4
+ import locale
5
+ import subprocess
6
+ import platform
7
+ from rich.console import Console
8
+ from rich.panel import Panel
9
+ from rich.text import Text
10
+ from rich.live import Live
11
+
12
+ def get_terminal_name() -> str:
13
+ """
14
+ 获取当前终端名称(自动适配 Windows/Linux/Mac)
15
+ 返回终端名称如: cmd.exe, bash, zsh 等
16
+ """
17
+ if sys.platform == 'win32':
18
+ return _get_windows_terminal_name()
19
+ else:
20
+ return _get_unix_terminal_name()
21
+
22
+ def _get_windows_terminal_name() -> str:
23
+ """Windows 系统终端检测"""
24
+ # 检查是否在 PowerShell
25
+ if 'POWERSHELL_DISTRIBUTION_CHANNEL' in os.environ:
26
+ return 'powershell'
27
+
28
+ # 检查是否在 Git Bash
29
+ if 'MINGW' in platform.system():
30
+ return 'git-bash'
31
+
32
+ # 默认返回 cmd.exe
33
+ return 'cmd.exe'
34
+
35
+ def _get_unix_terminal_name() -> str:
36
+ """Linux/Mac 系统终端检测"""
37
+ # 从环境变量获取终端名称
38
+ term = os.environ.get('TERM')
39
+ shell = os.environ.get('SHELL', '')
40
+
41
+ # 检查是否在 VS Code 终端
42
+ if 'VSCODE_GIT_IPC_HANDLE' in os.environ:
43
+ return 'vscode-terminal'
44
+
45
+ # 如果是 Mac 的 Terminal.app
46
+ if sys.platform == 'darwin' and 'Apple_Terminal' in os.environ.get('TERM_PROGRAM', ''):
47
+ return 'terminal.app'
48
+
49
+ # 从 shell 路径获取终端名称
50
+ if shell:
51
+ shell_name = os.path.basename(shell)
52
+ if shell_name in ['bash', 'zsh', 'fish']:
53
+ return shell_name
54
+
55
+ # 从 TERM 环境变量判断
56
+ if term:
57
+ if 'xterm' in term:
58
+ return 'xterm'
59
+ elif 'rxvt' in term:
60
+ return 'rxvt'
61
+ elif 'screen' in term:
62
+ return 'screen'
63
+ elif 'tmux' in term:
64
+ return 'tmux'
65
+
66
+ return 'unknown'
67
+
68
+ def get_terminal_encoding() -> str:
69
+ """
70
+ 获取当前终端编码(自动适配 Windows/Linux/Mac)
71
+ 返回标准编码名称如: utf-8, gbk, cp936 等
72
+ """
73
+ # 第一优先级:尝试标准库locale检测
74
+ try:
75
+ return locale.getencoding() # Python 3.10+ 新增方法
76
+ except AttributeError:
77
+ pass
78
+
79
+ # 第二优先级:各平台专用检测逻辑
80
+ if sys.platform == 'win32':
81
+ return _get_windows_terminal_encoding()
82
+ else:
83
+ return _get_unix_terminal_encoding()
84
+
85
+ def _get_windows_terminal_encoding() -> str:
86
+ """Windows 系统编码检测"""
87
+ try:
88
+ # 通过 chcp 命令获取代码页
89
+ result = subprocess.run(
90
+ ['chcp'],
91
+ capture_output=True,
92
+ text=True,
93
+ shell=True,
94
+ timeout=1
95
+ )
96
+ code_page = result.stdout.split(':')[-1].strip()
97
+ return _win_code_page_to_encoding(code_page)
98
+ except Exception:
99
+ return locale.getpreferredencoding(do_setlocale=False) or 'gbk'
100
+
101
+ def _get_unix_terminal_encoding() -> str:
102
+ """Linux/Mac 系统编码检测"""
103
+ # 尝试读取环境变量
104
+ for var in ['LC_ALL', 'LC_CTYPE', 'LANG']:
105
+ lang = os.environ.get(var)
106
+ if lang and '.' in lang:
107
+ return lang.split('.')[-1]
108
+
109
+ # 通过 locale 命令检测
110
+ try:
111
+ result = subprocess.run(
112
+ ['locale', '-c', 'LC_CTYPE'],
113
+ capture_output=True,
114
+ text=True,
115
+ timeout=1
116
+ )
117
+ return result.stdout.strip().split('.')[-1] or 'utf-8'
118
+ except Exception:
119
+ return locale.getpreferredencoding(do_setlocale=False) or 'utf-8'
120
+
121
+ def _win_code_page_to_encoding(code_page: str) -> str:
122
+ """Windows 代码页转编码名称"""
123
+ cp_map = {
124
+ '65001': 'utf-8',
125
+ '936': 'gbk',
126
+ '950': 'big5',
127
+ '54936': 'gb18030',
128
+ '437': 'cp437',
129
+ '850': 'cp850'
130
+ }
131
+ return cp_map.get(code_page, f'cp{code_page}')
132
+
133
+ def execute_shell_command(command: str):
134
+ """
135
+ Execute a shell command with cross-platform encoding support.
136
+
137
+ Args:
138
+ command (str): The shell command to execute
139
+ encoding (str, optional): Override default encoding. Defaults to None.
140
+ """
141
+ console = Console()
142
+ try:
143
+ # Get terminal encoding
144
+ encoding = get_terminal_encoding()
145
+
146
+ # Start subprocess
147
+ process = subprocess.Popen(
148
+ command,
149
+ stdout=subprocess.PIPE,
150
+ stderr=subprocess.PIPE,
151
+ shell=True
152
+ )
153
+
154
+ # Safe decoding helper
155
+ def safe_decode(byte_stream, encoding):
156
+ try:
157
+ return byte_stream.decode(encoding).strip()
158
+ except UnicodeDecodeError:
159
+ return byte_stream.decode(encoding, errors='replace').strip()
160
+
161
+ output = []
162
+ with Live(console=console, refresh_per_second=4) as live:
163
+ while True:
164
+ # Read output streams
165
+ output_bytes = process.stdout.readline()
166
+ error_bytes = process.stderr.readline()
167
+
168
+ # Handle standard output
169
+ if output_bytes:
170
+ output_line = safe_decode(output_bytes, encoding)
171
+ output.append(output_line)
172
+ live.update(
173
+ Panel(
174
+ Text("\n".join(output[-20:])),
175
+ title="Shell Output",
176
+ border_style="green",
177
+ )
178
+ )
179
+
180
+ # Handle error output
181
+ if error_bytes:
182
+ error_line = safe_decode(error_bytes, encoding)
183
+ output.append(f"ERROR: {error_line}")
184
+ live.update(
185
+ Panel(
186
+ Text("\n".join(output[-20:])),
187
+ title="Shell Output",
188
+ border_style="red",
189
+ )
190
+ )
191
+
192
+ # Check if process has ended
193
+ if process.poll() is not None:
194
+ break
195
+
196
+ # Get remaining output
197
+ remaining_out, remaining_err = process.communicate()
198
+ if remaining_out:
199
+ output.append(safe_decode(remaining_out, encoding))
200
+ if remaining_err:
201
+ output.append(f"ERROR: {safe_decode(remaining_err, encoding)}")
202
+
203
+ # Show final output
204
+ console.print(
205
+ Panel(
206
+ Text("\n".join(output)),
207
+ title="Final Output",
208
+ border_style="blue",
209
+ subtitle=f"Encoding: {encoding} | OS: {sys.platform}"
210
+ )
211
+ )
212
+
213
+ if process.returncode != 0:
214
+ console.print(
215
+ f"[bold red]Command failed with code {process.returncode}[/bold red]"
216
+ )
217
+
218
+ except FileNotFoundError:
219
+ console.print(
220
+ f"[bold red]Command not found:[/bold red] [yellow]{command}[/yellow]"
221
+ )
222
+ except Exception as e:
223
+ console.print(
224
+ f"[bold red]Unexpected error:[/bold red] [yellow]{str(e)}[/yellow]"
225
+ )
@@ -84,7 +84,8 @@ class QuickFilter():
84
84
  full_response, _ = stream_out(
85
85
  stream_generator,
86
86
  model_name=model_name,
87
- title=self.printer.get_message_from_key_with_format("quick_filter_title", model_name=model_name)
87
+ title=self.printer.get_message_from_key_with_format("quick_filter_title", model_name=model_name),
88
+ args=self.args
88
89
  )
89
90
  file_number_list = to_model(full_response, FileNumberList)
90
91
  else:
@@ -162,8 +163,7 @@ class QuickFilter():
162
163
 
163
164
  def filter(self, index_items: List[IndexItem], query: str) -> Dict[str, TargetFile]:
164
165
  final_files: Dict[str, TargetFile] = {}
165
- start_time = time.monotonic()
166
- index_items = self.index_manager.read_index()
166
+ start_time = time.monotonic()
167
167
 
168
168
  prompt_str = self.quick_filter_files.prompt(index_items,query)
169
169
 
@@ -198,7 +198,8 @@ class QuickFilter():
198
198
  full_response, last_meta = stream_out(
199
199
  stream_generator,
200
200
  model_name=model_name,
201
- title=self.printer.get_message_from_key_with_format("quick_filter_title", model_name=model_name)
201
+ title=self.printer.get_message_from_key_with_format("quick_filter_title", model_name=model_name),
202
+ args=self.args
202
203
  )
203
204
  # 解析结果
204
205
  file_number_list = to_model(full_response, FileNumberList)
@@ -10,6 +10,7 @@ from autocoder.utils.request_queue import RequestValue, RequestOption, StreamVal
10
10
  from autocoder.utils.request_queue import request_queue
11
11
  import time
12
12
  from byzerllm.utils.types import SingleOutputMeta
13
+ from autocoder.common import AutoCoderArgs
13
14
 
14
15
  MAX_HISTORY_LINES = 40 # 最大保留历史行数
15
16
 
@@ -144,7 +145,8 @@ def stream_out(
144
145
  request_id: Optional[str] = None,
145
146
  console: Optional[Console] = None,
146
147
  model_name: Optional[str] = None,
147
- title: Optional[str] = None
148
+ title: Optional[str] = None,
149
+ args: Optional[AutoCoderArgs] = None
148
150
  ) -> Tuple[str, Optional[SingleOutputMeta]]:
149
151
  """
150
152
  处理流式输出事件并在终端中展示
@@ -155,17 +157,22 @@ def stream_out(
155
157
  console: Rich Console对象
156
158
  model_name: 模型名称
157
159
  title: 面板标题,如果没有提供则使用默认值
160
+ args: AutoCoderArgs对象
158
161
  Returns:
159
- Tuple[str, Dict[str, Any]]: 返回完整的响应内容和最后的元数据
162
+ Tuple[str, Dict[SingleOutputMeta]]: 返回完整的响应内容和最后的元数据
160
163
  """
161
164
  if console is None:
162
165
  console = Console(force_terminal=True, color_system="auto", height=None)
163
-
166
+
167
+ keep_reasoning_content = True
168
+ if args:
169
+ keep_reasoning_content = args.keep_reasoning_content
170
+
164
171
  lines_buffer = [] # 存储历史行
165
172
  current_line = "" # 当前行
166
173
  assistant_response = ""
167
174
  last_meta = None
168
- panel_title = title if title is not None else f"Response[ {model_name} ]"
175
+ panel_title = title if title is not None else f"Response[ {model_name} ]"
169
176
  try:
170
177
  with Live(
171
178
  Panel("", title=panel_title, border_style="green"),
@@ -179,8 +186,22 @@ def stream_out(
179
186
 
180
187
  if reasoning_content == "" and content == "":
181
188
  continue
182
-
183
- assistant_response += content
189
+
190
+ if keep_reasoning_content:
191
+ # 处理思考内容
192
+ if reasoning_content:
193
+ if assistant_response == "": # 首次遇到思考内容时添加开标签
194
+ assistant_response = "<thinking>"
195
+ assistant_response += reasoning_content
196
+
197
+ # 处理正式内容
198
+ if content:
199
+ # 如果之前有思考内容,需要先关闭thinking标签
200
+ if "</thinking>" not in assistant_response and "<thinking>" in assistant_response:
201
+ assistant_response += "</thinking>"
202
+ assistant_response += content
203
+ else:
204
+ assistant_response += content
184
205
 
185
206
  display_delta = reasoning_content if reasoning_content else content
186
207
 
@@ -230,7 +251,7 @@ def stream_out(
230
251
  title=f"Final {panel_title}",
231
252
  border_style="blue"
232
253
  )
233
- )
254
+ )
234
255
 
235
256
  except Exception as e:
236
257
  console.print(Panel(
autocoder/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.248"
1
+ __version__ = "0.1.250"