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,374 @@
1
+ """
2
+ Config command - Manage SuperQode configuration.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ from pathlib import Path
9
+ from typing import Optional
10
+
11
+ import click
12
+ from rich.console import Console
13
+ from rich.panel import Panel
14
+ from rich.syntax import Syntax
15
+ from rich.table import Table
16
+ from rich.tree import Tree
17
+
18
+ console = Console()
19
+
20
+
21
+ @click.group()
22
+ def config():
23
+ """Manage SuperQode configuration.
24
+
25
+ View, validate, and modify configuration settings.
26
+ """
27
+ pass
28
+
29
+
30
+ @config.command("show")
31
+ @click.argument("path", type=click.Path(exists=True), default=".")
32
+ @click.option(
33
+ "--format",
34
+ "-f",
35
+ "fmt",
36
+ type=click.Choice(["yaml", "json", "tree"]),
37
+ default="yaml",
38
+ help="Output format",
39
+ )
40
+ @click.option("--section", "-s", help="Show specific section (e.g., 'team.modes.dev')")
41
+ def config_show(path: str, fmt: str, section: Optional[str]):
42
+ """Show current configuration.
43
+
44
+ Examples:
45
+
46
+ superqode config show # Show full config
47
+
48
+ superqode config show -f json # Output as JSON
49
+
50
+ superqode config show -s team.modes.dev # Show specific section
51
+ """
52
+ from superqode.config import load_config
53
+
54
+ project_root = Path(path).resolve()
55
+ config_file = project_root / "superqode.yaml"
56
+
57
+ if not config_file.exists():
58
+ console.print("[yellow]No configuration found.[/yellow]")
59
+ console.print("[dim]Run 'superqode init' to create a configuration.[/dim]")
60
+ return 1
61
+
62
+ # Load and parse config
63
+ try:
64
+ cfg = load_config(project_root)
65
+ except Exception as e:
66
+ console.print(f"[red]Error loading configuration:[/red] {e}")
67
+ return 1
68
+
69
+ console.print()
70
+ console.print(Panel("[bold]SuperQode Configuration[/bold]", border_style="cyan"))
71
+ console.print()
72
+
73
+ if fmt == "yaml":
74
+ # Show raw YAML
75
+ content = config_file.read_text()
76
+ syntax = Syntax(content, "yaml", theme="monokai", line_numbers=True)
77
+ console.print(syntax)
78
+
79
+ elif fmt == "json":
80
+ # Convert to JSON
81
+ import dataclasses
82
+
83
+ def to_dict(obj):
84
+ if dataclasses.is_dataclass(obj):
85
+ return {k: to_dict(v) for k, v in dataclasses.asdict(obj).items()}
86
+ elif isinstance(obj, dict):
87
+ return {k: to_dict(v) for k, v in obj.items()}
88
+ elif isinstance(obj, list):
89
+ return [to_dict(v) for v in obj]
90
+ elif hasattr(obj, "value"): # Enum
91
+ return obj.value
92
+ else:
93
+ return obj
94
+
95
+ config_dict = to_dict(cfg)
96
+ console.print(json.dumps(config_dict, indent=2))
97
+
98
+ elif fmt == "tree":
99
+ # Show as tree
100
+ _show_config_tree(cfg)
101
+
102
+ return 0
103
+
104
+
105
+ @config.command("validate")
106
+ @click.argument("path", type=click.Path(exists=True), default=".")
107
+ @click.option("--fix", is_flag=True, help="Attempt to fix common issues")
108
+ def config_validate(path: str, fix: bool):
109
+ """Validate configuration file.
110
+
111
+ Checks for:
112
+ - Valid YAML syntax
113
+ - Required fields
114
+ - Valid values
115
+ - Provider configurations
116
+ - Harness tool availability
117
+
118
+ Examples:
119
+
120
+ superqode config validate # Validate current directory
121
+
122
+ superqode config validate --fix # Auto-fix common issues
123
+ """
124
+ from superqode.config import load_config
125
+
126
+ project_root = Path(path).resolve()
127
+ config_file = project_root / "superqode.yaml"
128
+
129
+ console.print()
130
+ console.print(Panel("[bold]Configuration Validation[/bold]", border_style="cyan"))
131
+ console.print()
132
+
133
+ if not config_file.exists():
134
+ console.print("[red]✗[/red] No superqode.yaml found")
135
+ console.print("[dim]Run 'superqode init' to create a configuration.[/dim]")
136
+ return 1
137
+
138
+ issues = []
139
+ warnings = []
140
+
141
+ # Check YAML syntax
142
+ try:
143
+ import yaml
144
+
145
+ with open(config_file) as f:
146
+ raw_config = yaml.safe_load(f)
147
+ console.print("[green]✓[/green] YAML syntax is valid")
148
+ except yaml.YAMLError as e:
149
+ console.print(f"[red]✗[/red] YAML syntax error: {e}")
150
+ return 1
151
+
152
+ # Check required sections
153
+ if "superqode" not in raw_config:
154
+ issues.append("Missing 'superqode' section")
155
+ else:
156
+ if "version" not in raw_config.get("superqode", {}):
157
+ warnings.append("Missing 'superqode.version' field")
158
+ console.print("[green]✓[/green] 'superqode' section present")
159
+
160
+ # Check MCP servers config (if present)
161
+ mcp_config = raw_config.get("mcp_servers", {})
162
+ if mcp_config:
163
+ console.print("[green]✓[/green] MCP servers configured")
164
+ for name, server_config in mcp_config.items():
165
+ if server_config.get("enabled", False):
166
+ console.print(f" [green]✓[/green] {name}: enabled")
167
+ else:
168
+ console.print(f" [dim]○[/dim] {name}: disabled")
169
+
170
+ # Check providers
171
+ providers = raw_config.get("providers", {})
172
+ if providers:
173
+ console.print("[green]✓[/green] Providers configured")
174
+ for name, pconfig in providers.items():
175
+ api_key_env = pconfig.get("api_key_env")
176
+ if api_key_env:
177
+ import os
178
+
179
+ if os.environ.get(api_key_env):
180
+ console.print(f" [green]✓[/green] {name}: {api_key_env} is set")
181
+ else:
182
+ warnings.append(f"Provider '{name}': {api_key_env} not set in environment")
183
+
184
+ # Load full config to check for errors
185
+ try:
186
+ cfg = load_config(project_root)
187
+ console.print("[green]✓[/green] Configuration loads successfully")
188
+ except Exception as e:
189
+ issues.append(f"Configuration load error: {e}")
190
+
191
+ # Report results
192
+ console.print()
193
+ if issues:
194
+ console.print("[bold red]Issues found:[/bold red]")
195
+ for issue in issues:
196
+ console.print(f" [red]✗[/red] {issue}")
197
+ console.print()
198
+
199
+ if warnings:
200
+ console.print("[bold yellow]Warnings:[/bold yellow]")
201
+ for warning in warnings:
202
+ console.print(f" [yellow]![/yellow] {warning}")
203
+ console.print()
204
+
205
+ if not issues and not warnings:
206
+ console.print("[green]✓ Configuration is valid![/green]")
207
+ return 0
208
+ elif not issues:
209
+ console.print("[green]✓ Configuration is valid (with warnings)[/green]")
210
+ return 0
211
+ else:
212
+ console.print("[red]✗ Configuration has issues[/red]")
213
+ return 1
214
+
215
+
216
+ @config.command("set")
217
+ @click.argument("key")
218
+ @click.argument("value")
219
+ @click.argument("path", type=click.Path(exists=True), default=".")
220
+ def config_set(key: str, value: str, path: str):
221
+ """Set a configuration value.
222
+
223
+ Examples:
224
+
225
+ superqode config set superqode.team_name "My Team"
226
+
227
+ superqode config set team.modes.dev.roles.fullstack.enabled false
228
+ """
229
+ import yaml
230
+
231
+ project_root = Path(path).resolve()
232
+ config_file = project_root / "superqode.yaml"
233
+
234
+ if not config_file.exists():
235
+ console.print("[red]No configuration found.[/red]")
236
+ console.print("[dim]Run 'superqode init' first.[/dim]")
237
+ return 1
238
+
239
+ # Load existing config
240
+ with open(config_file) as f:
241
+ config = yaml.safe_load(f) or {}
242
+
243
+ # Parse the key path
244
+ keys = key.split(".")
245
+ current = config
246
+
247
+ # Navigate to parent
248
+ for k in keys[:-1]:
249
+ if k not in current:
250
+ current[k] = {}
251
+ current = current[k]
252
+
253
+ # Set value (try to parse as number/bool)
254
+ final_key = keys[-1]
255
+ try:
256
+ # Try int
257
+ parsed_value = int(value)
258
+ except ValueError:
259
+ try:
260
+ # Try float
261
+ parsed_value = float(value)
262
+ except ValueError:
263
+ # Try bool
264
+ if value.lower() in ("true", "yes", "on"):
265
+ parsed_value = True
266
+ elif value.lower() in ("false", "no", "off"):
267
+ parsed_value = False
268
+ else:
269
+ parsed_value = value
270
+
271
+ old_value = current.get(final_key)
272
+ current[final_key] = parsed_value
273
+
274
+ # Write back
275
+ with open(config_file, "w") as f:
276
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
277
+
278
+ console.print(f"[green]✓[/green] Set {key}: {old_value} → {parsed_value}")
279
+ return 0
280
+
281
+
282
+ @config.command("get")
283
+ @click.argument("key")
284
+ @click.argument("path", type=click.Path(exists=True), default=".")
285
+ def config_get(key: str, path: str):
286
+ """Get a configuration value.
287
+
288
+ Examples:
289
+
290
+ superqode config get superqode.team_name
291
+
292
+ superqode config get team.modes.dev.roles.fullstack.enabled
293
+ """
294
+ import yaml
295
+
296
+ project_root = Path(path).resolve()
297
+ config_file = project_root / "superqode.yaml"
298
+
299
+ if not config_file.exists():
300
+ console.print("[red]No configuration found.[/red]")
301
+ return 1
302
+
303
+ with open(config_file) as f:
304
+ config = yaml.safe_load(f) or {}
305
+
306
+ # Navigate to value
307
+ keys = key.split(".")
308
+ current = config
309
+
310
+ for k in keys:
311
+ if isinstance(current, dict) and k in current:
312
+ current = current[k]
313
+ else:
314
+ console.print(f"[yellow]Key not found:[/yellow] {key}")
315
+ return 1
316
+
317
+ # Output value
318
+ if isinstance(current, (dict, list)):
319
+ console.print(json.dumps(current, indent=2))
320
+ else:
321
+ console.print(current)
322
+
323
+ return 0
324
+
325
+
326
+ def _show_config_tree(cfg) -> None:
327
+ """Display configuration as a tree."""
328
+ import dataclasses
329
+
330
+ tree = Tree("[bold cyan]superqode.yaml[/bold cyan]")
331
+
332
+ def add_to_tree(node, obj, name=""):
333
+ if dataclasses.is_dataclass(obj):
334
+ branch = node.add(f"[bold]{name}[/bold]") if name else node
335
+ for field in dataclasses.fields(obj):
336
+ add_to_tree(branch, getattr(obj, field.name), field.name)
337
+ elif isinstance(obj, dict):
338
+ branch = node.add(f"[bold]{name}[/bold]") if name else node
339
+ for k, v in obj.items():
340
+ add_to_tree(branch, v, k)
341
+ elif isinstance(obj, list):
342
+ branch = node.add(f"[bold]{name}[/bold] [dim]({len(obj)} items)[/dim]")
343
+ for i, v in enumerate(obj[:5]): # Limit to 5 items
344
+ add_to_tree(branch, v, f"[{i}]")
345
+ if len(obj) > 5:
346
+ branch.add("[dim]...[/dim]")
347
+ else:
348
+ value = str(obj)
349
+ if len(value) > 50:
350
+ value = value[:47] + "..."
351
+ node.add(f"{name}: [green]{value}[/green]")
352
+
353
+ add_to_tree(tree, cfg)
354
+ console.print(tree)
355
+
356
+
357
+ def _check_harness_tools(harness: dict, warnings: list) -> None:
358
+ """Check if harness tools are available."""
359
+ import shutil
360
+
361
+ tool_checks = {
362
+ "python_tools": ["ruff", "mypy", "pyright"],
363
+ "javascript_tools": ["eslint", "tsc"],
364
+ "go_tools": ["golangci-lint"],
365
+ "rust_tools": ["cargo"],
366
+ "shell_tools": ["shellcheck"],
367
+ }
368
+
369
+ for category, tools in tool_checks.items():
370
+ configured_tools = harness.get(category, [])
371
+ for tool in configured_tools:
372
+ tool_name = tool.split()[0] # Handle "go vet" -> "go"
373
+ if not shutil.which(tool_name):
374
+ warnings.append(f"Harness tool not found: {tool_name}")