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.
Files changed (288) hide show
  1. superqode/__init__.py +33 -0
  2. superqode/acp/__init__.py +23 -0
  3. superqode/acp/client.py +913 -0
  4. superqode/acp/permission_screen.py +457 -0
  5. superqode/acp/types.py +480 -0
  6. superqode/acp_discovery.py +856 -0
  7. superqode/agent/__init__.py +22 -0
  8. superqode/agent/edit_strategies.py +334 -0
  9. superqode/agent/loop.py +892 -0
  10. superqode/agent/qe_report_templates.py +39 -0
  11. superqode/agent/system_prompts.py +353 -0
  12. superqode/agent_output.py +721 -0
  13. superqode/agent_stream.py +953 -0
  14. superqode/agents/__init__.py +59 -0
  15. superqode/agents/acp_registry.py +305 -0
  16. superqode/agents/client.py +249 -0
  17. superqode/agents/data/augmentcode.com.toml +51 -0
  18. superqode/agents/data/cagent.dev.toml +51 -0
  19. superqode/agents/data/claude.com.toml +60 -0
  20. superqode/agents/data/codeassistant.dev.toml +51 -0
  21. superqode/agents/data/codex.openai.com.toml +57 -0
  22. superqode/agents/data/fastagent.ai.toml +66 -0
  23. superqode/agents/data/geminicli.com.toml +77 -0
  24. superqode/agents/data/goose.block.xyz.toml +54 -0
  25. superqode/agents/data/junie.jetbrains.com.toml +56 -0
  26. superqode/agents/data/kimi.moonshot.cn.toml +57 -0
  27. superqode/agents/data/llmlingagent.dev.toml +51 -0
  28. superqode/agents/data/molt.bot.toml +49 -0
  29. superqode/agents/data/opencode.ai.toml +60 -0
  30. superqode/agents/data/stakpak.dev.toml +51 -0
  31. superqode/agents/data/vtcode.dev.toml +51 -0
  32. superqode/agents/discovery.py +266 -0
  33. superqode/agents/messaging.py +160 -0
  34. superqode/agents/persona.py +166 -0
  35. superqode/agents/registry.py +421 -0
  36. superqode/agents/schema.py +72 -0
  37. superqode/agents/unified.py +367 -0
  38. superqode/app/__init__.py +111 -0
  39. superqode/app/constants.py +314 -0
  40. superqode/app/css.py +366 -0
  41. superqode/app/models.py +118 -0
  42. superqode/app/suggester.py +125 -0
  43. superqode/app/widgets.py +1591 -0
  44. superqode/app_enhanced.py +399 -0
  45. superqode/app_main.py +17187 -0
  46. superqode/approval.py +312 -0
  47. superqode/atomic.py +296 -0
  48. superqode/commands/__init__.py +1 -0
  49. superqode/commands/acp.py +965 -0
  50. superqode/commands/agents.py +180 -0
  51. superqode/commands/auth.py +278 -0
  52. superqode/commands/config.py +374 -0
  53. superqode/commands/init.py +826 -0
  54. superqode/commands/providers.py +819 -0
  55. superqode/commands/qe.py +1145 -0
  56. superqode/commands/roles.py +380 -0
  57. superqode/commands/serve.py +172 -0
  58. superqode/commands/suggestions.py +127 -0
  59. superqode/commands/superqe.py +460 -0
  60. superqode/config/__init__.py +51 -0
  61. superqode/config/loader.py +812 -0
  62. superqode/config/schema.py +498 -0
  63. superqode/core/__init__.py +111 -0
  64. superqode/core/roles.py +281 -0
  65. superqode/danger.py +386 -0
  66. superqode/data/superqode-template.yaml +1522 -0
  67. superqode/design_system.py +1080 -0
  68. superqode/dialogs/__init__.py +6 -0
  69. superqode/dialogs/base.py +39 -0
  70. superqode/dialogs/model.py +130 -0
  71. superqode/dialogs/provider.py +870 -0
  72. superqode/diff_view.py +919 -0
  73. superqode/enterprise.py +21 -0
  74. superqode/evaluation/__init__.py +25 -0
  75. superqode/evaluation/adapters.py +93 -0
  76. superqode/evaluation/behaviors.py +89 -0
  77. superqode/evaluation/engine.py +209 -0
  78. superqode/evaluation/scenarios.py +96 -0
  79. superqode/execution/__init__.py +36 -0
  80. superqode/execution/linter.py +538 -0
  81. superqode/execution/modes.py +347 -0
  82. superqode/execution/resolver.py +283 -0
  83. superqode/execution/runner.py +642 -0
  84. superqode/file_explorer.py +811 -0
  85. superqode/file_viewer.py +471 -0
  86. superqode/flash.py +183 -0
  87. superqode/guidance/__init__.py +58 -0
  88. superqode/guidance/config.py +203 -0
  89. superqode/guidance/prompts.py +71 -0
  90. superqode/harness/__init__.py +54 -0
  91. superqode/harness/accelerator.py +291 -0
  92. superqode/harness/config.py +319 -0
  93. superqode/harness/validator.py +147 -0
  94. superqode/history.py +279 -0
  95. superqode/integrations/superopt_runner.py +124 -0
  96. superqode/logging/__init__.py +49 -0
  97. superqode/logging/adapters.py +219 -0
  98. superqode/logging/formatter.py +923 -0
  99. superqode/logging/integration.py +341 -0
  100. superqode/logging/sinks.py +170 -0
  101. superqode/logging/unified_log.py +417 -0
  102. superqode/lsp/__init__.py +26 -0
  103. superqode/lsp/client.py +544 -0
  104. superqode/main.py +1069 -0
  105. superqode/mcp/__init__.py +89 -0
  106. superqode/mcp/auth_storage.py +380 -0
  107. superqode/mcp/client.py +1236 -0
  108. superqode/mcp/config.py +319 -0
  109. superqode/mcp/integration.py +337 -0
  110. superqode/mcp/oauth.py +436 -0
  111. superqode/mcp/oauth_callback.py +385 -0
  112. superqode/mcp/types.py +290 -0
  113. superqode/memory/__init__.py +31 -0
  114. superqode/memory/feedback.py +342 -0
  115. superqode/memory/store.py +522 -0
  116. superqode/notifications.py +369 -0
  117. superqode/optimization/__init__.py +5 -0
  118. superqode/optimization/config.py +33 -0
  119. superqode/permissions/__init__.py +25 -0
  120. superqode/permissions/rules.py +488 -0
  121. superqode/plan.py +323 -0
  122. superqode/providers/__init__.py +33 -0
  123. superqode/providers/gateway/__init__.py +165 -0
  124. superqode/providers/gateway/base.py +228 -0
  125. superqode/providers/gateway/litellm_gateway.py +1170 -0
  126. superqode/providers/gateway/openresponses_gateway.py +436 -0
  127. superqode/providers/health.py +297 -0
  128. superqode/providers/huggingface/__init__.py +74 -0
  129. superqode/providers/huggingface/downloader.py +472 -0
  130. superqode/providers/huggingface/endpoints.py +442 -0
  131. superqode/providers/huggingface/hub.py +531 -0
  132. superqode/providers/huggingface/inference.py +394 -0
  133. superqode/providers/huggingface/transformers_runner.py +516 -0
  134. superqode/providers/local/__init__.py +100 -0
  135. superqode/providers/local/base.py +438 -0
  136. superqode/providers/local/discovery.py +418 -0
  137. superqode/providers/local/lmstudio.py +256 -0
  138. superqode/providers/local/mlx.py +457 -0
  139. superqode/providers/local/ollama.py +486 -0
  140. superqode/providers/local/sglang.py +268 -0
  141. superqode/providers/local/tgi.py +260 -0
  142. superqode/providers/local/tool_support.py +477 -0
  143. superqode/providers/local/vllm.py +258 -0
  144. superqode/providers/manager.py +1338 -0
  145. superqode/providers/models.py +1016 -0
  146. superqode/providers/models_dev.py +578 -0
  147. superqode/providers/openresponses/__init__.py +87 -0
  148. superqode/providers/openresponses/converters/__init__.py +17 -0
  149. superqode/providers/openresponses/converters/messages.py +343 -0
  150. superqode/providers/openresponses/converters/tools.py +268 -0
  151. superqode/providers/openresponses/schema/__init__.py +56 -0
  152. superqode/providers/openresponses/schema/models.py +585 -0
  153. superqode/providers/openresponses/streaming/__init__.py +5 -0
  154. superqode/providers/openresponses/streaming/parser.py +338 -0
  155. superqode/providers/openresponses/tools/__init__.py +21 -0
  156. superqode/providers/openresponses/tools/apply_patch.py +352 -0
  157. superqode/providers/openresponses/tools/code_interpreter.py +290 -0
  158. superqode/providers/openresponses/tools/file_search.py +333 -0
  159. superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
  160. superqode/providers/registry.py +716 -0
  161. superqode/providers/usage.py +332 -0
  162. superqode/pure_mode.py +384 -0
  163. superqode/qr/__init__.py +23 -0
  164. superqode/qr/dashboard.py +781 -0
  165. superqode/qr/generator.py +1018 -0
  166. superqode/qr/templates.py +135 -0
  167. superqode/safety/__init__.py +41 -0
  168. superqode/safety/sandbox.py +413 -0
  169. superqode/safety/warnings.py +256 -0
  170. superqode/server/__init__.py +33 -0
  171. superqode/server/lsp_server.py +775 -0
  172. superqode/server/web.py +250 -0
  173. superqode/session/__init__.py +25 -0
  174. superqode/session/persistence.py +580 -0
  175. superqode/session/sharing.py +477 -0
  176. superqode/session.py +475 -0
  177. superqode/sidebar.py +2991 -0
  178. superqode/stream_view.py +648 -0
  179. superqode/styles/__init__.py +3 -0
  180. superqode/superqe/__init__.py +184 -0
  181. superqode/superqe/acp_runner.py +1064 -0
  182. superqode/superqe/constitution/__init__.py +62 -0
  183. superqode/superqe/constitution/evaluator.py +308 -0
  184. superqode/superqe/constitution/loader.py +432 -0
  185. superqode/superqe/constitution/schema.py +250 -0
  186. superqode/superqe/events.py +591 -0
  187. superqode/superqe/frameworks/__init__.py +65 -0
  188. superqode/superqe/frameworks/base.py +234 -0
  189. superqode/superqe/frameworks/e2e.py +263 -0
  190. superqode/superqe/frameworks/executor.py +237 -0
  191. superqode/superqe/frameworks/javascript.py +409 -0
  192. superqode/superqe/frameworks/python.py +373 -0
  193. superqode/superqe/frameworks/registry.py +92 -0
  194. superqode/superqe/mcp_tools/__init__.py +47 -0
  195. superqode/superqe/mcp_tools/core_tools.py +418 -0
  196. superqode/superqe/mcp_tools/registry.py +230 -0
  197. superqode/superqe/mcp_tools/testing_tools.py +167 -0
  198. superqode/superqe/noise.py +89 -0
  199. superqode/superqe/orchestrator.py +778 -0
  200. superqode/superqe/roles.py +609 -0
  201. superqode/superqe/session.py +713 -0
  202. superqode/superqe/skills/__init__.py +57 -0
  203. superqode/superqe/skills/base.py +106 -0
  204. superqode/superqe/skills/core_skills.py +899 -0
  205. superqode/superqe/skills/registry.py +90 -0
  206. superqode/superqe/verifier.py +101 -0
  207. superqode/superqe_cli.py +76 -0
  208. superqode/tool_call.py +358 -0
  209. superqode/tools/__init__.py +93 -0
  210. superqode/tools/agent_tools.py +496 -0
  211. superqode/tools/base.py +324 -0
  212. superqode/tools/batch_tool.py +133 -0
  213. superqode/tools/diagnostics.py +311 -0
  214. superqode/tools/edit_tools.py +653 -0
  215. superqode/tools/enhanced_base.py +515 -0
  216. superqode/tools/file_tools.py +269 -0
  217. superqode/tools/file_tracking.py +45 -0
  218. superqode/tools/lsp_tools.py +610 -0
  219. superqode/tools/network_tools.py +350 -0
  220. superqode/tools/permissions.py +400 -0
  221. superqode/tools/question_tool.py +324 -0
  222. superqode/tools/search_tools.py +598 -0
  223. superqode/tools/shell_tools.py +259 -0
  224. superqode/tools/todo_tools.py +121 -0
  225. superqode/tools/validation.py +80 -0
  226. superqode/tools/web_tools.py +639 -0
  227. superqode/tui.py +1152 -0
  228. superqode/tui_integration.py +875 -0
  229. superqode/tui_widgets/__init__.py +27 -0
  230. superqode/tui_widgets/widgets/__init__.py +18 -0
  231. superqode/tui_widgets/widgets/progress.py +185 -0
  232. superqode/tui_widgets/widgets/tool_display.py +188 -0
  233. superqode/undo_manager.py +574 -0
  234. superqode/utils/__init__.py +5 -0
  235. superqode/utils/error_handling.py +323 -0
  236. superqode/utils/fuzzy.py +257 -0
  237. superqode/widgets/__init__.py +477 -0
  238. superqode/widgets/agent_collab.py +390 -0
  239. superqode/widgets/agent_store.py +936 -0
  240. superqode/widgets/agent_switcher.py +395 -0
  241. superqode/widgets/animation_manager.py +284 -0
  242. superqode/widgets/code_context.py +356 -0
  243. superqode/widgets/command_palette.py +412 -0
  244. superqode/widgets/connection_status.py +537 -0
  245. superqode/widgets/conversation_history.py +470 -0
  246. superqode/widgets/diff_indicator.py +155 -0
  247. superqode/widgets/enhanced_status_bar.py +385 -0
  248. superqode/widgets/enhanced_toast.py +476 -0
  249. superqode/widgets/file_browser.py +809 -0
  250. superqode/widgets/file_reference.py +585 -0
  251. superqode/widgets/issue_timeline.py +340 -0
  252. superqode/widgets/leader_key.py +264 -0
  253. superqode/widgets/mode_switcher.py +445 -0
  254. superqode/widgets/model_picker.py +234 -0
  255. superqode/widgets/permission_preview.py +1205 -0
  256. superqode/widgets/prompt.py +358 -0
  257. superqode/widgets/provider_connect.py +725 -0
  258. superqode/widgets/pty_shell.py +587 -0
  259. superqode/widgets/qe_dashboard.py +321 -0
  260. superqode/widgets/resizable_sidebar.py +377 -0
  261. superqode/widgets/response_changes.py +218 -0
  262. superqode/widgets/response_display.py +528 -0
  263. superqode/widgets/rich_tool_display.py +613 -0
  264. superqode/widgets/sidebar_panels.py +1180 -0
  265. superqode/widgets/slash_complete.py +356 -0
  266. superqode/widgets/split_view.py +612 -0
  267. superqode/widgets/status_bar.py +273 -0
  268. superqode/widgets/superqode_display.py +786 -0
  269. superqode/widgets/thinking_display.py +815 -0
  270. superqode/widgets/throbber.py +87 -0
  271. superqode/widgets/toast.py +206 -0
  272. superqode/widgets/unified_output.py +1073 -0
  273. superqode/workspace/__init__.py +75 -0
  274. superqode/workspace/artifacts.py +472 -0
  275. superqode/workspace/coordinator.py +353 -0
  276. superqode/workspace/diff_tracker.py +429 -0
  277. superqode/workspace/git_guard.py +373 -0
  278. superqode/workspace/git_snapshot.py +526 -0
  279. superqode/workspace/manager.py +750 -0
  280. superqode/workspace/snapshot.py +357 -0
  281. superqode/workspace/watcher.py +535 -0
  282. superqode/workspace/worktree.py +440 -0
  283. superqode-0.1.5.dist-info/METADATA +204 -0
  284. superqode-0.1.5.dist-info/RECORD +288 -0
  285. superqode-0.1.5.dist-info/WHEEL +5 -0
  286. superqode-0.1.5.dist-info/entry_points.txt +3 -0
  287. superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
  288. superqode-0.1.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,826 @@
