chatmcp-cli 0.1.0__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.
Files changed (228) hide show
  1. aider/__init__.py +20 -0
  2. aider/__main__.py +4 -0
  3. aider/_version.py +21 -0
  4. aider/analytics.py +250 -0
  5. aider/args.py +926 -0
  6. aider/args_formatter.py +228 -0
  7. aider/coders/__init__.py +34 -0
  8. aider/coders/architect_coder.py +48 -0
  9. aider/coders/architect_prompts.py +40 -0
  10. aider/coders/ask_coder.py +9 -0
  11. aider/coders/ask_prompts.py +35 -0
  12. aider/coders/base_coder.py +2483 -0
  13. aider/coders/base_prompts.py +60 -0
  14. aider/coders/chat_chunks.py +64 -0
  15. aider/coders/context_coder.py +53 -0
  16. aider/coders/context_prompts.py +75 -0
  17. aider/coders/editblock_coder.py +657 -0
  18. aider/coders/editblock_fenced_coder.py +10 -0
  19. aider/coders/editblock_fenced_prompts.py +143 -0
  20. aider/coders/editblock_func_coder.py +141 -0
  21. aider/coders/editblock_func_prompts.py +27 -0
  22. aider/coders/editblock_prompts.py +174 -0
  23. aider/coders/editor_diff_fenced_coder.py +9 -0
  24. aider/coders/editor_diff_fenced_prompts.py +11 -0
  25. aider/coders/editor_editblock_coder.py +8 -0
  26. aider/coders/editor_editblock_prompts.py +18 -0
  27. aider/coders/editor_whole_coder.py +8 -0
  28. aider/coders/editor_whole_prompts.py +10 -0
  29. aider/coders/help_coder.py +16 -0
  30. aider/coders/help_prompts.py +46 -0
  31. aider/coders/patch_coder.py +706 -0
  32. aider/coders/patch_prompts.py +161 -0
  33. aider/coders/search_replace.py +757 -0
  34. aider/coders/shell.py +37 -0
  35. aider/coders/single_wholefile_func_coder.py +102 -0
  36. aider/coders/single_wholefile_func_prompts.py +27 -0
  37. aider/coders/udiff_coder.py +429 -0
  38. aider/coders/udiff_prompts.py +115 -0
  39. aider/coders/udiff_simple.py +14 -0
  40. aider/coders/udiff_simple_prompts.py +25 -0
  41. aider/coders/wholefile_coder.py +144 -0
  42. aider/coders/wholefile_func_coder.py +134 -0
  43. aider/coders/wholefile_func_prompts.py +27 -0
  44. aider/coders/wholefile_prompts.py +67 -0
  45. aider/commands.py +1665 -0
  46. aider/copypaste.py +72 -0
  47. aider/deprecated.py +126 -0
  48. aider/diffs.py +128 -0
  49. aider/dump.py +29 -0
  50. aider/editor.py +147 -0
  51. aider/exceptions.py +107 -0
  52. aider/format_settings.py +26 -0
  53. aider/gui.py +545 -0
  54. aider/help.py +163 -0
  55. aider/help_pats.py +19 -0
  56. aider/history.py +143 -0
  57. aider/io.py +1175 -0
  58. aider/linter.py +304 -0
  59. aider/llm.py +47 -0
  60. aider/main.py +1267 -0
  61. aider/mdstream.py +243 -0
  62. aider/models.py +1286 -0
  63. aider/onboarding.py +428 -0
  64. aider/openrouter.py +128 -0
  65. aider/prompts.py +64 -0
  66. aider/queries/tree-sitter-language-pack/README.md +7 -0
  67. aider/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  68. aider/queries/tree-sitter-language-pack/c-tags.scm +9 -0
  69. aider/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  70. aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
  71. aider/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
  72. aider/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
  73. aider/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  74. aider/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
  75. aider/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  76. aider/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
  77. aider/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
  78. aider/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  79. aider/queries/tree-sitter-language-pack/go-tags.scm +42 -0
  80. aider/queries/tree-sitter-language-pack/java-tags.scm +20 -0
  81. aider/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
  82. aider/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
  83. aider/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  84. aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
  85. aider/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  86. aider/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  87. aider/queries/tree-sitter-language-pack/python-tags.scm +14 -0
  88. aider/queries/tree-sitter-language-pack/r-tags.scm +21 -0
  89. aider/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  90. aider/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
  91. aider/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
  92. aider/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  93. aider/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
  94. aider/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  95. aider/queries/tree-sitter-languages/README.md +23 -0
  96. aider/queries/tree-sitter-languages/c-tags.scm +9 -0
  97. aider/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  98. aider/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  99. aider/queries/tree-sitter-languages/dart-tags.scm +91 -0
  100. aider/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  101. aider/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  102. aider/queries/tree-sitter-languages/elm-tags.scm +19 -0
  103. aider/queries/tree-sitter-languages/go-tags.scm +30 -0
  104. aider/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  105. aider/queries/tree-sitter-languages/java-tags.scm +20 -0
  106. aider/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  107. aider/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  108. aider/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  109. aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  110. aider/queries/tree-sitter-languages/php-tags.scm +26 -0
  111. aider/queries/tree-sitter-languages/python-tags.scm +12 -0
  112. aider/queries/tree-sitter-languages/ql-tags.scm +26 -0
  113. aider/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  114. aider/queries/tree-sitter-languages/rust-tags.scm +60 -0
  115. aider/queries/tree-sitter-languages/scala-tags.scm +65 -0
  116. aider/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  117. aider/reasoning_tags.py +82 -0
  118. aider/repo.py +623 -0
  119. aider/repomap.py +847 -0
  120. aider/report.py +200 -0
  121. aider/resources/__init__.py +3 -0
  122. aider/resources/model-metadata.json +468 -0
  123. aider/resources/model-settings.yml +1767 -0
  124. aider/run_cmd.py +132 -0
  125. aider/scrape.py +284 -0
  126. aider/sendchat.py +61 -0
  127. aider/special.py +203 -0
  128. aider/urls.py +17 -0
  129. aider/utils.py +338 -0
  130. aider/versioncheck.py +113 -0
  131. aider/voice.py +187 -0
  132. aider/waiting.py +221 -0
  133. aider/watch.py +318 -0
  134. aider/watch_prompts.py +12 -0
  135. aider/website/Gemfile +8 -0
  136. aider/website/_includes/blame.md +162 -0
  137. aider/website/_includes/get-started.md +22 -0
  138. aider/website/_includes/help-tip.md +5 -0
  139. aider/website/_includes/help.md +24 -0
  140. aider/website/_includes/install.md +5 -0
  141. aider/website/_includes/keys.md +4 -0
  142. aider/website/_includes/model-warnings.md +67 -0
  143. aider/website/_includes/multi-line.md +22 -0
  144. aider/website/_includes/python-m-aider.md +5 -0
  145. aider/website/_includes/recording.css +228 -0
  146. aider/website/_includes/recording.md +34 -0
  147. aider/website/_includes/replit-pipx.md +9 -0
  148. aider/website/_includes/works-best.md +1 -0
  149. aider/website/_sass/custom/custom.scss +103 -0
  150. aider/website/docs/config/adv-model-settings.md +1881 -0
  151. aider/website/docs/config/aider_conf.md +527 -0
  152. aider/website/docs/config/api-keys.md +90 -0
  153. aider/website/docs/config/dotenv.md +478 -0
  154. aider/website/docs/config/editor.md +127 -0
  155. aider/website/docs/config/model-aliases.md +103 -0
  156. aider/website/docs/config/options.md +843 -0
  157. aider/website/docs/config/reasoning.md +209 -0
  158. aider/website/docs/config.md +44 -0
  159. aider/website/docs/faq.md +378 -0
  160. aider/website/docs/git.md +76 -0
  161. aider/website/docs/index.md +47 -0
  162. aider/website/docs/install/codespaces.md +39 -0
  163. aider/website/docs/install/docker.md +57 -0
  164. aider/website/docs/install/optional.md +100 -0
  165. aider/website/docs/install/replit.md +8 -0
  166. aider/website/docs/install.md +115 -0
  167. aider/website/docs/languages.md +264 -0
  168. aider/website/docs/legal/contributor-agreement.md +111 -0
  169. aider/website/docs/legal/privacy.md +104 -0
  170. aider/website/docs/llms/anthropic.md +77 -0
  171. aider/website/docs/llms/azure.md +48 -0
  172. aider/website/docs/llms/bedrock.md +132 -0
  173. aider/website/docs/llms/cohere.md +34 -0
  174. aider/website/docs/llms/deepseek.md +32 -0
  175. aider/website/docs/llms/gemini.md +49 -0
  176. aider/website/docs/llms/github.md +105 -0
  177. aider/website/docs/llms/groq.md +36 -0
  178. aider/website/docs/llms/lm-studio.md +39 -0
  179. aider/website/docs/llms/ollama.md +75 -0
  180. aider/website/docs/llms/openai-compat.md +39 -0
  181. aider/website/docs/llms/openai.md +58 -0
  182. aider/website/docs/llms/openrouter.md +78 -0
  183. aider/website/docs/llms/other.md +103 -0
  184. aider/website/docs/llms/vertex.md +50 -0
  185. aider/website/docs/llms/warnings.md +10 -0
  186. aider/website/docs/llms/xai.md +53 -0
  187. aider/website/docs/llms.md +54 -0
  188. aider/website/docs/more/analytics.md +122 -0
  189. aider/website/docs/more/edit-formats.md +116 -0
  190. aider/website/docs/more/infinite-output.md +137 -0
  191. aider/website/docs/more-info.md +8 -0
  192. aider/website/docs/recordings/auto-accept-architect.md +31 -0
  193. aider/website/docs/recordings/dont-drop-original-read-files.md +35 -0
  194. aider/website/docs/recordings/index.md +21 -0
  195. aider/website/docs/recordings/model-accepts-settings.md +69 -0
  196. aider/website/docs/recordings/tree-sitter-language-pack.md +80 -0
  197. aider/website/docs/repomap.md +112 -0
  198. aider/website/docs/scripting.md +100 -0
  199. aider/website/docs/troubleshooting/aider-not-found.md +24 -0
  200. aider/website/docs/troubleshooting/edit-errors.md +76 -0
  201. aider/website/docs/troubleshooting/imports.md +62 -0
  202. aider/website/docs/troubleshooting/models-and-keys.md +54 -0
  203. aider/website/docs/troubleshooting/support.md +79 -0
  204. aider/website/docs/troubleshooting/token-limits.md +96 -0
  205. aider/website/docs/troubleshooting/warnings.md +12 -0
  206. aider/website/docs/troubleshooting.md +11 -0
  207. aider/website/docs/usage/browser.md +57 -0
  208. aider/website/docs/usage/caching.md +49 -0
  209. aider/website/docs/usage/commands.md +132 -0
  210. aider/website/docs/usage/conventions.md +119 -0
  211. aider/website/docs/usage/copypaste.md +121 -0
  212. aider/website/docs/usage/images-urls.md +48 -0
  213. aider/website/docs/usage/lint-test.md +118 -0
  214. aider/website/docs/usage/modes.md +211 -0
  215. aider/website/docs/usage/not-code.md +179 -0
  216. aider/website/docs/usage/notifications.md +87 -0
  217. aider/website/docs/usage/tips.md +79 -0
  218. aider/website/docs/usage/tutorials.md +30 -0
  219. aider/website/docs/usage/voice.md +121 -0
  220. aider/website/docs/usage/watch.md +294 -0
  221. aider/website/docs/usage.md +92 -0
  222. aider/website/share/index.md +101 -0
  223. chatmcp_cli-0.1.0.dist-info/METADATA +502 -0
  224. chatmcp_cli-0.1.0.dist-info/RECORD +228 -0
  225. chatmcp_cli-0.1.0.dist-info/WHEEL +5 -0
  226. chatmcp_cli-0.1.0.dist-info/entry_points.txt +3 -0
  227. chatmcp_cli-0.1.0.dist-info/licenses/LICENSE.txt +202 -0
  228. chatmcp_cli-0.1.0.dist-info/top_level.txt +1 -0
