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
superqode/pure_mode.py
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pure Mode - Minimal Harness for Fair Model Testing.
|
|
3
|
+
|
|
4
|
+
Integrates with both TUI and CLI for testing model coding capabilities
|
|
5
|
+
without the bias of heavy harnesses.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
from rich.console import Console
|
|
14
|
+
from rich.panel import Panel
|
|
15
|
+
from rich.table import Table
|
|
16
|
+
from rich.text import Text
|
|
17
|
+
|
|
18
|
+
from .agent.loop import AgentLoop, AgentConfig, AgentResponse
|
|
19
|
+
from .agent.system_prompts import SystemPromptLevel
|
|
20
|
+
from .tools.base import ToolRegistry, ToolResult
|
|
21
|
+
from .providers.gateway.litellm_gateway import LiteLLMGateway
|
|
22
|
+
from .providers.registry import PROVIDERS, ProviderTier, ProviderCategory
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class PureSession:
|
|
27
|
+
"""Session state for Pure Mode."""
|
|
28
|
+
|
|
29
|
+
provider: str = ""
|
|
30
|
+
model: str = ""
|
|
31
|
+
system_level: SystemPromptLevel = SystemPromptLevel.MINIMAL
|
|
32
|
+
working_directory: Path = field(default_factory=Path.cwd)
|
|
33
|
+
connected: bool = False
|
|
34
|
+
|
|
35
|
+
# Stats
|
|
36
|
+
total_tool_calls: int = 0
|
|
37
|
+
total_iterations: int = 0
|
|
38
|
+
total_requests: int = 0
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class PureMode:
|
|
42
|
+
"""Pure Mode manager for TUI and CLI integration."""
|
|
43
|
+
|
|
44
|
+
def __init__(self):
|
|
45
|
+
self.session = PureSession()
|
|
46
|
+
self.gateway = LiteLLMGateway()
|
|
47
|
+
self.tools = ToolRegistry.default()
|
|
48
|
+
self._agent: Optional[AgentLoop] = None
|
|
49
|
+
|
|
50
|
+
# Callbacks for UI updates
|
|
51
|
+
self.on_tool_call: Optional[Callable[[str, Dict], None]] = None
|
|
52
|
+
self.on_tool_result: Optional[Callable[[str, ToolResult], None]] = None
|
|
53
|
+
self.on_thinking: Optional[Callable[[str], Awaitable[None]]] = None
|
|
54
|
+
self.on_stream_chunk: Optional[Callable[[str], None]] = None
|
|
55
|
+
|
|
56
|
+
def get_providers_for_picker(self) -> List[Dict[str, Any]]:
|
|
57
|
+
"""Get providers formatted for the TUI picker."""
|
|
58
|
+
providers = []
|
|
59
|
+
|
|
60
|
+
# Group by tier
|
|
61
|
+
tier_order = [ProviderTier.TIER1, ProviderTier.TIER2, ProviderTier.FREE, ProviderTier.LOCAL]
|
|
62
|
+
|
|
63
|
+
for tier in tier_order:
|
|
64
|
+
tier_providers = [p for p in PROVIDERS.values() if p.tier == tier]
|
|
65
|
+
for p in sorted(tier_providers, key=lambda x: x.name):
|
|
66
|
+
# Check if configured (has env var set)
|
|
67
|
+
import os
|
|
68
|
+
|
|
69
|
+
configured = any(os.environ.get(env) for env in p.env_vars) if p.env_vars else True
|
|
70
|
+
|
|
71
|
+
providers.append(
|
|
72
|
+
{
|
|
73
|
+
"id": p.id,
|
|
74
|
+
"name": p.name,
|
|
75
|
+
"tier": tier.name,
|
|
76
|
+
"category": p.category.value,
|
|
77
|
+
"configured": configured,
|
|
78
|
+
"example_models": p.example_models[:3],
|
|
79
|
+
"notes": p.notes,
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return providers
|
|
84
|
+
|
|
85
|
+
def get_models_for_provider(self, provider_id: str) -> List[str]:
|
|
86
|
+
"""Get example models for a provider."""
|
|
87
|
+
provider = PROVIDERS.get(provider_id)
|
|
88
|
+
if provider:
|
|
89
|
+
return provider.example_models
|
|
90
|
+
return []
|
|
91
|
+
|
|
92
|
+
def connect(
|
|
93
|
+
self,
|
|
94
|
+
provider: str,
|
|
95
|
+
model: str,
|
|
96
|
+
system_level: SystemPromptLevel = SystemPromptLevel.MINIMAL,
|
|
97
|
+
working_directory: Optional[Path] = None,
|
|
98
|
+
job_description: Optional[str] = None,
|
|
99
|
+
role_config: Optional[Any] = None,
|
|
100
|
+
) -> bool:
|
|
101
|
+
"""Connect to a provider in Pure Mode.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
provider: Provider ID (e.g., "ollama", "anthropic")
|
|
105
|
+
model: Model name (e.g., "llama3.2:3b")
|
|
106
|
+
system_level: System prompt verbosity level
|
|
107
|
+
working_directory: Optional working directory
|
|
108
|
+
job_description: Optional job description for role-based connections
|
|
109
|
+
role_config: Optional ResolvedRole config for role context
|
|
110
|
+
"""
|
|
111
|
+
self.session.provider = provider
|
|
112
|
+
self.session.model = model
|
|
113
|
+
self.session.system_level = system_level
|
|
114
|
+
self.session.working_directory = working_directory or Path.cwd()
|
|
115
|
+
self.session.connected = True
|
|
116
|
+
|
|
117
|
+
# Create agent loop with job description if provided
|
|
118
|
+
config = AgentConfig(
|
|
119
|
+
provider=provider,
|
|
120
|
+
model=model,
|
|
121
|
+
system_prompt_level=system_level,
|
|
122
|
+
working_directory=self.session.working_directory,
|
|
123
|
+
job_description=job_description,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
self._agent = AgentLoop(
|
|
127
|
+
gateway=self.gateway,
|
|
128
|
+
tools=self.tools,
|
|
129
|
+
config=config,
|
|
130
|
+
on_tool_call=self.on_tool_call,
|
|
131
|
+
on_tool_result=self.on_tool_result,
|
|
132
|
+
on_thinking=self.on_thinking,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Ensure callbacks are set on the agent (in case they were set after agent creation)
|
|
136
|
+
if self._agent:
|
|
137
|
+
self._agent.on_tool_call = self.on_tool_call
|
|
138
|
+
self._agent.on_tool_result = self.on_tool_result
|
|
139
|
+
self._agent.on_thinking = self.on_thinking
|
|
140
|
+
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
def disconnect(self):
|
|
144
|
+
"""Disconnect from Pure Mode."""
|
|
145
|
+
self.session = PureSession()
|
|
146
|
+
self._agent = None
|
|
147
|
+
|
|
148
|
+
def set_system_level(self, level: SystemPromptLevel):
|
|
149
|
+
"""Change the system prompt level."""
|
|
150
|
+
self.session.system_level = level
|
|
151
|
+
if self._agent:
|
|
152
|
+
self._agent.config.system_prompt_level = level
|
|
153
|
+
self._agent.system_prompt = self._agent._build_system_prompt()
|
|
154
|
+
|
|
155
|
+
async def run(self, prompt: str) -> AgentResponse:
|
|
156
|
+
"""Run a task in Pure Mode."""
|
|
157
|
+
if not self._agent:
|
|
158
|
+
raise RuntimeError("Not connected. Call connect() first.")
|
|
159
|
+
|
|
160
|
+
response = await self._agent.run(prompt)
|
|
161
|
+
|
|
162
|
+
# Update stats
|
|
163
|
+
self.session.total_tool_calls += response.tool_calls_made
|
|
164
|
+
self.session.total_iterations += response.iterations
|
|
165
|
+
self.session.total_requests += 1
|
|
166
|
+
|
|
167
|
+
return response
|
|
168
|
+
|
|
169
|
+
async def run_streaming(self, prompt: str):
|
|
170
|
+
"""Run a task with streaming output."""
|
|
171
|
+
if not self._agent:
|
|
172
|
+
raise RuntimeError("Not connected. Call connect() first.")
|
|
173
|
+
|
|
174
|
+
# Reset cancellation flag for new operation
|
|
175
|
+
self._agent.reset_cancellation()
|
|
176
|
+
|
|
177
|
+
async for chunk in self._agent.run_streaming(prompt):
|
|
178
|
+
if self.on_stream_chunk:
|
|
179
|
+
self.on_stream_chunk(chunk)
|
|
180
|
+
yield chunk
|
|
181
|
+
|
|
182
|
+
self.session.total_requests += 1
|
|
183
|
+
|
|
184
|
+
def cancel(self):
|
|
185
|
+
"""Cancel the current agent operation."""
|
|
186
|
+
if self._agent:
|
|
187
|
+
self._agent.cancel()
|
|
188
|
+
|
|
189
|
+
def get_status(self) -> Dict[str, Any]:
|
|
190
|
+
"""Get current Pure Mode status."""
|
|
191
|
+
return {
|
|
192
|
+
"connected": self.session.connected,
|
|
193
|
+
"provider": self.session.provider,
|
|
194
|
+
"model": self.session.model,
|
|
195
|
+
"system_level": self.session.system_level.value,
|
|
196
|
+
"working_directory": str(self.session.working_directory),
|
|
197
|
+
"stats": {
|
|
198
|
+
"total_requests": self.session.total_requests,
|
|
199
|
+
"total_tool_calls": self.session.total_tool_calls,
|
|
200
|
+
"total_iterations": self.session.total_iterations,
|
|
201
|
+
},
|
|
202
|
+
"tools": [t.name for t in self.tools.list()],
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def render_provider_picker(console: Console) -> tuple[str, str]:
|
|
207
|
+
"""Interactive provider picker for TUI.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Tuple of (provider_id, model)
|
|
211
|
+
"""
|
|
212
|
+
pure = PureMode()
|
|
213
|
+
providers = pure.get_providers_for_picker()
|
|
214
|
+
|
|
215
|
+
console.print()
|
|
216
|
+
console.print(
|
|
217
|
+
Panel.fit(
|
|
218
|
+
"[bold magenta]🧪 Pure Mode[/bold magenta]\n"
|
|
219
|
+
"Select a provider to test model coding capabilities",
|
|
220
|
+
border_style="magenta",
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
console.print()
|
|
224
|
+
|
|
225
|
+
# Group by tier
|
|
226
|
+
current_tier = None
|
|
227
|
+
tier_names = {
|
|
228
|
+
"TIER1": "⭐ Tier 1 (First-Class Support)",
|
|
229
|
+
"TIER2": "🔷 Tier 2 (Supported)",
|
|
230
|
+
"FREE": "🆓 Free Providers",
|
|
231
|
+
"LOCAL": "🏠 Local Providers",
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
provider_list = []
|
|
235
|
+
idx = 1
|
|
236
|
+
|
|
237
|
+
for p in providers:
|
|
238
|
+
if p["tier"] != current_tier:
|
|
239
|
+
current_tier = p["tier"]
|
|
240
|
+
console.print(f"\n[bold]{tier_names.get(current_tier, current_tier)}[/bold]")
|
|
241
|
+
|
|
242
|
+
status = "✅" if p["configured"] else "○"
|
|
243
|
+
models_hint = ", ".join(p["example_models"][:2]) if p["example_models"] else ""
|
|
244
|
+
|
|
245
|
+
console.print(f" [{idx}] {status} [bold]{p['name']:<15}[/bold] [dim]{models_hint}[/dim]")
|
|
246
|
+
provider_list.append(p)
|
|
247
|
+
idx += 1
|
|
248
|
+
|
|
249
|
+
console.print()
|
|
250
|
+
|
|
251
|
+
# Get provider selection
|
|
252
|
+
while True:
|
|
253
|
+
try:
|
|
254
|
+
choice = console.input("[bold cyan]Select provider (number): [/bold cyan]")
|
|
255
|
+
provider_idx = int(choice) - 1
|
|
256
|
+
if 0 <= provider_idx < len(provider_list):
|
|
257
|
+
selected_provider = provider_list[provider_idx]
|
|
258
|
+
break
|
|
259
|
+
console.print("[red]Invalid selection[/red]")
|
|
260
|
+
except ValueError:
|
|
261
|
+
console.print("[red]Please enter a number[/red]")
|
|
262
|
+
|
|
263
|
+
provider_id = selected_provider["id"]
|
|
264
|
+
|
|
265
|
+
# Get model selection
|
|
266
|
+
models = pure.get_models_for_provider(provider_id)
|
|
267
|
+
|
|
268
|
+
if models:
|
|
269
|
+
console.print(f"\n[bold]Available models for {selected_provider['name']}:[/bold]")
|
|
270
|
+
for i, model in enumerate(models, 1):
|
|
271
|
+
console.print(f" [{i}] {model}")
|
|
272
|
+
console.print(f" [0] Enter custom model")
|
|
273
|
+
console.print()
|
|
274
|
+
|
|
275
|
+
while True:
|
|
276
|
+
try:
|
|
277
|
+
choice = console.input("[bold cyan]Select model (number or name): [/bold cyan]")
|
|
278
|
+
if choice == "0":
|
|
279
|
+
model = console.input("[bold cyan]Enter model name: [/bold cyan]")
|
|
280
|
+
break
|
|
281
|
+
elif choice.isdigit():
|
|
282
|
+
model_idx = int(choice) - 1
|
|
283
|
+
if 0 <= model_idx < len(models):
|
|
284
|
+
model = models[model_idx]
|
|
285
|
+
break
|
|
286
|
+
else:
|
|
287
|
+
# Assume it's a model name
|
|
288
|
+
model = choice
|
|
289
|
+
break
|
|
290
|
+
console.print("[red]Invalid selection[/red]")
|
|
291
|
+
except ValueError:
|
|
292
|
+
console.print("[red]Please enter a number or model name[/red]")
|
|
293
|
+
else:
|
|
294
|
+
model = console.input("[bold cyan]Enter model name: [/bold cyan]")
|
|
295
|
+
|
|
296
|
+
return provider_id, model
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def render_system_level_picker(console: Console) -> SystemPromptLevel:
|
|
300
|
+
"""Interactive system prompt level picker."""
|
|
301
|
+
console.print()
|
|
302
|
+
console.print("[bold]System Prompt Level:[/bold]")
|
|
303
|
+
console.print(" [1] [yellow]none[/yellow] - No system prompt (pure model behavior)")
|
|
304
|
+
console.print(" [2] [green]minimal[/green] - Just 'You are a coding assistant' [default]")
|
|
305
|
+
console.print(" [3] [cyan]standard[/cyan] - Basic tool usage guidance")
|
|
306
|
+
console.print(" [4] [magenta]full[/magenta] - Detailed instructions (like other agents)")
|
|
307
|
+
console.print()
|
|
308
|
+
|
|
309
|
+
choice = console.input("[bold cyan]Select level (1-4, default=2): [/bold cyan]").strip()
|
|
310
|
+
|
|
311
|
+
level_map = {
|
|
312
|
+
"1": SystemPromptLevel.NONE,
|
|
313
|
+
"2": SystemPromptLevel.MINIMAL,
|
|
314
|
+
"3": SystemPromptLevel.STANDARD,
|
|
315
|
+
"4": SystemPromptLevel.FULL,
|
|
316
|
+
"": SystemPromptLevel.MINIMAL, # Default
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return level_map.get(choice, SystemPromptLevel.MINIMAL)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def render_pure_status(pure: PureMode, console: Console):
|
|
323
|
+
"""Render Pure Mode status panel."""
|
|
324
|
+
status = pure.get_status()
|
|
325
|
+
|
|
326
|
+
if not status["connected"]:
|
|
327
|
+
console.print("[dim]Pure Mode not connected[/dim]")
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
t = Text()
|
|
331
|
+
t.append("🧪 ", style="bold magenta")
|
|
332
|
+
t.append("PURE MODE", style="bold magenta reverse")
|
|
333
|
+
t.append("\n\n")
|
|
334
|
+
|
|
335
|
+
t.append("Provider: ", style="bold")
|
|
336
|
+
t.append(f"{status['provider']}\n", style="cyan")
|
|
337
|
+
|
|
338
|
+
t.append("Model: ", style="bold")
|
|
339
|
+
t.append(f"{status['model']}\n", style="cyan")
|
|
340
|
+
|
|
341
|
+
t.append("System Prompt: ", style="bold")
|
|
342
|
+
t.append(f"{status['system_level']}\n", style="yellow")
|
|
343
|
+
|
|
344
|
+
t.append("\nStats:\n", style="bold")
|
|
345
|
+
t.append(f" Requests: {status['stats']['total_requests']}\n", style="dim")
|
|
346
|
+
t.append(f" Tool Calls: {status['stats']['total_tool_calls']}\n", style="dim")
|
|
347
|
+
t.append(f" Iterations: {status['stats']['total_iterations']}\n", style="dim")
|
|
348
|
+
|
|
349
|
+
t.append(f"\nTools: {len(status['tools'])}\n", style="dim")
|
|
350
|
+
|
|
351
|
+
console.print(Panel(t, border_style="magenta"))
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def render_tool_call_inline(name: str, args: Dict, console: Console):
|
|
355
|
+
"""Render a tool call inline."""
|
|
356
|
+
console.print(f" [dim]→[/dim] [yellow]{name}[/yellow]", end="")
|
|
357
|
+
if args:
|
|
358
|
+
# Show key args
|
|
359
|
+
key_args = []
|
|
360
|
+
if "path" in args:
|
|
361
|
+
key_args.append(f"path={args['path']}")
|
|
362
|
+
if "command" in args:
|
|
363
|
+
cmd = (
|
|
364
|
+
args["command"][:30] + "..."
|
|
365
|
+
if len(args.get("command", "")) > 30
|
|
366
|
+
else args.get("command", "")
|
|
367
|
+
)
|
|
368
|
+
key_args.append(f"cmd={cmd}")
|
|
369
|
+
if "pattern" in args:
|
|
370
|
+
key_args.append(f"pattern={args['pattern']}")
|
|
371
|
+
if key_args:
|
|
372
|
+
console.print(f" [dim]({', '.join(key_args)})[/dim]")
|
|
373
|
+
else:
|
|
374
|
+
console.print()
|
|
375
|
+
else:
|
|
376
|
+
console.print()
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def render_tool_result_inline(name: str, result: ToolResult, console: Console):
|
|
380
|
+
"""Render a tool result inline."""
|
|
381
|
+
if result.success:
|
|
382
|
+
console.print(f" [green]✓[/green] [dim]{name}[/dim]")
|
|
383
|
+
else:
|
|
384
|
+
console.print(f" [red]✗[/red] [dim]{name}: {result.error}[/dim]")
|
superqode/qr/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Quality Report (QR) Module.
|
|
3
|
+
|
|
4
|
+
Generates research-grade QA reports that document:
|
|
5
|
+
- Investigation objective and scope
|
|
6
|
+
- Attack and exploration methodology
|
|
7
|
+
- Reproduction steps and evidence
|
|
8
|
+
- Root cause and failure analysis
|
|
9
|
+
- Suggested fixes and alternatives
|
|
10
|
+
- Benchmark and validation results
|
|
11
|
+
- Production-readiness assessment
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .generator import QRGenerator, QRSection, QRVerdict
|
|
15
|
+
from .templates import QRTemplate, get_template
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"QRGenerator",
|
|
19
|
+
"QRSection",
|
|
20
|
+
"QRVerdict",
|
|
21
|
+
"QRTemplate",
|
|
22
|
+
"get_template",
|
|
23
|
+
]
|