cecli-dev 0.93.1__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 (366) hide show
  1. cecli/__init__.py +20 -0
  2. cecli/__main__.py +4 -0
  3. cecli/_version.py +34 -0
  4. cecli/args.py +1092 -0
  5. cecli/args_formatter.py +228 -0
  6. cecli/change_tracker.py +133 -0
  7. cecli/coders/__init__.py +38 -0
  8. cecli/coders/agent_coder.py +1872 -0
  9. cecli/coders/architect_coder.py +63 -0
  10. cecli/coders/ask_coder.py +8 -0
  11. cecli/coders/base_coder.py +3993 -0
  12. cecli/coders/chat_chunks.py +116 -0
  13. cecli/coders/context_coder.py +52 -0
  14. cecli/coders/copypaste_coder.py +269 -0
  15. cecli/coders/editblock_coder.py +656 -0
  16. cecli/coders/editblock_fenced_coder.py +9 -0
  17. cecli/coders/editblock_func_coder.py +140 -0
  18. cecli/coders/editor_diff_fenced_coder.py +8 -0
  19. cecli/coders/editor_editblock_coder.py +8 -0
  20. cecli/coders/editor_whole_coder.py +8 -0
  21. cecli/coders/help_coder.py +15 -0
  22. cecli/coders/patch_coder.py +705 -0
  23. cecli/coders/search_replace.py +757 -0
  24. cecli/coders/shell.py +37 -0
  25. cecli/coders/single_wholefile_func_coder.py +101 -0
  26. cecli/coders/udiff_coder.py +428 -0
  27. cecli/coders/udiff_simple.py +12 -0
  28. cecli/coders/wholefile_coder.py +143 -0
  29. cecli/coders/wholefile_func_coder.py +133 -0
  30. cecli/commands/__init__.py +192 -0
  31. cecli/commands/add.py +226 -0
  32. cecli/commands/agent.py +51 -0
  33. cecli/commands/architect.py +46 -0
  34. cecli/commands/ask.py +44 -0
  35. cecli/commands/chat_mode.py +0 -0
  36. cecli/commands/clear.py +37 -0
  37. cecli/commands/code.py +46 -0
  38. cecli/commands/command_prefix.py +44 -0
  39. cecli/commands/commit.py +52 -0
  40. cecli/commands/context.py +47 -0
  41. cecli/commands/context_blocks.py +124 -0
  42. cecli/commands/context_management.py +51 -0
  43. cecli/commands/copy.py +62 -0
  44. cecli/commands/copy_context.py +81 -0
  45. cecli/commands/core.py +287 -0
  46. cecli/commands/diff.py +68 -0
  47. cecli/commands/drop.py +217 -0
  48. cecli/commands/editor.py +78 -0
  49. cecli/commands/exit.py +55 -0
  50. cecli/commands/git.py +57 -0
  51. cecli/commands/help.py +140 -0
  52. cecli/commands/history_search.py +40 -0
  53. cecli/commands/lint.py +109 -0
  54. cecli/commands/list_sessions.py +56 -0
  55. cecli/commands/load.py +85 -0
  56. cecli/commands/load_session.py +48 -0
  57. cecli/commands/load_skill.py +68 -0
  58. cecli/commands/ls.py +75 -0
  59. cecli/commands/map.py +37 -0
  60. cecli/commands/map_refresh.py +35 -0
  61. cecli/commands/model.py +118 -0
  62. cecli/commands/models.py +41 -0
  63. cecli/commands/multiline_mode.py +38 -0
  64. cecli/commands/paste.py +91 -0
  65. cecli/commands/quit.py +32 -0
  66. cecli/commands/read_only.py +267 -0
  67. cecli/commands/read_only_stub.py +270 -0
  68. cecli/commands/reasoning_effort.py +70 -0
  69. cecli/commands/remove_skill.py +68 -0
  70. cecli/commands/report.py +40 -0
  71. cecli/commands/reset.py +88 -0
  72. cecli/commands/run.py +99 -0
  73. cecli/commands/save.py +49 -0
  74. cecli/commands/save_session.py +43 -0
  75. cecli/commands/settings.py +69 -0
  76. cecli/commands/test.py +58 -0
  77. cecli/commands/think_tokens.py +74 -0
  78. cecli/commands/tokens.py +207 -0
  79. cecli/commands/undo.py +145 -0
  80. cecli/commands/utils/__init__.py +0 -0
  81. cecli/commands/utils/base_command.py +131 -0
  82. cecli/commands/utils/helpers.py +142 -0
  83. cecli/commands/utils/registry.py +53 -0
  84. cecli/commands/utils/save_load_manager.py +98 -0
  85. cecli/commands/voice.py +78 -0
  86. cecli/commands/weak_model.py +123 -0
  87. cecli/commands/web.py +87 -0
  88. cecli/deprecated_args.py +185 -0
  89. cecli/diffs.py +129 -0
  90. cecli/dump.py +29 -0
  91. cecli/editor.py +147 -0
  92. cecli/exceptions.py +115 -0
  93. cecli/format_settings.py +26 -0
  94. cecli/help.py +119 -0
  95. cecli/help_pats.py +19 -0
  96. cecli/helpers/__init__.py +9 -0
  97. cecli/helpers/copypaste.py +123 -0
  98. cecli/helpers/coroutines.py +8 -0
  99. cecli/helpers/file_searcher.py +142 -0
  100. cecli/helpers/model_providers.py +552 -0
  101. cecli/helpers/plugin_manager.py +81 -0
  102. cecli/helpers/profiler.py +162 -0
  103. cecli/helpers/requests.py +77 -0
  104. cecli/helpers/similarity.py +98 -0
  105. cecli/helpers/skills.py +577 -0
  106. cecli/history.py +186 -0
  107. cecli/io.py +1782 -0
  108. cecli/linter.py +304 -0
  109. cecli/llm.py +101 -0
  110. cecli/main.py +1280 -0
  111. cecli/mcp/__init__.py +154 -0
  112. cecli/mcp/oauth.py +250 -0
  113. cecli/mcp/server.py +278 -0
  114. cecli/mdstream.py +243 -0
  115. cecli/models.py +1255 -0
  116. cecli/onboarding.py +301 -0
  117. cecli/prompts/__init__.py +0 -0
  118. cecli/prompts/agent.yml +71 -0
  119. cecli/prompts/architect.yml +35 -0
  120. cecli/prompts/ask.yml +31 -0
  121. cecli/prompts/base.yml +99 -0
  122. cecli/prompts/context.yml +60 -0
  123. cecli/prompts/copypaste.yml +5 -0
  124. cecli/prompts/editblock.yml +143 -0
  125. cecli/prompts/editblock_fenced.yml +106 -0
  126. cecli/prompts/editblock_func.yml +25 -0
  127. cecli/prompts/editor_diff_fenced.yml +115 -0
  128. cecli/prompts/editor_editblock.yml +121 -0
  129. cecli/prompts/editor_whole.yml +46 -0
  130. cecli/prompts/help.yml +37 -0
  131. cecli/prompts/patch.yml +110 -0
  132. cecli/prompts/single_wholefile_func.yml +24 -0
  133. cecli/prompts/udiff.yml +106 -0
  134. cecli/prompts/udiff_simple.yml +13 -0
  135. cecli/prompts/utils/__init__.py +0 -0
  136. cecli/prompts/utils/prompt_registry.py +167 -0
  137. cecli/prompts/utils/system.py +56 -0
  138. cecli/prompts/wholefile.yml +50 -0
  139. cecli/prompts/wholefile_func.yml +24 -0
  140. cecli/queries/tree-sitter-language-pack/README.md +7 -0
  141. cecli/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  142. cecli/queries/tree-sitter-language-pack/c-tags.scm +12 -0
  143. cecli/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  144. cecli/queries/tree-sitter-language-pack/clojure-tags.scm +12 -0
  145. cecli/queries/tree-sitter-language-pack/commonlisp-tags.scm +127 -0
  146. cecli/queries/tree-sitter-language-pack/cpp-tags.scm +18 -0
  147. cecli/queries/tree-sitter-language-pack/csharp-tags.scm +32 -0
  148. cecli/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  149. cecli/queries/tree-sitter-language-pack/dart-tags.scm +97 -0
  150. cecli/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  151. cecli/queries/tree-sitter-language-pack/elixir-tags.scm +59 -0
  152. cecli/queries/tree-sitter-language-pack/elm-tags.scm +22 -0
  153. cecli/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  154. cecli/queries/tree-sitter-language-pack/go-tags.scm +49 -0
  155. cecli/queries/tree-sitter-language-pack/java-tags.scm +26 -0
  156. cecli/queries/tree-sitter-language-pack/javascript-tags.scm +96 -0
  157. cecli/queries/tree-sitter-language-pack/lua-tags.scm +39 -0
  158. cecli/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
  159. cecli/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  160. cecli/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +101 -0
  161. cecli/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  162. cecli/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  163. cecli/queries/tree-sitter-language-pack/python-tags.scm +24 -0
  164. cecli/queries/tree-sitter-language-pack/r-tags.scm +27 -0
  165. cecli/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  166. cecli/queries/tree-sitter-language-pack/ruby-tags.scm +69 -0
  167. cecli/queries/tree-sitter-language-pack/rust-tags.scm +63 -0
  168. cecli/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  169. cecli/queries/tree-sitter-language-pack/swift-tags.scm +54 -0
  170. cecli/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  171. cecli/queries/tree-sitter-languages/README.md +24 -0
  172. cecli/queries/tree-sitter-languages/c-tags.scm +12 -0
  173. cecli/queries/tree-sitter-languages/c_sharp-tags.scm +52 -0
  174. cecli/queries/tree-sitter-languages/cpp-tags.scm +18 -0
  175. cecli/queries/tree-sitter-languages/dart-tags.scm +92 -0
  176. cecli/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  177. cecli/queries/tree-sitter-languages/elixir-tags.scm +59 -0
  178. cecli/queries/tree-sitter-languages/elm-tags.scm +22 -0
  179. cecli/queries/tree-sitter-languages/fortran-tags.scm +18 -0
  180. cecli/queries/tree-sitter-languages/go-tags.scm +36 -0
  181. cecli/queries/tree-sitter-languages/haskell-tags.scm +5 -0
  182. cecli/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  183. cecli/queries/tree-sitter-languages/java-tags.scm +26 -0
  184. cecli/queries/tree-sitter-languages/javascript-tags.scm +96 -0
  185. cecli/queries/tree-sitter-languages/julia-tags.scm +60 -0
  186. cecli/queries/tree-sitter-languages/kotlin-tags.scm +30 -0
  187. cecli/queries/tree-sitter-languages/matlab-tags.scm +10 -0
  188. cecli/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  189. cecli/queries/tree-sitter-languages/ocaml_interface-tags.scm +104 -0
  190. cecli/queries/tree-sitter-languages/php-tags.scm +32 -0
  191. cecli/queries/tree-sitter-languages/python-tags.scm +22 -0
  192. cecli/queries/tree-sitter-languages/ql-tags.scm +26 -0
  193. cecli/queries/tree-sitter-languages/ruby-tags.scm +69 -0
  194. cecli/queries/tree-sitter-languages/rust-tags.scm +63 -0
  195. cecli/queries/tree-sitter-languages/scala-tags.scm +64 -0
  196. cecli/queries/tree-sitter-languages/typescript-tags.scm +44 -0
  197. cecli/queries/tree-sitter-languages/zig-tags.scm +20 -0
  198. cecli/reasoning_tags.py +82 -0
  199. cecli/repo.py +626 -0
  200. cecli/repomap.py +1368 -0
  201. cecli/report.py +260 -0
  202. cecli/resources/__init__.py +3 -0
  203. cecli/resources/model-metadata.json +25751 -0
  204. cecli/resources/model-settings.yml +2394 -0
  205. cecli/resources/providers.json +67 -0
  206. cecli/run_cmd.py +143 -0
  207. cecli/scrape.py +295 -0
  208. cecli/sendchat.py +250 -0
  209. cecli/sessions.py +281 -0
  210. cecli/special.py +203 -0
  211. cecli/tools/__init__.py +72 -0
  212. cecli/tools/command.py +103 -0
  213. cecli/tools/command_interactive.py +113 -0
  214. cecli/tools/context_manager.py +175 -0
  215. cecli/tools/delete_block.py +154 -0
  216. cecli/tools/delete_line.py +120 -0
  217. cecli/tools/delete_lines.py +144 -0
  218. cecli/tools/extract_lines.py +281 -0
  219. cecli/tools/finished.py +35 -0
  220. cecli/tools/git_branch.py +132 -0
  221. cecli/tools/git_diff.py +49 -0
  222. cecli/tools/git_log.py +43 -0
  223. cecli/tools/git_remote.py +39 -0
  224. cecli/tools/git_show.py +37 -0
  225. cecli/tools/git_status.py +32 -0
  226. cecli/tools/grep.py +242 -0
  227. cecli/tools/indent_lines.py +195 -0
  228. cecli/tools/insert_block.py +263 -0
  229. cecli/tools/list_changes.py +71 -0
  230. cecli/tools/load_skill.py +51 -0
  231. cecli/tools/ls.py +77 -0
  232. cecli/tools/remove_skill.py +51 -0
  233. cecli/tools/replace_all.py +113 -0
  234. cecli/tools/replace_line.py +135 -0
  235. cecli/tools/replace_lines.py +180 -0
  236. cecli/tools/replace_text.py +186 -0
  237. cecli/tools/show_numbered_context.py +137 -0
  238. cecli/tools/thinking.py +52 -0
  239. cecli/tools/undo_change.py +82 -0
  240. cecli/tools/update_todo_list.py +148 -0
  241. cecli/tools/utils/base_tool.py +64 -0
  242. cecli/tools/utils/helpers.py +359 -0
  243. cecli/tools/utils/output.py +119 -0
  244. cecli/tools/utils/registry.py +145 -0
  245. cecli/tools/view_files_matching.py +138 -0
  246. cecli/tools/view_files_with_symbol.py +117 -0
  247. cecli/tui/__init__.py +83 -0
  248. cecli/tui/app.py +971 -0
  249. cecli/tui/io.py +566 -0
  250. cecli/tui/styles.tcss +117 -0
  251. cecli/tui/widgets/__init__.py +19 -0
  252. cecli/tui/widgets/completion_bar.py +331 -0
  253. cecli/tui/widgets/file_list.py +76 -0
  254. cecli/tui/widgets/footer.py +165 -0
  255. cecli/tui/widgets/input_area.py +320 -0
  256. cecli/tui/widgets/key_hints.py +16 -0
  257. cecli/tui/widgets/output.py +354 -0
  258. cecli/tui/widgets/status_bar.py +279 -0
  259. cecli/tui/worker.py +160 -0
  260. cecli/urls.py +16 -0
  261. cecli/utils.py +499 -0
  262. cecli/versioncheck.py +90 -0
  263. cecli/voice.py +90 -0
  264. cecli/waiting.py +38 -0
  265. cecli/watch.py +316 -0
  266. cecli/watch_prompts.py +12 -0
  267. cecli/website/Gemfile +8 -0
  268. cecli/website/_includes/blame.md +162 -0
  269. cecli/website/_includes/get-started.md +22 -0
  270. cecli/website/_includes/help-tip.md +5 -0
  271. cecli/website/_includes/help.md +24 -0
  272. cecli/website/_includes/install.md +5 -0
  273. cecli/website/_includes/keys.md +4 -0
  274. cecli/website/_includes/model-warnings.md +67 -0
  275. cecli/website/_includes/multi-line.md +22 -0
  276. cecli/website/_includes/python-m-aider.md +5 -0
  277. cecli/website/_includes/recording.css +228 -0
  278. cecli/website/_includes/recording.md +34 -0
  279. cecli/website/_includes/replit-pipx.md +9 -0
  280. cecli/website/_includes/works-best.md +1 -0
  281. cecli/website/_sass/custom/custom.scss +103 -0
  282. cecli/website/docs/config/adv-model-settings.md +2498 -0
  283. cecli/website/docs/config/agent-mode.md +320 -0
  284. cecli/website/docs/config/aider_conf.md +548 -0
  285. cecli/website/docs/config/api-keys.md +90 -0
  286. cecli/website/docs/config/custom-commands.md +187 -0
  287. cecli/website/docs/config/dotenv.md +493 -0
  288. cecli/website/docs/config/editor.md +127 -0
  289. cecli/website/docs/config/mcp.md +210 -0
  290. cecli/website/docs/config/model-aliases.md +173 -0
  291. cecli/website/docs/config/options.md +890 -0
  292. cecli/website/docs/config/reasoning.md +210 -0
  293. cecli/website/docs/config/skills.md +172 -0
  294. cecli/website/docs/config/tui.md +126 -0
  295. cecli/website/docs/config.md +44 -0
  296. cecli/website/docs/faq.md +379 -0
  297. cecli/website/docs/git.md +76 -0
  298. cecli/website/docs/index.md +47 -0
  299. cecli/website/docs/install/codespaces.md +39 -0
  300. cecli/website/docs/install/docker.md +48 -0
  301. cecli/website/docs/install/optional.md +100 -0
  302. cecli/website/docs/install/replit.md +8 -0
  303. cecli/website/docs/install.md +115 -0
  304. cecli/website/docs/languages.md +264 -0
  305. cecli/website/docs/legal/contributor-agreement.md +111 -0
  306. cecli/website/docs/legal/privacy.md +104 -0
  307. cecli/website/docs/llms/anthropic.md +77 -0
  308. cecli/website/docs/llms/azure.md +48 -0
  309. cecli/website/docs/llms/bedrock.md +132 -0
  310. cecli/website/docs/llms/cohere.md +34 -0
  311. cecli/website/docs/llms/deepseek.md +32 -0
  312. cecli/website/docs/llms/gemini.md +49 -0
  313. cecli/website/docs/llms/github.md +111 -0
  314. cecli/website/docs/llms/groq.md +36 -0
  315. cecli/website/docs/llms/lm-studio.md +39 -0
  316. cecli/website/docs/llms/ollama.md +75 -0
  317. cecli/website/docs/llms/openai-compat.md +39 -0
  318. cecli/website/docs/llms/openai.md +58 -0
  319. cecli/website/docs/llms/openrouter.md +78 -0
  320. cecli/website/docs/llms/other.md +117 -0
  321. cecli/website/docs/llms/vertex.md +50 -0
  322. cecli/website/docs/llms/warnings.md +10 -0
  323. cecli/website/docs/llms/xai.md +53 -0
  324. cecli/website/docs/llms.md +54 -0
  325. cecli/website/docs/more/analytics.md +127 -0
  326. cecli/website/docs/more/edit-formats.md +116 -0
  327. cecli/website/docs/more/infinite-output.md +192 -0
  328. cecli/website/docs/more-info.md +8 -0
  329. cecli/website/docs/recordings/auto-accept-architect.md +31 -0
  330. cecli/website/docs/recordings/dont-drop-original-read-files.md +35 -0
  331. cecli/website/docs/recordings/index.md +21 -0
  332. cecli/website/docs/recordings/model-accepts-settings.md +69 -0
  333. cecli/website/docs/recordings/tree-sitter-language-pack.md +80 -0
  334. cecli/website/docs/repomap.md +112 -0
  335. cecli/website/docs/scripting.md +100 -0
  336. cecli/website/docs/sessions.md +213 -0
  337. cecli/website/docs/troubleshooting/aider-not-found.md +24 -0
  338. cecli/website/docs/troubleshooting/edit-errors.md +76 -0
  339. cecli/website/docs/troubleshooting/imports.md +62 -0
  340. cecli/website/docs/troubleshooting/models-and-keys.md +54 -0
  341. cecli/website/docs/troubleshooting/support.md +79 -0
  342. cecli/website/docs/troubleshooting/token-limits.md +96 -0
  343. cecli/website/docs/troubleshooting/warnings.md +12 -0
  344. cecli/website/docs/troubleshooting.md +11 -0
  345. cecli/website/docs/usage/browser.md +57 -0
  346. cecli/website/docs/usage/caching.md +49 -0
  347. cecli/website/docs/usage/commands.md +133 -0
  348. cecli/website/docs/usage/conventions.md +119 -0
  349. cecli/website/docs/usage/copypaste.md +136 -0
  350. cecli/website/docs/usage/images-urls.md +48 -0
  351. cecli/website/docs/usage/lint-test.md +118 -0
  352. cecli/website/docs/usage/modes.md +211 -0
  353. cecli/website/docs/usage/not-code.md +179 -0
  354. cecli/website/docs/usage/notifications.md +87 -0
  355. cecli/website/docs/usage/tips.md +79 -0
  356. cecli/website/docs/usage/tutorials.md +30 -0
  357. cecli/website/docs/usage/voice.md +121 -0
  358. cecli/website/docs/usage/watch.md +294 -0
  359. cecli/website/docs/usage.md +102 -0
  360. cecli/website/share/index.md +101 -0
  361. cecli_dev-0.93.1.dist-info/METADATA +549 -0
  362. cecli_dev-0.93.1.dist-info/RECORD +366 -0
  363. cecli_dev-0.93.1.dist-info/WHEEL +5 -0
  364. cecli_dev-0.93.1.dist-info/entry_points.txt +4 -0
  365. cecli_dev-0.93.1.dist-info/licenses/LICENSE.txt +202 -0
  366. cecli_dev-0.93.1.dist-info/top_level.txt +1 -0