aider/run_cmd.py ADDED
@@ -0,0 +1,132 @@
1
+ import os
2
+ import platform
3
+ import subprocess
4
+ import sys
5
+ from io import BytesIO
6
+
7
+ import pexpect
8
+ import psutil
9
+
10
+
11
+ def run_cmd(command, verbose=False, error_print=None, cwd=None):
12
+ try:
13
+ if sys.stdin.isatty() and hasattr(pexpect, "spawn") and platform.system() != "Windows":
14
+ return run_cmd_pexpect(command, verbose, cwd)
15
+
16
+ return run_cmd_subprocess(command, verbose, cwd)
17
+ except OSError as e:
18
+ error_message = f"Error occurred while running command '{command}': {str(e)}"
19
+ if error_print is None:
20
+ print(error_message)
21
+ else:
22
+ error_print(error_message)
23
+ return 1, error_message
24
+
25
+
26
+ def get_windows_parent_process_name():
27
+ try:
28
+ current_process = psutil.Process()
29
+ while True:
30
+ parent = current_process.parent()
31
+ if parent is None:
32
+ break
33
+ parent_name = parent.name().lower()
34
+ if parent_name in ["powershell.exe", "cmd.exe"]:
35
+ return parent_name
36
+ current_process = parent
37
+ return None
38
+ except Exception:
39
+ return None
40
+
41
+
42
+ def run_cmd_subprocess(command, verbose=False, cwd=None, encoding=sys.stdout.encoding):
43
+ if verbose:
44
+ print("Using run_cmd_subprocess:", command)
45
+
46
+ try:
47
+ shell = os.environ.get("SHELL", "/bin/sh")
48
+ parent_process = None
49
+
50
+ # Determine the appropriate shell
51
+ if platform.system() == "Windows":
52
+ parent_process = get_windows_parent_process_name()
53
+ if parent_process == "powershell.exe":
54
+ command = f"powershell -Command {command}"
55
+
56
+ if verbose:
57
+ print("Running command:", command)
58
+ print("SHELL:", shell)
59
+ if platform.system() == "Windows":
60
+ print("Parent process:", parent_process)
61
+
62
+ process = subprocess.Popen(
63
+ command,
64
+ stdout=subprocess.PIPE,
65
+ stderr=subprocess.STDOUT,
66
+ text=True,
67
+ shell=True,
68
+ encoding=encoding,
69
+ errors="replace",
70
+ bufsize=0, # Set bufsize to 0 for unbuffered output
71
+ universal_newlines=True,
72
+ cwd=cwd,
73
+ )
74
+
75
+ output = []
76
+ while True:
77
+ chunk = process.stdout.read(1)
78
+ if not chunk:
79
+ break
80
+ print(chunk, end="", flush=True) # Print the chunk in real-time
81
+ output.append(chunk) # Store the chunk for later use
82
+
83
+ process.wait()
84
+ return process.returncode, "".join(output)
85
+ except Exception as e:
86
+ return 1, str(e)
87
+
88
+
89
+ def run_cmd_pexpect(command, verbose=False, cwd=None):
90
+ """
91
+ Run a shell command interactively using pexpect, capturing all output.
92
+
93
+ :param command: The command to run as a string.
94
+ :param verbose: If True, print output in real-time.
95
+ :return: A tuple containing (exit_status, output)
96
+ """
97
+ if verbose:
98
+ print("Using run_cmd_pexpect:", command)
99
+
100
+ output = BytesIO()
101
+
102
+ def output_callback(b):
103
+ output.write(b)
104
+ return b
105
+
106
+ try:
107
+ # Use the SHELL environment variable, falling back to /bin/sh if not set
108
+ shell = os.environ.get("SHELL", "/bin/sh")
109
+ if verbose:
110
+ print("With shell:", shell)
111
+
112
+ if os.path.exists(shell):
113
+ # Use the shell from SHELL environment variable
114
+ if verbose:
115
+ print("Running pexpect.spawn with shell:", shell)
116
+ child = pexpect.spawn(shell, args=["-i", "-c", command], encoding="utf-8", cwd=cwd)
117
+ else:
118
+ # Fall back to spawning the command directly
119
+ if verbose:
120
+ print("Running pexpect.spawn without shell.")
121
+ child = pexpect.spawn(command, encoding="utf-8", cwd=cwd)
122
+
123
+ # Transfer control to the user, capturing output
124
+ child.interact(output_filter=output_callback)
125
+
126
+ # Wait for the command to finish and get the exit status
127
+ child.close()
128
+ return child.exitstatus, output.getvalue().decode("utf-8", errors="replace")
129
+
130
+ except (pexpect.ExceptionPexpect, TypeError, ValueError) as e:
131
+ error_msg = f"Error running command {command}: {e}"
132
+ return 1, error_msg
aider/scrape.py ADDED
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env python
2
+
3
+ import re
4
+ import sys
5
+
6
+ import pypandoc
7
+
8
+ from aider import __version__, urls, utils
9
+ from aider.dump import dump # noqa: F401
10
+
11
+ aider_user_agent = f"Aider/{__version__} +{urls.website}"
12
+
13
+ # Playwright is nice because it has a simple way to install dependencies on most
14
+ # platforms.
15
+
16
+
17
+ def check_env():
18
+ try:
19
+ from playwright.sync_api import sync_playwright
20
+
21
+ has_pip = True
22
+ except ImportError:
23
+ has_pip = False
24
+
25
+ try:
26
+ with sync_playwright() as p:
27
+ p.chromium.launch()
28
+ has_chromium = True
29
+ except Exception:
30
+ has_chromium = False
31
+
32
+ return has_pip, has_chromium
33
+
34
+
35
+ def has_playwright():
36
+ has_pip, has_chromium = check_env()
37
+ return has_pip and has_chromium
38
+
39
+
40
+ def install_playwright(io):
41
+ has_pip, has_chromium = check_env()
42
+ if has_pip and has_chromium:
43
+ return True
44
+
45
+ pip_cmd = utils.get_pip_install(["aider-chat[playwright]"])
46
+ chromium_cmd = "-m playwright install --with-deps chromium"
47
+ chromium_cmd = [sys.executable] + chromium_cmd.split()
48
+
49
+ cmds = ""
50
+ if not has_pip:
51
+ cmds += " ".join(pip_cmd) + "\n"
52
+ if not has_chromium:
53
+ cmds += " ".join(chromium_cmd) + "\n"
54
+
55
+ text = f"""For the best web scraping, install Playwright:
56
+
57
+ {cmds}
58
+ See {urls.enable_playwright} for more info.
59
+ """
60
+
61
+ io.tool_output(text)
62
+ if not io.confirm_ask("Install playwright?", default="y"):
63
+ return
64
+
65
+ if not has_pip:
66
+ success, output = utils.run_install(pip_cmd)
67
+ if not success:
68
+ io.tool_error(output)
69
+ return
70
+
71
+ success, output = utils.run_install(chromium_cmd)
72
+ if not success:
73
+ io.tool_error(output)
74
+ return
75
+
76
+ return True
77
+
78
+
79
+ class Scraper:
80
+ pandoc_available = None
81
+ playwright_available = None
82
+ playwright_instructions_shown = False
83
+
84
+ # Public API...
85
+ def __init__(self, print_error=None, playwright_available=None, verify_ssl=True):
86
+ """
87
+ `print_error` - a function to call to print error/debug info.
88
+ `verify_ssl` - if False, disable SSL certificate verification when scraping.
89
+ """
90
+ if print_error:
91
+ self.print_error = print_error
92
+ else:
93
+ self.print_error = print
94
+
95
+ self.playwright_available = playwright_available
96
+ self.verify_ssl = verify_ssl
97
+
98
+ def scrape(self, url):
99
+ """
100
+ Scrape a url and turn it into readable markdown if it's HTML.
101
+ If it's plain text or non-HTML, return it as-is.
102
+
103
+ `url` - the URL to scrape.
104
+ """
105
+
106
+ if self.playwright_available:
107
+ content, mime_type = self.scrape_with_playwright(url)
108
+ else:
109
+ content, mime_type = self.scrape_with_httpx(url)
110
+
111
+ if not content:
112
+ self.print_error(f"Failed to retrieve content from {url}")
113
+ return None
114
+
115
+ # Check if the content is HTML based on MIME type or content
116
+ if (mime_type and mime_type.startswith("text/html")) or (
117
+ mime_type is None and self.looks_like_html(content)
118
+ ):
119
+ self.try_pandoc()
120
+ content = self.html_to_markdown(content)
121
+
122
+ return content
123
+
124
+ def looks_like_html(self, content):
125
+ """
126
+ Check if the content looks like HTML.
127
+ """
128
+ if isinstance(content, str):
129
+ # Check for common HTML tags
130
+ html_patterns = [
131
+ r"<!DOCTYPE\s+html",
132
+ r"<html",
133
+ r"<head",
134
+ r"<body",
135
+ r"<div",
136
+ r"<p>",
137
+ r"<a\s+href=",
138
+ ]
139
+ return any(re.search(pattern, content, re.IGNORECASE) for pattern in html_patterns)
140
+ return False
141
+
142
+ # Internals...
143
+ def scrape_with_playwright(self, url):
144
+ import playwright # noqa: F401
145
+ from playwright.sync_api import Error as PlaywrightError
146
+ from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
147
+ from playwright.sync_api import sync_playwright
148
+
149
+ with sync_playwright() as p:
150
+ try:
151
+ browser = p.chromium.launch()
152
+ except Exception as e:
153
+ self.playwright_available = False
154
+ self.print_error(str(e))
155
+ return None, None
156
+
157
+ try:
158
+ context = browser.new_context(ignore_https_errors=not self.verify_ssl)
159
+ page = context.new_page()
160
+
161
+ user_agent = page.evaluate("navigator.userAgent")
162
+ user_agent = user_agent.replace("Headless", "")
163
+ user_agent = user_agent.replace("headless", "")
164
+ user_agent += " " + aider_user_agent
165
+
166
+ page.set_extra_http_headers({"User-Agent": user_agent})
167
+
168
+ response = None
169
+ try:
170
+ response = page.goto(url, wait_until="networkidle", timeout=5000)
171
+ except PlaywrightTimeoutError:
172
+ print(f"Page didn't quiesce, scraping content anyway: {url}")
173
+ response = None
174
+ except PlaywrightError as e:
175
+ self.print_error(f"Error navigating to {url}: {str(e)}")
176
+ return None, None
177
+
178
+ try:
179
+ content = page.content()
180
+ mime_type = None
181
+ if response:
182
+ content_type = response.header_value("content-type")
183
+ if content_type:
184
+ mime_type = content_type.split(";")[0]
185
+ except PlaywrightError as e:
186
+ self.print_error(f"Error retrieving page content: {str(e)}")
187
+ content = None
188
+ mime_type = None
189
+ finally:
190
+ browser.close()
191
+
192
+ return content, mime_type
193
+
194
+ def scrape_with_httpx(self, url):
195
+ import httpx
196
+
197
+ headers = {"User-Agent": f"Mozilla./5.0 ({aider_user_agent})"}
198
+ try:
199
+ with httpx.Client(
200
+ headers=headers, verify=self.verify_ssl, follow_redirects=True
201
+ ) as client:
202
+ response = client.get(url)
203
+ response.raise_for_status()
204
+ return response.text, response.headers.get("content-type", "").split(";")[0]
205
+ except httpx.HTTPError as http_err:
206
+ self.print_error(f"HTTP error occurred: {http_err}")
207
+ except Exception as err:
208
+ self.print_error(f"An error occurred: {err}")
209
+ return None, None
210
+
211
+ def try_pandoc(self):
212
+ if self.pandoc_available:
213
+ return
214
+
215
+ try:
216
+ pypandoc.get_pandoc_version()
217
+ self.pandoc_available = True
218
+ return
219
+ except OSError:
220
+ pass
221
+
222
+ try:
223
+ pypandoc.download_pandoc(delete_installer=True)
224
+ except Exception as err:
225
+ self.print_error(f"Unable to install pandoc: {err}")
226
+ return
227
+
228
+ self.pandoc_available = True
229
+
230
+ def html_to_markdown(self, page_source):
231
+ from bs4 import BeautifulSoup
232
+
233
+ soup = BeautifulSoup(page_source, "html.parser")
234
+ soup = slimdown_html(soup)
235
+ page_source = str(soup)
236
+
237
+ if not self.pandoc_available:
238
+ return page_source
239
+
240
+ try:
241
+ md = pypandoc.convert_text(page_source, "markdown", format="html")
242
+ except OSError:
243
+ return page_source
244
+
245
+ md = re.sub(r"</div>", " ", md)
246
+ md = re.sub(r"<div>", " ", md)
247
+
248
+ md = re.sub(r"\n\s*\n", "\n\n", md)
249
+
250
+ return md
251
+
252
+
253
+ def slimdown_html(soup):
254
+ for svg in soup.find_all("svg"):
255
+ svg.decompose()
256
+
257
+ if soup.img:
258
+ soup.img.decompose()
259
+
260
+ for tag in soup.find_all(href=lambda x: x and x.startswith("data:")):
261
+ tag.decompose()
262
+
263
+ for tag in soup.find_all(src=lambda x: x and x.startswith("data:")):
264
+ tag.decompose()
265
+
266
+ for tag in soup.find_all(True):
267
+ for attr in list(tag.attrs):
268
+ if attr != "href":
269
+ tag.attrs.pop(attr, None)
270
+
271
+ return soup
272
+
273
+
274
+ def main(url):
275
+ scraper = Scraper(playwright_available=has_playwright())
276
+ content = scraper.scrape(url)
277
+ print(content)
278
+
279
+
280
+ if __name__ == "__main__":
281
+ if len(sys.argv) < 2:
282
+ print("Usage: python playw.py <URL>")
283
+ sys.exit(1)
284
+ main(sys.argv[1])
aider/sendchat.py ADDED
@@ -0,0 +1,61 @@
1
+ from aider.dump import dump # noqa: F401
2
+ from aider.utils import format_messages
3
+
4
+
5
+ def sanity_check_messages(messages):
6
+ """Check if messages alternate between user and assistant roles.
7
+ System messages can be interspersed anywhere.
8
+ Also verifies the last non-system message is from the user.
9
+ Returns True if valid, False otherwise."""
10
+ last_role = None
11
+ last_non_system_role = None
12
+
13
+ for msg in messages:
14
+ role = msg.get("role")
15
+ if role == "system":
16
+ continue
17
+
18
+ if last_role and role == last_role:
19
+ turns = format_messages(messages)
20
+ raise ValueError("Messages don't properly alternate user/assistant:\n\n" + turns)
21
+
22
+ last_role = role
23
+ last_non_system_role = role
24
+
25
+ # Ensure last non-system message is from user
26
+ return last_non_system_role == "user"
27
+
28
+
29
+ def ensure_alternating_roles(messages):
30
+ """Ensure messages alternate between 'assistant' and 'user' roles.
31
+
32
+ Inserts empty messages of the opposite role when consecutive messages
33
+ of the same role are found.
34
+
35
+ Args:
36
+ messages: List of message dictionaries with 'role' and 'content' keys.
37
+
38
+ Returns:
39
+ List of messages with alternating roles.
40
+ """
41
+ if not messages:
42
+ return messages
43
+
44
+ fixed_messages = []
45
+ prev_role = None
46
+
47
+ for msg in messages:
48
+ current_role = msg.get("role") # Get 'role', None if missing
49
+
50
+ # If current role same as previous, insert empty message
51
+ # of the opposite role
52
+ if current_role == prev_role:
53
+ if current_role == "user":
54
+ fixed_messages.append({"role": "assistant", "content": ""})
55
+ else:
56
+ fixed_messages.append({"role": "user", "content": ""})
57
+
58
+ fixed_messages.append(msg)
59
+ prev_role = current_role
60
+
61
+ return fixed_messages
aider/special.py ADDED
@@ -0,0 +1,203 @@
1
+ import os
2
+
3
+ ROOT_IMPORTANT_FILES = [
4
+ # Version Control
5
+ ".gitignore",
6
+ ".gitattributes",
7
+ # Documentation
8
+ "README",
9
+ "README.md",
10
+ "README.txt",
11
+ "README.rst",
12
+ "CONTRIBUTING",
13
+ "CONTRIBUTING.md",
14
+ "CONTRIBUTING.txt",
15
+ "CONTRIBUTING.rst",
16
+ "LICENSE",
17
+ "LICENSE.md",
18
+ "LICENSE.txt",
19
+ "CHANGELOG",
20
+ "CHANGELOG.md",
21
+ "CHANGELOG.txt",
22
+ "CHANGELOG.rst",
23
+ "SECURITY",
24
+ "SECURITY.md",
25
+ "SECURITY.txt",
26
+ "CODEOWNERS",
27
+ # Package Management and Dependencies
28
+ "requirements.txt",
29
+ "Pipfile",
30
+ "Pipfile.lock",
31
+ "pyproject.toml",
32
+ "setup.py",
33
+ "setup.cfg",
34
+ "package.json",
35
+ "package-lock.json",
36
+ "yarn.lock",
37
+ "npm-shrinkwrap.json",
38
+ "Gemfile",
39
+ "Gemfile.lock",
40
+ "composer.json",
41
+ "composer.lock",
42
+ "pom.xml",
43
+ "build.gradle",
44
+ "build.gradle.kts",
45
+ "build.sbt",
46
+ "go.mod",
47
+ "go.sum",
48
+ "Cargo.toml",
49
+ "Cargo.lock",
50
+ "mix.exs",
51
+ "rebar.config",
52
+ "project.clj",
53
+ "Podfile",
54
+ "Cartfile",
55
+ "dub.json",
56
+ "dub.sdl",
57
+ # Configuration and Settings
58
+ ".env",
59
+ ".env.example",
60
+ ".editorconfig",
61
+ "tsconfig.json",
62
+ "jsconfig.json",
63
+ ".babelrc",
64
+ "babel.config.js",
65
+ ".eslintrc",
66
+ ".eslintignore",
67
+ ".prettierrc",
68
+ ".stylelintrc",
69
+ "tslint.json",
70
+ ".pylintrc",
71
+ ".flake8",
72
+ ".rubocop.yml",
73
+ ".scalafmt.conf",
74
+ ".dockerignore",
75
+ ".gitpod.yml",
76
+ "sonar-project.properties",
77
+ "renovate.json",
78
+ "dependabot.yml",
79
+ ".pre-commit-config.yaml",
80
+ "mypy.ini",
81
+ "tox.ini",
82
+ ".yamllint",
83
+ "pyrightconfig.json",
84
+ # Build and Compilation
85
+ "webpack.config.js",
86
+ "rollup.config.js",
87
+ "parcel.config.js",
88
+ "gulpfile.js",
89
+ "Gruntfile.js",
90
+ "build.xml",
91
+ "build.boot",
92
+ "project.json",
93
+ "build.cake",
94
+ "MANIFEST.in",
95
+ # Testing
96
+ "pytest.ini",
97
+ "phpunit.xml",
98
+ "karma.conf.js",
99
+ "jest.config.js",
100
+ "cypress.json",
101
+ ".nycrc",
102
+ ".nycrc.json",
103
+ # CI/CD
104
+ ".travis.yml",
105
+ ".gitlab-ci.yml",
106
+ "Jenkinsfile",
107
+ "azure-pipelines.yml",
108
+ "bitbucket-pipelines.yml",
109
+ "appveyor.yml",
110
+ "circle.yml",
111
+ ".circleci/config.yml",
112
+ ".github/dependabot.yml",
113
+ "codecov.yml",
114
+ ".coveragerc",
115
+ # Docker and Containers
116
+ "Dockerfile",
117
+ "docker-compose.yml",
118
+ "docker-compose.override.yml",
119
+ # Cloud and Serverless
120
+ "serverless.yml",
121
+ "firebase.json",
122
+ "now.json",
123
+ "netlify.toml",
124
+ "vercel.json",
125
+ "app.yaml",
126
+ "terraform.tf",
127
+ "main.tf",
128
+ "cloudformation.yaml",
129
+ "cloudformation.json",
130
+ "ansible.cfg",
131
+ "kubernetes.yaml",
132
+ "k8s.yaml",
133
+ # Database
134
+ "schema.sql",
135
+ "liquibase.properties",
136
+ "flyway.conf",
137
+ # Framework-specific
138
+ "next.config.js",
139
+ "nuxt.config.js",
140
+ "vue.config.js",
141
+ "angular.json",
142
+ "gatsby-config.js",
143
+ "gridsome.config.js",
144
+ # API Documentation
145
+ "swagger.yaml",
146
+ "swagger.json",
147
+ "openapi.yaml",
148
+ "openapi.json",
149
+ # Development environment
150
+ ".nvmrc",
151
+ ".ruby-version",
152
+ ".python-version",
153
+ "Vagrantfile",
154
+ # Quality and metrics
155
+ ".codeclimate.yml",
156
+ "codecov.yml",
157
+ # Documentation
158
+ "mkdocs.yml",
159
+ "_config.yml",
160
+ "book.toml",
161
+ "readthedocs.yml",
162
+ ".readthedocs.yaml",
163
+ # Package registries
164
+ ".npmrc",
165
+ ".yarnrc",
166
+ # Linting and formatting
167
+ ".isort.cfg",
168
+ ".markdownlint.json",
169
+ ".markdownlint.yaml",
170
+ # Security
171
+ ".bandit",
172
+ ".secrets.baseline",
173
+ # Misc
174
+ ".pypirc",
175
+ ".gitkeep",
176
+ ".npmignore",
177
+ ]
178
+
179
+
180
+ # Normalize the lists once
181
+ NORMALIZED_ROOT_IMPORTANT_FILES = set(os.path.normpath(path) for path in ROOT_IMPORTANT_FILES)
182
+
183
+
184
+ def is_important(file_path):
185
+ file_name = os.path.basename(file_path)
186
+ dir_name = os.path.normpath(os.path.dirname(file_path))
187
+ normalized_path = os.path.normpath(file_path)
188
+
189
+ # Check for GitHub Actions workflow files
190
+ if dir_name == os.path.normpath(".github/workflows") and file_name.endswith(".yml"):
191
+ return True
192
+
193
+ return normalized_path in NORMALIZED_ROOT_IMPORTANT_FILES
194
+
195
+
196
+ def filter_important_files(file_paths):
197
+ """
198
+ Filter a list of file paths to return only those that are commonly important in codebases.
199
+
200
+ :param file_paths: List of file paths to check
201
+ :return: List of file paths that match important file patterns
202
+ """
203
+ return list(filter(is_important, file_paths))
aider/urls.py ADDED
@@ -0,0 +1,17 @@
1
+ website = "https://aider.chat/"
2
+ add_all_files = "https://aider.chat/docs/faq.html#how-can-i-add-all-the-files-to-the-chat"
3
+ edit_errors = "https://aider.chat/docs/troubleshooting/edit-errors.html"
4
+ git = "https://aider.chat/docs/git.html"
5
+ enable_playwright = "https://aider.chat/docs/install/optional.html#enable-playwright"
6
+ favicon = "https://aider.chat/assets/icons/favicon-32x32.png"
7
+ model_warnings = "https://aider.chat/docs/llms/warnings.html"
8
+ token_limits = "https://aider.chat/docs/troubleshooting/token-limits.html"
9
+ llms = "https://aider.chat/docs/llms.html"
10
+ large_repos = "https://aider.chat/docs/faq.html#can-i-use-aider-in-a-large-mono-repo"
11
+ github_issues = "https://github.com/Aider-AI/aider/issues/new"
12
+ git_index_version = "https://github.com/Aider-AI/aider/issues/211"
13
+ install_properly = "https://aider.chat/docs/troubleshooting/imports.html"
14
+ analytics = "https://aider.chat/docs/more/analytics.html"
15
+ release_notes = "https://aider.chat/HISTORY.html#release-notes"
16
+ edit_formats = "https://aider.chat/docs/more/edit-formats.html"
17
+ models_and_keys = "https://aider.chat/docs/troubleshooting/models-and-keys.html"