1
+ """
2
+ Init command - Initialize SuperQE configuration for a project.
3
+
4
+ Supports guided mode with:
5
+ - Framework detection (React, Django, FastAPI, etc.)
6
+ - Team size configuration
7
+ - Provider setup with API key detection
8
+ - Validation with quick scan
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ import subprocess
15
+ from dataclasses import dataclass
16
+ from pathlib import Path
17
+ from typing import Dict, List, Optional, Tuple
18
+
19
+ import click
20
+ from rich.console import Console
21
+ from rich.panel import Panel
22
+ from rich.prompt import Confirm, Prompt
23
+ from rich.table import Table
24
+
25
+ console = Console()
26
+
27
+
28
+ @dataclass
29
+ class FrameworkInfo:
30
+ """Detected framework information."""
31
+
32
+ name: str
33
+ category: str # "frontend", "backend", "fullstack", "cli"
34
+ language: str
35
+ recommended_roles: List[str]
36
+ test_patterns: List[str]
37
+
38
+
39
+ # Framework detection rules
40
+ FRAMEWORK_DETECTORS = {
41
+ # Frontend frameworks
42
+ "next.js": {
43
+ "files": ["next.config.js", "next.config.mjs", "next.config.ts"],
44
+ "package_json_deps": ["next"],
45
+ "info": FrameworkInfo(
46
+ name="Next.js",
47
+ category="fullstack",
48
+ language="typescript",
49
+ recommended_roles=["e2e_tester", "api_tester", "unit_tester"],
50
+ test_patterns=["**/*.test.tsx", "**/*.spec.tsx", "**/__tests__/**"],
51
+ ),
52
+ },
53
+ "react": {
54
+ "files": [],
55
+ "package_json_deps": ["react", "react-dom"],
56
+ "info": FrameworkInfo(
57
+ name="React",
58
+ category="frontend",
59
+ language="typescript",
60
+ recommended_roles=["e2e_tester", "unit_tester"],
61
+ test_patterns=["**/*.test.tsx", "**/*.test.jsx", "**/*.spec.tsx"],
62
+ ),
63
+ },
64
+ "vue": {
65
+ "files": ["vue.config.js", "vite.config.ts"],
66
+ "package_json_deps": ["vue"],
67
+ "info": FrameworkInfo(
68
+ name="Vue.js",
69
+ category="frontend",
70
+ language="typescript",
71
+ recommended_roles=["e2e_tester", "unit_tester"],
72
+ test_patterns=["**/*.spec.ts", "**/*.test.ts"],
73
+ ),
74
+ },
75
+ # Backend frameworks
76
+ "django": {
77
+ "files": ["manage.py"],
78
+ "pyproject_deps": ["django"],
79
+ "requirements_deps": ["django", "Django"],
80
+ "info": FrameworkInfo(
81
+ name="Django",
82
+ category="backend",
83
+ language="python",
84
+ recommended_roles=[
85
+ "api_tester",
86
+ "security_tester",
87
+ "unit_tester",
88
+ "performance_tester",
89
+ ],
90
+ test_patterns=["**/test_*.py", "**/tests.py", "**/tests/*.py"],
91
+ ),
92
+ },
93
+ "fastapi": {
94
+ "files": [],
95
+ "pyproject_deps": ["fastapi"],
96
+ "requirements_deps": ["fastapi"],
97
+ "info": FrameworkInfo(
98
+ name="FastAPI",
99
+ category="backend",
100
+ language="python",
101
+ recommended_roles=[
102
+ "api_tester",
103
+ "security_tester",
104
+ "unit_tester",
105
+ "performance_tester",
106
+ ],
107
+ test_patterns=["**/test_*.py", "**/tests/*.py"],
108
+ ),
109
+ },
110
+ "flask": {
111
+ "files": [],
112
+ "pyproject_deps": ["flask"],
113
+ "requirements_deps": ["flask", "Flask"],
114
+ "info": FrameworkInfo(
115
+ name="Flask",
116
+ category="backend",
117
+ language="python",
118
+ recommended_roles=["api_tester", "security_tester", "unit_tester"],
119
+ test_patterns=["**/test_*.py"],
120
+ ),
121
+ },
122
+ "express": {
123
+ "files": [],
124
+ "package_json_deps": ["express"],
125
+ "info": FrameworkInfo(
126
+ name="Express.js",
127
+ category="backend",
128
+ language="typescript",
129
+ recommended_roles=["api_tester", "security_tester", "unit_tester"],
130
+ test_patterns=["**/*.test.js", "**/*.spec.js"],
131
+ ),
132
+ },
133
+ # Go frameworks
134
+ "go-chi": {
135
+ "files": [],
136
+ "go_mod_deps": ["github.com/go-chi/chi"],
137
+ "info": FrameworkInfo(
138
+ name="Go Chi",
139
+ category="backend",
140
+ language="go",
141
+ recommended_roles=["api_tester", "performance_tester", "unit_tester"],
142
+ test_patterns=["**/*_test.go"],
143
+ ),
144
+ },
145
+ "go-gin": {
146
+ "files": [],
147
+ "go_mod_deps": ["github.com/gin-gonic/gin"],
148
+ "info": FrameworkInfo(
149
+ name="Go Gin",
150
+ category="backend",
151
+ language="go",
152
+ recommended_roles=["api_tester", "performance_tester", "unit_tester"],
153
+ test_patterns=["**/*_test.go"],
154
+ ),
155
+ },
156
+ # Rust
157
+ "rust-actix": {
158
+ "files": [],
159
+ "cargo_deps": ["actix-web"],
160
+ "info": FrameworkInfo(
161
+ name="Actix Web",
162
+ category="backend",
163
+ language="rust",
164
+ recommended_roles=["api_tester", "performance_tester", "unit_tester"],
165
+ test_patterns=["**/tests/*.rs"],
166
+ ),
167
+ },
168
+ }
169
+
170
+
171
+ # Provider detection (check environment variables)
172
+ PROVIDER_ENV_VARS = {
173
+ "anthropic": "ANTHROPIC_API_KEY",
174
+ "openai": "OPENAI_API_KEY",
175
+ "google": "GOOGLE_API_KEY",
176
+ "xai": "XAI_API_KEY",
177
+ "zhipuai": "ZHIPUAI_API_KEY",
178
+ "deepseek": "DEEPSEEK_API_KEY",
179
+ "groq": "GROQ_API_KEY",
180
+ "together": "TOGETHER_API_KEY",
181
+ }
182
+
183
+ DEFAULT_CONFIG = """# SuperQode Configuration (used by SuperQE)
184
+ # https://super-agentic.ai/superqode
185
+
186
+ superqode:
187
+ version: "1.0"
188
+ team_name: "{team_name}"
189
+
190
+ qe:
191
+ # Output settings
192
+ output:
193
+ directory: ".superqode"
194
+ reports_format: "markdown"
195
+ keep_history: true
196
+
197
+ # Execution modes
198
+ modes:
199
+ quick_scan:
200
+ timeout: 60
201
+ depth: shallow
202
+ generate_tests: false
203
+ destructive: false
204
+
205
+ deep_qe:
206
+ timeout: 1800
207
+ depth: full
208
+ generate_tests: true
209
+ destructive: true
210
+
211
+ # Execution roles (deterministic - run existing tests only)
212
+ execution_roles:
213
+ smoke:
214
+ test_pattern: "**/test_smoke*.py"
215
+ fail_fast: true
216
+
217
+ sanity:
218
+ test_pattern: "**/test_sanity*.py"
219
+ fail_fast: false
220
+
221
+ regression:
222
+ test_pattern: "**/test_*.py"
223
+ detect_flakes: true
224
+
225
+ # Noise controls
226
+ noise:
227
+ min_confidence: 0.7
228
+ deduplicate: true
229
+ suppress_known_risks: false
230
+ min_severity: "low" # low, medium, high, critical
231
+
232
+ # Harness validation
233
+ harness:
234
+ enabled: true
235
+ timeout_seconds: 30
236
+ python_tools: ["ruff", "mypy"]
237
+ javascript_tools: ["eslint"]
238
+ go_tools: ["go vet"]
239
+ rust_tools: ["cargo check"]
240
+ shell_tools: ["shellcheck"]
241
+ custom_steps:
242
+ - name: "project-harness"
243
+ command: "python scripts/harness_check.py"
244
+ timeout_seconds: 120
245
+ enabled: false
246
+
247
+ # SuperOpt optimization hook (command-based, optional)
248
+ qe:
249
+ optimize:
250
+ enabled: false
251
+ command: ""
252
+
253
+ # Provider configuration (for BYOK mode)
254
+ providers:
255
+ anthropic:
256
+ api_key_env: "ANTHROPIC_API_KEY"
257
+ openai:
258
+ api_key_env: "OPENAI_API_KEY"
259
+ google:
260
+ api_key_env: "GOOGLE_API_KEY"
261
+ """
262
+
263
+
264
+ def _detect_frameworks(project_root: Path) -> List[FrameworkInfo]:
265
+ """Detect frameworks used in the project."""
266
+ detected = []
267
+
268
+ # Read package.json if exists
269
+ package_json_deps = set()
270
+ package_json_path = project_root / "package.json"
271
+ if package_json_path.exists():
272
+ try:
273
+ import json
274
+
275
+ pkg = json.loads(package_json_path.read_text())
276
+ package_json_deps.update(pkg.get("dependencies", {}).keys())
277
+ package_json_deps.update(pkg.get("devDependencies", {}).keys())
278
+ except Exception:
279
+ pass
280
+
281
+ # Read pyproject.toml if exists
282
+ pyproject_deps = set()
283
+ pyproject_path = project_root / "pyproject.toml"
284
+ if pyproject_path.exists():
285
+ try:
286
+ content = pyproject_path.read_text()
287
+ # Simple parsing - look for dependencies section
288
+ for line in content.split("\n"):
289
+ line = line.strip()
290
+ if "=" in line and not line.startswith("#"):
291
+ dep = line.split("=")[0].strip().strip('"').lower()
292
+ pyproject_deps.add(dep)
293
+ except Exception:
294
+ pass
295
+
296
+ # Read requirements.txt if exists
297
+ requirements_deps = set()
298
+ for req_file in ["requirements.txt", "requirements-dev.txt", "requirements/base.txt"]:
299
+ req_path = project_root / req_file
300
+ if req_path.exists():
301
+ try:
302
+ for line in req_path.read_text().split("\n"):
303
+ line = line.strip()
304
+ if line and not line.startswith("#"):
305
+ dep = line.split("==")[0].split(">=")[0].split("[")[0].strip()
306
+ requirements_deps.add(dep.lower())
307
+ except Exception:
308
+ pass
309
+
310
+ # Read go.mod if exists
311
+ go_mod_deps = set()
312
+ go_mod_path = project_root / "go.mod"
313
+ if go_mod_path.exists():
314
+ try:
315
+ for line in go_mod_path.read_text().split("\n"):
316
+ if line.strip() and not line.startswith("module") and not line.startswith("go "):
317
+ dep = line.strip().split()[0]
318
+ go_mod_deps.add(dep)
319
+ except Exception:
320
+ pass
321
+
322
+ # Read Cargo.toml if exists
323
+ cargo_deps = set()
324
+ cargo_path = project_root / "Cargo.toml"
325
+ if cargo_path.exists():
326
+ try:
327
+ content = cargo_path.read_text()
328
+ in_deps = False
329
+ for line in content.split("\n"):
330
+ if "[dependencies]" in line:
331
+ in_deps = True
332
+ elif line.startswith("[") and in_deps:
333
+ in_deps = False
334
+ elif in_deps and "=" in line:
335
+ dep = line.split("=")[0].strip()
336
+ cargo_deps.add(dep)
337
+ except Exception:
338
+ pass
339
+
340
+ # Check each framework
341
+ for framework_id, detector in FRAMEWORK_DETECTORS.items():
342
+ found = False
343
+
344
+ # Check for specific files
345
+ for file_pattern in detector.get("files", []):
346
+ if (project_root / file_pattern).exists():
347
+ found = True
348
+ break
349
+
350
+ # Check package.json dependencies
351
+ if not found:
352
+ for dep in detector.get("package_json_deps", []):
353
+ if dep in package_json_deps:
354
+ found = True
355
+ break
356
+
357
+ # Check pyproject.toml dependencies
358
+ if not found:
359
+ for dep in detector.get("pyproject_deps", []):
360
+ if dep.lower() in pyproject_deps:
361
+ found = True
362
+ break
363
+
364
+ # Check requirements.txt dependencies
365
+ if not found:
366
+ for dep in detector.get("requirements_deps", []):
367
+ if dep.lower() in requirements_deps:
368
+ found = True
369
+ break
370
+
371
+ # Check go.mod dependencies
372
+ if not found:
373
+ for dep in detector.get("go_mod_deps", []):
374
+ if any(dep in d for d in go_mod_deps):
375
+ found = True
376
+ break
377
+
378
+ # Check Cargo.toml dependencies
379
+ if not found:
380
+ for dep in detector.get("cargo_deps", []):
381
+ if dep in cargo_deps:
382
+ found = True
383
+ break
384
+
385
+ if found:
386
+ detected.append(detector["info"])
387
+
388
+ return detected
389
+
390
+
391
+ def _detect_providers() -> List[Tuple[str, str]]:
392
+ """Detect configured providers from environment variables."""
393
+ configured = []
394
+ for provider, env_var in PROVIDER_ENV_VARS.items():
395
+ if os.environ.get(env_var):
396
+ configured.append((provider, env_var))
397
+ return configured
398
+
399
+
400
+ def _create_guided_config(
401
+ team_name: str,
402
+ team_size: str,
403
+ frameworks: List[FrameworkInfo],
404
+ provider: Optional[str],
405
+ ) -> str:
406
+ """Create configuration based on guided setup choices."""
407
+ # Collect recommended roles from frameworks
408
+ roles = set()
409
+ test_patterns = []
410
+ for fw in frameworks:
411
+ roles.update(fw.recommended_roles)
412
+ test_patterns.extend(fw.test_patterns)
413
+
414
+ # Add default roles if none detected
415
+ if not roles:
416
+ roles = {"unit_tester", "api_tester", "security_tester"}
417
+
418
+ # Adjust roles based on team size
419
+ if team_size == "solo":
420
+ # Minimal set for solo developers
421
+ roles = {"unit_tester", "security_tester"}
422
+ elif team_size == "small":
423
+ # Keep detected roles, add security
424
+ roles.add("security_tester")
425
+ # "full" keeps all detected roles
426
+
427
+ # Build roles section
428
+ roles_yaml = ""
429
+ role_configs = {
430
+ "unit_tester": 'description: "Unit testing with coverage analysis"',
431
+ "api_tester": 'description: "API endpoint testing and validation"',
432
+ "security_tester": 'description: "Security vulnerability scanning"',
433
+ "e2e_tester": 'description: "End-to-end user journey testing"',
434
+ "performance_tester": 'description: "Performance and load testing"',
435
+ }
436
+
437
+ for role in sorted(roles):
438
+ if role in role_configs:
439
+ roles_yaml += f"""
440
+ {role}:
441
+ {role_configs[role]}
442
+ enabled: true"""
443
+
444
+ # Build test patterns
445
+ patterns_yaml = ""
446
+ if test_patterns:
447
+ unique_patterns = list(set(test_patterns))[:5] # Limit to 5
448
+ patterns_yaml = "\n ".join(f'- "{p}"' for p in unique_patterns)
449
+
450
+ # Provider config
451
+ provider_section = ""
452
+ if provider:
453
+ provider_section = f"""
454
+ # Default provider
455
+ default:
456
+ provider: {provider}
457
+ """
458
+
459
+ # Framework info comment
460
+ framework_comment = ""
461
+ if frameworks:
462
+ fw_names = ", ".join(fw.name for fw in frameworks)
463
+ framework_comment = f"# Detected frameworks: {fw_names}\n"
464
+
465
+ return f'''{framework_comment}# SuperQode Configuration (used by SuperQE)
466
+ # Generated by guided setup
467
+
468
+ superqode:
469
+ version: "2.0"
470
+ team_name: "{team_name}"
471
+ {provider_section}
472
+ team:
473
+ qe:
474
+ description: "Quality Engineering"
475
+ roles:{roles_yaml}
476
+
477
+ qe:
478
+ output:
479
+ directory: ".superqode"
480
+ reports_format: "markdown"
481
+
482
+ modes:
483
+ quick_scan:
484
+ timeout: 60
485
+ depth: shallow
486
+
487
+ deep_qe:
488
+ timeout: 1800
489
+ depth: full
490
+ generate_tests: true
491
+
492
+ noise:
493
+ min_confidence: 0.7
494
+ deduplicate: true
495
+ min_severity: "low"
496
+
497
+ harness:
498
+ enabled: true
499
+ timeout_seconds: 30
500
+ '''
501
+
502
+
503
+ @click.command("init")
504
+ @click.argument("path", type=click.Path(), default=".")
505
+ @click.option("--force", "-f", is_flag=True, help="Overwrite existing configuration")
506
+ @click.option("--minimal", "-m", is_flag=True, help="Create minimal configuration")
507
+ @click.option("--guided", "-g", is_flag=True, help="Run guided setup wizard")
508
+ def init(path: str, force: bool, minimal: bool, guided: bool):
509
+ """Initialize SuperQE configuration for a project.
510
+
511
+ Creates a superqode.yaml configuration file and .superqode directory.
512
+
513
+ Examples:
514
+
515
+ superqe init # Initialize current directory
516
+
517
+ superqe init ./myproject # Initialize specific directory
518
+
519
+ superqe init --minimal # Create minimal config
520
+
521
+ superqe init --guided # Run guided setup wizard
522
+ """
523
+ project_root = Path(path).resolve()
524
+
525
+ console.print()
526
+ console.print(Panel("[bold]SuperQE Initialization[/bold]", border_style="cyan"))
527
+ console.print()
528
+
529
+ # Check if project exists
530
+ if not project_root.exists():
531
+ console.print(f"[red]Error:[/red] Path does not exist: {project_root}")
532
+ return 1
533
+
534
+ config_file = project_root / "superqode.yaml"
535
+ superqode_dir = project_root / ".superqode"
536
+
537
+ # Check for existing config
538
+ if config_file.exists() and not force:
539
+ console.print(f"[yellow]Configuration already exists:[/yellow] {config_file}")
540
+ if not Confirm.ask("Overwrite existing configuration?"):
541
+ console.print("[dim]Initialization cancelled.[/dim]")
542
+ return 0
543
+
544
+ # Guided setup mode
545
+ if guided:
546
+ return _run_guided_setup(project_root, config_file, superqode_dir)
547
+
548
+ # Standard setup
549
+ # Detect project info
550
+ team_name = _detect_team_name(project_root)
551
+
552
+ # Ask for team name
553
+ team_name = Prompt.ask("Team name", default=team_name)
554
+
555
+ # Create configuration
556
+ if minimal:
557
+ config_content = _create_minimal_config(team_name)
558
+ else:
559
+ config_content = DEFAULT_CONFIG.format(team_name=team_name)
560
+
561
+ # Write config file
562
+ config_file.write_text(config_content)
563
+ console.print(f"[green]✓[/green] Created {config_file}")
564
+ console.print(
565
+ "[dim]⚡ Power QE roles: unit, integration, api, ui, accessibility, security, usability[/dim]"
566
+ )
567
+ console.print(
568
+ "[dim]💡 Tip: Update each role's job_description in superqode.yaml for best results[/dim]"
569
+ )
570
+
571
+ # Create .superqode directory structure
572
+ _create_superqode_directory(superqode_dir)
573
+
574
+ # Detect test patterns
575
+ _detect_and_suggest_patterns(project_root)
576
+
577
+ console.print()
578
+ console.print("[green]SuperQE initialized successfully![/green]")
579
+ console.print()
580
+ console.print("[dim]Next steps:[/dim]")
581
+ console.print(" 1. Review superqode.yaml and customize settings")
582
+ console.print(" 2. Run [cyan]superqe run . --mode quick[/cyan] for a quick scan")
583
+ console.print(" 3. Run [cyan]superqe run . --mode deep[/cyan] for full analysis")
584
+ console.print()
585
+
586
+ return 0
587
+
588
+
589
+ def _run_guided_setup(project_root: Path, config_file: Path, superqode_dir: Path) -> int:
590
+ """Run the guided setup wizard."""
591
+ console.print("[bold cyan]Step 1/4: Project Detection[/bold cyan]")
592
+ console.print()
593
+
594
+ # Detect frameworks
595
+ frameworks = _detect_frameworks(project_root)
596
+ if frameworks:
597
+ console.print("[green]Detected frameworks:[/green]")
598
+ table = Table(show_header=False, box=None)
599
+ table.add_column("Framework", style="cyan")
600
+ table.add_column("Category")
601
+ table.add_column("Language")
602
+ for fw in frameworks:
603
+ table.add_row(fw.name, fw.category, fw.language)
604
+ console.print(table)
605
+ else:
606
+ console.print("[dim]No specific framework detected[/dim]")
607
+
608
+ # Detect test files
609
+ _detect_and_suggest_patterns(project_root)
610
+ console.print()
611
+
612
+ # Step 2: Team size
613
+ console.print("[bold cyan]Step 2/4: Team Size[/bold cyan]")
614
+ console.print()
615
+ console.print("Select your team size to optimize QE role configuration:")
616
+ console.print(" [cyan]1[/cyan]. Solo developer (minimal roles, fast feedback)")
617
+ console.print(" [cyan]2[/cyan]. Small team (2-10 people, balanced coverage)")
618
+ console.print(" [cyan]3[/cyan]. Full team (all roles enabled)")
619
+ console.print()
620
+
621
+ team_size_choice = Prompt.ask("Team size", choices=["1", "2", "3"], default="2")
622
+ team_size_map = {"1": "solo", "2": "small", "3": "full"}
623
+ team_size = team_size_map[team_size_choice]
624
+ console.print()
625
+
626
+ # Step 3: Provider configuration
627
+ console.print("[bold cyan]Step 3/4: Provider Configuration[/bold cyan]")
628
+ console.print()
629
+
630
+ configured_providers = _detect_providers()
631
+ selected_provider = None
632
+
633
+ if configured_providers:
634
+ console.print("[green]Detected API keys:[/green]")
635
+ for provider, env_var in configured_providers:
636
+ console.print(f" [cyan]{provider}[/cyan] ({env_var})")
637
+ console.print()
638
+
639
+ if len(configured_providers) == 1:
640
+ selected_provider = configured_providers[0][0]
641
+ console.print(f"[dim]Using {selected_provider} as default provider[/dim]")
642
+ else:
643
+ provider_names = [p[0] for p in configured_providers]
644
+ selected_provider = Prompt.ask(
645
+ "Select default provider", choices=provider_names, default=provider_names[0]
646
+ )
647
+ else:
648
+ console.print("[yellow]No API keys detected in environment.[/yellow]")
649
+ console.print("[dim]You can configure providers later in superqode.yaml[/dim]")
650
+ console.print()
651
+ console.print("Free tier options:")
652
+ console.print(" - ZhipuAI (ZHIPUAI_API_KEY)")
653
+ console.print(" - Groq (GROQ_API_KEY)")
654
+ console.print()
655
+
656
+ console.print()
657
+
658
+ # Step 4: Team name
659
+ console.print("[bold cyan]Step 4/4: Team Name[/bold cyan]")
660
+ console.print()
661
+ team_name = _detect_team_name(project_root)
662
+ team_name = Prompt.ask("Team name", default=team_name)
663
+ console.print()
664
+
665
+ # Generate configuration
666
+ config_content = _create_guided_config(
667
+ team_name=team_name,
668
+ team_size=team_size,
669
+ frameworks=frameworks,
670
+ provider=selected_provider,
671
+ )
672
+
673
+ # Write config file
674
+ config_file.write_text(config_content)
675
+ console.print(f"[green]✓[/green] Created {config_file}")
676
+ console.print(
677
+ "[dim]⚡ Power QE roles: unit, integration, api, ui, accessibility, security, usability[/dim]"
678
+ )
679
+ console.print(
680
+ "[dim]💡 Tip: Update each role's job_description in superqode.yaml for best results[/dim]"
681
+ )
682
+
683
+ # Create directory structure
684
+ _create_superqode_directory(superqode_dir)
685
+
686
+ # Success message
687
+ console.print()
688
+ console.print(
689
+ Panel("[bold green]SuperQE initialized successfully![/bold green]", border_style="green")
690
+ )
691
+ console.print()
692
+
693
+ # Show what was configured
694
+ if frameworks:
695
+ fw_names = ", ".join(fw.name for fw in frameworks)
696
+ console.print(f"[dim]Frameworks:[/dim] {fw_names}")
697
+ console.print(f"[dim]Team size:[/dim] {team_size}")
698
+ if selected_provider:
699
+ console.print(f"[dim]Provider:[/dim] {selected_provider}")
700
+ console.print()
701
+
702
+ # Offer to run quick scan
703
+ if Confirm.ask("Run a quick scan to validate setup?", default=True):
704
+ console.print()
705
+ console.print("[cyan]Running quick scan...[/cyan]")
706
+ console.print()
707
+ try:
708
+ result = subprocess.run(
709
+ ["superqe", "run", str(project_root), "--mode", "quick"],
710
+ cwd=str(project_root),
711
+ )
712
+ if result.returncode == 0:
713
+ console.print()
714
+ console.print("[green]Setup validated successfully![/green]")
715
+ else:
716
+ console.print()
717
+ console.print(
718
+ "[yellow]Quick scan completed with findings. Check the report above.[/yellow]"
719
+ )
720
+ except Exception as e:
721
+ console.print(f"[dim]Could not run quick scan: {e}[/dim]")
722
+ else:
723
+ console.print()
724
+ console.print("[dim]Next steps:[/dim]")
725
+ console.print(" 1. Run [cyan]superqe run . --mode quick[/cyan] for a quick scan")
726
+ console.print(" 2. Run [cyan]superqe dashboard[/cyan] to view results")
727
+ console.print()
728
+
729
+ return 0
730
+
731
+
732
+ def _create_superqode_directory(superqode_dir: Path) -> None:
733
+ """Create the .superqode directory structure."""
734
+ superqode_dir.mkdir(exist_ok=True)
735
+ (superqode_dir / "qe-artifacts").mkdir(exist_ok=True)
736
+ (superqode_dir / "qe-artifacts" / "patches").mkdir(exist_ok=True)
737
+ (superqode_dir / "qe-artifacts" / "generated-tests").mkdir(exist_ok=True)
738
+ (superqode_dir / "qe-artifacts" / "qr").mkdir(exist_ok=True)
739
+ (superqode_dir / "history").mkdir(exist_ok=True)
740
+ console.print(f"[green]✓[/green] Created {superqode_dir}/")
741
+
742
+ # Create .gitignore in .superqode
743
+ gitignore_file = superqode_dir / ".gitignore"
744
+ gitignore_content = """# SuperQode / SuperQE temporary files
745
+ temp/
746
+ *.log
747
+ workspace-state.json
748
+
749
+ # Keep artifacts
750
+ !qe-artifacts/
751
+ """
752
+ gitignore_file.write_text(gitignore_content)
753
+
754
+
755
+ def _detect_team_name(project_root: Path) -> str:
756
+ """Detect team name from project directory or git config."""
757
+ # Try to get from git config
758
+ try:
759
+ import subprocess
760
+
761
+ result = subprocess.run(
762
+ ["git", "config", "user.name"],
763
+ cwd=str(project_root),
764
+ capture_output=True,
765
+ text=True,
766
+ )
767
+ if result.returncode == 0 and result.stdout.strip():
768
+ return f"{result.stdout.strip()}'s Team"
769
+ except Exception:
770
+ pass
771
+
772
+ # Fall back to directory name
773
+ return f"{project_root.name} Team"
774
+
775
+
776
+ def _create_minimal_config(team_name: str) -> str:
777
+ """Create a minimal configuration."""
778
+ return f'''# SuperQode Configuration (Minimal, used by SuperQE)
779
+ superqode:
780
+ version: "1.0"
781
+ team_name: "{team_name}"
782
+
783
+ qe:
784
+ modes:
785
+ quick_scan:
786
+ timeout: 60
787
+ deep_qe:
788
+ timeout: 1800
789
+
790
+ noise:
791
+ min_confidence: 0.7
792
+ deduplicate: true
793
+ '''
794
+
795
+
796
+ def _detect_and_suggest_patterns(project_root: Path) -> None:
797
+ """Detect existing test patterns and suggest configuration."""
798
+ patterns_found = []
799
+
800
+ # Python tests
801
+ pytest_files = list(project_root.glob("**/test_*.py"))
802
+ if pytest_files:
803
+ patterns_found.append(f" - Python (pytest): {len(pytest_files)} test files")
804
+
805
+ # JavaScript tests
806
+ jest_files = list(project_root.glob("**/*.test.js")) + list(project_root.glob("**/*.spec.js"))
807
+ if jest_files:
808
+ patterns_found.append(f" - JavaScript (jest): {len(jest_files)} test files")
809
+
810
+ # TypeScript tests
811
+ ts_test_files = list(project_root.glob("**/*.test.ts")) + list(
812
+ project_root.glob("**/*.spec.ts")
813
+ )
814
+ if ts_test_files:
815
+ patterns_found.append(f" - TypeScript: {len(ts_test_files)} test files")
816
+
817
+ # Go tests
818
+ go_test_files = list(project_root.glob("**/*_test.go"))
819
+ if go_test_files:
820
+ patterns_found.append(f" - Go: {len(go_test_files)} test files")
821
+
822
+ if patterns_found:
823
+ console.print()
824
+ console.print("[dim]Detected test files:[/dim]")
825
+ for p in patterns_found:
826
+ console.print(p)