cecli/onboarding.py ADDED
@@ -0,0 +1,301 @@
1
+ import http.server
2
+ import os
3
+ import socketserver
4
+ import threading
5
+ import time
6
+ import webbrowser
7
+ from urllib.parse import parse_qs, urlparse
8
+
9
+ import requests
10
+
11
+ from cecli import urls
12
+ from cecli.io import InputOutput
13
+ from cecli.mcp.oauth import find_available_port, generate_pkce_codes
14
+
15
+
16
+ def check_openrouter_tier(api_key):
17
+ """
18
+ Checks if the user is on a free tier for OpenRouter.
19
+
20
+ Args:
21
+ api_key: The OpenRouter API key to check.
22
+
23
+ Returns:
24
+ A boolean indicating if the user is on a free tier (True) or paid tier (False).
25
+ Returns True if the check fails.
26
+ """
27
+ try:
28
+ response = requests.get(
29
+ "https://openrouter.ai/api/v1/auth/key",
30
+ headers={"Authorization": f"Bearer {api_key}"},
31
+ timeout=5,
32
+ )
33
+ response.raise_for_status()
34
+ data = response.json()
35
+ return data.get("data", {}).get("is_free_tier", True)
36
+ except Exception:
37
+ return True
38
+
39
+
40
+ def try_to_select_default_model():
41
+ """
42
+ Attempts to select a default model based on available API keys.
43
+ Checks OpenRouter tier status to select appropriate model.
44
+
45
+ Returns:
46
+ The name of the selected model, or None if no suitable default is found.
47
+ """
48
+ openrouter_key = os.environ.get("OPENROUTER_API_KEY")
49
+ if openrouter_key:
50
+ is_free_tier = check_openrouter_tier(openrouter_key)
51
+ if is_free_tier:
52
+ return "openrouter/deepseek/deepseek-r1:free"
53
+ else:
54
+ return "openrouter/anthropic/claude-sonnet-4"
55
+ model_key_pairs = [
56
+ ("ANTHROPIC_API_KEY", "sonnet"),
57
+ ("DEEPSEEK_API_KEY", "deepseek"),
58
+ ("OPENAI_API_KEY", "gpt-4o"),
59
+ ("GEMINI_API_KEY", "gemini/gemini-2.5-pro-exp-03-25"),
60
+ ("VERTEXAI_PROJECT", "vertex_ai/gemini-2.5-pro-exp-03-25"),
61
+ ]
62
+ for env_key, model_name in model_key_pairs:
63
+ api_key_value = os.environ.get(env_key)
64
+ if api_key_value:
65
+ return model_name
66
+ return None
67
+
68
+
69
+ async def offer_openrouter_oauth(io):
70
+ """
71
+ Offers OpenRouter OAuth flow to the user if no API keys are found.
72
+
73
+ Args:
74
+ io: The InputOutput object for user interaction.
75
+
76
+ Returns:
77
+ True if authentication was successful, False otherwise.
78
+ """
79
+ io.tool_output("OpenRouter provides free and paid access to many LLMs.")
80
+ if await io.confirm_ask(
81
+ "Login to OpenRouter or create a free account?", default="y", acknowledge=True
82
+ ):
83
+ openrouter_key = start_openrouter_oauth_flow(io)
84
+ if openrouter_key:
85
+ os.environ["OPENROUTER_API_KEY"] = openrouter_key
86
+ return True
87
+ io.tool_error("OpenRouter authentication did not complete successfully.")
88
+ return False
89
+
90
+
91
+ async def select_default_model(args, io):
92
+ """
93
+ Selects a default model based on available API keys if no model is specified.
94
+ Offers OAuth flow for OpenRouter if no keys are found.
95
+
96
+ Args:
97
+ args: The command line arguments object.
98
+ io: The InputOutput object for user interaction.
99
+
100
+ Returns:
101
+ The name of the selected model, or None if no suitable default is found.
102
+ """
103
+ if args.model:
104
+ return args.model
105
+ model = try_to_select_default_model()
106
+ if model:
107
+ io.tool_warning(f"Using {model} model with API key from environment.")
108
+ return model
109
+ no_model_msg = "No LLM model was specified and no API keys were provided."
110
+ io.tool_warning(no_model_msg)
111
+ await offer_openrouter_oauth(io)
112
+ model = try_to_select_default_model()
113
+ if model:
114
+ return model
115
+ await io.offer_url(urls.models_and_keys, "Open documentation URL for more info?")
116
+
117
+
118
+ # Function to exchange the authorization code for an API key
119
+ def exchange_code_for_key(code, code_verifier, io):
120
+ try:
121
+ response = requests.post(
122
+ "https://openrouter.ai/api/v1/auth/keys",
123
+ headers={"Content-Type": "application/json"},
124
+ json={"code": code, "code_verifier": code_verifier, "code_challenge_method": "S256"},
125
+ timeout=30,
126
+ )
127
+ response.raise_for_status()
128
+ data = response.json()
129
+ api_key = data.get("key")
130
+ if not api_key:
131
+ io.tool_error("Error: 'key' not found in OpenRouter response.")
132
+ io.tool_error(f"Response: {response.text}")
133
+ return None
134
+ return api_key
135
+ except requests.exceptions.Timeout:
136
+ io.tool_error("Error: Request to OpenRouter timed out during code exchange.")
137
+ return None
138
+ except requests.exceptions.HTTPError as e:
139
+ io.tool_error(
140
+ "Error exchanging code for OpenRouter key:"
141
+ f" {e.response.status_code} {e.response.reason}"
142
+ )
143
+ io.tool_error(f"Response: {e.response.text}")
144
+ return None
145
+ except requests.exceptions.RequestException as e:
146
+ io.tool_error(f"Error exchanging code for OpenRouter key: {e}")
147
+ return None
148
+ except Exception as e:
149
+ io.tool_error(f"Unexpected error during code exchange: {e}")
150
+ return None
151
+
152
+
153
+ def start_openrouter_oauth_flow(io):
154
+ """Initiates the OpenRouter OAuth PKCE flow using a local server."""
155
+ port = find_available_port()
156
+ if not port:
157
+ io.tool_error("Could not find an available port between 8484 and 8584.")
158
+ io.tool_error("Please ensure a port in this range is free, or configure manually.")
159
+ return None
160
+ callback_url = f"http://localhost:{port}/callback/cecli"
161
+ auth_code = None
162
+ server_error = None
163
+ server_started = threading.Event()
164
+ shutdown_server = threading.Event()
165
+
166
+ class OAuthCallbackHandler(http.server.SimpleHTTPRequestHandler):
167
+ def do_GET(self):
168
+ nonlocal auth_code, server_error
169
+ parsed_path = urlparse(self.path)
170
+ if parsed_path.path == "/callback/cecli":
171
+ query_params = parse_qs(parsed_path.query)
172
+ if "code" in query_params:
173
+ auth_code = query_params["code"][0]
174
+ self.send_response(200)
175
+ self.send_header("Content-type", "text/html")
176
+ self.end_headers()
177
+ self.wfile.write(
178
+ b"<html><body><h1>Success!</h1><p>cecli has received the authentication"
179
+ b" code. You can close this browser tab.</p></body></html>"
180
+ )
181
+ shutdown_server.set()
182
+ else:
183
+ self.send_response(302)
184
+ self.send_header("Location", urls.website)
185
+ self.end_headers()
186
+ else:
187
+ self.send_response(302)
188
+ self.send_header("Location", urls.website)
189
+ self.end_headers()
190
+ self.wfile.write(b"Not Found")
191
+
192
+ def log_message(self, format, *args):
193
+ pass
194
+
195
+ def run_server():
196
+ nonlocal server_error
197
+ try:
198
+ with socketserver.TCPServer(("localhost", port), OAuthCallbackHandler) as httpd:
199
+ io.tool_output(f"Temporary server listening on {callback_url}", log_only=True)
200
+ server_started.set()
201
+ while not shutdown_server.is_set():
202
+ httpd.handle_request()
203
+ time.sleep(0.1)
204
+ io.tool_output("Shutting down temporary server.", log_only=True)
205
+ except Exception as e:
206
+ server_error = f"Failed to start or run temporary server: {e}"
207
+ server_started.set()
208
+ shutdown_server.set()
209
+
210
+ server_thread = threading.Thread(target=run_server, daemon=True)
211
+ server_thread.start()
212
+ if not server_started.wait(timeout=5):
213
+ io.tool_error("Temporary authentication server failed to start in time.")
214
+ shutdown_server.set()
215
+ server_thread.join(timeout=1)
216
+ return None
217
+ if server_error:
218
+ io.tool_error(server_error)
219
+ shutdown_server.set()
220
+ server_thread.join(timeout=1)
221
+ return None
222
+ code_verifier, code_challenge = generate_pkce_codes()
223
+ auth_url_base = "https://openrouter.ai/auth"
224
+ auth_params = {
225
+ "callback_url": callback_url,
226
+ "code_challenge": code_challenge,
227
+ "code_challenge_method": "S256",
228
+ }
229
+ auth_url = f"{auth_url_base}?{'&'.join(f'{k}={v}' for k, v in auth_params.items())}"
230
+ io.tool_output("\nPlease open this URL in your browser to connect cecli with OpenRouter:")
231
+ io.tool_output()
232
+ print(auth_url)
233
+ MINUTES = 5
234
+ io.tool_output(f"\nWaiting up to {MINUTES} minutes for you to finish in the browser...")
235
+ io.tool_output("Use Control-C to interrupt.")
236
+ try:
237
+ webbrowser.open(auth_url)
238
+ except Exception:
239
+ pass
240
+ interrupted = False
241
+ try:
242
+ shutdown_server.wait(timeout=MINUTES * 60)
243
+ except KeyboardInterrupt:
244
+ io.tool_warning("\nOAuth flow interrupted.")
245
+ interrupted = True
246
+ shutdown_server.set()
247
+ server_thread.join(timeout=1)
248
+ if interrupted:
249
+ return None
250
+ if server_error:
251
+ io.tool_error(f"Authentication failed: {server_error}")
252
+ return None
253
+ if not auth_code:
254
+ io.tool_error("Authentication with OpenRouter failed.")
255
+ return None
256
+ io.tool_output("Completing authentication...")
257
+ api_key = exchange_code_for_key(auth_code, code_verifier, io)
258
+ if api_key:
259
+ os.environ["OPENROUTER_API_KEY"] = api_key
260
+ try:
261
+ config_dir = os.path.expanduser("~/.cecli")
262
+ os.makedirs(config_dir, exist_ok=True)
263
+ key_file = os.path.join(config_dir, "oauth-keys.env")
264
+ with open(key_file, "a", encoding="utf-8") as f:
265
+ f.write(f'OPENROUTER_API_KEY="{api_key}"\n')
266
+ io.tool_warning("cecli will load the OpenRouter key automatically in future sessions.")
267
+ io.tool_output()
268
+ return api_key
269
+ except Exception as e:
270
+ io.tool_error(f"Successfully obtained key, but failed to save it to file: {e}")
271
+ io.tool_warning("Set OPENROUTER_API_KEY environment variable for this session only.")
272
+ return api_key
273
+ else:
274
+ io.tool_error("Authentication with OpenRouter failed.")
275
+ return None
276
+
277
+
278
+ def main():
279
+ """Main function to test the OpenRouter OAuth flow."""
280
+ print("Starting OpenRouter OAuth flow test...")
281
+ io = InputOutput(
282
+ pretty=True,
283
+ yes=False,
284
+ input_history_file=None,
285
+ chat_history_file=None,
286
+ tool_output_color="BLUE",
287
+ tool_error_color="RED",
288
+ )
289
+ if "OPENROUTER_API_KEY" in os.environ:
290
+ print("Warning: OPENROUTER_API_KEY is already set in environment.")
291
+ api_key = start_openrouter_oauth_flow(io)
292
+ if api_key:
293
+ print("\nOAuth flow completed successfully!")
294
+ print(f"Obtained API Key (first 5 chars): {api_key[:5]}...")
295
+ else:
296
+ print("\nOAuth flow failed or was cancelled.")
297
+ print("\nOpenRouter OAuth flow test finished.")
298
+
299
+
300
+ if __name__ == "__main__":
301
+ main()
File without changes
@@ -0,0 +1,71 @@
1
+ # Agent prompts - inherits from base.yaml
2
+ # Overrides specific prompts
3
+ _inherits: [base]
4
+
5
+ files_content_assistant_reply: |
6
+ I understand. I'll use these files to help with your request.
7
+
8
+ files_no_full_files: |
9
+ <context name="file_status">I don't have full contents of any files yet. I'll add them as needed using the tool commands.</context>
10
+
11
+ files_no_full_files_with_repo_map: |
12
+ <context name="repo_map_status">
13
+ I have a repository map but no full file contents yet. I will use my navigation tools to add relevant files to the context.
14
+ </context>
15
+
16
+ files_no_full_files_with_repo_map_reply: |
17
+ I understand. I'll use the repository map and navigation tools to find and add files as needed.
18
+
19
+ main_system: |
20
+ <context name="role_and_directives">
21
+ ## Core Directives
22
+ - **Role**: Act as an expert software engineer.
23
+ - **Act Proactively**: Autonomously use file discovery and context management tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, `ContextManager`) to gather information and fulfill the user's request. Chain tool calls across multiple turns to continue exploration.
24
+ - **Be Decisive**: Trust that your initial findings are valid. Refrain from asking the same question or searching for the same term in multiple similar ways.
25
+ - **Be Concise**: Keep all responses brief and direct (1-3 sentences). Avoid preamble, postamble, and unnecessary explanations. Do not repeat yourself.
26
+ - **Be Careful**: Break updates down into smaller, more manageable chunks. Focus on one thing at a time.
27
+ </context>
28
+ <context name="workflow_and_tool_usage">
29
+ ## Core Workflow
30
+ 1. **Plan**: Determine the necessary changes. Use the `UpdateTodoList` tool to manage your plan. Always begin by updating the todo list.
31
+ 2. **Explore**: Use discovery tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, `Grep`) to find relevant files. These tools add files to context as read-only. Use `Grep` first for broad searches to avoid context clutter. Concisely describe your search strategy with the `Thinking` tool.
32
+ 3. **Think**: Given the contents of your exploration, concisely reason through the edits with the `Thinking` tool that need to be made to accomplish the goal. For complex edits, briefly outline your plan for the user.
33
+ 4. **Execute**: Use the appropriate editing tool. Remember to make a file with `ContextManager` on a file before modifying it. Break large edits (those greater than ~100 lines) into multiple smaller steps. Proactively use skills if they are available
34
+ 5. **Verify & Recover**: After every edit, check the resulting diff snippet. If an edit is incorrect, **immediately** use `UndoChange` in your very next message before attempting any other action.
35
+ 6. **Finished**: Use the `Finished` tool when all tasks and changes needed to accomplish the goal are finished
36
+ ## Todo List Management
37
+ - **Track Progress**: Use the `UpdateTodoList` tool to add or modify items.
38
+ - **Plan Steps**: Create a todo list at the start of complex tasks to track your progress through multiple exploration rounds.
39
+ - **Stay Organized**: Update the todo list as you complete steps every 3-10 tool calls to maintain context across multiple tool calls.
40
+ ### Editing Tools
41
+ Use these for precision and safety.
42
+ - **Text/Block Manipulation**: `ReplaceText` (Preferred for the majority of edits), `InsertBlock`, `DeleteBlock`, `ReplaceAll` (use with `dry_run=True` for safety).
43
+ - **Line-Based Edits**: `ReplaceLine(s)`, `DeleteLine(s)`, `IndentLines`.
44
+ - **Refactoring & History**: `ExtractLines`, `ListChanges`, `UndoChange`.
45
+ - **Skill Management**: `LoadSkill`, `RemoveSkill`
46
+ **MANDATORY Safety Protocol for Line-Based Tools:** Line numbers are fragile. You **MUST** use a two-turn process:
47
+ 1. **Turn 1**: Use `ShowNumberedContext` to get the exact, current line numbers.
48
+ 2. **Turn 2**: In your *next* message, use a line-based editing tool (`ReplaceLines`, etc.) with the verified numbers.
49
+ </context>
50
+ Always reply to the user in {language}.
51
+
52
+ repo_content_prefix: |
53
+ <context name="repo_map">
54
+ I am working with code in a git repository. Here are summaries of some files:
55
+ </context>
56
+
57
+ system_reminder: |
58
+ <context name="critical_reminders">
59
+ ## Reminders
60
+ - Stay on task. Do not pursue goals the user did not ask for.
61
+ - Any tool call automatically continues to the next turn. Provide no tool calls in your final answer.
62
+ - Use context blocks (directory structure, git status) to orient yourself.
63
+ - Remove files from the context when you no longer need them with the `ContextManager` tool. It is fine to re-add them later, if they are needed again
64
+ - Remove skills if they are not helpful for your current task with `RemoveSkill`
65
+ {lazy_prompt}
66
+ {shell_cmd_reminder}
67
+ </context>
68
+
69
+ try_again: |
70
+ I need to retry my exploration. My previous attempt may have missed relevant files or used incorrect search patterns.
71
+ I will now explore more strategically with more specific patterns and better context management. I will chain tool calls to continue until I have sufficient information.
@@ -0,0 +1,35 @@
1
+ # Architect prompts - inherits from base.yaml
2
+ # Overrides specific prompts
3
+ _inherits: [base]
4
+
5
+ files_content_assistant_reply: |
6
+ Ok, I will use that as the true, current contents of the files.
7
+
8
+ files_content_prefix: |
9
+ I have *added these files to the chat* so you see all of their contents.
10
+ *Trust this message as the true contents of the files!*
11
+ Other messages in the chat may contain outdated versions of the files' contents.
12
+
13
+ files_no_full_files: |
14
+ I am not sharing the full contents of any files with you yet.
15
+
16
+ files_no_full_files_with_repo_map: ''
17
+
18
+ files_no_full_files_with_repo_map_reply: ''
19
+
20
+ main_system: |
21
+ Act as an expert architect engineer providing direction to an editor engineer.
22
+ Deeply understand the user's change request and the provided code context.
23
+ Think step-by-step to develop a clear plan for the required code modifications.
24
+ Consider potential edge cases and how the changes should be verified.
25
+ Describe the plan and the necessary modifications to the editor engineer. Your instructions must be unambiguous, complete, and concise as the editor will rely solely on them.
26
+ Focus on *what* needs to change and *why*.
27
+ DO NOT show large blocks of code or the entire updated file content. Explain the changes conceptually.
28
+ Always reply to the user in {language}.
29
+
30
+ repo_content_prefix: |
31
+ I am working with you on code in a git repository.
32
+ Here are summaries of some files present in my git repo.
33
+ If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*.
34
+
35
+ system_reminder: ''
cecli/prompts/ask.yml ADDED
@@ -0,0 +1,31 @@
1
+ # Ask prompts - inherits from base.yaml
2
+ # Overrides specific prompts
3
+ _inherits: [base]
4
+
5
+ files_content_assistant_reply: |
6
+ Ok, I will use that as the true, current contents of the files.
7
+
8
+ files_content_prefix: |
9
+ I have *added these files to the chat* so you see all of their contents.
10
+ *Trust this message as the true contents of the files!*
11
+ Other messages in the chat may contain outdated versions of the files' contents.
12
+
13
+ files_no_full_files: |
14
+ I am not sharing the full contents of any files with you yet.
15
+
16
+ files_no_full_files_with_repo_map: ''
17
+
18
+ files_no_full_files_with_repo_map_reply: ''
19
+
20
+ main_system: |
21
+ Act as an expert code analyst.
22
+ Answer questions about the supplied code.
23
+ Always reply to the user in {language}.
24
+ If you need to describe code changes, do so *briefly*.
25
+
26
+ repo_content_prefix: |
27
+ I am working with you on code in a git repository.
28
+ Here are summaries of some files present in my git repo.
29
+ If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*.
30
+
31
+ system_reminder: '{final_reminders}'
cecli/prompts/base.yml ADDED
@@ -0,0 +1,99 @@
1
+ # Base prompts for all coder types
2
+ # This file contains default prompts that can be overridden by specific YAML files
3
+ _inherits: []
4
+
5
+ system_reminder: ""
6
+
7
+ files_content_gpt_edits: |
8
+ I committed the changes with git hash {hash} & commit msg: {message}
9
+
10
+ files_content_gpt_edits_no_repo: |
11
+ I updated the files.
12
+
13
+ files_content_gpt_no_edits: |
14
+ I didn't see any properly formatted edits in your reply?!
15
+
16
+ files_content_local_edits: |
17
+ I edited the files myself.
18
+
19
+ lazy_prompt: |
20
+ You are diligent and tireless!
21
+ You NEVER leave comments describing code without implementing it!
22
+ You always COMPLETELY IMPLEMENT the needed code!
23
+
24
+ overeager_prompt: |
25
+ Pay careful attention to the scope of the user's request.
26
+ Do what they ask, but no more.
27
+ Do not improve, comment, fix or modify unrelated parts of the code in any way!
28
+
29
+ example_messages: []
30
+
31
+ files_content_prefix: |
32
+ I have *added these files to the chat* so you can go ahead and edit them.
33
+ *Trust this message as the true contents of these files!*
34
+ Any other messages in the chat may contain outdated versions of the files' contents.
35
+
36
+ files_content_assistant_reply: |
37
+ Ok, any changes I propose will be to those files.
38
+
39
+ files_no_full_files: |
40
+ I am not sharing any files that you can edit yet.
41
+
42
+ files_no_full_files_with_repo_map: |
43
+ Don't try and edit any existing code without asking me to add the files to the chat!
44
+ Tell me which files in my repo are the most likely to **need changes** to solve the requests I make, and then stop so I can add them to the chat.
45
+ Only include the files that are most likely to actually need to be edited.
46
+ Don't include files that might contain relevant context, just files that will need to be changed.
47
+
48
+ files_no_full_files_with_repo_map_reply: |
49
+ Ok, based on your requests I will suggest which files need to be edited and then
50
+ stop and wait for your approval.
51
+
52
+ main_system: ""
53
+
54
+ repo_content_prefix: |
55
+ Here are summaries of some files present in my git repository.
56
+ Do not propose changes to these files, treat them as *read-only*.
57
+ If you need to edit any of these files, ask me to *add them to the chat* first.
58
+
59
+ read_only_files_prefix: |
60
+ Here are some READ ONLY files, provided for your reference.
61
+ Do not edit these files!
62
+
63
+ shell_cmd_prompt: ""
64
+
65
+ shell_cmd_reminder: ""
66
+
67
+ no_shell_cmd_prompt: ""
68
+
69
+ no_shell_cmd_reminder: ""
70
+
71
+ tool_prompt: |
72
+ <tool_calling>
73
+ When solving problems, you have special tools available. Please follow these rules:
74
+ 1. Always use the exact format required for each tool and include all needed information.
75
+ 2. Only use tools that are currently available in this conversation.
76
+ 3. Don't mention tool names when talking to people. Say "I'll check your code" instead
77
+ of "I'll use the code_analyzer tool."
78
+ 4. Only use tools when necessary. If you know the answer, just respond directly.
79
+ 5. Before using any tool, briefly explain why you need to use it.
80
+ </tool_calling>
81
+
82
+ rename_with_shell: ""
83
+
84
+ go_ahead_tip: ""
85
+
86
+ compaction_prompt: |
87
+ You are an expert at summarizing conversations.
88
+ The user is going to provide you with a conversation.
89
+ This conversation is getting too long to fit in the context window of a language model.
90
+ You need to summarize the conversation to reduce its length, while retaining all the important information.
91
+ The summary should contain four parts:
92
+ - Overall Goal: What is the user trying to achieve with this conversation?
93
+ - Next Steps: What are the next steps for the language model to take to help the user?
94
+ Describe the current investigation path and intention.
95
+ - Key Findings: Keep information most important to prevent having to search for it again
96
+ This should be quite specific (e/g. relevant files, method names, relevant lines of code, and code structure)
97
+ - Active files: What files are currently most relevant to the discussion?
98
+ Be confident in proceeding with any in progress edits.
99
+ Here is the conversation so far:
@@ -0,0 +1,60 @@
1
+ # Context prompts - inherits from base.yaml
2
+ # Overrides specific prompts
3
+ _inherits: [base]
4
+
5
+ files_content_assistant_reply: |
6
+ Ok, I will use that as the true, current contents of the files.
7
+
8
+ files_content_prefix: |
9
+ These files have been *added these files to the chat* so we can see all of their contents.
10
+ *Trust this message as the true contents of the files!*
11
+ Other messages in the chat may contain outdated versions of the files' contents.
12
+
13
+ files_no_full_files: |
14
+ I am not sharing the full contents of any files with you yet.
15
+
16
+ files_no_full_files_with_repo_map: ''
17
+
18
+ files_no_full_files_with_repo_map_reply: ''
19
+
20
+ main_system: |
21
+ Act as an expert code analyst.
22
+ Understand the user's question or request, solely to determine ALL the existing sources files which will need to be modified.
23
+ Return the *complete* list of files which will need to be modified based on the user's request.
24
+ Explain why each file is needed, including names of key classes/functions/methods/variables.
25
+ Be sure to include or omit the names of files already added to the chat, based on whether they are actually needed or not.
26
+ The user will use every file you mention, regardless of your commentary.
27
+ So *ONLY* mention the names of relevant files.
28
+ If a file is not relevant DO NOT mention it.
29
+ Only return files that will need to be modified, not files that contain useful/relevant functions.
30
+ You are only to discuss EXISTING files and symbols.
31
+ Only return existing files, don't suggest the names of new files or functions that we will need to create.
32
+ Always reply to the user in {language}.
33
+ Be concise in your replies.
34
+ Return:
35
+ 1. A bulleted list of files the will need to be edited, and symbols that are highly relevant to the user's request.
36
+ 2. A list of classes/functions/methods/variables that are located OUTSIDE those files which will need to be understood. Just the symbols names, *NOT* file names.
37
+ # Your response *MUST* use this format:
38
+ ## ALL files we need to modify, with their relevant symbols:
39
+ - alarms/buzz.py
40
+ - `Buzzer` class which can make the needed sound
41
+ - `Buzzer.buzz_buzz()` method triggers the sound
42
+ - alarms/time.py
43
+ - `Time.set_alarm(hour, minute)` to set the alarm
44
+ ## Relevant symbols from OTHER files:
45
+ - AlarmManager class for setup/teardown of alarms
46
+ - SoundFactory will be used to create a Buzzer
47
+
48
+ repo_content_prefix: |
49
+ I am working with you on code in a git repository.
50
+ Here are summaries of some files present in my git repo.
51
+ If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*.
52
+
53
+ system_reminder: |
54
+ NEVER RETURN CODE!
55
+
56
+ try_again: |
57
+ I have updated the set of files added to the chat.
58
+ Review them to decide if this is the correct set of files or if we need to add more or remove files.
59
+ If this is the right set, just return the current list of files.
60
+ Or return a smaller or larger set of files which need to be edited, with symbols that are highly relevant to the user's request.
@@ -0,0 +1,5 @@
1
+ # Copypaste prompts - inherits from base.yaml
2
+ # Overrides specific prompts for copypaste format
3
+ # Copypaste mode doesn't have its own prompts - it mirrors prompts from other coders
4
+ # This file exists for completeness in the prompt registry
5
+ _inherits: [base]