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.
- 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.93.1.dist-info/METADATA +549 -0
- cecli_dev-0.93.1.dist-info/RECORD +366 -0
- cecli_dev-0.93.1.dist-info/WHEEL +5 -0
- cecli_dev-0.93.1.dist-info/entry_points.txt +4 -0
- cecli_dev-0.93.1.dist-info/licenses/LICENSE.txt +202 -0
- cecli_dev-0.93.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Unified status bar widget for notifications and confirmations."""
|
|
2
|
+
|
|
3
|
+
from textual.app import ComposeResult
|
|
4
|
+
from textual.containers import Horizontal
|
|
5
|
+
from textual.message import Message
|
|
6
|
+
from textual.reactive import reactive
|
|
7
|
+
from textual.widget import Widget
|
|
8
|
+
from textual.widgets import Static
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StatusBar(Widget, can_focus=True):
|
|
12
|
+
"""Unified status bar for notifications, confirmations, and prompts.
|
|
13
|
+
|
|
14
|
+
Modes:
|
|
15
|
+
- hidden: Bar is not displayed
|
|
16
|
+
- notification: Shows a transient message (auto-dismisses)
|
|
17
|
+
- confirm: Shows a y/n/a confirmation prompt
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
DEFAULT_CSS = """
|
|
21
|
+
StatusBar {
|
|
22
|
+
height: auto;
|
|
23
|
+
background: $surface;
|
|
24
|
+
margin: 0 0;
|
|
25
|
+
padding: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
StatusBar.hidden {
|
|
29
|
+
display: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Content container */
|
|
33
|
+
StatusBar .status-content {
|
|
34
|
+
height: 3;
|
|
35
|
+
padding: 1 0 0 2;
|
|
36
|
+
layout: horizontal;
|
|
37
|
+
align: left middle;
|
|
38
|
+
background: $surface;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Notification styles */
|
|
42
|
+
StatusBar .notification-text {
|
|
43
|
+
width: 1fr;
|
|
44
|
+
height: 1;
|
|
45
|
+
color: $secondary;
|
|
46
|
+
content-align: left middle;
|
|
47
|
+
background: $surface;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
StatusBar .notification-text.info {
|
|
51
|
+
color: $secondary;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
StatusBar .notification-text.warning {
|
|
55
|
+
color: $warning;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
StatusBar .notification-text.error {
|
|
59
|
+
color: $error;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
StatusBar .notification-text.success {
|
|
63
|
+
color: $success;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Confirmation styles */
|
|
67
|
+
StatusBar .confirm-question {
|
|
68
|
+
width: 1fr;
|
|
69
|
+
height: 1;
|
|
70
|
+
color: $foreground;
|
|
71
|
+
content-align: left middle;
|
|
72
|
+
background: $surface;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
StatusBar .confirm-hints {
|
|
76
|
+
width: auto;
|
|
77
|
+
height: 1;
|
|
78
|
+
dock: right;
|
|
79
|
+
background: $surface;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
StatusBar .hint {
|
|
83
|
+
width: auto;
|
|
84
|
+
height: 1;
|
|
85
|
+
margin-left: 2;
|
|
86
|
+
color: $secondary;
|
|
87
|
+
background: $surface;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
StatusBar .hint-yes {
|
|
91
|
+
color: $success;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
StatusBar .hint-no {
|
|
95
|
+
color: $warning;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
StatusBar .hint-all {
|
|
99
|
+
color: $secondary;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
StatusBar .hint-skip {
|
|
103
|
+
color: $secondary;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
StatusBar .hint-tweak {
|
|
107
|
+
color: $accent;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
StatusBar .hint-never {
|
|
111
|
+
color: $warning;
|
|
112
|
+
}
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
# Current mode
|
|
116
|
+
mode: reactive[str] = reactive("hidden")
|
|
117
|
+
|
|
118
|
+
class ConfirmResponse(Message):
|
|
119
|
+
"""Confirmation response message."""
|
|
120
|
+
|
|
121
|
+
def __init__(self, result: bool | str):
|
|
122
|
+
self.result = result
|
|
123
|
+
super().__init__()
|
|
124
|
+
|
|
125
|
+
def __init__(self, **kwargs):
|
|
126
|
+
"""Initialize status bar."""
|
|
127
|
+
super().__init__(**kwargs)
|
|
128
|
+
self._text = ""
|
|
129
|
+
self._severity = "info"
|
|
130
|
+
self._show_all = False
|
|
131
|
+
self._allow_tweak = False
|
|
132
|
+
self._allow_never = False
|
|
133
|
+
self._default = "y"
|
|
134
|
+
self._explicit_yes_required = False
|
|
135
|
+
self._timer = None
|
|
136
|
+
|
|
137
|
+
def compose(self) -> ComposeResult:
|
|
138
|
+
"""Create empty container - content added dynamically."""
|
|
139
|
+
yield Horizontal(classes="status-content")
|
|
140
|
+
|
|
141
|
+
def watch_mode(self, mode: str) -> None:
|
|
142
|
+
"""React to mode changes."""
|
|
143
|
+
self.remove_class("hidden")
|
|
144
|
+
if mode == "hidden":
|
|
145
|
+
self.add_class("hidden")
|
|
146
|
+
self.can_focus = False
|
|
147
|
+
else:
|
|
148
|
+
self.can_focus = mode == "confirm"
|
|
149
|
+
|
|
150
|
+
def _rebuild_content(self) -> None:
|
|
151
|
+
"""Rebuild the content based on current mode."""
|
|
152
|
+
container = self.query_one(".status-content")
|
|
153
|
+
container.remove_children()
|
|
154
|
+
|
|
155
|
+
if self.mode == "notification":
|
|
156
|
+
container.mount(Static(self._text, classes=f"notification-text {self._severity}"))
|
|
157
|
+
elif self.mode == "confirm":
|
|
158
|
+
container.mount(Static(self._text, classes="confirm-question"))
|
|
159
|
+
hints = Horizontal(classes="confirm-hints")
|
|
160
|
+
container.mount(hints)
|
|
161
|
+
hints.mount(Static("\\[y]es", classes="hint hint-yes"))
|
|
162
|
+
hints.mount(Static("\\[n]o", classes="hint hint-no"))
|
|
163
|
+
if self._show_all:
|
|
164
|
+
hints.mount(Static("\\[a]ll", classes="hint hint-all"))
|
|
165
|
+
hints.mount(Static("\\[s]kip", classes="hint hint-skip"))
|
|
166
|
+
if self._allow_tweak:
|
|
167
|
+
hints.mount(Static("\\[t]weak", classes="hint hint-tweak"))
|
|
168
|
+
if self._allow_never:
|
|
169
|
+
hints.mount(Static("\\[d]on't ask", classes="hint hint-never"))
|
|
170
|
+
|
|
171
|
+
def show_notification(
|
|
172
|
+
self, text: str, severity: str = "info", timeout: float | None = 3.0
|
|
173
|
+
) -> None:
|
|
174
|
+
"""Show a transient notification message.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
text: Message to display
|
|
178
|
+
severity: One of "info", "warning", "error", "success"
|
|
179
|
+
timeout: Auto-dismiss after this many seconds (None = no auto-dismiss)
|
|
180
|
+
"""
|
|
181
|
+
# Cancel any existing timer
|
|
182
|
+
if self._timer:
|
|
183
|
+
self._timer.stop()
|
|
184
|
+
self._timer = None
|
|
185
|
+
|
|
186
|
+
self._text = text
|
|
187
|
+
self._severity = severity
|
|
188
|
+
self.mode = "notification"
|
|
189
|
+
self._rebuild_content()
|
|
190
|
+
|
|
191
|
+
if timeout:
|
|
192
|
+
self._timer = self.set_timer(timeout, self.hide)
|
|
193
|
+
|
|
194
|
+
def show_confirm(
|
|
195
|
+
self,
|
|
196
|
+
question: str,
|
|
197
|
+
show_all: bool = False,
|
|
198
|
+
allow_tweak: bool = False,
|
|
199
|
+
allow_never: bool = False,
|
|
200
|
+
default: str = "y",
|
|
201
|
+
explicit_yes_required: bool = False,
|
|
202
|
+
) -> None:
|
|
203
|
+
"""Show a confirmation prompt.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
question: Question to display
|
|
207
|
+
show_all: Whether to show "all" option
|
|
208
|
+
allow_tweak: Whether to show "tweak" option
|
|
209
|
+
allow_never: Whether to show "don't ask again" option
|
|
210
|
+
default: Default response ("y" or "n")
|
|
211
|
+
explicit_yes_required: Whether explicit yes is required
|
|
212
|
+
"""
|
|
213
|
+
# Cancel any existing timer
|
|
214
|
+
if self._timer:
|
|
215
|
+
self._timer.stop()
|
|
216
|
+
self._timer = None
|
|
217
|
+
|
|
218
|
+
self._text = question
|
|
219
|
+
self._show_all = show_all
|
|
220
|
+
self._allow_tweak = allow_tweak
|
|
221
|
+
self._allow_never = allow_never
|
|
222
|
+
self._default = default
|
|
223
|
+
self._explicit_yes_required = explicit_yes_required
|
|
224
|
+
self.mode = "confirm"
|
|
225
|
+
self._rebuild_content()
|
|
226
|
+
self.focus()
|
|
227
|
+
|
|
228
|
+
def hide(self) -> None:
|
|
229
|
+
"""Hide the status bar."""
|
|
230
|
+
if self._timer:
|
|
231
|
+
self._timer.stop()
|
|
232
|
+
self._timer = None
|
|
233
|
+
self.mode = "hidden"
|
|
234
|
+
|
|
235
|
+
def on_key(self, event) -> None:
|
|
236
|
+
"""Handle key shortcuts for confirm mode."""
|
|
237
|
+
if self.mode != "confirm":
|
|
238
|
+
return
|
|
239
|
+
|
|
240
|
+
key = event.key.lower()
|
|
241
|
+
if key == "y":
|
|
242
|
+
event.stop()
|
|
243
|
+
event.prevent_default()
|
|
244
|
+
self.post_message(self.ConfirmResponse(True))
|
|
245
|
+
self.hide()
|
|
246
|
+
elif key == "n":
|
|
247
|
+
event.stop()
|
|
248
|
+
event.prevent_default()
|
|
249
|
+
self.post_message(self.ConfirmResponse(False))
|
|
250
|
+
self.hide()
|
|
251
|
+
elif key == "a" and self._show_all:
|
|
252
|
+
event.stop()
|
|
253
|
+
event.prevent_default()
|
|
254
|
+
self.post_message(self.ConfirmResponse("all"))
|
|
255
|
+
self.hide()
|
|
256
|
+
elif key == "s" and self._show_all:
|
|
257
|
+
event.stop()
|
|
258
|
+
event.prevent_default()
|
|
259
|
+
self.post_message(self.ConfirmResponse("skip"))
|
|
260
|
+
self.hide()
|
|
261
|
+
elif key == "t" and self._allow_tweak:
|
|
262
|
+
event.stop()
|
|
263
|
+
event.prevent_default()
|
|
264
|
+
self.post_message(self.ConfirmResponse("tweak"))
|
|
265
|
+
self.hide()
|
|
266
|
+
elif key == "d" and self._allow_never:
|
|
267
|
+
event.stop()
|
|
268
|
+
event.prevent_default()
|
|
269
|
+
self.post_message(self.ConfirmResponse("never"))
|
|
270
|
+
self.hide()
|
|
271
|
+
elif key == "escape":
|
|
272
|
+
event.stop()
|
|
273
|
+
event.prevent_default()
|
|
274
|
+
# Return default based on default parameter
|
|
275
|
+
if self._default.lower().startswith("y"):
|
|
276
|
+
self.post_message(self.ConfirmResponse(True))
|
|
277
|
+
else:
|
|
278
|
+
self.post_message(self.ConfirmResponse(False))
|
|
279
|
+
self.hide()
|
cecli/tui/worker.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Worker thread for running Coder in background."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import threading
|
|
6
|
+
import warnings
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from cecli.coders import Coder
|
|
10
|
+
from cecli.commands import SwitchCoderSignal
|
|
11
|
+
|
|
12
|
+
# Suppress asyncio task destroyed warnings during shutdown
|
|
13
|
+
logging.getLogger("asyncio").setLevel(logging.CRITICAL)
|
|
14
|
+
|
|
15
|
+
# Also suppress via warnings module
|
|
16
|
+
warnings.filterwarnings("ignore", message=".*Task was destroyed.*")
|
|
17
|
+
warnings.filterwarnings("ignore", message=".*coroutine.*was never awaited.*")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CoderWorker:
|
|
21
|
+
"""Runs Coder in a background thread with its own event loop."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, coder, output_queue, input_queue):
|
|
24
|
+
"""Initialize worker with coder instance and communication queues.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
coder: The Coder instance to run
|
|
28
|
+
output_queue: queue.Queue for sending output to TUI
|
|
29
|
+
input_queue: queue.Queue for receiving input from TUI
|
|
30
|
+
"""
|
|
31
|
+
self.coder = coder
|
|
32
|
+
self.output_queue = output_queue # queue.Queue
|
|
33
|
+
self.input_queue = input_queue # queue.Queue
|
|
34
|
+
self.thread: Optional[threading.Thread] = None
|
|
35
|
+
self.loop: Optional[asyncio.AbstractEventLoop] = None
|
|
36
|
+
self.running = False
|
|
37
|
+
|
|
38
|
+
def start(self):
|
|
39
|
+
"""Start the worker thread."""
|
|
40
|
+
self.running = True
|
|
41
|
+
self.thread = threading.Thread(target=self._run_thread, daemon=True)
|
|
42
|
+
self.thread.start()
|
|
43
|
+
|
|
44
|
+
def _run_thread(self):
|
|
45
|
+
"""Thread entry point - creates event loop and runs coder."""
|
|
46
|
+
self.loop = asyncio.new_event_loop()
|
|
47
|
+
asyncio.set_event_loop(self.loop)
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
self.loop.run_until_complete(self._async_run())
|
|
51
|
+
except asyncio.CancelledError:
|
|
52
|
+
pass
|
|
53
|
+
except RuntimeError:
|
|
54
|
+
# Event loop stopped - this is expected during shutdown
|
|
55
|
+
pass
|
|
56
|
+
finally:
|
|
57
|
+
self._cleanup_loop()
|
|
58
|
+
|
|
59
|
+
def _cleanup_loop(self):
|
|
60
|
+
"""Clean up the event loop safely."""
|
|
61
|
+
if not self.loop:
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
# Cancel pending tasks if loop is still running
|
|
66
|
+
if not self.loop.is_closed():
|
|
67
|
+
pending = asyncio.all_tasks(self.loop)
|
|
68
|
+
for task in pending:
|
|
69
|
+
task.cancel()
|
|
70
|
+
|
|
71
|
+
# Only try to gather if loop isn't stopped
|
|
72
|
+
if self.loop.is_running():
|
|
73
|
+
pass # Can't do much if loop is still running
|
|
74
|
+
elif pending:
|
|
75
|
+
try:
|
|
76
|
+
self.loop.run_until_complete(
|
|
77
|
+
asyncio.gather(*pending, return_exceptions=True)
|
|
78
|
+
)
|
|
79
|
+
except RuntimeError:
|
|
80
|
+
pass # Loop already stopped
|
|
81
|
+
|
|
82
|
+
self.loop.close()
|
|
83
|
+
except Exception:
|
|
84
|
+
pass # Ignore cleanup errors
|
|
85
|
+
|
|
86
|
+
async def _async_run(self):
|
|
87
|
+
"""Async entry point - runs coder loop."""
|
|
88
|
+
while self.running:
|
|
89
|
+
try:
|
|
90
|
+
await self.coder.run()
|
|
91
|
+
break # Normal exit
|
|
92
|
+
except asyncio.CancelledError:
|
|
93
|
+
break
|
|
94
|
+
except SwitchCoderSignal as switch:
|
|
95
|
+
# Handle chat mode switches (e.g., /chat-mode architect)
|
|
96
|
+
try:
|
|
97
|
+
kwargs = dict(io=self.coder.io, from_coder=self.coder)
|
|
98
|
+
kwargs.update(switch.kwargs)
|
|
99
|
+
if "show_announcements" in kwargs:
|
|
100
|
+
del kwargs["show_announcements"]
|
|
101
|
+
kwargs["num_cache_warming_pings"] = 0
|
|
102
|
+
kwargs["args"] = self.coder.args
|
|
103
|
+
# Skip summarization to avoid blocking LLM calls during mode switch
|
|
104
|
+
kwargs["summarize_from_coder"] = False
|
|
105
|
+
|
|
106
|
+
new_coder = await Coder.create(**kwargs)
|
|
107
|
+
new_coder.args = self.coder.args
|
|
108
|
+
|
|
109
|
+
if switch.kwargs.get("show_announcements") is False:
|
|
110
|
+
new_coder.suppress_announcements_for_next_prompt = True
|
|
111
|
+
|
|
112
|
+
# Notify TUI of mode change
|
|
113
|
+
self.coder = new_coder
|
|
114
|
+
edit_format = getattr(self.coder, "edit_format", "code") or "code"
|
|
115
|
+
self.output_queue.put(
|
|
116
|
+
{
|
|
117
|
+
"type": "mode_change",
|
|
118
|
+
"mode": edit_format,
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
self.output_queue.put(
|
|
123
|
+
{"type": "error", "message": f"Failed to switch mode: {e}"}
|
|
124
|
+
)
|
|
125
|
+
break
|
|
126
|
+
# Continue the loop with the new coder
|
|
127
|
+
except Exception as e:
|
|
128
|
+
self.output_queue.put({"type": "error", "message": str(e)})
|
|
129
|
+
break
|
|
130
|
+
|
|
131
|
+
def interrupt(self):
|
|
132
|
+
"""Cancel the current output task on the coder instance."""
|
|
133
|
+
if self.coder and hasattr(self.coder, "io") and self.coder.io:
|
|
134
|
+
# Cancel the output task if it exists
|
|
135
|
+
if hasattr(self.coder.io, "output_task") and self.coder.io.output_task:
|
|
136
|
+
self.coder.io.output_task.cancel()
|
|
137
|
+
# Also set output_running to False to stop the output_task loop
|
|
138
|
+
if hasattr(self.coder, "output_running"):
|
|
139
|
+
self.coder.output_running = False
|
|
140
|
+
|
|
141
|
+
def stop(self):
|
|
142
|
+
"""Stop the worker thread gracefully."""
|
|
143
|
+
self.running = False
|
|
144
|
+
|
|
145
|
+
# Signal the coder to stop
|
|
146
|
+
if hasattr(self.coder, "input_running"):
|
|
147
|
+
self.coder.input_running = False
|
|
148
|
+
if hasattr(self.coder, "output_running"):
|
|
149
|
+
self.coder.output_running = False
|
|
150
|
+
|
|
151
|
+
if self.loop and self.loop.is_running():
|
|
152
|
+
try:
|
|
153
|
+
self.loop.call_soon_threadsafe(self.loop.stop)
|
|
154
|
+
except RuntimeError:
|
|
155
|
+
# Loop may already be closed
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
# Wait for thread to finish
|
|
159
|
+
if self.thread and self.thread.is_alive():
|
|
160
|
+
self.thread.join(timeout=2.0)
|
cecli/urls.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
website = "https://cecli.dev/"
|
|
2
|
+
add_all_files = "https://cecli.dev/docs/faq.html#how-can-i-add-all-the-files-to-the-chat"
|
|
3
|
+
edit_errors = "https://cecli.dev/docs/troubleshooting/edit-errors.html"
|
|
4
|
+
git = "https://cecli.dev/docs/git.html"
|
|
5
|
+
enable_playwright = "https://cecli.dev/docs/install/optional.html#enable-playwright"
|
|
6
|
+
favicon = "https://cecli.dev/assets/icons/favicon-32x32.png"
|
|
7
|
+
model_warnings = "https://cecli.dev/docs/llms/warnings.html"
|
|
8
|
+
token_limits = "https://cecli.dev/docs/troubleshooting/token-limits.html"
|
|
9
|
+
llms = "https://cecli.dev/docs/llms.html"
|
|
10
|
+
large_repos = "https://cecli.dev/docs/faq.html#can-i-use-cecli-in-a-large-mono-repo"
|
|
11
|
+
github_issues = "https://github.com/dwash96/aider-ce/issues/new"
|
|
12
|
+
git_index_version = "https://github.com/Aider-AI/aider/issues/211"
|
|
13
|
+
install_properly = "https://cecli.dev/docs/troubleshooting/imports.html"
|
|
14
|
+
release_notes = "https://github.com/dwash96/aider-ce/releases/latest"
|
|
15
|
+
edit_formats = "https://cecli.dev/docs/more/edit-formats.html"
|
|
16
|
+
models_and_keys = "https://cecli.dev/docs/troubleshooting/models-and-keys.html"
|