superqode 0.1.9__tar.gz → 0.1.10__tar.gz
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-0.1.9/src/superqode.egg-info → superqode-0.1.10}/PKG-INFO +1 -1
- {superqode-0.1.9 → superqode-0.1.10}/pyproject.toml +1 -1
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/__init__.py +1 -1
- superqode-0.1.10/src/superqode/auth/__init__.py +264 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/acp.py +109 -109
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/auth.py +134 -12
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/execution/resolver.py +40 -2
- {superqode-0.1.9 → superqode-0.1.10/src/superqode.egg-info}/PKG-INFO +1 -1
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode.egg-info/SOURCES.txt +2 -0
- superqode-0.1.10/tests/test_auth.py +181 -0
- {superqode-0.1.9 → superqode-0.1.10}/LICENSE +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/README.md +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/setup.cfg +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/acp/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/acp/client.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/acp/permission_screen.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/acp/types.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/acp_discovery.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent/edit_strategies.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent/loop.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent/qe_report_templates.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent/system_prompts.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent_output.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agent_stream.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/acp_registry.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/client.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/ampcode.com.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/augmentcode.com.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/cagent.dev.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/claude.com.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/codeassistant.dev.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/codex.openai.com.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/fastagent.ai.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/geminicli.com.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/goose.block.xyz.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/junie.jetbrains.com.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/kimi.moonshot.cn.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/llmlingagent.dev.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/molt.bot.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/opencode.ai.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/stakpak.dev.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/data/vtcode.dev.toml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/discovery.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/messaging.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/persona.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/registry.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/schema.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/agents/unified.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app/constants.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app/css.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app/models.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app/suggester.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app/widgets.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app_enhanced.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/app_main.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/approval.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/atomic.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/agents.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/config.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/init.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/providers.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/qe.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/roles.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/serve.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/suggestions.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/commands/superqe.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/config/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/config/loader.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/config/schema.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/core/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/core/roles.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/danger.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/data/superqode-template.yaml +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/design_system.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/dialogs/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/dialogs/base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/dialogs/model.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/dialogs/provider.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/diff_view.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/enterprise.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/evaluation/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/evaluation/adapters.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/evaluation/behaviors.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/evaluation/engine.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/evaluation/scenarios.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/execution/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/execution/linter.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/execution/modes.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/execution/runner.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/file_explorer.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/file_viewer.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/flash.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/guidance/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/guidance/config.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/guidance/prompts.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/harness/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/harness/accelerator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/harness/config.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/harness/validator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/history.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/integrations/superopt_runner.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/logging/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/logging/adapters.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/logging/formatter.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/logging/integration.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/logging/sinks.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/logging/unified_log.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/lsp/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/lsp/client.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/main.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/auth_storage.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/client.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/config.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/integration.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/oauth.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/oauth_callback.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/mcp/types.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/memory/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/memory/feedback.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/memory/store.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/notifications.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/optimization/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/optimization/config.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/permissions/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/permissions/rules.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/plan.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/gateway/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/gateway/base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/gateway/litellm_gateway.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/gateway/openresponses_gateway.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/health.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/huggingface/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/huggingface/downloader.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/huggingface/endpoints.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/huggingface/hub.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/huggingface/inference.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/huggingface/transformers_runner.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/discovery.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/lmstudio.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/mlx.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/ollama.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/sglang.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/tgi.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/tool_support.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/local/vllm.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/manager.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/models.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/models_dev.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/converters/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/converters/messages.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/converters/tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/schema/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/schema/models.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/streaming/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/streaming/parser.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/tools/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/tools/apply_patch.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/tools/code_interpreter.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/tools/file_search.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/openresponses/tools/mcp_adapter.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/registry.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/providers/usage.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/pure_mode.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/qr/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/qr/dashboard.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/qr/generator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/qr/templates.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/safety/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/safety/sandbox.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/safety/warnings.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/server/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/server/lsp_server.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/server/web.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/session/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/session/persistence.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/session/sharing.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/session.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/sidebar.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/stream_view.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/styles/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/acp_runner.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/constitution/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/constitution/evaluator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/constitution/loader.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/constitution/schema.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/events.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/e2e.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/executor.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/javascript.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/python.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/frameworks/registry.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/mcp_tools/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/mcp_tools/core_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/mcp_tools/registry.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/mcp_tools/testing_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/noise.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/orchestrator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/roles.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/session.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/skills/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/skills/base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/skills/core_skills.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/skills/registry.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe/verifier.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/superqe_cli.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tool_call.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/agent_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/batch_tool.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/diagnostics.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/edit_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/enhanced_base.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/file_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/file_tracking.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/lsp_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/network_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/permissions.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/question_tool.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/search_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/shell_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/todo_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/validation.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tools/web_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tui.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tui_integration.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tui_widgets/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tui_widgets/widgets/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tui_widgets/widgets/progress.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/tui_widgets/widgets/tool_display.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/undo_manager.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/utils/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/utils/error_handling.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/utils/fuzzy.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/agent_collab.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/agent_store.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/agent_switcher.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/animation_manager.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/code_context.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/command_palette.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/connection_status.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/conversation_history.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/diff_indicator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/enhanced_status_bar.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/enhanced_toast.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/file_browser.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/file_reference.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/issue_timeline.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/leader_key.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/mode_switcher.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/model_picker.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/permission_preview.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/prompt.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/provider_connect.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/pty_shell.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/qe_dashboard.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/resizable_sidebar.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/response_changes.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/response_display.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/rich_tool_display.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/sidebar_panels.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/slash_complete.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/split_view.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/status_bar.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/superqode_display.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/thinking_display.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/throbber.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/toast.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/widgets/unified_output.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/__init__.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/artifacts.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/coordinator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/diff_tracker.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/git_guard.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/git_snapshot.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/manager.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/snapshot.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/watcher.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode/workspace/worktree.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode.egg-info/dependency_links.txt +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode.egg-info/entry_points.txt +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode.egg-info/requires.txt +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/src/superqode.egg-info/top_level.txt +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_acp_client.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_cli_commands.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_linter_runner.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_login_api.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_mcp.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_mcp_integration.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_mcp_live.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_orchestrator.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_oss_integration.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_simple_login.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_tools.py +0 -0
- {superqode-0.1.9 → superqode-0.1.10}/tests/test_workspace.py +0 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Local Auth Storage for SuperQode.
|
|
3
|
+
|
|
4
|
+
Simple, minimal local storage for API keys. Inspired by opencode's approach.
|
|
5
|
+
|
|
6
|
+
Security:
|
|
7
|
+
- File permissions set to 0o600 (owner read/write only)
|
|
8
|
+
- Stored in ~/.superqode/auth.json
|
|
9
|
+
- Never logs or exposes key values
|
|
10
|
+
|
|
11
|
+
This is OPTIONAL - SuperQode still supports BYOK (env vars) as primary.
|
|
12
|
+
Local storage is for users who prefer file-based key management.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import logging
|
|
19
|
+
import os
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from datetime import datetime
|
|
22
|
+
from enum import Enum
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any, Dict, Optional, Union
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AuthType(Enum):
|
|
30
|
+
"""Type of authentication credential."""
|
|
31
|
+
|
|
32
|
+
API = "api" # Simple API key
|
|
33
|
+
OAUTH = "oauth" # OAuth with refresh token
|
|
34
|
+
WELLKNOWN = "wellknown" # Well-known auth (key + token pair)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class ApiAuth:
|
|
39
|
+
"""Simple API key authentication."""
|
|
40
|
+
|
|
41
|
+
type: str = "api"
|
|
42
|
+
key: str = ""
|
|
43
|
+
|
|
44
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
45
|
+
return {"type": self.type, "key": self.key}
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ApiAuth":
|
|
49
|
+
return cls(type=data.get("type", "api"), key=data.get("key", ""))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class OAuthAuth:
|
|
54
|
+
"""OAuth authentication with refresh token."""
|
|
55
|
+
|
|
56
|
+
type: str = "oauth"
|
|
57
|
+
refresh: str = ""
|
|
58
|
+
access: str = ""
|
|
59
|
+
expires: int = 0
|
|
60
|
+
account_id: Optional[str] = None
|
|
61
|
+
enterprise_url: Optional[str] = None
|
|
62
|
+
|
|
63
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
64
|
+
result = {
|
|
65
|
+
"type": self.type,
|
|
66
|
+
"refresh": self.refresh,
|
|
67
|
+
"access": self.access,
|
|
68
|
+
"expires": self.expires,
|
|
69
|
+
}
|
|
70
|
+
if self.account_id:
|
|
71
|
+
result["account_id"] = self.account_id
|
|
72
|
+
if self.enterprise_url:
|
|
73
|
+
result["enterprise_url"] = self.enterprise_url
|
|
74
|
+
return result
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_dict(cls, data: Dict[str, Any]) -> "OAuthAuth":
|
|
78
|
+
return cls(
|
|
79
|
+
type=data.get("type", "oauth"),
|
|
80
|
+
refresh=data.get("refresh", ""),
|
|
81
|
+
access=data.get("access", ""),
|
|
82
|
+
expires=data.get("expires", 0),
|
|
83
|
+
account_id=data.get("account_id"),
|
|
84
|
+
enterprise_url=data.get("enterprise_url"),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def is_expired(self) -> bool:
|
|
88
|
+
"""Check if access token is expired."""
|
|
89
|
+
return self.expires > 0 and self.expires < int(datetime.now().timestamp())
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass
|
|
93
|
+
class WellKnownAuth:
|
|
94
|
+
"""Well-known authentication (key + token pair)."""
|
|
95
|
+
|
|
96
|
+
type: str = "wellknown"
|
|
97
|
+
key: str = ""
|
|
98
|
+
token: str = ""
|
|
99
|
+
|
|
100
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
101
|
+
return {"type": self.type, "key": self.key, "token": self.token}
|
|
102
|
+
|
|
103
|
+
@classmethod
|
|
104
|
+
def from_dict(cls, data: Dict[str, Any]) -> "WellKnownAuth":
|
|
105
|
+
return cls(
|
|
106
|
+
type=data.get("type", "wellknown"),
|
|
107
|
+
key=data.get("key", ""),
|
|
108
|
+
token=data.get("token", ""),
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
AuthInfo = Union[ApiAuth, OAuthAuth, WellKnownAuth]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def parse_auth_info(data: Dict[str, Any]) -> Optional[AuthInfo]:
|
|
116
|
+
"""Parse auth info from dict based on type."""
|
|
117
|
+
auth_type = data.get("type")
|
|
118
|
+
if auth_type == "api":
|
|
119
|
+
return ApiAuth.from_dict(data)
|
|
120
|
+
if auth_type == "oauth":
|
|
121
|
+
return OAuthAuth.from_dict(data)
|
|
122
|
+
if auth_type == "wellknown":
|
|
123
|
+
return WellKnownAuth.from_dict(data)
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class LocalAuthStorage:
|
|
128
|
+
"""
|
|
129
|
+
Local storage for API keys and OAuth tokens.
|
|
130
|
+
|
|
131
|
+
Stores credentials in ~/.superqode/auth.json with restricted permissions.
|
|
132
|
+
|
|
133
|
+
Usage:
|
|
134
|
+
auth = LocalAuthStorage()
|
|
135
|
+
|
|
136
|
+
# Set API key
|
|
137
|
+
auth.set("anthropic", ApiAuth(key="sk-..."))
|
|
138
|
+
|
|
139
|
+
# Get credentials
|
|
140
|
+
creds = auth.get("anthropic")
|
|
141
|
+
|
|
142
|
+
# Remove
|
|
143
|
+
auth.remove("anthropic")
|
|
144
|
+
|
|
145
|
+
# List all
|
|
146
|
+
all_creds = auth.all()
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
DEFAULT_PATH = Path.home() / ".superqode" / "auth.json"
|
|
150
|
+
|
|
151
|
+
def __init__(self, filepath: Optional[Path] = None):
|
|
152
|
+
self.filepath = filepath or self.DEFAULT_PATH
|
|
153
|
+
self._ensure_dir()
|
|
154
|
+
|
|
155
|
+
def _ensure_dir(self) -> None:
|
|
156
|
+
"""Ensure parent directory exists with proper permissions."""
|
|
157
|
+
parent = self.filepath.parent
|
|
158
|
+
if not parent.exists():
|
|
159
|
+
parent.mkdir(parents=True, mode=0o700)
|
|
160
|
+
|
|
161
|
+
def _read_file(self) -> Dict[str, Any]:
|
|
162
|
+
"""Read auth file, return empty dict if not exists or invalid."""
|
|
163
|
+
if not self.filepath.exists():
|
|
164
|
+
return {}
|
|
165
|
+
try:
|
|
166
|
+
with open(self.filepath) as f:
|
|
167
|
+
return json.load(f)
|
|
168
|
+
except (json.JSONDecodeError, IOError):
|
|
169
|
+
return {}
|
|
170
|
+
|
|
171
|
+
def _write_file(self, data: Dict[str, Any]) -> None:
|
|
172
|
+
"""Write auth file with secure permissions."""
|
|
173
|
+
# Write to temp file first, then rename (atomic)
|
|
174
|
+
temp_path = self.filepath.with_suffix(".tmp")
|
|
175
|
+
with open(temp_path, "w") as f:
|
|
176
|
+
json.dump(data, f, indent=2)
|
|
177
|
+
|
|
178
|
+
# Set permissions before moving
|
|
179
|
+
os.chmod(temp_path, 0o600)
|
|
180
|
+
|
|
181
|
+
# Atomic rename
|
|
182
|
+
temp_path.rename(self.filepath)
|
|
183
|
+
|
|
184
|
+
def get(self, provider_id: str) -> Optional[AuthInfo]:
|
|
185
|
+
"""Get credentials for a provider."""
|
|
186
|
+
data = self._read_file()
|
|
187
|
+
if provider_id not in data:
|
|
188
|
+
return None
|
|
189
|
+
return parse_auth_info(data[provider_id])
|
|
190
|
+
|
|
191
|
+
def all(self) -> Dict[str, AuthInfo]:
|
|
192
|
+
"""Get all stored credentials."""
|
|
193
|
+
data = self._read_file()
|
|
194
|
+
result: Dict[str, AuthInfo] = {}
|
|
195
|
+
for key, value in data.items():
|
|
196
|
+
if isinstance(value, dict):
|
|
197
|
+
parsed = parse_auth_info(value)
|
|
198
|
+
if parsed:
|
|
199
|
+
result[key] = parsed
|
|
200
|
+
return result
|
|
201
|
+
|
|
202
|
+
def set(self, provider_id: str, info: AuthInfo) -> None:
|
|
203
|
+
"""Set credentials for a provider."""
|
|
204
|
+
data = self._read_file()
|
|
205
|
+
data[provider_id] = info.to_dict()
|
|
206
|
+
self._write_file(data)
|
|
207
|
+
logger.debug(f"Saved auth for {provider_id}")
|
|
208
|
+
|
|
209
|
+
def remove(self, provider_id: str) -> bool:
|
|
210
|
+
"""Remove credentials for a provider. Returns True if removed."""
|
|
211
|
+
data = self._read_file()
|
|
212
|
+
if provider_id not in data:
|
|
213
|
+
return False
|
|
214
|
+
del data[provider_id]
|
|
215
|
+
self._write_file(data)
|
|
216
|
+
logger.debug(f"Removed auth for {provider_id}")
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
def exists(self, provider_id: str) -> bool:
|
|
220
|
+
"""Check if credentials exist for a provider."""
|
|
221
|
+
return provider_id in self._read_file()
|
|
222
|
+
|
|
223
|
+
def clear(self) -> None:
|
|
224
|
+
"""Clear all stored credentials."""
|
|
225
|
+
self._write_file({})
|
|
226
|
+
logger.debug("Cleared all auth")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# Singleton instance
|
|
230
|
+
_storage: Optional[LocalAuthStorage] = None
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def get_storage() -> LocalAuthStorage:
|
|
234
|
+
"""Get the singleton auth storage instance."""
|
|
235
|
+
global _storage
|
|
236
|
+
if _storage is None:
|
|
237
|
+
_storage = LocalAuthStorage()
|
|
238
|
+
return _storage
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# Convenience functions
|
|
242
|
+
def get(provider_id: str) -> Optional[AuthInfo]:
|
|
243
|
+
"""Get credentials for a provider."""
|
|
244
|
+
return get_storage().get(provider_id)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def all() -> Dict[str, AuthInfo]:
|
|
248
|
+
"""Get all stored credentials."""
|
|
249
|
+
return get_storage().all()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def set(provider_id: str, info: AuthInfo) -> None:
|
|
253
|
+
"""Set credentials for a provider."""
|
|
254
|
+
get_storage().set(provider_id, info)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def remove(provider_id: str) -> bool:
|
|
258
|
+
"""Remove credentials for a provider."""
|
|
259
|
+
return get_storage().remove(provider_id)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def exists(provider_id: str) -> bool:
|
|
263
|
+
"""Check if credentials exist for a provider."""
|
|
264
|
+
return get_storage().exists(provider_id)
|
|
@@ -780,136 +780,136 @@ def install_agent(agent_identifier: str) -> int:
|
|
|
780
780
|
)
|
|
781
781
|
return 1
|
|
782
782
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
783
|
+
# Pre-flight checks
|
|
784
|
+
_console.print(f"[bold cyan]🚀 Installing {agent['name']}[/bold cyan]")
|
|
785
|
+
_console.print(f"[dim]{agent.get('description', '')}[/dim]")
|
|
786
|
+
_console.print()
|
|
787
787
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
788
|
+
# Check system dependencies
|
|
789
|
+
deps = check_system_dependencies()
|
|
790
|
+
missing_deps = [dep for dep, available in deps.items() if not available]
|
|
791
|
+
|
|
792
|
+
if missing_deps:
|
|
793
|
+
_console.print("[yellow]⚠️ Missing system dependencies detected:[/yellow]")
|
|
794
|
+
for dep in missing_deps:
|
|
795
|
+
_console.print(f" [red]• {dep}[/red]")
|
|
796
|
+
|
|
797
|
+
# Try to auto-install critical dependencies
|
|
798
|
+
critical_deps = ["uv"] # Add more as needed
|
|
799
|
+
for dep in critical_deps:
|
|
800
|
+
if dep in missing_deps:
|
|
801
|
+
if not install_system_dependency(dep):
|
|
802
|
+
_console.print(
|
|
803
|
+
f"[red]Cannot proceed without {dep}. Please install it manually.[/red]"
|
|
804
|
+
)
|
|
805
|
+
return 1
|
|
806
|
+
|
|
807
|
+
_console.print()
|
|
808
|
+
|
|
809
|
+
# Get the install command for current OS
|
|
810
|
+
install_command = get_os_command(actions, "install")
|
|
811
|
+
if not install_command:
|
|
812
|
+
_console.print("[red]No installation command found for this agent on your OS.[/red]")
|
|
813
|
+
return 1
|
|
791
814
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
for
|
|
795
|
-
|
|
815
|
+
# Check for bootstrap_uv flag
|
|
816
|
+
needs_uv_bootstrap = False
|
|
817
|
+
for os_actions in actions.values():
|
|
818
|
+
if isinstance(os_actions, dict) and os_actions.get("bootstrap_uv", False):
|
|
819
|
+
needs_uv_bootstrap = True
|
|
820
|
+
break
|
|
796
821
|
|
|
797
|
-
#
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
if
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
f"[red]Cannot proceed without {dep}. Please install it manually.[/red]"
|
|
804
|
-
)
|
|
805
|
-
return 1
|
|
822
|
+
# Bootstrap UV if needed
|
|
823
|
+
if needs_uv_bootstrap and not deps.get("uv", False):
|
|
824
|
+
_console.print("[cyan]Bootstrapping UV package manager...[/cyan]")
|
|
825
|
+
if not install_system_dependency("uv"):
|
|
826
|
+
_console.print("[red]UV bootstrap failed. Cannot proceed.[/red]")
|
|
827
|
+
return 1
|
|
806
828
|
|
|
829
|
+
_console.print(f"[green]Installing {agent['name']}...[/green]")
|
|
830
|
+
_console.print(f"[dim]Command: {install_command}[/dim]")
|
|
807
831
|
_console.print()
|
|
808
832
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
# Bootstrap UV if needed
|
|
823
|
-
if needs_uv_bootstrap and not deps.get("uv", False):
|
|
824
|
-
_console.print("[cyan]Bootstrapping UV package manager...[/cyan]")
|
|
825
|
-
if not install_system_dependency("uv"):
|
|
826
|
-
_console.print("[red]UV bootstrap failed. Cannot proceed.[/red]")
|
|
827
|
-
return 1
|
|
828
|
-
|
|
829
|
-
_console.print(f"[green]Installing {agent['name']}...[/green]")
|
|
830
|
-
_console.print(f"[dim]Command: {install_command}[/dim]")
|
|
831
|
-
_console.print()
|
|
833
|
+
# Run the installation command with progress feedback
|
|
834
|
+
try:
|
|
835
|
+
# Use a more interactive approach for long-running installs
|
|
836
|
+
process = subprocess.Popen(
|
|
837
|
+
install_command,
|
|
838
|
+
shell=True,
|
|
839
|
+
stdout=subprocess.PIPE,
|
|
840
|
+
stderr=subprocess.PIPE,
|
|
841
|
+
text=True,
|
|
842
|
+
bufsize=1,
|
|
843
|
+
universal_newlines=True,
|
|
844
|
+
)
|
|
832
845
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
# Use a more interactive approach for long-running installs
|
|
836
|
-
process = subprocess.Popen(
|
|
837
|
-
install_command,
|
|
838
|
-
shell=True,
|
|
839
|
-
stdout=subprocess.PIPE,
|
|
840
|
-
stderr=subprocess.PIPE,
|
|
841
|
-
text=True,
|
|
842
|
-
bufsize=1,
|
|
843
|
-
universal_newlines=True,
|
|
844
|
-
)
|
|
846
|
+
# Show progress
|
|
847
|
+
_console.print("[cyan]Installation in progress...[/cyan]")
|
|
845
848
|
|
|
846
|
-
|
|
847
|
-
|
|
849
|
+
# Wait for completion
|
|
850
|
+
stdout, stderr = process.communicate()
|
|
848
851
|
|
|
849
|
-
|
|
850
|
-
|
|
852
|
+
if process.returncode == 0:
|
|
853
|
+
_console.print("[green]✓ Installation completed successfully![/green]")
|
|
851
854
|
|
|
852
|
-
|
|
853
|
-
|
|
855
|
+
# Verify installation
|
|
856
|
+
if check_agent_installed(agent):
|
|
857
|
+
_console.print(f"[green]✓ Agent '{agent['short_name']}' is ready to use![/green]")
|
|
858
|
+
_console.print(f"[dim]Try: superqode agents connect {agent['short_name']}[/dim]")
|
|
859
|
+
else:
|
|
860
|
+
_console.print("[yellow]⚠️ Agent installed but verification failed[/yellow]")
|
|
861
|
+
_console.print(
|
|
862
|
+
"[dim]You may need to restart your shell or check the installation manually[/dim]"
|
|
863
|
+
)
|
|
854
864
|
|
|
855
|
-
|
|
856
|
-
if check_agent_installed(agent):
|
|
857
|
-
_console.print(f"[green]✓ Agent '{agent['short_name']}' is ready to use![/green]")
|
|
858
|
-
_console.print(f"[dim]Try: superqode agents connect {agent['short_name']}[/dim]")
|
|
865
|
+
return 0
|
|
859
866
|
else:
|
|
860
|
-
_console.print("[
|
|
861
|
-
_console.print(
|
|
862
|
-
f"[dim]You may need to restart your shell or check the installation manually[/dim]"
|
|
863
|
-
)
|
|
867
|
+
_console.print(f"[red]✗ Installation failed (exit code {process.returncode})[/red]")
|
|
864
868
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
_console.print(f"[red]✗ Installation failed (exit code {process.returncode})[/red]")
|
|
869
|
+
# Enhanced error analysis
|
|
870
|
+
error_msg = stderr.lower() if stderr else ""
|
|
868
871
|
|
|
869
|
-
|
|
870
|
-
|
|
872
|
+
if "eacces" in error_msg or "permission denied" in error_msg:
|
|
873
|
+
_console.print("[yellow]💡 Permission Error:[/yellow]")
|
|
874
|
+
_console.print(" This command requires administrator privileges.")
|
|
875
|
+
_console.print(f" Try: [bold]sudo {install_command}[/bold]")
|
|
876
|
+
_console.print(
|
|
877
|
+
" Or use a Node version manager like nvm/fnm for user-space installation"
|
|
878
|
+
)
|
|
879
|
+
elif "command not found" in error_msg or "npm: command not found" in error_msg:
|
|
880
|
+
_console.print("[yellow]💡 Missing npm:[/yellow]")
|
|
881
|
+
_console.print(" Node.js/npm is not installed. Install from:")
|
|
882
|
+
_console.print(" https://nodejs.org/ or use your system package manager")
|
|
883
|
+
elif "uv: command not found" in error_msg:
|
|
884
|
+
_console.print("[yellow]💡 Missing UV:[/yellow]")
|
|
885
|
+
_console.print(" UV package manager is not installed. Install with:")
|
|
886
|
+
_console.print(" curl -LsSf https://astral.sh/uv/install.sh | sh")
|
|
887
|
+
elif "certificate" in error_msg or "ssl" in error_msg:
|
|
888
|
+
_console.print("[yellow]💡 SSL/Certificate Error:[/yellow]")
|
|
889
|
+
_console.print(" There may be network or certificate issues.")
|
|
890
|
+
_console.print(" Try updating your system's CA certificates.")
|
|
891
|
+
else:
|
|
892
|
+
# Show the actual error output
|
|
893
|
+
if stdout.strip():
|
|
894
|
+
_console.print("[dim]Output:[/dim]")
|
|
895
|
+
_console.print(stdout.strip())
|
|
896
|
+
if stderr.strip():
|
|
897
|
+
_console.print("[dim]Error:[/dim]")
|
|
898
|
+
_console.print(stderr.strip())
|
|
871
899
|
|
|
872
|
-
if "eacces" in error_msg or "permission denied" in error_msg:
|
|
873
|
-
_console.print("[yellow]💡 Permission Error:[/yellow]")
|
|
874
|
-
_console.print(" This command requires administrator privileges.")
|
|
875
|
-
_console.print(f" Try: [bold]sudo {install_command}[/bold]")
|
|
876
900
|
_console.print(
|
|
877
|
-
"
|
|
901
|
+
f"\n[dim]💡 Alternative: Try installing manually with: {install_command}[/dim]"
|
|
878
902
|
)
|
|
879
|
-
|
|
880
|
-
_console.print("[yellow]💡 Missing npm:[/yellow]")
|
|
881
|
-
_console.print(" Node.js/npm is not installed. Install from:")
|
|
882
|
-
_console.print(" https://nodejs.org/ or use your system package manager")
|
|
883
|
-
elif "uv: command not found" in error_msg:
|
|
884
|
-
_console.print("[yellow]💡 Missing UV:[/yellow]")
|
|
885
|
-
_console.print(" UV package manager is not installed. Install with:")
|
|
886
|
-
_console.print(" curl -LsSf https://astral.sh/uv/install.sh | sh")
|
|
887
|
-
elif "certificate" in error_msg or "ssl" in error_msg:
|
|
888
|
-
_console.print("[yellow]💡 SSL/Certificate Error:[/yellow]")
|
|
889
|
-
_console.print(" There may be network or certificate issues.")
|
|
890
|
-
_console.print(" Try updating your system's CA certificates.")
|
|
891
|
-
else:
|
|
892
|
-
# Show the actual error output
|
|
893
|
-
if stdout.strip():
|
|
894
|
-
_console.print("[dim]Output:[/dim]")
|
|
895
|
-
_console.print(stdout.strip())
|
|
896
|
-
if stderr.strip():
|
|
897
|
-
_console.print("[dim]Error:[/dim]")
|
|
898
|
-
_console.print(stderr.strip())
|
|
903
|
+
return 1
|
|
899
904
|
|
|
905
|
+
except FileNotFoundError:
|
|
900
906
|
_console.print(
|
|
901
|
-
|
|
907
|
+
"[red]Command not found. Please ensure required dependencies are installed.[/red]"
|
|
902
908
|
)
|
|
903
909
|
return 1
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
f"[red]Command not found. Please ensure required dependencies are installed.[/red]"
|
|
908
|
-
)
|
|
909
|
-
return 1
|
|
910
|
-
except Exception as e:
|
|
911
|
-
_console.print(f"[red]Installation error: {e}[/red]")
|
|
912
|
-
return 1
|
|
910
|
+
except Exception as e:
|
|
911
|
+
_console.print(f"[red]Installation error: {e}[/red]")
|
|
912
|
+
return 1
|
|
913
913
|
|
|
914
914
|
try:
|
|
915
915
|
return asyncio.run(install_agent_async())
|