superqode 0.1.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.
- superqode/__init__.py +33 -0
- superqode/acp/__init__.py +23 -0
- superqode/acp/client.py +913 -0
- superqode/acp/permission_screen.py +457 -0
- superqode/acp/types.py +480 -0
- superqode/acp_discovery.py +856 -0
- superqode/agent/__init__.py +22 -0
- superqode/agent/edit_strategies.py +334 -0
- superqode/agent/loop.py +892 -0
- superqode/agent/qe_report_templates.py +39 -0
- superqode/agent/system_prompts.py +353 -0
- superqode/agent_output.py +721 -0
- superqode/agent_stream.py +953 -0
- superqode/agents/__init__.py +59 -0
- superqode/agents/acp_registry.py +305 -0
- superqode/agents/client.py +249 -0
- superqode/agents/data/augmentcode.com.toml +51 -0
- superqode/agents/data/cagent.dev.toml +51 -0
- superqode/agents/data/claude.com.toml +60 -0
- superqode/agents/data/codeassistant.dev.toml +51 -0
- superqode/agents/data/codex.openai.com.toml +57 -0
- superqode/agents/data/fastagent.ai.toml +66 -0
- superqode/agents/data/geminicli.com.toml +77 -0
- superqode/agents/data/goose.block.xyz.toml +54 -0
- superqode/agents/data/junie.jetbrains.com.toml +56 -0
- superqode/agents/data/kimi.moonshot.cn.toml +57 -0
- superqode/agents/data/llmlingagent.dev.toml +51 -0
- superqode/agents/data/molt.bot.toml +49 -0
- superqode/agents/data/opencode.ai.toml +60 -0
- superqode/agents/data/stakpak.dev.toml +51 -0
- superqode/agents/data/vtcode.dev.toml +51 -0
- superqode/agents/discovery.py +266 -0
- superqode/agents/messaging.py +160 -0
- superqode/agents/persona.py +166 -0
- superqode/agents/registry.py +421 -0
- superqode/agents/schema.py +72 -0
- superqode/agents/unified.py +367 -0
- superqode/app/__init__.py +111 -0
- superqode/app/constants.py +314 -0
- superqode/app/css.py +366 -0
- superqode/app/models.py +118 -0
- superqode/app/suggester.py +125 -0
- superqode/app/widgets.py +1591 -0
- superqode/app_enhanced.py +399 -0
- superqode/app_main.py +17187 -0
- superqode/approval.py +312 -0
- superqode/atomic.py +296 -0
- superqode/commands/__init__.py +1 -0
- superqode/commands/acp.py +965 -0
- superqode/commands/agents.py +180 -0
- superqode/commands/auth.py +278 -0
- superqode/commands/config.py +374 -0
- superqode/commands/init.py +826 -0
- superqode/commands/providers.py +819 -0
- superqode/commands/qe.py +1145 -0
- superqode/commands/roles.py +380 -0
- superqode/commands/serve.py +172 -0
- superqode/commands/suggestions.py +127 -0
- superqode/commands/superqe.py +460 -0
- superqode/config/__init__.py +51 -0
- superqode/config/loader.py +812 -0
- superqode/config/schema.py +498 -0
- superqode/core/__init__.py +111 -0
- superqode/core/roles.py +281 -0
- superqode/danger.py +386 -0
- superqode/data/superqode-template.yaml +1522 -0
- superqode/design_system.py +1080 -0
- superqode/dialogs/__init__.py +6 -0
- superqode/dialogs/base.py +39 -0
- superqode/dialogs/model.py +130 -0
- superqode/dialogs/provider.py +870 -0
- superqode/diff_view.py +919 -0
- superqode/enterprise.py +21 -0
- superqode/evaluation/__init__.py +25 -0
- superqode/evaluation/adapters.py +93 -0
- superqode/evaluation/behaviors.py +89 -0
- superqode/evaluation/engine.py +209 -0
- superqode/evaluation/scenarios.py +96 -0
- superqode/execution/__init__.py +36 -0
- superqode/execution/linter.py +538 -0
- superqode/execution/modes.py +347 -0
- superqode/execution/resolver.py +283 -0
- superqode/execution/runner.py +642 -0
- superqode/file_explorer.py +811 -0
- superqode/file_viewer.py +471 -0
- superqode/flash.py +183 -0
- superqode/guidance/__init__.py +58 -0
- superqode/guidance/config.py +203 -0
- superqode/guidance/prompts.py +71 -0
- superqode/harness/__init__.py +54 -0
- superqode/harness/accelerator.py +291 -0
- superqode/harness/config.py +319 -0
- superqode/harness/validator.py +147 -0
- superqode/history.py +279 -0
- superqode/integrations/superopt_runner.py +124 -0
- superqode/logging/__init__.py +49 -0
- superqode/logging/adapters.py +219 -0
- superqode/logging/formatter.py +923 -0
- superqode/logging/integration.py +341 -0
- superqode/logging/sinks.py +170 -0
- superqode/logging/unified_log.py +417 -0
- superqode/lsp/__init__.py +26 -0
- superqode/lsp/client.py +544 -0
- superqode/main.py +1069 -0
- superqode/mcp/__init__.py +89 -0
- superqode/mcp/auth_storage.py +380 -0
- superqode/mcp/client.py +1236 -0
- superqode/mcp/config.py +319 -0
- superqode/mcp/integration.py +337 -0
- superqode/mcp/oauth.py +436 -0
- superqode/mcp/oauth_callback.py +385 -0
- superqode/mcp/types.py +290 -0
- superqode/memory/__init__.py +31 -0
- superqode/memory/feedback.py +342 -0
- superqode/memory/store.py +522 -0
- superqode/notifications.py +369 -0
- superqode/optimization/__init__.py +5 -0
- superqode/optimization/config.py +33 -0
- superqode/permissions/__init__.py +25 -0
- superqode/permissions/rules.py +488 -0
- superqode/plan.py +323 -0
- superqode/providers/__init__.py +33 -0
- superqode/providers/gateway/__init__.py +165 -0
- superqode/providers/gateway/base.py +228 -0
- superqode/providers/gateway/litellm_gateway.py +1170 -0
- superqode/providers/gateway/openresponses_gateway.py +436 -0
- superqode/providers/health.py +297 -0
- superqode/providers/huggingface/__init__.py +74 -0
- superqode/providers/huggingface/downloader.py +472 -0
- superqode/providers/huggingface/endpoints.py +442 -0
- superqode/providers/huggingface/hub.py +531 -0
- superqode/providers/huggingface/inference.py +394 -0
- superqode/providers/huggingface/transformers_runner.py +516 -0
- superqode/providers/local/__init__.py +100 -0
- superqode/providers/local/base.py +438 -0
- superqode/providers/local/discovery.py +418 -0
- superqode/providers/local/lmstudio.py +256 -0
- superqode/providers/local/mlx.py +457 -0
- superqode/providers/local/ollama.py +486 -0
- superqode/providers/local/sglang.py +268 -0
- superqode/providers/local/tgi.py +260 -0
- superqode/providers/local/tool_support.py +477 -0
- superqode/providers/local/vllm.py +258 -0
- superqode/providers/manager.py +1338 -0
- superqode/providers/models.py +1016 -0
- superqode/providers/models_dev.py +578 -0
- superqode/providers/openresponses/__init__.py +87 -0
- superqode/providers/openresponses/converters/__init__.py +17 -0
- superqode/providers/openresponses/converters/messages.py +343 -0
- superqode/providers/openresponses/converters/tools.py +268 -0
- superqode/providers/openresponses/schema/__init__.py +56 -0
- superqode/providers/openresponses/schema/models.py +585 -0
- superqode/providers/openresponses/streaming/__init__.py +5 -0
- superqode/providers/openresponses/streaming/parser.py +338 -0
- superqode/providers/openresponses/tools/__init__.py +21 -0
- superqode/providers/openresponses/tools/apply_patch.py +352 -0
- superqode/providers/openresponses/tools/code_interpreter.py +290 -0
- superqode/providers/openresponses/tools/file_search.py +333 -0
- superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
- superqode/providers/registry.py +716 -0
- superqode/providers/usage.py +332 -0
- superqode/pure_mode.py +384 -0
- superqode/qr/__init__.py +23 -0
- superqode/qr/dashboard.py +781 -0
- superqode/qr/generator.py +1018 -0
- superqode/qr/templates.py +135 -0
- superqode/safety/__init__.py +41 -0
- superqode/safety/sandbox.py +413 -0
- superqode/safety/warnings.py +256 -0
- superqode/server/__init__.py +33 -0
- superqode/server/lsp_server.py +775 -0
- superqode/server/web.py +250 -0
- superqode/session/__init__.py +25 -0
- superqode/session/persistence.py +580 -0
- superqode/session/sharing.py +477 -0
- superqode/session.py +475 -0
- superqode/sidebar.py +2991 -0
- superqode/stream_view.py +648 -0
- superqode/styles/__init__.py +3 -0
- superqode/superqe/__init__.py +184 -0
- superqode/superqe/acp_runner.py +1064 -0
- superqode/superqe/constitution/__init__.py +62 -0
- superqode/superqe/constitution/evaluator.py +308 -0
- superqode/superqe/constitution/loader.py +432 -0
- superqode/superqe/constitution/schema.py +250 -0
- superqode/superqe/events.py +591 -0
- superqode/superqe/frameworks/__init__.py +65 -0
- superqode/superqe/frameworks/base.py +234 -0
- superqode/superqe/frameworks/e2e.py +263 -0
- superqode/superqe/frameworks/executor.py +237 -0
- superqode/superqe/frameworks/javascript.py +409 -0
- superqode/superqe/frameworks/python.py +373 -0
- superqode/superqe/frameworks/registry.py +92 -0
- superqode/superqe/mcp_tools/__init__.py +47 -0
- superqode/superqe/mcp_tools/core_tools.py +418 -0
- superqode/superqe/mcp_tools/registry.py +230 -0
- superqode/superqe/mcp_tools/testing_tools.py +167 -0
- superqode/superqe/noise.py +89 -0
- superqode/superqe/orchestrator.py +778 -0
- superqode/superqe/roles.py +609 -0
- superqode/superqe/session.py +713 -0
- superqode/superqe/skills/__init__.py +57 -0
- superqode/superqe/skills/base.py +106 -0
- superqode/superqe/skills/core_skills.py +899 -0
- superqode/superqe/skills/registry.py +90 -0
- superqode/superqe/verifier.py +101 -0
- superqode/superqe_cli.py +76 -0
- superqode/tool_call.py +358 -0
- superqode/tools/__init__.py +93 -0
- superqode/tools/agent_tools.py +496 -0
- superqode/tools/base.py +324 -0
- superqode/tools/batch_tool.py +133 -0
- superqode/tools/diagnostics.py +311 -0
- superqode/tools/edit_tools.py +653 -0
- superqode/tools/enhanced_base.py +515 -0
- superqode/tools/file_tools.py +269 -0
- superqode/tools/file_tracking.py +45 -0
- superqode/tools/lsp_tools.py +610 -0
- superqode/tools/network_tools.py +350 -0
- superqode/tools/permissions.py +400 -0
- superqode/tools/question_tool.py +324 -0
- superqode/tools/search_tools.py +598 -0
- superqode/tools/shell_tools.py +259 -0
- superqode/tools/todo_tools.py +121 -0
- superqode/tools/validation.py +80 -0
- superqode/tools/web_tools.py +639 -0
- superqode/tui.py +1152 -0
- superqode/tui_integration.py +875 -0
- superqode/tui_widgets/__init__.py +27 -0
- superqode/tui_widgets/widgets/__init__.py +18 -0
- superqode/tui_widgets/widgets/progress.py +185 -0
- superqode/tui_widgets/widgets/tool_display.py +188 -0
- superqode/undo_manager.py +574 -0
- superqode/utils/__init__.py +5 -0
- superqode/utils/error_handling.py +323 -0
- superqode/utils/fuzzy.py +257 -0
- superqode/widgets/__init__.py +477 -0
- superqode/widgets/agent_collab.py +390 -0
- superqode/widgets/agent_store.py +936 -0
- superqode/widgets/agent_switcher.py +395 -0
- superqode/widgets/animation_manager.py +284 -0
- superqode/widgets/code_context.py +356 -0
- superqode/widgets/command_palette.py +412 -0
- superqode/widgets/connection_status.py +537 -0
- superqode/widgets/conversation_history.py +470 -0
- superqode/widgets/diff_indicator.py +155 -0
- superqode/widgets/enhanced_status_bar.py +385 -0
- superqode/widgets/enhanced_toast.py +476 -0
- superqode/widgets/file_browser.py +809 -0
- superqode/widgets/file_reference.py +585 -0
- superqode/widgets/issue_timeline.py +340 -0
- superqode/widgets/leader_key.py +264 -0
- superqode/widgets/mode_switcher.py +445 -0
- superqode/widgets/model_picker.py +234 -0
- superqode/widgets/permission_preview.py +1205 -0
- superqode/widgets/prompt.py +358 -0
- superqode/widgets/provider_connect.py +725 -0
- superqode/widgets/pty_shell.py +587 -0
- superqode/widgets/qe_dashboard.py +321 -0
- superqode/widgets/resizable_sidebar.py +377 -0
- superqode/widgets/response_changes.py +218 -0
- superqode/widgets/response_display.py +528 -0
- superqode/widgets/rich_tool_display.py +613 -0
- superqode/widgets/sidebar_panels.py +1180 -0
- superqode/widgets/slash_complete.py +356 -0
- superqode/widgets/split_view.py +612 -0
- superqode/widgets/status_bar.py +273 -0
- superqode/widgets/superqode_display.py +786 -0
- superqode/widgets/thinking_display.py +815 -0
- superqode/widgets/throbber.py +87 -0
- superqode/widgets/toast.py +206 -0
- superqode/widgets/unified_output.py +1073 -0
- superqode/workspace/__init__.py +75 -0
- superqode/workspace/artifacts.py +472 -0
- superqode/workspace/coordinator.py +353 -0
- superqode/workspace/diff_tracker.py +429 -0
- superqode/workspace/git_guard.py +373 -0
- superqode/workspace/git_snapshot.py +526 -0
- superqode/workspace/manager.py +750 -0
- superqode/workspace/snapshot.py +357 -0
- superqode/workspace/watcher.py +535 -0
- superqode/workspace/worktree.py +440 -0
- superqode-0.1.5.dist-info/METADATA +204 -0
- superqode-0.1.5.dist-info/RECORD +288 -0
- superqode-0.1.5.dist-info/WHEEL +5 -0
- superqode-0.1.5.dist-info/entry_points.txt +3 -0
- superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
- superqode-0.1.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Enhanced App Layout - OpenCode-Style TUI.
|
|
3
|
+
|
|
4
|
+
This module provides an enhanced app layout that integrates all the new
|
|
5
|
+
TUI widgets for a competitive coding agent experience.
|
|
6
|
+
|
|
7
|
+
To use: Import EnhancedAppMixin and mix it into SuperQodeApp, or use
|
|
8
|
+
the compose_enhanced() method in your existing compose().
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from textual.app import ComposeResult
|
|
17
|
+
from textual.containers import Container, Horizontal, Vertical, ScrollableContainer
|
|
18
|
+
from textual.widgets import Static, Input, Footer
|
|
19
|
+
from textual.reactive import reactive
|
|
20
|
+
|
|
21
|
+
from rich.text import Text
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class EnhancedLayout(Container):
|
|
25
|
+
"""
|
|
26
|
+
Enhanced layout container with OpenCode-style UX.
|
|
27
|
+
|
|
28
|
+
Layout:
|
|
29
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
30
|
+
│ [Enhanced Status Bar - connection, model, tokens, cost] │
|
|
31
|
+
├──────────────────────┬──────────────────────────────────────────┤
|
|
32
|
+
│ │ [Tool Call Panel - collapsible] │
|
|
33
|
+
│ ├──────────────────────────────────────────┤
|
|
34
|
+
│ [Sidebar] │ [Thinking Panel - collapsible] │
|
|
35
|
+
│ - Files ├──────────────────────────────────────────┤
|
|
36
|
+
│ - Git Status │ │
|
|
37
|
+
│ - Context │ [Conversation / Response Area] │
|
|
38
|
+
│ │ │
|
|
39
|
+
│ │ │
|
|
40
|
+
│ ├──────────────────────────────────────────┤
|
|
41
|
+
│ │ [Prompt Input] │
|
|
42
|
+
└──────────────────────┴──────────────────────────────────────────┘
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
DEFAULT_CSS = """
|
|
46
|
+
EnhancedLayout {
|
|
47
|
+
height: 100%;
|
|
48
|
+
width: 100%;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
EnhancedLayout #enhanced-main {
|
|
52
|
+
height: 100%;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
EnhancedLayout #enhanced-sidebar {
|
|
56
|
+
width: 30;
|
|
57
|
+
border-right: solid #27272a;
|
|
58
|
+
background: #0a0a0a;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
EnhancedLayout #enhanced-sidebar.collapsed {
|
|
62
|
+
width: 0;
|
|
63
|
+
display: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
EnhancedLayout #enhanced-content {
|
|
67
|
+
width: 1fr;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
EnhancedLayout #enhanced-status {
|
|
71
|
+
height: 1;
|
|
72
|
+
dock: top;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
EnhancedLayout #enhanced-tools {
|
|
76
|
+
height: auto;
|
|
77
|
+
max-height: 30%;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
EnhancedLayout #enhanced-tools.collapsed {
|
|
81
|
+
max-height: 3;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
EnhancedLayout #enhanced-thinking {
|
|
85
|
+
height: auto;
|
|
86
|
+
max-height: 20%;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
EnhancedLayout #enhanced-thinking.collapsed {
|
|
90
|
+
max-height: 2;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
EnhancedLayout #enhanced-conversation {
|
|
94
|
+
height: 1fr;
|
|
95
|
+
overflow-y: auto;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
EnhancedLayout #enhanced-prompt-area {
|
|
99
|
+
height: auto;
|
|
100
|
+
min-height: 3;
|
|
101
|
+
max-height: 10;
|
|
102
|
+
dock: bottom;
|
|
103
|
+
border-top: solid #27272a;
|
|
104
|
+
padding: 1;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
EnhancedLayout #enhanced-prompt-input {
|
|
108
|
+
width: 100%;
|
|
109
|
+
}
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
# State
|
|
113
|
+
sidebar_visible: reactive[bool] = reactive(True)
|
|
114
|
+
tools_collapsed: reactive[bool] = reactive(True)
|
|
115
|
+
thinking_collapsed: reactive[bool] = reactive(True)
|
|
116
|
+
|
|
117
|
+
def __init__(self, **kwargs):
|
|
118
|
+
super().__init__(**kwargs)
|
|
119
|
+
self._tui_enhancer = None
|
|
120
|
+
|
|
121
|
+
def compose(self) -> ComposeResult:
|
|
122
|
+
"""Compose the enhanced layout."""
|
|
123
|
+
# Import widgets
|
|
124
|
+
from superqode.widgets import (
|
|
125
|
+
get_rich_tool_display,
|
|
126
|
+
get_thinking_display,
|
|
127
|
+
get_connection_status,
|
|
128
|
+
get_enhanced_status_bar,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Get classes
|
|
132
|
+
ToolCallPanel, *_ = get_rich_tool_display()
|
|
133
|
+
ThinkingPanel, *_ = get_thinking_display()
|
|
134
|
+
ConnectionIndicator, *_ = get_connection_status()
|
|
135
|
+
EnhancedStatusBar, *_ = get_enhanced_status_bar()
|
|
136
|
+
|
|
137
|
+
# Status bar at top
|
|
138
|
+
yield EnhancedStatusBar(id="enhanced-status")
|
|
139
|
+
|
|
140
|
+
# Main horizontal split
|
|
141
|
+
with Horizontal(id="enhanced-main"):
|
|
142
|
+
# Sidebar
|
|
143
|
+
with Container(id="enhanced-sidebar"):
|
|
144
|
+
yield Static(self._render_sidebar_header(), id="sidebar-header")
|
|
145
|
+
yield Static("", id="sidebar-content")
|
|
146
|
+
|
|
147
|
+
# Main content area
|
|
148
|
+
with Vertical(id="enhanced-content"):
|
|
149
|
+
# Tool calls panel (collapsible)
|
|
150
|
+
yield ToolCallPanel(id="enhanced-tools", classes="collapsed")
|
|
151
|
+
|
|
152
|
+
# Thinking panel (collapsible)
|
|
153
|
+
yield ThinkingPanel(id="enhanced-thinking", classes="collapsed")
|
|
154
|
+
|
|
155
|
+
# Conversation area
|
|
156
|
+
with ScrollableContainer(id="enhanced-conversation"):
|
|
157
|
+
yield Static("", id="conversation-content")
|
|
158
|
+
|
|
159
|
+
# Prompt area
|
|
160
|
+
with Container(id="enhanced-prompt-area"):
|
|
161
|
+
yield Static(self._render_prompt_prefix(), id="prompt-prefix")
|
|
162
|
+
yield Input(
|
|
163
|
+
placeholder="Ask anything... (type :help for commands)",
|
|
164
|
+
id="enhanced-prompt-input",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
def _render_sidebar_header(self) -> Text:
|
|
168
|
+
"""Render sidebar header."""
|
|
169
|
+
text = Text()
|
|
170
|
+
text.append("📁 ", style="#3b82f6")
|
|
171
|
+
text.append("Files", style="bold #e4e4e7")
|
|
172
|
+
return text
|
|
173
|
+
|
|
174
|
+
def _render_prompt_prefix(self) -> Text:
|
|
175
|
+
"""Render prompt prefix."""
|
|
176
|
+
text = Text()
|
|
177
|
+
text.append("🖋️ ", style="#a855f7")
|
|
178
|
+
return text
|
|
179
|
+
|
|
180
|
+
def toggle_sidebar(self) -> None:
|
|
181
|
+
"""Toggle sidebar visibility."""
|
|
182
|
+
self.sidebar_visible = not self.sidebar_visible
|
|
183
|
+
sidebar = self.query_one("#enhanced-sidebar")
|
|
184
|
+
if self.sidebar_visible:
|
|
185
|
+
sidebar.remove_class("collapsed")
|
|
186
|
+
else:
|
|
187
|
+
sidebar.add_class("collapsed")
|
|
188
|
+
|
|
189
|
+
def toggle_tools(self) -> None:
|
|
190
|
+
"""Toggle tools panel."""
|
|
191
|
+
self.tools_collapsed = not self.tools_collapsed
|
|
192
|
+
tools = self.query_one("#enhanced-tools")
|
|
193
|
+
if self.tools_collapsed:
|
|
194
|
+
tools.add_class("collapsed")
|
|
195
|
+
else:
|
|
196
|
+
tools.remove_class("collapsed")
|
|
197
|
+
|
|
198
|
+
def toggle_thinking(self) -> None:
|
|
199
|
+
"""Toggle thinking panel."""
|
|
200
|
+
self.thinking_collapsed = not self.thinking_collapsed
|
|
201
|
+
thinking = self.query_one("#enhanced-thinking")
|
|
202
|
+
if self.thinking_collapsed:
|
|
203
|
+
thinking.add_class("collapsed")
|
|
204
|
+
else:
|
|
205
|
+
thinking.remove_class("collapsed")
|
|
206
|
+
|
|
207
|
+
def get_status_bar(self):
|
|
208
|
+
"""Get the status bar widget."""
|
|
209
|
+
try:
|
|
210
|
+
return self.query_one("#enhanced-status")
|
|
211
|
+
except Exception:
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
def get_tool_panel(self):
|
|
215
|
+
"""Get the tool panel widget."""
|
|
216
|
+
try:
|
|
217
|
+
return self.query_one("#enhanced-tools")
|
|
218
|
+
except Exception:
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
def get_thinking_panel(self):
|
|
222
|
+
"""Get the thinking panel widget."""
|
|
223
|
+
try:
|
|
224
|
+
return self.query_one("#enhanced-thinking")
|
|
225
|
+
except Exception:
|
|
226
|
+
return None
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def create_enhanced_app_mixin():
|
|
230
|
+
"""
|
|
231
|
+
Create a mixin class that adds enhanced TUI features to SuperQodeApp.
|
|
232
|
+
|
|
233
|
+
Usage:
|
|
234
|
+
from superqode.app_enhanced import create_enhanced_app_mixin
|
|
235
|
+
|
|
236
|
+
EnhancedMixin = create_enhanced_app_mixin()
|
|
237
|
+
|
|
238
|
+
class MyApp(EnhancedMixin, SuperQodeApp):
|
|
239
|
+
pass
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
class EnhancedAppMixin:
|
|
243
|
+
"""Mixin that adds enhanced TUI features."""
|
|
244
|
+
|
|
245
|
+
def setup_enhanced_tui(self):
|
|
246
|
+
"""Set up enhanced TUI components."""
|
|
247
|
+
from superqode.tui_integration import TUIEnhancer
|
|
248
|
+
|
|
249
|
+
self._tui_enhancer = TUIEnhancer(self)
|
|
250
|
+
self._tui_enhancer.setup()
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def tui(self):
|
|
254
|
+
"""Get the TUI enhancer."""
|
|
255
|
+
if not hasattr(self, "_tui_enhancer"):
|
|
256
|
+
self.setup_enhanced_tui()
|
|
257
|
+
return self._tui_enhancer
|
|
258
|
+
|
|
259
|
+
# Tool call helpers
|
|
260
|
+
def _show_tool_start(self, tool_id, tool_name, tool_kind, arguments=None, file_path=None):
|
|
261
|
+
"""Show tool start with enhanced display."""
|
|
262
|
+
self.tui.start_tool(tool_id, tool_name, tool_kind, arguments, file_path)
|
|
263
|
+
|
|
264
|
+
def _show_tool_complete(self, tool_id, result="", error=""):
|
|
265
|
+
"""Show tool completion."""
|
|
266
|
+
self.tui.complete_tool(tool_id, result=result, error=error)
|
|
267
|
+
|
|
268
|
+
# Thinking helpers
|
|
269
|
+
def _show_thinking_start(self):
|
|
270
|
+
"""Start thinking display."""
|
|
271
|
+
self.tui.start_thinking()
|
|
272
|
+
|
|
273
|
+
def _show_thinking_chunk(self, text):
|
|
274
|
+
"""Add thinking chunk."""
|
|
275
|
+
self.tui.add_thought(text)
|
|
276
|
+
|
|
277
|
+
def _show_thinking_complete(self):
|
|
278
|
+
"""Complete thinking."""
|
|
279
|
+
self.tui.complete_thinking()
|
|
280
|
+
|
|
281
|
+
# Response helpers
|
|
282
|
+
def _show_response_start(self, agent_name="", model_name=""):
|
|
283
|
+
"""Start response streaming."""
|
|
284
|
+
self.tui.start_response(agent_name, model_name)
|
|
285
|
+
|
|
286
|
+
def _show_response_chunk(self, text):
|
|
287
|
+
"""Add response chunk."""
|
|
288
|
+
self.tui.append_response(text)
|
|
289
|
+
|
|
290
|
+
def _show_response_complete(self, token_count=0):
|
|
291
|
+
"""Complete response."""
|
|
292
|
+
self.tui.complete_response(token_count)
|
|
293
|
+
|
|
294
|
+
# Connection helpers
|
|
295
|
+
def _connect_agent_enhanced(
|
|
296
|
+
self, agent_name, model_name="", provider="", connection_type="byok"
|
|
297
|
+
):
|
|
298
|
+
"""Connect to agent with enhanced status."""
|
|
299
|
+
self.tui.connect_agent(agent_name, model_name, provider, connection_type)
|
|
300
|
+
|
|
301
|
+
def _disconnect_agent_enhanced(self):
|
|
302
|
+
"""Disconnect agent."""
|
|
303
|
+
self.tui.disconnect_agent()
|
|
304
|
+
|
|
305
|
+
return EnhancedAppMixin
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
# ============================================================================
|
|
309
|
+
# EXAMPLE: How to integrate into app_main.py
|
|
310
|
+
# ============================================================================
|
|
311
|
+
|
|
312
|
+
INTEGRATION_EXAMPLE = '''
|
|
313
|
+
# In app_main.py, modify the SuperQodeApp class:
|
|
314
|
+
|
|
315
|
+
from superqode.app_enhanced import create_enhanced_app_mixin
|
|
316
|
+
from superqode.tui_integration import TUIEnhancer
|
|
317
|
+
|
|
318
|
+
EnhancedMixin = create_enhanced_app_mixin()
|
|
319
|
+
|
|
320
|
+
class SuperQodeApp(EnhancedMixin, App):
|
|
321
|
+
# ... existing code ...
|
|
322
|
+
|
|
323
|
+
def on_mount(self):
|
|
324
|
+
# Existing mount code...
|
|
325
|
+
self.query_one("#prompt-input", Input).focus()
|
|
326
|
+
self._load_welcome()
|
|
327
|
+
|
|
328
|
+
# NEW: Set up enhanced TUI
|
|
329
|
+
self.setup_enhanced_tui()
|
|
330
|
+
|
|
331
|
+
# In the ACP message handling, update to use enhanced widgets:
|
|
332
|
+
|
|
333
|
+
async def _handle_acp_tool_call(self, update):
|
|
334
|
+
"""Handle tool call from ACP agent."""
|
|
335
|
+
tool_id = update.get("toolCallId", "")
|
|
336
|
+
title = update.get("title", "")
|
|
337
|
+
kind = update.get("kind", "other")
|
|
338
|
+
raw_input = update.get("rawInput", {})
|
|
339
|
+
|
|
340
|
+
# NEW: Use enhanced tool display
|
|
341
|
+
self._show_tool_start(tool_id, title, kind, raw_input)
|
|
342
|
+
|
|
343
|
+
# Track files
|
|
344
|
+
file_path = raw_input.get("path", "")
|
|
345
|
+
if file_path:
|
|
346
|
+
if kind in ("edit", "write"):
|
|
347
|
+
self.tui.track_file_modified(file_path)
|
|
348
|
+
elif kind == "read":
|
|
349
|
+
self.tui.track_file_read(file_path)
|
|
350
|
+
|
|
351
|
+
async def _handle_acp_tool_update(self, update):
|
|
352
|
+
"""Handle tool update from ACP agent."""
|
|
353
|
+
tool_id = update.get("toolCallId", "")
|
|
354
|
+
status = update.get("status", "")
|
|
355
|
+
output = update.get("output", "")
|
|
356
|
+
|
|
357
|
+
if status == "completed":
|
|
358
|
+
# NEW: Use enhanced display
|
|
359
|
+
self._show_tool_complete(tool_id, result=output)
|
|
360
|
+
elif status == "failed":
|
|
361
|
+
self._show_tool_complete(tool_id, error=output)
|
|
362
|
+
|
|
363
|
+
async def _handle_acp_thought(self, update):
|
|
364
|
+
"""Handle thought/reasoning from ACP agent."""
|
|
365
|
+
content = update.get("content", {})
|
|
366
|
+
text = content.get("text", "")
|
|
367
|
+
|
|
368
|
+
if text:
|
|
369
|
+
# NEW: Use enhanced thinking display
|
|
370
|
+
self._show_thinking_chunk(text)
|
|
371
|
+
|
|
372
|
+
async def _handle_acp_message(self, update):
|
|
373
|
+
"""Handle message chunk from ACP agent."""
|
|
374
|
+
content = update.get("content", {})
|
|
375
|
+
text = content.get("text", "")
|
|
376
|
+
|
|
377
|
+
if text:
|
|
378
|
+
# NEW: Use enhanced response display
|
|
379
|
+
self._show_response_chunk(text)
|
|
380
|
+
|
|
381
|
+
# When connecting to an agent:
|
|
382
|
+
|
|
383
|
+
def _connect_to_opencode(self, model):
|
|
384
|
+
"""Connect to OpenCode."""
|
|
385
|
+
# Existing connection code...
|
|
386
|
+
|
|
387
|
+
# NEW: Update enhanced status
|
|
388
|
+
self._connect_agent_enhanced(
|
|
389
|
+
agent_name="OpenCode",
|
|
390
|
+
model_name=model,
|
|
391
|
+
provider="opencode",
|
|
392
|
+
connection_type="acp",
|
|
393
|
+
)
|
|
394
|
+
'''
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def get_integration_example() -> str:
|
|
398
|
+
"""Get the integration example code."""
|
|
399
|
+
return INTEGRATION_EXAMPLE
|