forgex-cli 0.1.2__tar.gz → 0.1.3__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.
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/PKG-INFO +1 -1
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/__init__.py +1 -1
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/config.py +82 -12
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/.github/workflows/ci.yml +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/.github/workflows/release.yml +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/.gitignore +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/CHANGELOG.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/LICENSE +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/README.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/SECURITY.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/agents.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/architecture.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/configuration.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/decisions.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/providers.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/quickstart.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/sandbox.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/docs/security.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/examples/demo-project/README.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/examples/demo-project/pyproject.toml +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/examples/demo-project/src/demo/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/examples/demo-project/src/demo/calc.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/examples/demo-project/tests/test_calc.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/pyproject.toml +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/__main__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/architect.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/base.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/builder.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/ensemble.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/expert_coder.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/agents/supervisor.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/app.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/build_views.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/build.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/checkpoint.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/context.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/diff.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/do_cmd.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/doctor.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/fix.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/init.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/logs.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/models.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/plan.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/review.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/rollback.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/run.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/status.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/supervise.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/task.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/tools.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/commands/verify.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/context_memory.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/intent.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/progress.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/repl.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/runtime.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/session.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/cli/ui.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/config/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/config/loader.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/config/schema.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/context/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/context/chunker.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/context/dependency_graph.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/context/indexer.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/context/manager.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/context/retriever.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/base.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/capabilities.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/factory.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/groq.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/local.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/openai_compatible.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/registry.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/models/router.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/checkpoints.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/engine.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/events.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/lockfile.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/retry.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/state.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/stores.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/orchestration/workflow.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/project.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/prompts/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/prompts/architect.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/prompts/builder.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/prompts/expert_coder.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/prompts/reviewer.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/prompts/supervisor.md +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/research/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/research/citations.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/research/engine.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/research/sources.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/sandbox/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/sandbox/executor.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/sandbox/permissions.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/sandbox/policies.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/agent.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/checkpoint.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/error.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/event.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/plan.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/project.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/research.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/result.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/schemas/task.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/storage/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/storage/database.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/storage/migrations.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/storage/repositories.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/base.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/dependencies.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/filesystem.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/git.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/project.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/search.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/terminal.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/testing.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/tools/verification.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/utils/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/utils/logging.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/utils/paths.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/src/forgex/utils/redact.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/conftest.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/__init__.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_agents_architect.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_builder_agent.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_checkpoints.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_build.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_checkpoint.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_do.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_models.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_plan.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_review.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_surface.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_task.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_tools.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_cli_verify.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_config.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_config_env.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_config_setup.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_context_agents.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_context_manager.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_context_memory.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_engine.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_ensemble.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_events.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_executor.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_expert_coder.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_fix.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_indexer.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_init.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_intent.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_large_repo.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_offline.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_packaging.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_paths.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_permissions.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_plan_schemas.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_policies.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_project.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_providers.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_recovery.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_redact.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_registry.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_repl.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_research.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_retriever.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_retry.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_router.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_run_cli.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_runtime.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_security.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_session.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_state.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_storage.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_stores.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_supervisor.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_tasks.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_tools_dependencies.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_tools_filesystem.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_tools_git.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_tools_search.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_tools_terminal.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_verification.py +0 -0
- {forgex_cli-0.1.2 → forgex_cli-0.1.3}/tests/unit/test_workflow.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: forgex-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: FORGEX — multi-agent AI software engineering. Plan. Build. Refine. Verify.
|
|
5
5
|
Project-URL: Homepage, https://github.com/B-max12/Forgex
|
|
6
6
|
Project-URL: Repository, https://github.com/B-max12/Forgex
|
|
@@ -145,11 +145,43 @@ def _test_provider_connectivity(provider: str, base_url: str | None, api_key: st
|
|
|
145
145
|
return False, str(exc)
|
|
146
146
|
|
|
147
147
|
|
|
148
|
+
def _strip_quotes(value: str) -> str:
|
|
149
|
+
"""Strip surrounding single or double quotes from user input."""
|
|
150
|
+
v = value.strip()
|
|
151
|
+
if len(v) >= 2 and v[0] == v[-1] and v[0] in ("'", '"'):
|
|
152
|
+
return v[1:-1]
|
|
153
|
+
return v
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _fetch_models(base_url: str, api_key: str | None) -> list[str]:
|
|
157
|
+
"""Fetch the list of available model IDs from an OpenAI-compatible /models endpoint."""
|
|
158
|
+
import httpx
|
|
159
|
+
|
|
160
|
+
url = base_url.rstrip("/") + "/models"
|
|
161
|
+
headers: dict[str, str] = {}
|
|
162
|
+
if api_key:
|
|
163
|
+
headers["Authorization"] = f"Bearer {api_key}"
|
|
164
|
+
try:
|
|
165
|
+
with httpx.Client(timeout=8.0) as client:
|
|
166
|
+
resp = client.get(url, headers=headers)
|
|
167
|
+
if resp.status_code == 200:
|
|
168
|
+
data = resp.json()
|
|
169
|
+
models = data.get("data", [])
|
|
170
|
+
return sorted([m["id"] for m in models if isinstance(m, dict) and "id" in m])
|
|
171
|
+
except Exception:
|
|
172
|
+
pass
|
|
173
|
+
return []
|
|
174
|
+
|
|
175
|
+
|
|
148
176
|
@app.command("setup")
|
|
149
177
|
def setup_command(
|
|
150
178
|
ctx: typer.Context,
|
|
151
179
|
) -> None:
|
|
152
180
|
"""Interactive setup wizard for provider credentials and defaults."""
|
|
181
|
+
from rich.console import Console
|
|
182
|
+
from rich.table import Table
|
|
183
|
+
|
|
184
|
+
console = Console()
|
|
153
185
|
ui = ui_from(ctx)
|
|
154
186
|
ui.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
|
155
187
|
ui.text("FORGEX Configuration Setup Wizard — Welcome!")
|
|
@@ -165,37 +197,74 @@ def setup_command(
|
|
|
165
197
|
base_url = None
|
|
166
198
|
api_key_env: str | None = "FORGEX_GROQ_API_KEY"
|
|
167
199
|
api_key = None
|
|
200
|
+
provider_name = prov
|
|
168
201
|
|
|
169
202
|
if prov == "groq":
|
|
170
203
|
provider_name = "groq"
|
|
171
|
-
|
|
172
|
-
|
|
204
|
+
base_url = "https://api.groq.com/openai/v1"
|
|
205
|
+
api_key = _strip_quotes(Prompt.ask("Enter your Groq API key", password=True, default=""))
|
|
173
206
|
elif prov == "openai":
|
|
174
207
|
provider_name = "openai_compatible"
|
|
175
208
|
api_key_env = "FORGEX_OPENAI_API_KEY"
|
|
176
|
-
|
|
177
|
-
|
|
209
|
+
base_url = "https://api.openai.com/v1"
|
|
210
|
+
api_key = _strip_quotes(Prompt.ask("Enter your OpenAI API key", password=True, default=""))
|
|
178
211
|
elif prov == "local":
|
|
179
212
|
provider_name = "local"
|
|
180
|
-
base_url = Prompt.ask("Enter local OpenAI-compatible endpoint", default="http://localhost:11434/v1")
|
|
213
|
+
base_url = _strip_quotes(Prompt.ask("Enter local OpenAI-compatible endpoint", default="http://localhost:11434/v1"))
|
|
181
214
|
api_key_env = None
|
|
182
|
-
default_model = Prompt.ask("Enter model name", default="llama3.1:8b")
|
|
183
215
|
else:
|
|
184
|
-
provider_name = Prompt.ask("Enter custom provider name", default="custom")
|
|
185
|
-
base_url = Prompt.ask("Enter base URL", default="http://localhost:8080/v1")
|
|
216
|
+
provider_name = _strip_quotes(Prompt.ask("Enter custom provider name", default="custom"))
|
|
217
|
+
base_url = _strip_quotes(Prompt.ask("Enter base URL (no surrounding quotes)", default="http://localhost:8080/v1"))
|
|
186
218
|
api_key_env = f"FORGEX_{provider_name.upper()}_API_KEY"
|
|
187
|
-
api_key = Prompt.ask("Enter API key (if required)", password=True, default="")
|
|
188
|
-
default_model = Prompt.ask("Enter default model", default="qwen2.5:14b")
|
|
219
|
+
api_key = _strip_quotes(Prompt.ask("Enter API key (if required)", password=True, default=""))
|
|
189
220
|
|
|
190
221
|
# Health check verification
|
|
222
|
+
effective_url = base_url or ""
|
|
191
223
|
if api_key or (prov == "local" and base_url):
|
|
192
|
-
ui.text(f"
|
|
224
|
+
ui.text(f"\nTesting connectivity to {provider_name}...")
|
|
193
225
|
ok, detail = _test_provider_connectivity(provider_name, base_url, api_key)
|
|
194
226
|
if ok:
|
|
195
227
|
ui.ok(f"Provider connection verified: {detail}")
|
|
196
228
|
else:
|
|
197
229
|
ui.warn(f"Provider test: {detail} (proceeding; test with `forgex doctor --ping`)")
|
|
198
230
|
|
|
231
|
+
# Fetch and display available models
|
|
232
|
+
default_model = "llama-3.3-70b-versatile" if prov == "groq" else (
|
|
233
|
+
"gpt-4o-mini" if prov == "openai" else "llama3.1:8b"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
if effective_url:
|
|
237
|
+
ui.text(f"\nFetching available models from {provider_name}...")
|
|
238
|
+
available = _fetch_models(effective_url, api_key)
|
|
239
|
+
if available:
|
|
240
|
+
table = Table(title="Available Models", show_header=True, header_style="bold cyan", border_style="dim")
|
|
241
|
+
table.add_column("#", style="dim", width=4)
|
|
242
|
+
table.add_column("Model ID", style="green")
|
|
243
|
+
for i, m in enumerate(available, 1):
|
|
244
|
+
table.add_row(str(i), m)
|
|
245
|
+
console.print(table)
|
|
246
|
+
|
|
247
|
+
choice = Prompt.ask(
|
|
248
|
+
f"Select model (enter number 1-{len(available)} or type a model name)",
|
|
249
|
+
default="1",
|
|
250
|
+
)
|
|
251
|
+
choice = choice.strip()
|
|
252
|
+
try:
|
|
253
|
+
idx = int(choice)
|
|
254
|
+
if 1 <= idx <= len(available):
|
|
255
|
+
default_model = available[idx - 1]
|
|
256
|
+
else:
|
|
257
|
+
default_model = choice
|
|
258
|
+
except ValueError:
|
|
259
|
+
default_model = _strip_quotes(choice)
|
|
260
|
+
|
|
261
|
+
ui.ok(f"Selected model: {default_model}")
|
|
262
|
+
else:
|
|
263
|
+
ui.warn("Could not fetch model list from provider.")
|
|
264
|
+
default_model = _strip_quotes(Prompt.ask("Enter default model name", default=default_model))
|
|
265
|
+
else:
|
|
266
|
+
default_model = _strip_quotes(Prompt.ask("Enter default model name", default=default_model))
|
|
267
|
+
|
|
199
268
|
models = {
|
|
200
269
|
"architect": default_model,
|
|
201
270
|
"builder": default_model,
|
|
@@ -205,7 +274,7 @@ def setup_command(
|
|
|
205
274
|
|
|
206
275
|
if Confirm.ask("Customize models for specific agent roles?", default=False):
|
|
207
276
|
for role in ("architect", "builder", "expert_coder", "supervisor"):
|
|
208
|
-
models[role] = Prompt.ask(f"Model for {role}", default=default_model)
|
|
277
|
+
models[role] = _strip_quotes(Prompt.ask(f"Model for {role}", default=default_model))
|
|
209
278
|
|
|
210
279
|
use_sandbox = Confirm.ask("Enable Docker sandbox for command execution?", default=False)
|
|
211
280
|
mode = Prompt.ask("Approval mode for commands and network", choices=["auto", "ask", "safe"], default="ask")
|
|
@@ -223,3 +292,4 @@ def setup_command(
|
|
|
223
292
|
g_dir = global_config_path().parent
|
|
224
293
|
apply_setup(answers, global_dir=g_dir)
|
|
225
294
|
ui.ok(f"Setup complete! Config written to {g_dir}")
|
|
295
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|