cecli-dev 0.95.5__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.
- cecli/__init__.py +20 -0
- cecli/__main__.py +4 -0
- cecli/_version.py +34 -0
- cecli/args.py +1092 -0
- cecli/args_formatter.py +228 -0
- cecli/change_tracker.py +133 -0
- cecli/coders/__init__.py +38 -0
- cecli/coders/agent_coder.py +1872 -0
- cecli/coders/architect_coder.py +63 -0
- cecli/coders/ask_coder.py +8 -0
- cecli/coders/base_coder.py +3993 -0
- cecli/coders/chat_chunks.py +116 -0
- cecli/coders/context_coder.py +52 -0
- cecli/coders/copypaste_coder.py +269 -0
- cecli/coders/editblock_coder.py +656 -0
- cecli/coders/editblock_fenced_coder.py +9 -0
- cecli/coders/editblock_func_coder.py +140 -0
- cecli/coders/editor_diff_fenced_coder.py +8 -0
- cecli/coders/editor_editblock_coder.py +8 -0
- cecli/coders/editor_whole_coder.py +8 -0
- cecli/coders/help_coder.py +15 -0
- cecli/coders/patch_coder.py +705 -0
- cecli/coders/search_replace.py +757 -0
- cecli/coders/shell.py +37 -0
- cecli/coders/single_wholefile_func_coder.py +101 -0
- cecli/coders/udiff_coder.py +428 -0
- cecli/coders/udiff_simple.py +12 -0
- cecli/coders/wholefile_coder.py +143 -0
- cecli/coders/wholefile_func_coder.py +133 -0
- cecli/commands/__init__.py +192 -0
- cecli/commands/add.py +226 -0
- cecli/commands/agent.py +51 -0
- cecli/commands/architect.py +46 -0
- cecli/commands/ask.py +44 -0
- cecli/commands/chat_mode.py +0 -0
- cecli/commands/clear.py +37 -0
- cecli/commands/code.py +46 -0
- cecli/commands/command_prefix.py +44 -0
- cecli/commands/commit.py +52 -0
- cecli/commands/context.py +47 -0
- cecli/commands/context_blocks.py +124 -0
- cecli/commands/context_management.py +51 -0
- cecli/commands/copy.py +62 -0
- cecli/commands/copy_context.py +81 -0
- cecli/commands/core.py +287 -0
- cecli/commands/diff.py +68 -0
- cecli/commands/drop.py +217 -0
- cecli/commands/editor.py +78 -0
- cecli/commands/exit.py +55 -0
- cecli/commands/git.py +57 -0
- cecli/commands/help.py +140 -0
- cecli/commands/history_search.py +40 -0
- cecli/commands/lint.py +109 -0
- cecli/commands/list_sessions.py +56 -0
- cecli/commands/load.py +85 -0
- cecli/commands/load_session.py +48 -0
- cecli/commands/load_skill.py +68 -0
- cecli/commands/ls.py +75 -0
- cecli/commands/map.py +37 -0
- cecli/commands/map_refresh.py +35 -0
- cecli/commands/model.py +118 -0
- cecli/commands/models.py +41 -0
- cecli/commands/multiline_mode.py +38 -0
- cecli/commands/paste.py +91 -0
- cecli/commands/quit.py +32 -0
- cecli/commands/read_only.py +267 -0
- cecli/commands/read_only_stub.py +270 -0
- cecli/commands/reasoning_effort.py +70 -0
- cecli/commands/remove_skill.py +68 -0
- cecli/commands/report.py +40 -0
- cecli/commands/reset.py +88 -0
- cecli/commands/run.py +99 -0
- cecli/commands/save.py +49 -0
- cecli/commands/save_session.py +43 -0
- cecli/commands/settings.py +69 -0
- cecli/commands/test.py +58 -0
- cecli/commands/think_tokens.py +74 -0
- cecli/commands/tokens.py +207 -0
- cecli/commands/undo.py +145 -0
- cecli/commands/utils/__init__.py +0 -0
- cecli/commands/utils/base_command.py +131 -0
- cecli/commands/utils/helpers.py +142 -0
- cecli/commands/utils/registry.py +53 -0
- cecli/commands/utils/save_load_manager.py +98 -0
- cecli/commands/voice.py +78 -0
- cecli/commands/weak_model.py +123 -0
- cecli/commands/web.py +87 -0
- cecli/deprecated_args.py +185 -0
- cecli/diffs.py +129 -0
- cecli/dump.py +29 -0
- cecli/editor.py +147 -0
- cecli/exceptions.py +115 -0
- cecli/format_settings.py +26 -0
- cecli/help.py +119 -0
- cecli/help_pats.py +19 -0
- cecli/helpers/__init__.py +9 -0
- cecli/helpers/copypaste.py +123 -0
- cecli/helpers/coroutines.py +8 -0
- cecli/helpers/file_searcher.py +142 -0
- cecli/helpers/model_providers.py +552 -0
- cecli/helpers/plugin_manager.py +81 -0
- cecli/helpers/profiler.py +162 -0
- cecli/helpers/requests.py +77 -0
- cecli/helpers/similarity.py +98 -0
- cecli/helpers/skills.py +577 -0
- cecli/history.py +186 -0
- cecli/io.py +1782 -0
- cecli/linter.py +304 -0
- cecli/llm.py +101 -0
- cecli/main.py +1280 -0
- cecli/mcp/__init__.py +154 -0
- cecli/mcp/oauth.py +250 -0
- cecli/mcp/server.py +278 -0
- cecli/mdstream.py +243 -0
- cecli/models.py +1255 -0
- cecli/onboarding.py +301 -0
- cecli/prompts/__init__.py +0 -0
- cecli/prompts/agent.yml +71 -0
- cecli/prompts/architect.yml +35 -0
- cecli/prompts/ask.yml +31 -0
- cecli/prompts/base.yml +99 -0
- cecli/prompts/context.yml +60 -0
- cecli/prompts/copypaste.yml +5 -0
- cecli/prompts/editblock.yml +143 -0
- cecli/prompts/editblock_fenced.yml +106 -0
- cecli/prompts/editblock_func.yml +25 -0
- cecli/prompts/editor_diff_fenced.yml +115 -0
- cecli/prompts/editor_editblock.yml +121 -0
- cecli/prompts/editor_whole.yml +46 -0
- cecli/prompts/help.yml +37 -0
- cecli/prompts/patch.yml +110 -0
- cecli/prompts/single_wholefile_func.yml +24 -0
- cecli/prompts/udiff.yml +106 -0
- cecli/prompts/udiff_simple.yml +13 -0
- cecli/prompts/utils/__init__.py +0 -0
- cecli/prompts/utils/prompt_registry.py +167 -0
- cecli/prompts/utils/system.py +56 -0
- cecli/prompts/wholefile.yml +50 -0
- cecli/prompts/wholefile_func.yml +24 -0
- cecli/queries/tree-sitter-language-pack/README.md +7 -0
- cecli/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
- cecli/queries/tree-sitter-language-pack/c-tags.scm +12 -0
- cecli/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
- cecli/queries/tree-sitter-language-pack/clojure-tags.scm +12 -0
- cecli/queries/tree-sitter-language-pack/commonlisp-tags.scm +127 -0
- cecli/queries/tree-sitter-language-pack/cpp-tags.scm +18 -0
- cecli/queries/tree-sitter-language-pack/csharp-tags.scm +32 -0
- cecli/queries/tree-sitter-language-pack/d-tags.scm +26 -0
- cecli/queries/tree-sitter-language-pack/dart-tags.scm +97 -0
- cecli/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
- cecli/queries/tree-sitter-language-pack/elixir-tags.scm +59 -0
- cecli/queries/tree-sitter-language-pack/elm-tags.scm +22 -0
- cecli/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
- cecli/queries/tree-sitter-language-pack/go-tags.scm +49 -0
- cecli/queries/tree-sitter-language-pack/java-tags.scm +26 -0
- cecli/queries/tree-sitter-language-pack/javascript-tags.scm +96 -0
- cecli/queries/tree-sitter-language-pack/lua-tags.scm +39 -0
- cecli/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
- cecli/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
- cecli/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +101 -0
- cecli/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
- cecli/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
- cecli/queries/tree-sitter-language-pack/python-tags.scm +24 -0
- cecli/queries/tree-sitter-language-pack/r-tags.scm +27 -0
- cecli/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
- cecli/queries/tree-sitter-language-pack/ruby-tags.scm +69 -0
- cecli/queries/tree-sitter-language-pack/rust-tags.scm +63 -0
- cecli/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
- cecli/queries/tree-sitter-language-pack/swift-tags.scm +54 -0
- cecli/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
- cecli/queries/tree-sitter-languages/README.md +24 -0
- cecli/queries/tree-sitter-languages/c-tags.scm +12 -0
- cecli/queries/tree-sitter-languages/c_sharp-tags.scm +52 -0
- cecli/queries/tree-sitter-languages/cpp-tags.scm +18 -0
- cecli/queries/tree-sitter-languages/dart-tags.scm +92 -0
- cecli/queries/tree-sitter-languages/elisp-tags.scm +8 -0
- cecli/queries/tree-sitter-languages/elixir-tags.scm +59 -0
- cecli/queries/tree-sitter-languages/elm-tags.scm +22 -0
- cecli/queries/tree-sitter-languages/fortran-tags.scm +18 -0
- cecli/queries/tree-sitter-languages/go-tags.scm +36 -0
- cecli/queries/tree-sitter-languages/haskell-tags.scm +5 -0
- cecli/queries/tree-sitter-languages/hcl-tags.scm +77 -0
- cecli/queries/tree-sitter-languages/java-tags.scm +26 -0
- cecli/queries/tree-sitter-languages/javascript-tags.scm +96 -0
- cecli/queries/tree-sitter-languages/julia-tags.scm +60 -0
- cecli/queries/tree-sitter-languages/kotlin-tags.scm +30 -0
- cecli/queries/tree-sitter-languages/matlab-tags.scm +10 -0
- cecli/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
- cecli/queries/tree-sitter-languages/ocaml_interface-tags.scm +104 -0
- cecli/queries/tree-sitter-languages/php-tags.scm +32 -0
- cecli/queries/tree-sitter-languages/python-tags.scm +22 -0
- cecli/queries/tree-sitter-languages/ql-tags.scm +26 -0
- cecli/queries/tree-sitter-languages/ruby-tags.scm +69 -0
- cecli/queries/tree-sitter-languages/rust-tags.scm +63 -0
- cecli/queries/tree-sitter-languages/scala-tags.scm +64 -0
- cecli/queries/tree-sitter-languages/typescript-tags.scm +44 -0
- cecli/queries/tree-sitter-languages/zig-tags.scm +20 -0
- cecli/reasoning_tags.py +82 -0
- cecli/repo.py +626 -0
- cecli/repomap.py +1368 -0
- cecli/report.py +260 -0
- cecli/resources/__init__.py +3 -0
- cecli/resources/model-metadata.json +25751 -0
- cecli/resources/model-settings.yml +2394 -0
- cecli/resources/providers.json +67 -0
- cecli/run_cmd.py +143 -0
- cecli/scrape.py +295 -0
- cecli/sendchat.py +250 -0
- cecli/sessions.py +281 -0
- cecli/special.py +203 -0
- cecli/tools/__init__.py +72 -0
- cecli/tools/command.py +103 -0
- cecli/tools/command_interactive.py +113 -0
- cecli/tools/context_manager.py +175 -0
- cecli/tools/delete_block.py +154 -0
- cecli/tools/delete_line.py +120 -0
- cecli/tools/delete_lines.py +144 -0
- cecli/tools/extract_lines.py +281 -0
- cecli/tools/finished.py +35 -0
- cecli/tools/git_branch.py +132 -0
- cecli/tools/git_diff.py +49 -0
- cecli/tools/git_log.py +43 -0
- cecli/tools/git_remote.py +39 -0
- cecli/tools/git_show.py +37 -0
- cecli/tools/git_status.py +32 -0
- cecli/tools/grep.py +242 -0
- cecli/tools/indent_lines.py +195 -0
- cecli/tools/insert_block.py +263 -0
- cecli/tools/list_changes.py +71 -0
- cecli/tools/load_skill.py +51 -0
- cecli/tools/ls.py +77 -0
- cecli/tools/remove_skill.py +51 -0
- cecli/tools/replace_all.py +113 -0
- cecli/tools/replace_line.py +135 -0
- cecli/tools/replace_lines.py +180 -0
- cecli/tools/replace_text.py +186 -0
- cecli/tools/show_numbered_context.py +137 -0
- cecli/tools/thinking.py +52 -0
- cecli/tools/undo_change.py +82 -0
- cecli/tools/update_todo_list.py +148 -0
- cecli/tools/utils/base_tool.py +64 -0
- cecli/tools/utils/helpers.py +359 -0
- cecli/tools/utils/output.py +119 -0
- cecli/tools/utils/registry.py +145 -0
- cecli/tools/view_files_matching.py +138 -0
- cecli/tools/view_files_with_symbol.py +117 -0
- cecli/tui/__init__.py +83 -0
- cecli/tui/app.py +971 -0
- cecli/tui/io.py +566 -0
- cecli/tui/styles.tcss +117 -0
- cecli/tui/widgets/__init__.py +19 -0
- cecli/tui/widgets/completion_bar.py +331 -0
- cecli/tui/widgets/file_list.py +76 -0
- cecli/tui/widgets/footer.py +165 -0
- cecli/tui/widgets/input_area.py +320 -0
- cecli/tui/widgets/key_hints.py +16 -0
- cecli/tui/widgets/output.py +354 -0
- cecli/tui/widgets/status_bar.py +279 -0
- cecli/tui/worker.py +160 -0
- cecli/urls.py +16 -0
- cecli/utils.py +499 -0
- cecli/versioncheck.py +90 -0
- cecli/voice.py +90 -0
- cecli/waiting.py +38 -0
- cecli/watch.py +316 -0
- cecli/watch_prompts.py +12 -0
- cecli/website/Gemfile +8 -0
- cecli/website/_includes/blame.md +162 -0
- cecli/website/_includes/get-started.md +22 -0
- cecli/website/_includes/help-tip.md +5 -0
- cecli/website/_includes/help.md +24 -0
- cecli/website/_includes/install.md +5 -0
- cecli/website/_includes/keys.md +4 -0
- cecli/website/_includes/model-warnings.md +67 -0
- cecli/website/_includes/multi-line.md +22 -0
- cecli/website/_includes/python-m-aider.md +5 -0
- cecli/website/_includes/recording.css +228 -0
- cecli/website/_includes/recording.md +34 -0
- cecli/website/_includes/replit-pipx.md +9 -0
- cecli/website/_includes/works-best.md +1 -0
- cecli/website/_sass/custom/custom.scss +103 -0
- cecli/website/docs/config/adv-model-settings.md +2498 -0
- cecli/website/docs/config/agent-mode.md +320 -0
- cecli/website/docs/config/aider_conf.md +548 -0
- cecli/website/docs/config/api-keys.md +90 -0
- cecli/website/docs/config/custom-commands.md +187 -0
- cecli/website/docs/config/dotenv.md +493 -0
- cecli/website/docs/config/editor.md +127 -0
- cecli/website/docs/config/mcp.md +210 -0
- cecli/website/docs/config/model-aliases.md +173 -0
- cecli/website/docs/config/options.md +890 -0
- cecli/website/docs/config/reasoning.md +210 -0
- cecli/website/docs/config/skills.md +172 -0
- cecli/website/docs/config/tui.md +126 -0
- cecli/website/docs/config.md +44 -0
- cecli/website/docs/faq.md +379 -0
- cecli/website/docs/git.md +76 -0
- cecli/website/docs/index.md +47 -0
- cecli/website/docs/install/codespaces.md +39 -0
- cecli/website/docs/install/docker.md +48 -0
- cecli/website/docs/install/optional.md +100 -0
- cecli/website/docs/install/replit.md +8 -0
- cecli/website/docs/install.md +115 -0
- cecli/website/docs/languages.md +264 -0
- cecli/website/docs/legal/contributor-agreement.md +111 -0
- cecli/website/docs/legal/privacy.md +104 -0
- cecli/website/docs/llms/anthropic.md +77 -0
- cecli/website/docs/llms/azure.md +48 -0
- cecli/website/docs/llms/bedrock.md +132 -0
- cecli/website/docs/llms/cohere.md +34 -0
- cecli/website/docs/llms/deepseek.md +32 -0
- cecli/website/docs/llms/gemini.md +49 -0
- cecli/website/docs/llms/github.md +111 -0
- cecli/website/docs/llms/groq.md +36 -0
- cecli/website/docs/llms/lm-studio.md +39 -0
- cecli/website/docs/llms/ollama.md +75 -0
- cecli/website/docs/llms/openai-compat.md +39 -0
- cecli/website/docs/llms/openai.md +58 -0
- cecli/website/docs/llms/openrouter.md +78 -0
- cecli/website/docs/llms/other.md +117 -0
- cecli/website/docs/llms/vertex.md +50 -0
- cecli/website/docs/llms/warnings.md +10 -0
- cecli/website/docs/llms/xai.md +53 -0
- cecli/website/docs/llms.md +54 -0
- cecli/website/docs/more/analytics.md +127 -0
- cecli/website/docs/more/edit-formats.md +116 -0
- cecli/website/docs/more/infinite-output.md +192 -0
- cecli/website/docs/more-info.md +8 -0
- cecli/website/docs/recordings/auto-accept-architect.md +31 -0
- cecli/website/docs/recordings/dont-drop-original-read-files.md +35 -0
- cecli/website/docs/recordings/index.md +21 -0
- cecli/website/docs/recordings/model-accepts-settings.md +69 -0
- cecli/website/docs/recordings/tree-sitter-language-pack.md +80 -0
- cecli/website/docs/repomap.md +112 -0
- cecli/website/docs/scripting.md +100 -0
- cecli/website/docs/sessions.md +213 -0
- cecli/website/docs/troubleshooting/aider-not-found.md +24 -0
- cecli/website/docs/troubleshooting/edit-errors.md +76 -0
- cecli/website/docs/troubleshooting/imports.md +62 -0
- cecli/website/docs/troubleshooting/models-and-keys.md +54 -0
- cecli/website/docs/troubleshooting/support.md +79 -0
- cecli/website/docs/troubleshooting/token-limits.md +96 -0
- cecli/website/docs/troubleshooting/warnings.md +12 -0
- cecli/website/docs/troubleshooting.md +11 -0
- cecli/website/docs/usage/browser.md +57 -0
- cecli/website/docs/usage/caching.md +49 -0
- cecli/website/docs/usage/commands.md +133 -0
- cecli/website/docs/usage/conventions.md +119 -0
- cecli/website/docs/usage/copypaste.md +136 -0
- cecli/website/docs/usage/images-urls.md +48 -0
- cecli/website/docs/usage/lint-test.md +118 -0
- cecli/website/docs/usage/modes.md +211 -0
- cecli/website/docs/usage/not-code.md +179 -0
- cecli/website/docs/usage/notifications.md +87 -0
- cecli/website/docs/usage/tips.md +79 -0
- cecli/website/docs/usage/tutorials.md +30 -0
- cecli/website/docs/usage/voice.md +121 -0
- cecli/website/docs/usage/watch.md +294 -0
- cecli/website/docs/usage.md +102 -0
- cecli/website/share/index.md +101 -0
- cecli_dev-0.95.5.dist-info/METADATA +549 -0
- cecli_dev-0.95.5.dist-info/RECORD +366 -0
- cecli_dev-0.95.5.dist-info/WHEEL +5 -0
- cecli_dev-0.95.5.dist-info/entry_points.txt +4 -0
- cecli_dev-0.95.5.dist-info/licenses/LICENSE.txt +202 -0
- cecli_dev-0.95.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def print_tool_response(coder, mcp_server, tool_response):
|
|
6
|
+
"""
|
|
7
|
+
Format the output for display.
|
|
8
|
+
Prints a Header to identify the tool, a body for the relevant information
|
|
9
|
+
for the user and a footer for verbose information
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
coder: An instance of base_coder
|
|
13
|
+
mcp_server: An mcp server instance
|
|
14
|
+
tool_response: a tool_response dictionary
|
|
15
|
+
"""
|
|
16
|
+
tool_header(coder=coder, mcp_server=mcp_server, tool_response=tool_response)
|
|
17
|
+
tool_body(coder=coder, tool_response=tool_response)
|
|
18
|
+
tool_footer(coder=coder, tool_response=tool_response)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def tool_header(coder, mcp_server, tool_response):
|
|
22
|
+
"""
|
|
23
|
+
Prints the header for the tool call output
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
coder: An instance of base_coder
|
|
27
|
+
mcp_server: An mcp server instance
|
|
28
|
+
tool_response: a tool_response dictionary
|
|
29
|
+
"""
|
|
30
|
+
color_start, color_end = color_markers(coder)
|
|
31
|
+
|
|
32
|
+
coder.io.tool_output(
|
|
33
|
+
f"{color_start}Tool Call:{color_end} {mcp_server.name} • {tool_response.function.name}",
|
|
34
|
+
type="Tool Call",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def tool_body(coder, tool_response):
|
|
39
|
+
"""
|
|
40
|
+
Prints the output body of a tool call as the raw json returned from the model
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
coder: An instance of base_coder
|
|
44
|
+
tool_response: a tool_response dictionary
|
|
45
|
+
"""
|
|
46
|
+
color_start, color_end = color_markers(coder)
|
|
47
|
+
|
|
48
|
+
# Parse and format arguments as headers with values
|
|
49
|
+
if tool_response.function.arguments:
|
|
50
|
+
# For non-replace tools, show raw arguments
|
|
51
|
+
raw_args = tool_response.function.arguments
|
|
52
|
+
coder.io.tool_output(f"{color_start}Arguments:{color_end} {raw_args}")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def tool_body_unwrapped(coder, tool_response):
|
|
56
|
+
"""
|
|
57
|
+
Prints the output body of a tool call with the argument
|
|
58
|
+
and content sections separated
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
coder: An instance of base_coder
|
|
62
|
+
tool_response: a tool_response dictionary
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
color_start, color_end = color_markers(coder)
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
args_dict = json.loads(tool_response.function.arguments)
|
|
69
|
+
first_key = True
|
|
70
|
+
for key, value in args_dict.items():
|
|
71
|
+
# Convert explicit \\n sequences to actual newlines using regex
|
|
72
|
+
# Only match \\n that is not preceded by any other backslashes
|
|
73
|
+
if isinstance(value, str):
|
|
74
|
+
value = re.sub(r"(?<!\\)\\n", "\n", value)
|
|
75
|
+
# Add extra newline before first key/header
|
|
76
|
+
if first_key:
|
|
77
|
+
coder.io.tool_output("\n")
|
|
78
|
+
first_key = False
|
|
79
|
+
coder.io.tool_output(f"{color_start}{key}:{color_end}")
|
|
80
|
+
# Split the value by newlines and output each line separately
|
|
81
|
+
if isinstance(value, str):
|
|
82
|
+
for line in value.split("\n"):
|
|
83
|
+
coder.io.tool_output(f"{line}")
|
|
84
|
+
else:
|
|
85
|
+
coder.io.tool_output(f"{str(value)}")
|
|
86
|
+
coder.io.tool_output("")
|
|
87
|
+
except json.JSONDecodeError:
|
|
88
|
+
# If JSON parsing fails, show raw arguments
|
|
89
|
+
raw_args = tool_response.function.arguments
|
|
90
|
+
coder.io.tool_output(f"{color_start}Arguments:{color_end} {raw_args}")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def tool_footer(coder, tool_response):
|
|
94
|
+
"""
|
|
95
|
+
Prints the output footer of a tool call, generally a new line
|
|
96
|
+
But can include id's if ran in verbose mode
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
coder: An instance of base_coder
|
|
100
|
+
tool_response: a tool_response dictionary
|
|
101
|
+
"""
|
|
102
|
+
if coder.verbose:
|
|
103
|
+
coder.io.tool_output(f"Tool ID: {tool_response.id}")
|
|
104
|
+
coder.io.tool_output(f"Tool type: {tool_response.type}")
|
|
105
|
+
|
|
106
|
+
coder.io.tool_output("\n", type="tool-footer")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def color_markers(coder):
|
|
110
|
+
"""
|
|
111
|
+
Rich.console color markers
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
coder: An instance of base_coder
|
|
115
|
+
"""
|
|
116
|
+
color_start = "[bright_cyan]" if coder.pretty else ""
|
|
117
|
+
color_end = "[/bright_cyan]" if coder.pretty else ""
|
|
118
|
+
|
|
119
|
+
return color_start, color_end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Registry for tool discovery and management.
|
|
3
|
+
|
|
4
|
+
Similar to the command registry in cecli/commands/utils/registry.py,
|
|
5
|
+
this provides centralized tool registration, discovery, and filtering
|
|
6
|
+
based on agent configuration.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, List, Optional, Set, Type
|
|
11
|
+
|
|
12
|
+
from cecli.helpers import plugin_manager
|
|
13
|
+
from cecli.tools import TOOL_MODULES
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ToolRegistry:
|
|
17
|
+
"""Registry for tool discovery and management."""
|
|
18
|
+
|
|
19
|
+
_tools: Dict[str, Type] = {} # normalized name -> Tool class
|
|
20
|
+
_essential_tools: Set[str] = {"contextmanager", "replacetext", "finished"}
|
|
21
|
+
_registry: Dict[str, Type] = {} # cached filtered registry
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def register(cls, tool_class):
|
|
25
|
+
"""Register a tool class."""
|
|
26
|
+
name = tool_class.NORM_NAME
|
|
27
|
+
cls._tools[name] = tool_class
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_tool(cls, name: str) -> Optional[Type]:
|
|
31
|
+
"""Get tool class by normalized name."""
|
|
32
|
+
return cls._tools.get(name, None)
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def list_tools(cls) -> List[str]:
|
|
36
|
+
"""List all registered tool names."""
|
|
37
|
+
return list(cls._tools.keys())
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def build_registry(cls, agent_config: Optional[Dict] = None) -> Dict[str, Type]:
|
|
41
|
+
"""
|
|
42
|
+
Build a filtered registry of tools based on agent configuration.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
agent_config: Agent configuration dictionary with optional
|
|
46
|
+
tools_includelist/tools_excludelist keys
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Dictionary mapping normalized tool names to tool classes
|
|
50
|
+
"""
|
|
51
|
+
if agent_config is None:
|
|
52
|
+
agent_config = {}
|
|
53
|
+
|
|
54
|
+
# Load tools from tool_paths if specified
|
|
55
|
+
tool_paths = agent_config.get("tool_paths", [])
|
|
56
|
+
|
|
57
|
+
for tool_path in tool_paths:
|
|
58
|
+
path = Path(tool_path)
|
|
59
|
+
if path.is_dir():
|
|
60
|
+
# Find all Python files in the directory
|
|
61
|
+
for py_file in path.glob("*.py"):
|
|
62
|
+
try:
|
|
63
|
+
# Load the module using plugin_manager
|
|
64
|
+
module = plugin_manager.load_module(str(py_file))
|
|
65
|
+
# Check if module has a Tool class
|
|
66
|
+
if hasattr(module, "Tool"):
|
|
67
|
+
cls.register(module.Tool)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
# Log error but continue with other files
|
|
70
|
+
print(f"Error loading tool from {py_file}: {e}")
|
|
71
|
+
else:
|
|
72
|
+
# If it's a file, try to load it directly
|
|
73
|
+
if path.exists() and path.suffix == ".py":
|
|
74
|
+
try:
|
|
75
|
+
module = plugin_manager.load_module(str(path))
|
|
76
|
+
if hasattr(module, "Tool"):
|
|
77
|
+
cls.register(module.Tool)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"Error loading tool from {path}: {e}")
|
|
80
|
+
|
|
81
|
+
# Get include/exclude lists from config
|
|
82
|
+
tools_includelist = agent_config.get(
|
|
83
|
+
"tools_includelist", agent_config.get("tools_whitelist", [])
|
|
84
|
+
)
|
|
85
|
+
tools_excludelist = agent_config.get(
|
|
86
|
+
"tools_excludelist", agent_config.get("tools_blacklist", [])
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
registry = {}
|
|
90
|
+
|
|
91
|
+
for tool_name, tool_class in cls._tools.items():
|
|
92
|
+
should_include = True
|
|
93
|
+
|
|
94
|
+
# Apply include list if specified
|
|
95
|
+
if tools_includelist:
|
|
96
|
+
should_include = tool_name in tools_includelist
|
|
97
|
+
|
|
98
|
+
# Essential tools are always included
|
|
99
|
+
if tool_name in cls._essential_tools:
|
|
100
|
+
should_include = True
|
|
101
|
+
|
|
102
|
+
# Apply exclude list (unless essential)
|
|
103
|
+
if tool_name in tools_excludelist and tool_name not in cls._essential_tools:
|
|
104
|
+
should_include = False
|
|
105
|
+
|
|
106
|
+
if should_include:
|
|
107
|
+
registry[tool_name] = tool_class
|
|
108
|
+
|
|
109
|
+
# Store the built registry in the class attribute
|
|
110
|
+
cls._registry = registry
|
|
111
|
+
return registry
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def get_registered_tools(cls) -> List[str]:
|
|
115
|
+
"""
|
|
116
|
+
Get the list of registered tools from the cached registry.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
List of normalized tool names that are currently registered
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
RuntimeError: If no tools are registered (registry is empty)
|
|
123
|
+
"""
|
|
124
|
+
if not cls._registry:
|
|
125
|
+
raise RuntimeError(
|
|
126
|
+
"No tools are currently registered in the registry. "
|
|
127
|
+
"Call build_registry() first to initialize the registry."
|
|
128
|
+
)
|
|
129
|
+
return list(cls._registry.keys())
|
|
130
|
+
|
|
131
|
+
@classmethod
|
|
132
|
+
def initialize_registry(cls):
|
|
133
|
+
"""Initialize the registry by importing and registering all tools."""
|
|
134
|
+
# Clear existing registry
|
|
135
|
+
cls._tools.clear()
|
|
136
|
+
|
|
137
|
+
# Register all tools from TOOL_MODULES
|
|
138
|
+
for module in TOOL_MODULES:
|
|
139
|
+
if hasattr(module, "Tool"):
|
|
140
|
+
tool_class = module.Tool
|
|
141
|
+
cls.register(tool_class)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Initialize the registry when module is imported
|
|
145
|
+
ToolRegistry.initialize_registry()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import fnmatch
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from cecli.tools.utils.base_tool import BaseTool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Tool(BaseTool):
|
|
8
|
+
NORM_NAME = "viewfilesmatching"
|
|
9
|
+
SCHEMA = {
|
|
10
|
+
"type": "function",
|
|
11
|
+
"function": {
|
|
12
|
+
"name": "ViewFilesMatching",
|
|
13
|
+
"description": "View files containing a specific pattern.",
|
|
14
|
+
"parameters": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"pattern": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "The pattern to search for in file contents.",
|
|
20
|
+
},
|
|
21
|
+
"file_pattern": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": (
|
|
24
|
+
"An optional glob pattern to filter which files are searched."
|
|
25
|
+
),
|
|
26
|
+
},
|
|
27
|
+
"regex": {
|
|
28
|
+
"type": "boolean",
|
|
29
|
+
"description": (
|
|
30
|
+
"Whether the pattern is a regular expression. Defaults to False."
|
|
31
|
+
),
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
"required": ["pattern"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def execute(cls, coder, pattern, file_pattern=None, regex=False):
|
|
41
|
+
"""
|
|
42
|
+
Search for pattern (literal string or regex) in files and return matching files as text.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
coder: The Coder instance.
|
|
46
|
+
pattern (str): The pattern to search for.
|
|
47
|
+
Treated as a literal string by default.
|
|
48
|
+
file_pattern (str, optional): Glob pattern to filter which files are searched.
|
|
49
|
+
Defaults to None (search all files).
|
|
50
|
+
regex (bool, optional): If True, treat pattern as a regular expression.
|
|
51
|
+
Defaults to False.
|
|
52
|
+
|
|
53
|
+
This tool lets the LLM search for content within files, mimicking
|
|
54
|
+
how a developer would use grep or regex search to find relevant code.
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
# Get list of files to search
|
|
58
|
+
if file_pattern:
|
|
59
|
+
# Use glob pattern to filter files
|
|
60
|
+
all_files = coder.get_all_relative_files()
|
|
61
|
+
files_to_search = []
|
|
62
|
+
for file in all_files:
|
|
63
|
+
if fnmatch.fnmatch(file, file_pattern):
|
|
64
|
+
files_to_search.append(file)
|
|
65
|
+
|
|
66
|
+
if not files_to_search:
|
|
67
|
+
return f"No files matching '{file_pattern}' to search for pattern '{pattern}'"
|
|
68
|
+
else:
|
|
69
|
+
# Search all files if no pattern provided
|
|
70
|
+
files_to_search = coder.get_all_relative_files()
|
|
71
|
+
|
|
72
|
+
# Search for pattern in files
|
|
73
|
+
matches = {}
|
|
74
|
+
num_matches = 0
|
|
75
|
+
inspecific_search_flag = False
|
|
76
|
+
|
|
77
|
+
for file in files_to_search:
|
|
78
|
+
abs_path = coder.abs_root_path(file)
|
|
79
|
+
|
|
80
|
+
if num_matches >= 25:
|
|
81
|
+
inspecific_search_flag = True
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
if coder.repo.ignored_file(abs_path):
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
with open(abs_path, "r", encoding="utf-8") as f:
|
|
88
|
+
content = f.read()
|
|
89
|
+
match_count = 0
|
|
90
|
+
if regex:
|
|
91
|
+
try:
|
|
92
|
+
matches_found = re.findall(pattern, content)
|
|
93
|
+
match_count = len(matches_found)
|
|
94
|
+
except re.error as e:
|
|
95
|
+
# Handle invalid regex patterns gracefully
|
|
96
|
+
coder.io.tool_error(f"Invalid regex pattern '{pattern}': {e}")
|
|
97
|
+
# Skip this file for this search if regex is invalid
|
|
98
|
+
continue
|
|
99
|
+
else:
|
|
100
|
+
# Exact string matching
|
|
101
|
+
match_count = content.count(pattern)
|
|
102
|
+
|
|
103
|
+
if match_count > 0:
|
|
104
|
+
matches[file] = match_count
|
|
105
|
+
num_matches += 1
|
|
106
|
+
except Exception:
|
|
107
|
+
# Skip files that can't be read (binary, etc.)
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
# Return formatted text instead of adding to context
|
|
111
|
+
if matches:
|
|
112
|
+
# Sort by number of matches (most matches first)
|
|
113
|
+
sorted_matches = sorted(matches.items(), key=lambda x: x[1], reverse=True)
|
|
114
|
+
match_list = [f"{file} ({count} matches)" for file, count in sorted_matches]
|
|
115
|
+
|
|
116
|
+
if len(matches) > 10:
|
|
117
|
+
result = (
|
|
118
|
+
f"Found '{pattern}' in {len(matches)} files:"
|
|
119
|
+
f" {', '.join(match_list[:10])} and {len(matches) - 10} more"
|
|
120
|
+
"\nTry more specific search terms going forward"
|
|
121
|
+
if inspecific_search_flag
|
|
122
|
+
else ""
|
|
123
|
+
)
|
|
124
|
+
coder.io.tool_output(f"🔍 Found '{pattern}' in {len(matches)} files")
|
|
125
|
+
else:
|
|
126
|
+
result = f"Found '{pattern}' in {len(matches)} files: {', '.join(match_list)}"
|
|
127
|
+
coder.io.tool_output(
|
|
128
|
+
f"🔍 Found '{pattern}' in:"
|
|
129
|
+
f" {', '.join(match_list[:5])}{' and more' if len(matches) > 5 else ''}"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
return result
|
|
133
|
+
else:
|
|
134
|
+
coder.io.tool_output(f"⚠️ Pattern '{pattern}' not found in any files")
|
|
135
|
+
return "Pattern not found in any files"
|
|
136
|
+
except Exception as e:
|
|
137
|
+
coder.io.tool_error(f"Error in ViewFilesMatching: {str(e)}")
|
|
138
|
+
return f"Error: {str(e)}"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from cecli.tools.utils.base_tool import BaseTool
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Tool(BaseTool):
|
|
5
|
+
NORM_NAME = "viewfileswithsymbol"
|
|
6
|
+
SCHEMA = {
|
|
7
|
+
"type": "function",
|
|
8
|
+
"function": {
|
|
9
|
+
"name": "ViewFilesWithSymbol",
|
|
10
|
+
"description": "View files that contain a specific symbol (e.g., class, function).",
|
|
11
|
+
"parameters": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"symbol": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The symbol to search for.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
"required": ["symbol"],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def execute(cls, coder, symbol):
|
|
26
|
+
"""
|
|
27
|
+
Find files containing a symbol using RepoMap and return them as text.
|
|
28
|
+
Checks files already in context first.
|
|
29
|
+
"""
|
|
30
|
+
if not coder.repo_map:
|
|
31
|
+
coder.io.tool_output("⚠️ Repo map not available, cannot use ViewFilesWithSymbol tool.")
|
|
32
|
+
return "Repo map not available"
|
|
33
|
+
|
|
34
|
+
if not symbol:
|
|
35
|
+
return "Error: Missing 'symbol' parameter for ViewFilesWithSymbol"
|
|
36
|
+
|
|
37
|
+
# 1. Check files already in context
|
|
38
|
+
files_in_context = list(coder.abs_fnames) + list(coder.abs_read_only_fnames)
|
|
39
|
+
found_in_context = []
|
|
40
|
+
for abs_fname in files_in_context:
|
|
41
|
+
rel_fname = coder.get_rel_fname(abs_fname)
|
|
42
|
+
try:
|
|
43
|
+
# Use get_tags for consistency with RepoMap usage elsewhere for now.
|
|
44
|
+
tags = coder.repo_map.get_tags(abs_fname, rel_fname)
|
|
45
|
+
for tag in tags:
|
|
46
|
+
if tag.name == symbol:
|
|
47
|
+
found_in_context.append(rel_fname)
|
|
48
|
+
break # Found in this file, move to next
|
|
49
|
+
except Exception as e:
|
|
50
|
+
coder.io.tool_warning(
|
|
51
|
+
f"Could not get symbols for {rel_fname} while checking context: {e}"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
if found_in_context:
|
|
55
|
+
# Symbol found in already loaded files. Report this and stop.
|
|
56
|
+
file_list = ", ".join(sorted(list(set(found_in_context))))
|
|
57
|
+
coder.io.tool_output(f"Symbol '{symbol}' found in already loaded file(s): {file_list}")
|
|
58
|
+
return f"Symbol '{symbol}' found in already loaded file(s): {file_list}"
|
|
59
|
+
|
|
60
|
+
# 2. If not found in context, search the repository using RepoMap
|
|
61
|
+
coder.io.tool_output(f"🔎 Searching for symbol '{symbol}' in repository...")
|
|
62
|
+
try:
|
|
63
|
+
found_files = set()
|
|
64
|
+
current_context_files = coder.abs_fnames | coder.abs_read_only_fnames
|
|
65
|
+
files_to_search = set(coder.get_all_abs_files()) - current_context_files
|
|
66
|
+
|
|
67
|
+
rel_fname_to_abs = {}
|
|
68
|
+
all_tags = []
|
|
69
|
+
|
|
70
|
+
for fname in files_to_search:
|
|
71
|
+
rel_fname = coder.get_rel_fname(fname)
|
|
72
|
+
rel_fname_to_abs[rel_fname] = fname
|
|
73
|
+
try:
|
|
74
|
+
tags = coder.repo_map.get_tags(fname, rel_fname)
|
|
75
|
+
all_tags.extend(tags)
|
|
76
|
+
except Exception as e:
|
|
77
|
+
coder.io.tool_warning(f"Could not get tags for {rel_fname}: {e}")
|
|
78
|
+
|
|
79
|
+
# Find matching symbols
|
|
80
|
+
for tag in all_tags:
|
|
81
|
+
if tag.name == symbol:
|
|
82
|
+
# Use absolute path directly if available, otherwise resolve from relative path
|
|
83
|
+
abs_fname = rel_fname_to_abs.get(tag.rel_fname) or coder.abs_root_path(
|
|
84
|
+
tag.fname
|
|
85
|
+
)
|
|
86
|
+
if (
|
|
87
|
+
abs_fname in files_to_search
|
|
88
|
+
): # Ensure we only add files we intended to search
|
|
89
|
+
found_files.add(coder.get_rel_fname(abs_fname))
|
|
90
|
+
|
|
91
|
+
# Return formatted text instead of adding to context
|
|
92
|
+
if found_files:
|
|
93
|
+
found_files_list = sorted(list(found_files))
|
|
94
|
+
if len(found_files) > 10:
|
|
95
|
+
result = (
|
|
96
|
+
f"Found symbol '{symbol}' in {len(found_files)} files:"
|
|
97
|
+
f" {', '.join(found_files_list[:10])} and {len(found_files) - 10} more"
|
|
98
|
+
)
|
|
99
|
+
coder.io.tool_output(f"🔎 Found '{symbol}' in {len(found_files)} files")
|
|
100
|
+
else:
|
|
101
|
+
result = (
|
|
102
|
+
f"Found symbol '{symbol}' in {len(found_files)} files:"
|
|
103
|
+
f" {', '.join(found_files_list)}"
|
|
104
|
+
)
|
|
105
|
+
coder.io.tool_output(
|
|
106
|
+
f"🔎 Found '{symbol}' in files:"
|
|
107
|
+
f" {', '.join(found_files_list[:5])}{' and more' if len(found_files) > 5 else ''}"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return result
|
|
111
|
+
else:
|
|
112
|
+
coder.io.tool_output(f"⚠️ Symbol '{symbol}' not found in searchable files")
|
|
113
|
+
return f"Symbol '{symbol}' not found in searchable files"
|
|
114
|
+
|
|
115
|
+
except Exception as e:
|
|
116
|
+
coder.io.tool_error(f"Error in ViewFilesWithSymbol: {str(e)}")
|
|
117
|
+
return f"Error: {str(e)}"
|
cecli/tui/__init__.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Textual TUI interface for cecli.
|
|
2
|
+
|
|
3
|
+
This package provides an experimental TUI (Terminal User Interface) for cecli
|
|
4
|
+
using the Textual framework. Launch with: cecli --tui
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import queue
|
|
8
|
+
import weakref
|
|
9
|
+
|
|
10
|
+
from .app import TUI
|
|
11
|
+
from .io import TextualInputOutput
|
|
12
|
+
from .worker import CoderWorker
|
|
13
|
+
|
|
14
|
+
__all__ = ["TUI", "TextualInputOutput", "CoderWorker", "create_tui_io", "launch_tui"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def create_tui_io(args, editing_mode):
|
|
18
|
+
"""Create TUI IO instance and communication queues.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
args: Parsed command line arguments
|
|
22
|
+
editing_mode: EditingMode.VI or EditingMode.EMACS
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Tuple of (io, output_queue, input_queue)
|
|
26
|
+
"""
|
|
27
|
+
output_queue = queue.Queue()
|
|
28
|
+
input_queue = queue.Queue()
|
|
29
|
+
|
|
30
|
+
io = TextualInputOutput(
|
|
31
|
+
output_queue=output_queue,
|
|
32
|
+
input_queue=input_queue,
|
|
33
|
+
pretty=True,
|
|
34
|
+
yes=args.yes_always,
|
|
35
|
+
input_history_file=args.input_history_file,
|
|
36
|
+
chat_history_file=args.chat_history_file,
|
|
37
|
+
input=None,
|
|
38
|
+
output=None,
|
|
39
|
+
user_input_color=args.user_input_color,
|
|
40
|
+
tool_output_color=args.tool_output_color,
|
|
41
|
+
tool_warning_color=args.tool_warning_color,
|
|
42
|
+
tool_error_color=args.tool_error_color,
|
|
43
|
+
completion_menu_color=args.completion_menu_color,
|
|
44
|
+
completion_menu_bg_color=args.completion_menu_bg_color,
|
|
45
|
+
completion_menu_current_color=args.completion_menu_current_color,
|
|
46
|
+
completion_menu_current_bg_color=args.completion_menu_current_bg_color,
|
|
47
|
+
assistant_output_color=args.assistant_output_color,
|
|
48
|
+
code_theme=args.code_theme,
|
|
49
|
+
dry_run=args.dry_run,
|
|
50
|
+
encoding=args.encoding,
|
|
51
|
+
line_endings=args.line_endings,
|
|
52
|
+
editingmode=editing_mode,
|
|
53
|
+
fancy_input=False,
|
|
54
|
+
multiline_mode=args.multiline,
|
|
55
|
+
notifications=args.notifications,
|
|
56
|
+
notifications_command=args.notifications_command,
|
|
57
|
+
verbose=args.verbose,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return io, output_queue, input_queue
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def launch_tui(coder, output_queue, input_queue, args):
|
|
64
|
+
"""Launch the TUI application.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
coder: Initialized Coder instance
|
|
68
|
+
output_queue: Queue for output messages
|
|
69
|
+
input_queue: Queue for input messages
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Exit code from TUI
|
|
73
|
+
"""
|
|
74
|
+
worker = CoderWorker(coder, output_queue, input_queue)
|
|
75
|
+
app = TUI(worker, output_queue, input_queue, args)
|
|
76
|
+
|
|
77
|
+
# Set weak reference to TUI app on the coder instance
|
|
78
|
+
coder.tui = weakref.ref(app)
|
|
79
|
+
|
|
80
|
+
return_code = await app.run_async()
|
|
81
|
+
|
|
82
|
+
worker.stop()
|
|
83
|
+
return return_code if return_code else 0
|