agentforge-py 0.2.2__tar.gz → 0.2.4__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.
- agentforge_py-0.2.4/PKG-INFO +158 -0
- agentforge_py-0.2.4/pyproject.toml +189 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/__init__.py +1 -1
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_tools/decorator.py +9 -1
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/agent.py +10 -1
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/_build.py +109 -12
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/_shared_scaffold.py +3 -1
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/new_cmd.py +59 -2
- agentforge_py-0.2.4/src/agentforge/cli/upgrade_cmd.py +366 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/_base.py +22 -11
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/react.py +17 -2
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/02-add-a-tool.md +5 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_build.py +139 -1
- agentforge_py-0.2.4/tests/unit/test_extras_chain.py +103 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_new_cmd.py +21 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_react_stream.py +23 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_scaffold_state.py +95 -6
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_react.py +28 -0
- agentforge_py-0.2.2/PKG-INFO +0 -158
- agentforge_py-0.2.2/pyproject.toml +0 -187
- agentforge_py-0.2.2/src/agentforge/cli/upgrade_cmd.py +0 -230
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/LICENSE +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_testing/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_testing/fake_llm.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_testing/fake_tool.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_tools/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_tools/calculator.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_tools/file_read.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_tools/shell.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/_tools/web_search.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/auth.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/_scaffold_state.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/config_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/db_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/debug_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/docs_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/eval_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/health_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/list_modules.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/manifest_apply.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/module_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/cli/run_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/config/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/eval/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/eval/consistency.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/eval/coverage.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/eval/format_compliance.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/eval/regression.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/findings.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/guardrails/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/guardrails/allowlist.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/guardrails/capability_check.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/guardrails/engine.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/guardrails/pii_redact_basic.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/guardrails/prompt_injection_basic.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/memory/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/memory/in_memory.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/memory/in_memory_graph.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/memory/in_memory_vector.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/pipeline/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/pipeline/engine.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/pipeline/errors.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/pipeline/tool.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/py.typed +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/recording.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/_defaults.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/markdown.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/patch_applier.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/registry.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/scorecard.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/renderers/span_table.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/replay.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/resolver_register.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/retrieval.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/runtime.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/_plan.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/multi_agent.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/plan_execute.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/strategies/tot.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/.cursorrules +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/.github/copilot-instructions.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/.gitkeep +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/AGENTS.md.tmpl +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/CLAUDE.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/01-set-up-new-agent.md.tmpl +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/03-add-a-pipeline-task.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/04-pick-reasoning-strategy.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/05-write-prompts.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/06-test-your-agent.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/07-debug-a-run.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/08-add-memory.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/09-add-mcp.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/10-add-evaluators.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/11-add-safety-guardrails.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/12-add-observability.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/13-configure-multi-provider.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/14-deploy-your-agent.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/15-upgrade-your-agent.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/16-configuration-reference.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/17-add-reranker.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/18-add-hybrid-search.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/19-add-graphrag.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/20-apply-schema-migrations.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/21-use-streaming-guardrails.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/_shared/docs/runbooks/README.md.tmpl +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/.env.example +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/agentforge.yaml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/copier.yml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/pyproject.toml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/src/{{project_slug.replace('-', '_')}}/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/code-reviewer/src/{{project_slug.replace('-', '_')}}/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/.env.example +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/agentforge.yaml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/copier.yml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/pyproject.toml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/src/{{project_slug.replace('-', '_')}}/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/docs-qa/src/{{project_slug.replace('-', '_')}}/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/.env.example +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/agentforge.yaml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/copier.yml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/pyproject.toml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/src/{{project_slug.replace('-', '_')}}/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/minimal/src/{{project_slug.replace('-', '_')}}/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/.env.example +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/agentforge.yaml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/copier.yml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/pyproject.toml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/src/{{project_slug.replace('-', '_')}}/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/patch-bot/src/{{project_slug.replace('-', '_')}}/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/.env.example +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/agentforge.yaml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/copier.yml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/pyproject.toml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/src/{{project_slug.replace('-', '_')}}/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/research/src/{{project_slug.replace('-', '_')}}/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/.env.example +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/.gitignore +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/README.md +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/agentforge.yaml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/copier.yml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/pyproject.toml +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/src/{{project_slug.replace('-', '_')}}/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/templates/triage/src/{{project_slug.replace('-', '_')}}/main.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/testing/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/testing/conformance.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/testing/factory.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/testing/fixtures.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/testing/llm.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/testing/recording.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/src/agentforge/tools/__init__.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/conftest.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/integration/test_web_search_live.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/.gitkeep +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent_evaluators.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent_fallback_chain.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent_graph_store.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent_hooks.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent_pipeline.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_agent_retriever.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_build_retriever.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_build_pipeline.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_config.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_db.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_debug.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_docs.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_eval.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_health.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_list_modules.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_cli_run.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_config.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_env_bearer_auth.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_eval_consistency.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_eval_coverage.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_eval_format_compliance.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_eval_regression.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_fake_tool.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_findings.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_graph_store_properties.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_guardrails_builtins.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_guardrails_conformance.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_guardrails_engine.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_in_memory_graph_store.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_in_memory_store.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_in_memory_vector_store.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_manifest_apply.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_module_cmd.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_multi_agent_stream.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_pipeline_engine.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_plan.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_plan_execute_stream.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_recording.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_renderer_pipeline_findings.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_renderer_registry.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_renderers_builtin.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_replay.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_retrieval.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_retrieval_rerank.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_retriever_graphrag.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_retriever_hybrid.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_runtime.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_shared_scaffold.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_base.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_budget_properties.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_dispatch_tool.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_multi_agent.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_plan_execute.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_strategies_tot.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_testing_factory.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_testing_fake_llm.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_testing_mock_llm.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_testing_recording.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_three_section_format.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_tool_decorator.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_tools_calculator.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_tools_file_read.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_tools_shell.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_tools_web_search.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_tot_stream.py +0 -0
- {agentforge_py-0.2.2 → agentforge_py-0.2.4}/tests/unit/test_vector_store_properties.py +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentforge-py
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: AgentForge — open-source plug-and-play framework for production AI agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/Scaffoldic/agentforge-py
|
|
6
|
+
Project-URL: Repository, https://github.com/Scaffoldic/agentforge-py
|
|
7
|
+
Project-URL: Documentation, https://github.com/Scaffoldic/agentforge-py
|
|
8
|
+
Project-URL: Changelog, https://github.com/Scaffoldic/agentforge-py/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/Scaffoldic/agentforge-py/issues
|
|
10
|
+
Author: The AgentForge Authors
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agent,agentic,ai,framework,llm,react,tools
|
|
14
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.13
|
|
23
|
+
Requires-Dist: agentforge-core~=0.2.4
|
|
24
|
+
Requires-Dist: copier>=9.4
|
|
25
|
+
Requires-Dist: pydantic>=2.10
|
|
26
|
+
Requires-Dist: pyyaml>=6.0
|
|
27
|
+
Requires-Dist: typer>=0.15
|
|
28
|
+
Provides-Extra: a2a
|
|
29
|
+
Requires-Dist: agentforge-a2a~=0.2.4; extra == 'a2a'
|
|
30
|
+
Provides-Extra: all
|
|
31
|
+
Requires-Dist: agentforge-a2a~=0.2.4; extra == 'all'
|
|
32
|
+
Requires-Dist: agentforge-anthropic[anthropic]~=0.2.4; extra == 'all'
|
|
33
|
+
Requires-Dist: agentforge-bedrock~=0.2.4; extra == 'all'
|
|
34
|
+
Requires-Dist: agentforge-chat-history-postgres~=0.2.4; extra == 'all'
|
|
35
|
+
Requires-Dist: agentforge-chat-history-redis~=0.2.4; extra == 'all'
|
|
36
|
+
Requires-Dist: agentforge-chat-http~=0.2.4; extra == 'all'
|
|
37
|
+
Requires-Dist: agentforge-chat-slack~=0.2.4; extra == 'all'
|
|
38
|
+
Requires-Dist: agentforge-chat~=0.2.4; extra == 'all'
|
|
39
|
+
Requires-Dist: agentforge-eval-geval~=0.2.4; extra == 'all'
|
|
40
|
+
Requires-Dist: agentforge-evidently[evidently]~=0.2.4; extra == 'all'
|
|
41
|
+
Requires-Dist: agentforge-guard-llamaguard~=0.2.4; extra == 'all'
|
|
42
|
+
Requires-Dist: agentforge-guard-llmguard~=0.2.4; extra == 'all'
|
|
43
|
+
Requires-Dist: agentforge-guard-nemo~=0.2.4; extra == 'all'
|
|
44
|
+
Requires-Dist: agentforge-guard-presidio~=0.2.4; extra == 'all'
|
|
45
|
+
Requires-Dist: agentforge-langfuse[langfuse]~=0.2.4; extra == 'all'
|
|
46
|
+
Requires-Dist: agentforge-litellm[litellm]~=0.2.4; extra == 'all'
|
|
47
|
+
Requires-Dist: agentforge-mcp[mcp]~=0.2.4; extra == 'all'
|
|
48
|
+
Requires-Dist: agentforge-memory-neo4j~=0.2.4; extra == 'all'
|
|
49
|
+
Requires-Dist: agentforge-memory-postgres~=0.2.4; extra == 'all'
|
|
50
|
+
Requires-Dist: agentforge-memory-sqlite~=0.2.4; extra == 'all'
|
|
51
|
+
Requires-Dist: agentforge-memory-surrealdb~=0.2.4; extra == 'all'
|
|
52
|
+
Requires-Dist: agentforge-ollama[ollama]~=0.2.4; extra == 'all'
|
|
53
|
+
Requires-Dist: agentforge-openai[openai]~=0.2.4; extra == 'all'
|
|
54
|
+
Requires-Dist: agentforge-otel~=0.2.4; extra == 'all'
|
|
55
|
+
Requires-Dist: agentforge-phoenix[phoenix]~=0.2.4; extra == 'all'
|
|
56
|
+
Requires-Dist: agentforge-reranker-cohere[cohere]~=0.2.4; extra == 'all'
|
|
57
|
+
Requires-Dist: agentforge-reranker-mixedbread[mixedbread]~=0.2.4; extra == 'all'
|
|
58
|
+
Requires-Dist: agentforge-reranker-sentence-transformers[sentence-transformers]~=0.2.4; extra == 'all'
|
|
59
|
+
Requires-Dist: agentforge-reranker-voyage[voyage]~=0.2.4; extra == 'all'
|
|
60
|
+
Requires-Dist: agentforge-statsd[statsd]~=0.2.4; extra == 'all'
|
|
61
|
+
Requires-Dist: agentforge-testing~=0.2.4; extra == 'all'
|
|
62
|
+
Requires-Dist: agentforge-voyage[voyage]~=0.2.4; extra == 'all'
|
|
63
|
+
Provides-Extra: anthropic
|
|
64
|
+
Requires-Dist: agentforge-anthropic[anthropic]~=0.2.4; extra == 'anthropic'
|
|
65
|
+
Provides-Extra: bedrock
|
|
66
|
+
Requires-Dist: agentforge-bedrock~=0.2.4; extra == 'bedrock'
|
|
67
|
+
Provides-Extra: chat
|
|
68
|
+
Requires-Dist: agentforge-chat~=0.2.4; extra == 'chat'
|
|
69
|
+
Provides-Extra: chat-history-postgres
|
|
70
|
+
Requires-Dist: agentforge-chat-history-postgres~=0.2.4; extra == 'chat-history-postgres'
|
|
71
|
+
Provides-Extra: chat-history-redis
|
|
72
|
+
Requires-Dist: agentforge-chat-history-redis~=0.2.4; extra == 'chat-history-redis'
|
|
73
|
+
Provides-Extra: chat-http
|
|
74
|
+
Requires-Dist: agentforge-chat-http~=0.2.4; extra == 'chat-http'
|
|
75
|
+
Provides-Extra: chat-slack
|
|
76
|
+
Requires-Dist: agentforge-chat-slack~=0.2.4; extra == 'chat-slack'
|
|
77
|
+
Provides-Extra: eval
|
|
78
|
+
Requires-Dist: agentforge-eval-geval~=0.2.4; extra == 'eval'
|
|
79
|
+
Provides-Extra: evidently
|
|
80
|
+
Requires-Dist: agentforge-evidently[evidently]~=0.2.4; extra == 'evidently'
|
|
81
|
+
Provides-Extra: guard-llamaguard
|
|
82
|
+
Requires-Dist: agentforge-guard-llamaguard~=0.2.4; extra == 'guard-llamaguard'
|
|
83
|
+
Provides-Extra: guard-llmguard
|
|
84
|
+
Requires-Dist: agentforge-guard-llmguard~=0.2.4; extra == 'guard-llmguard'
|
|
85
|
+
Provides-Extra: guard-nemo
|
|
86
|
+
Requires-Dist: agentforge-guard-nemo~=0.2.4; extra == 'guard-nemo'
|
|
87
|
+
Provides-Extra: guard-presidio
|
|
88
|
+
Requires-Dist: agentforge-guard-presidio~=0.2.4; extra == 'guard-presidio'
|
|
89
|
+
Provides-Extra: langfuse
|
|
90
|
+
Requires-Dist: agentforge-langfuse[langfuse]~=0.2.4; extra == 'langfuse'
|
|
91
|
+
Provides-Extra: litellm
|
|
92
|
+
Requires-Dist: agentforge-litellm[litellm]~=0.2.4; extra == 'litellm'
|
|
93
|
+
Provides-Extra: mcp
|
|
94
|
+
Requires-Dist: agentforge-mcp[mcp]~=0.2.4; extra == 'mcp'
|
|
95
|
+
Provides-Extra: memory-neo4j
|
|
96
|
+
Requires-Dist: agentforge-memory-neo4j~=0.2.4; extra == 'memory-neo4j'
|
|
97
|
+
Provides-Extra: memory-postgres
|
|
98
|
+
Requires-Dist: agentforge-memory-postgres~=0.2.4; extra == 'memory-postgres'
|
|
99
|
+
Provides-Extra: memory-sqlite
|
|
100
|
+
Requires-Dist: agentforge-memory-sqlite~=0.2.4; extra == 'memory-sqlite'
|
|
101
|
+
Provides-Extra: memory-surrealdb
|
|
102
|
+
Requires-Dist: agentforge-memory-surrealdb~=0.2.4; extra == 'memory-surrealdb'
|
|
103
|
+
Provides-Extra: ollama
|
|
104
|
+
Requires-Dist: agentforge-ollama[ollama]~=0.2.4; extra == 'ollama'
|
|
105
|
+
Provides-Extra: openai
|
|
106
|
+
Requires-Dist: agentforge-openai[openai]~=0.2.4; extra == 'openai'
|
|
107
|
+
Provides-Extra: otel
|
|
108
|
+
Requires-Dist: agentforge-otel~=0.2.4; extra == 'otel'
|
|
109
|
+
Provides-Extra: phoenix
|
|
110
|
+
Requires-Dist: agentforge-phoenix[phoenix]~=0.2.4; extra == 'phoenix'
|
|
111
|
+
Provides-Extra: reranker-cohere
|
|
112
|
+
Requires-Dist: agentforge-reranker-cohere[cohere]~=0.2.4; extra == 'reranker-cohere'
|
|
113
|
+
Provides-Extra: reranker-mixedbread
|
|
114
|
+
Requires-Dist: agentforge-reranker-mixedbread[mixedbread]~=0.2.4; extra == 'reranker-mixedbread'
|
|
115
|
+
Provides-Extra: reranker-sentence-transformers
|
|
116
|
+
Requires-Dist: agentforge-reranker-sentence-transformers[sentence-transformers]~=0.2.4; extra == 'reranker-sentence-transformers'
|
|
117
|
+
Provides-Extra: reranker-voyage
|
|
118
|
+
Requires-Dist: agentforge-reranker-voyage[voyage]~=0.2.4; extra == 'reranker-voyage'
|
|
119
|
+
Provides-Extra: statsd
|
|
120
|
+
Requires-Dist: agentforge-statsd[statsd]~=0.2.4; extra == 'statsd'
|
|
121
|
+
Provides-Extra: testing
|
|
122
|
+
Requires-Dist: agentforge-testing~=0.2.4; extra == 'testing'
|
|
123
|
+
Provides-Extra: voyage
|
|
124
|
+
Requires-Dist: agentforge-voyage[voyage]~=0.2.4; extra == 'voyage'
|
|
125
|
+
Description-Content-Type: text/markdown
|
|
126
|
+
|
|
127
|
+
# agentforge
|
|
128
|
+
|
|
129
|
+
The default runtime for the AgentForge framework — `Agent`, `ReActLoop`,
|
|
130
|
+
default tools, `SimpleFinding`, in-memory store, basic safety defaults,
|
|
131
|
+
`BudgetPolicy`. Most users install this package and add module extras
|
|
132
|
+
as needed.
|
|
133
|
+
|
|
134
|
+
## Three-line agent (once feat-001 lands)
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from agentforge import Agent
|
|
138
|
+
|
|
139
|
+
agent = Agent(model="anthropic:claude-sonnet-4.7")
|
|
140
|
+
result = await agent.run("Say hello in three words.")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Install
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install agentforge-py # core runtime
|
|
147
|
+
pip install "agentforge-py[anthropic]" # + Anthropic provider
|
|
148
|
+
pip install "agentforge-py[anthropic,memory-postgres]" # + persistence
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Status
|
|
152
|
+
|
|
153
|
+
v0.0 — pre-alpha. Repo bootstrapped; feat-001 (Core contracts &
|
|
154
|
+
`Agent` orchestrator) is the next milestone.
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
Apache 2.0.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# agentforge — default runtime + prebuilt for the AgentForge framework.
|
|
2
|
+
#
|
|
3
|
+
# This package ships the sane defaults a developer expects on a fresh
|
|
4
|
+
# install: the `Agent` orchestrator, `ReActLoop` (stable reasoning
|
|
5
|
+
# strategy), the four built-in tools, the `SimpleFinding` variant +
|
|
6
|
+
# scorecard renderer, the in-memory MemoryStore, the basic safety
|
|
7
|
+
# defaults, and the BudgetPolicy.
|
|
8
|
+
#
|
|
9
|
+
# This package depends on `agentforge-core` (locked contracts) and
|
|
10
|
+
# nothing else from the AgentForge family. Optional extras pull in
|
|
11
|
+
# specific provider/persistence/observability modules.
|
|
12
|
+
#
|
|
13
|
+
# Per ADR-0003 (three-tier package model — this is Tier 2).
|
|
14
|
+
|
|
15
|
+
[project]
|
|
16
|
+
name = "agentforge-py"
|
|
17
|
+
version = "0.2.4"
|
|
18
|
+
description = "AgentForge — open-source plug-and-play framework for production AI agents"
|
|
19
|
+
readme = "README.md"
|
|
20
|
+
requires-python = ">=3.13"
|
|
21
|
+
license = "Apache-2.0"
|
|
22
|
+
license-files = ["LICENSE"]
|
|
23
|
+
authors = [
|
|
24
|
+
{name = "The AgentForge Authors"},
|
|
25
|
+
]
|
|
26
|
+
keywords = ["ai", "agent", "llm", "framework", "agentic", "react", "tools"]
|
|
27
|
+
classifiers = [
|
|
28
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
29
|
+
"Intended Audience :: Developers",
|
|
30
|
+
"License :: OSI Approved :: Apache Software License",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
34
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
35
|
+
"Typing :: Typed",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
dependencies = [
|
|
39
|
+
"agentforge-core ~= 0.2.4",
|
|
40
|
+
"pydantic>=2.10",
|
|
41
|
+
"pyyaml>=6.0",
|
|
42
|
+
"typer>=0.15",
|
|
43
|
+
# feat-011: Copier is the scaffolding + three-way-merge engine
|
|
44
|
+
# (ADR-0005). Used by `agentforge new` / `agentforge upgrade`.
|
|
45
|
+
"copier>=9.4",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
# Optional extras — names match the underlying provider/module package.
|
|
49
|
+
# Adding a module via `pip install "agentforge[<name>]"` pulls the
|
|
50
|
+
# corresponding package onto the path; entry-point discovery does the
|
|
51
|
+
# rest (per ADR-0004).
|
|
52
|
+
[project.optional-dependencies]
|
|
53
|
+
# Each extra installs one sister package at the matching coordinated
|
|
54
|
+
# release-train version. `pip install agentforge-py[anthropic]`
|
|
55
|
+
# resolves to `agentforge-py + agentforge-anthropic`, etc.
|
|
56
|
+
# Add a new entry here every time a new sister package ships.
|
|
57
|
+
|
|
58
|
+
# LLM providers. Where a sister package keeps its vendor SDK behind
|
|
59
|
+
# an optional `[<sdk>]` extra (the lazy-import pattern), the meta extra
|
|
60
|
+
# MUST chain that extra — otherwise `pip install "agentforge-py[x]"`
|
|
61
|
+
# installs the wrapper but not the SDK and the first call raises a
|
|
62
|
+
# ModuleError (bug-015). bedrock hard-deps its SDK (aioboto3/botocore),
|
|
63
|
+
# so it requests no extra — and must NOT request a phantom `[bedrock]`.
|
|
64
|
+
anthropic = ["agentforge-anthropic[anthropic] ~= 0.2.4"]
|
|
65
|
+
openai = ["agentforge-openai[openai] ~= 0.2.4"]
|
|
66
|
+
bedrock = ["agentforge-bedrock ~= 0.2.4"]
|
|
67
|
+
ollama = ["agentforge-ollama[ollama] ~= 0.2.4"]
|
|
68
|
+
litellm = ["agentforge-litellm[litellm] ~= 0.2.4"]
|
|
69
|
+
|
|
70
|
+
# Embeddings
|
|
71
|
+
voyage = ["agentforge-voyage[voyage] ~= 0.2.4"]
|
|
72
|
+
|
|
73
|
+
# Memory backends (each hard-deps its driver SDK — no extra to chain)
|
|
74
|
+
memory-sqlite = ["agentforge-memory-sqlite ~= 0.2.4"]
|
|
75
|
+
memory-postgres = ["agentforge-memory-postgres ~= 0.2.4"]
|
|
76
|
+
memory-neo4j = ["agentforge-memory-neo4j ~= 0.2.4"]
|
|
77
|
+
memory-surrealdb = ["agentforge-memory-surrealdb ~= 0.2.4"]
|
|
78
|
+
|
|
79
|
+
# Chat surface (chat hard-deps aiosqlite; history backends hard-dep their SDK)
|
|
80
|
+
chat = ["agentforge-chat ~= 0.2.4"]
|
|
81
|
+
chat-http = ["agentforge-chat-http ~= 0.2.4"]
|
|
82
|
+
chat-slack = ["agentforge-chat-slack ~= 0.2.4"]
|
|
83
|
+
chat-history-postgres = ["agentforge-chat-history-postgres ~= 0.2.4"]
|
|
84
|
+
chat-history-redis = ["agentforge-chat-history-redis ~= 0.2.4"]
|
|
85
|
+
|
|
86
|
+
# Rerankers
|
|
87
|
+
reranker-cohere = ["agentforge-reranker-cohere[cohere] ~= 0.2.4"]
|
|
88
|
+
reranker-voyage = ["agentforge-reranker-voyage[voyage] ~= 0.2.4"]
|
|
89
|
+
reranker-mixedbread = ["agentforge-reranker-mixedbread[mixedbread] ~= 0.2.4"]
|
|
90
|
+
reranker-sentence-transformers = ["agentforge-reranker-sentence-transformers[sentence-transformers] ~= 0.2.4"]
|
|
91
|
+
|
|
92
|
+
# Guardrails (each hard-deps its SDK — no extra to chain)
|
|
93
|
+
guard-llmguard = ["agentforge-guard-llmguard ~= 0.2.4"]
|
|
94
|
+
guard-presidio = ["agentforge-guard-presidio ~= 0.2.4"]
|
|
95
|
+
guard-nemo = ["agentforge-guard-nemo ~= 0.2.4"]
|
|
96
|
+
guard-llamaguard = ["agentforge-guard-llamaguard ~= 0.2.4"]
|
|
97
|
+
|
|
98
|
+
# Observability
|
|
99
|
+
langfuse = ["agentforge-langfuse[langfuse] ~= 0.2.4"]
|
|
100
|
+
phoenix = ["agentforge-phoenix[phoenix] ~= 0.2.4"]
|
|
101
|
+
otel = ["agentforge-otel ~= 0.2.4"]
|
|
102
|
+
statsd = ["agentforge-statsd[statsd] ~= 0.2.4"]
|
|
103
|
+
evidently = ["agentforge-evidently[evidently] ~= 0.2.4"]
|
|
104
|
+
|
|
105
|
+
# Protocols
|
|
106
|
+
mcp = ["agentforge-mcp[mcp] ~= 0.2.4"]
|
|
107
|
+
a2a = ["agentforge-a2a ~= 0.2.4"]
|
|
108
|
+
|
|
109
|
+
# Eval
|
|
110
|
+
eval = ["agentforge-eval-geval ~= 0.2.4"]
|
|
111
|
+
|
|
112
|
+
# Testing
|
|
113
|
+
testing = ["agentforge-testing ~= 0.2.4"]
|
|
114
|
+
|
|
115
|
+
# Everything (development / docs / smoke-test convenience — not
|
|
116
|
+
# recommended for production deploys; pick the actual integrations
|
|
117
|
+
# you use to keep the dependency tree small). Vendor-SDK extras are
|
|
118
|
+
# chained here too so `[all]` actually installs every SDK.
|
|
119
|
+
all = [
|
|
120
|
+
"agentforge-anthropic[anthropic] ~= 0.2.4",
|
|
121
|
+
"agentforge-openai[openai] ~= 0.2.4",
|
|
122
|
+
"agentforge-bedrock ~= 0.2.4",
|
|
123
|
+
"agentforge-ollama[ollama] ~= 0.2.4",
|
|
124
|
+
"agentforge-litellm[litellm] ~= 0.2.4",
|
|
125
|
+
"agentforge-voyage[voyage] ~= 0.2.4",
|
|
126
|
+
"agentforge-memory-sqlite ~= 0.2.4",
|
|
127
|
+
"agentforge-memory-postgres ~= 0.2.4",
|
|
128
|
+
"agentforge-memory-neo4j ~= 0.2.4",
|
|
129
|
+
"agentforge-memory-surrealdb ~= 0.2.4",
|
|
130
|
+
"agentforge-chat ~= 0.2.4",
|
|
131
|
+
"agentforge-chat-http ~= 0.2.4",
|
|
132
|
+
"agentforge-chat-slack ~= 0.2.4",
|
|
133
|
+
"agentforge-chat-history-postgres ~= 0.2.4",
|
|
134
|
+
"agentforge-chat-history-redis ~= 0.2.4",
|
|
135
|
+
"agentforge-reranker-cohere[cohere] ~= 0.2.4",
|
|
136
|
+
"agentforge-reranker-voyage[voyage] ~= 0.2.4",
|
|
137
|
+
"agentforge-reranker-mixedbread[mixedbread] ~= 0.2.4",
|
|
138
|
+
"agentforge-reranker-sentence-transformers[sentence-transformers] ~= 0.2.4",
|
|
139
|
+
"agentforge-guard-llmguard ~= 0.2.4",
|
|
140
|
+
"agentforge-guard-presidio ~= 0.2.4",
|
|
141
|
+
"agentforge-guard-nemo ~= 0.2.4",
|
|
142
|
+
"agentforge-guard-llamaguard ~= 0.2.4",
|
|
143
|
+
"agentforge-langfuse[langfuse] ~= 0.2.4",
|
|
144
|
+
"agentforge-phoenix[phoenix] ~= 0.2.4",
|
|
145
|
+
"agentforge-otel ~= 0.2.4",
|
|
146
|
+
"agentforge-statsd[statsd] ~= 0.2.4",
|
|
147
|
+
"agentforge-evidently[evidently] ~= 0.2.4",
|
|
148
|
+
"agentforge-mcp[mcp] ~= 0.2.4",
|
|
149
|
+
"agentforge-a2a ~= 0.2.4",
|
|
150
|
+
"agentforge-eval-geval ~= 0.2.4",
|
|
151
|
+
"agentforge-testing ~= 0.2.4",
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
[project.scripts]
|
|
155
|
+
# feat-010 ships the read-only `list` command. Destructive commands
|
|
156
|
+
# (`add`, `swap`, `remove`) ship in a follow-up sub-feat alongside
|
|
157
|
+
# feat-012 (Configuration system).
|
|
158
|
+
agentforge = "agentforge.cli.main:main"
|
|
159
|
+
|
|
160
|
+
[project.urls]
|
|
161
|
+
Homepage = "https://github.com/Scaffoldic/agentforge-py"
|
|
162
|
+
Repository = "https://github.com/Scaffoldic/agentforge-py"
|
|
163
|
+
Documentation = "https://github.com/Scaffoldic/agentforge-py"
|
|
164
|
+
Changelog = "https://github.com/Scaffoldic/agentforge-py/blob/main/CHANGELOG.md"
|
|
165
|
+
Issues = "https://github.com/Scaffoldic/agentforge-py/issues"
|
|
166
|
+
|
|
167
|
+
[tool.uv.sources]
|
|
168
|
+
agentforge-core = { workspace = true }
|
|
169
|
+
|
|
170
|
+
[build-system]
|
|
171
|
+
requires = ["hatchling>=1.27"]
|
|
172
|
+
build-backend = "hatchling.build"
|
|
173
|
+
|
|
174
|
+
[tool.hatch.build.targets.wheel]
|
|
175
|
+
packages = ["src/agentforge"]
|
|
176
|
+
# feat-011: ship Copier templates inside the wheel. The
|
|
177
|
+
# `{{project_slug}}/` subdir is auto-included via the `packages`
|
|
178
|
+
# directive — hatchling walks all files under src/agentforge,
|
|
179
|
+
# including the Jinja2-named subdirs. Do NOT add a force-include
|
|
180
|
+
# for templates: it duplicates every entry and PyPI rejects the
|
|
181
|
+
# wheel with "Duplicate filename in local headers".
|
|
182
|
+
|
|
183
|
+
[tool.hatch.build.targets.sdist]
|
|
184
|
+
include = [
|
|
185
|
+
"src/agentforge",
|
|
186
|
+
"tests",
|
|
187
|
+
"README.md",
|
|
188
|
+
"LICENSE",
|
|
189
|
+
]
|
|
@@ -20,7 +20,15 @@ Wraps a typed function as a concrete `Tool` subclass:
|
|
|
20
20
|
The decorator inspects the wrapped function and constructs:
|
|
21
21
|
|
|
22
22
|
- `name` from the function's `__name__` (or the
|
|
23
|
-
`name=` override argument).
|
|
23
|
+
`name=` override argument). Keep it within
|
|
24
|
+
`[a-zA-Z0-9_-]` (1-64 chars): that's the
|
|
25
|
+
tool-name charset Bedrock, OpenAI, and
|
|
26
|
+
Anthropic all enforce, so a name outside it
|
|
27
|
+
is rejected at request-build time with
|
|
28
|
+
`ToolNameInvalidError` (bug-017). A plain
|
|
29
|
+
function name like `lookup_user` is already
|
|
30
|
+
legal; avoid dots / colons / spaces in
|
|
31
|
+
`name=` overrides.
|
|
24
32
|
- `description` from the docstring's summary line + Args
|
|
25
33
|
section, parsed Google-style. The first
|
|
26
34
|
non-blank non-arg line is the summary;
|
|
@@ -22,7 +22,7 @@ from __future__ import annotations
|
|
|
22
22
|
|
|
23
23
|
import logging
|
|
24
24
|
import time
|
|
25
|
-
from collections.abc import AsyncIterator, Awaitable, Callable
|
|
25
|
+
from collections.abc import AsyncIterator, Awaitable, Callable, Sequence
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from types import TracebackType
|
|
28
28
|
from typing import Any
|
|
@@ -37,6 +37,7 @@ from agentforge_core.contracts.guardrails import (
|
|
|
37
37
|
)
|
|
38
38
|
from agentforge_core.contracts.llm import LLMClient
|
|
39
39
|
from agentforge_core.contracts.memory import MemoryStore
|
|
40
|
+
from agentforge_core.contracts.protocol_bridge import ProtocolBridge
|
|
40
41
|
from agentforge_core.contracts.strategy import ReasoningStrategy
|
|
41
42
|
from agentforge_core.contracts.tool import Tool
|
|
42
43
|
from agentforge_core.observability import get_tracer
|
|
@@ -119,6 +120,7 @@ class Agent:
|
|
|
119
120
|
tool_gates: list[ToolCallGate] | None = None,
|
|
120
121
|
guardrail_policy: GuardrailPolicy | None = None,
|
|
121
122
|
pipeline: Pipeline | None = None,
|
|
123
|
+
protocol_bridges: Sequence[ProtocolBridge] | None = None,
|
|
122
124
|
) -> None:
|
|
123
125
|
self._config: AgentForgeConfig = load_config(config_path)
|
|
124
126
|
|
|
@@ -198,6 +200,11 @@ class Agent:
|
|
|
198
200
|
self._pipeline_tool = PipelineFindingsTool()
|
|
199
201
|
self._tools.append(self._pipeline_tool)
|
|
200
202
|
|
|
203
|
+
# feat-013: protocol handlers (e.g. MCP bridges) already started
|
|
204
|
+
# by the config builder. Their tools are passed in via `tools=`;
|
|
205
|
+
# the Agent only owns tearing them down on `close()`.
|
|
206
|
+
self._protocol_bridges: list[ProtocolBridge] = list(protocol_bridges or [])
|
|
207
|
+
|
|
201
208
|
self._closed = False
|
|
202
209
|
|
|
203
210
|
if install_log_filter and self._config.logging.run_id_filter:
|
|
@@ -677,6 +684,8 @@ class Agent:
|
|
|
677
684
|
await self._memory.close()
|
|
678
685
|
if self._graph_store is not None:
|
|
679
686
|
await self._graph_store.close()
|
|
687
|
+
for bridge in self._protocol_bridges:
|
|
688
|
+
await bridge.close()
|
|
680
689
|
uninstall_run_id_filter()
|
|
681
690
|
uninstall_json_formatter()
|
|
682
691
|
|
|
@@ -20,6 +20,7 @@ deterministic exit codes (per feat-017 §4 — config invalid → 2).
|
|
|
20
20
|
|
|
21
21
|
from __future__ import annotations
|
|
22
22
|
|
|
23
|
+
import contextlib
|
|
23
24
|
from pathlib import Path
|
|
24
25
|
from typing import TYPE_CHECKING, Any
|
|
25
26
|
|
|
@@ -30,6 +31,7 @@ from agentforge_core.contracts.evaluator import Evaluator
|
|
|
30
31
|
from agentforge_core.contracts.graph_store import GraphStore
|
|
31
32
|
from agentforge_core.contracts.llm import LLMClient
|
|
32
33
|
from agentforge_core.contracts.memory import MemoryStore
|
|
34
|
+
from agentforge_core.contracts.protocol_bridge import ProtocolBridge
|
|
33
35
|
from agentforge_core.contracts.reranker import Reranker
|
|
34
36
|
from agentforge_core.contracts.vector_store import VectorStore
|
|
35
37
|
from agentforge_core.production.exceptions import ModuleError
|
|
@@ -82,18 +84,35 @@ async def build_agent_from_config(
|
|
|
82
84
|
llm = _resolve_llm(config)
|
|
83
85
|
strategy = config.agent.strategy if isinstance(config.agent.strategy, str) else None
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
# feat-013 (bug-020): wire `modules.protocols` — resolve + start each
|
|
88
|
+
# handler (e.g. the MCP bridge), merge its tools with the native
|
|
89
|
+
# `agent.tools`, and hand the started bridges to the Agent so they're
|
|
90
|
+
# closed on `Agent.close()`. `build_protocols_from_config` has already
|
|
91
|
+
# awaited `start()` for every bridge it returns.
|
|
92
|
+
native_tools = build_tools_from_config(config)
|
|
93
|
+
mcp_tools, protocol_bridges = await build_protocols_from_config(config)
|
|
94
|
+
all_tools = [*native_tools, *mcp_tools]
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
return Agent(
|
|
98
|
+
model=llm,
|
|
99
|
+
tools=all_tools or None,
|
|
100
|
+
memory=memory if memory is not None else InMemoryStore(),
|
|
101
|
+
evaluators=evaluators,
|
|
102
|
+
strategy=strategy,
|
|
103
|
+
retriever=retriever,
|
|
104
|
+
system_prompt=config.agent.system_prompt,
|
|
105
|
+
budget_usd=config.agent.budget.usd,
|
|
106
|
+
max_iterations=config.agent.max_iterations,
|
|
107
|
+
record_runs=memory if enable_recording and memory is not None else None,
|
|
108
|
+
pipeline=pipeline,
|
|
109
|
+
protocol_bridges=protocol_bridges,
|
|
110
|
+
)
|
|
111
|
+
except BaseException:
|
|
112
|
+
# Agent construction failed after bridges were started — don't
|
|
113
|
+
# leak the open transports / spawned subprocesses.
|
|
114
|
+
await _close_bridges(protocol_bridges)
|
|
115
|
+
raise
|
|
97
116
|
|
|
98
117
|
|
|
99
118
|
def build_memory_from_config(config: AgentForgeConfig) -> MemoryStore | None:
|
|
@@ -259,6 +278,83 @@ def build_tools_from_config(config: AgentForgeConfig) -> list[Tool]:
|
|
|
259
278
|
return tools
|
|
260
279
|
|
|
261
280
|
|
|
281
|
+
async def build_protocols_from_config(
|
|
282
|
+
config: AgentForgeConfig,
|
|
283
|
+
) -> tuple[list[Tool], list[ProtocolBridge]]:
|
|
284
|
+
"""Resolve + start every `modules.protocols` handler (feat-013).
|
|
285
|
+
|
|
286
|
+
For each entry: resolve its name under the ``protocols`` resolver
|
|
287
|
+
category, build the handler via its ``from_config(config)``
|
|
288
|
+
classmethod, ``await start()`` to open connections and discover
|
|
289
|
+
tools, then collect the merged tool list. The started bridges are
|
|
290
|
+
returned so the caller can ``close()`` them on agent teardown.
|
|
291
|
+
|
|
292
|
+
Returns an empty ``([], [])`` when no protocols are configured.
|
|
293
|
+
|
|
294
|
+
Raises:
|
|
295
|
+
ModuleError: a protocol isn't registered, lacks a
|
|
296
|
+
``from_config`` classmethod, doesn't implement
|
|
297
|
+
`ProtocolBridge`, or requests server-side ``expose`` (not
|
|
298
|
+
wired into the runtime yet — see `_reject_unsupported_expose`).
|
|
299
|
+
"""
|
|
300
|
+
from agentforge_core.contracts.tool import Tool as ToolBase # noqa: PLC0415
|
|
301
|
+
|
|
302
|
+
tools: list[ToolBase] = []
|
|
303
|
+
bridges: list[ProtocolBridge] = []
|
|
304
|
+
for entry in config.modules.protocols:
|
|
305
|
+
_reject_unsupported_expose(entry.name, entry.config)
|
|
306
|
+
cls = _resolve_class("protocols", entry.name)
|
|
307
|
+
from_config = getattr(cls, "from_config", None)
|
|
308
|
+
if not callable(from_config):
|
|
309
|
+
msg = (
|
|
310
|
+
f"Resolved protocol {entry.name!r} ({cls.__name__}) has no "
|
|
311
|
+
f"from_config(config) classmethod."
|
|
312
|
+
)
|
|
313
|
+
raise ModuleError(msg)
|
|
314
|
+
bridge = from_config(entry.config)
|
|
315
|
+
if not isinstance(bridge, ProtocolBridge):
|
|
316
|
+
msg = (
|
|
317
|
+
f"Resolved protocol {entry.name!r} ({cls.__name__}) does not "
|
|
318
|
+
f"implement ProtocolBridge (needs tools / start / close)."
|
|
319
|
+
)
|
|
320
|
+
raise ModuleError(msg)
|
|
321
|
+
try:
|
|
322
|
+
await bridge.start()
|
|
323
|
+
except BaseException:
|
|
324
|
+
# A later bridge failing must not leak earlier ones.
|
|
325
|
+
await _close_bridges(bridges)
|
|
326
|
+
raise
|
|
327
|
+
bridges.append(bridge)
|
|
328
|
+
tools.extend(bridge.tools)
|
|
329
|
+
return tools, bridges
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _reject_unsupported_expose(name: str, cfg: dict[str, Any]) -> None:
|
|
333
|
+
"""Fail loud on server-side `expose`, which the runtime can't wire yet.
|
|
334
|
+
|
|
335
|
+
Auto-serving an MCP server from inside the agent process would hijack
|
|
336
|
+
the process's stdio. Consume-only is supported; expose runtime-wiring
|
|
337
|
+
is a follow-up (tracked alongside enh-001, MCP HTTP server transport).
|
|
338
|
+
"""
|
|
339
|
+
expose = cfg.get("expose") or {}
|
|
340
|
+
if expose.get("enabled"):
|
|
341
|
+
msg = (
|
|
342
|
+
f"modules.protocols[{name!r}]: server-side `expose` is not wired "
|
|
343
|
+
"into the agent runtime yet (it would hijack the agent process's "
|
|
344
|
+
"stdio). Use consume-only config for now; expose runtime-wiring is "
|
|
345
|
+
"a follow-up (see enh-001)."
|
|
346
|
+
)
|
|
347
|
+
raise ModuleError(msg)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
async def _close_bridges(bridges: list[ProtocolBridge]) -> None:
|
|
351
|
+
"""Close every started bridge, swallowing teardown errors so one bad
|
|
352
|
+
close doesn't mask the original failure."""
|
|
353
|
+
for bridge in bridges:
|
|
354
|
+
with contextlib.suppress(Exception):
|
|
355
|
+
await bridge.close()
|
|
356
|
+
|
|
357
|
+
|
|
262
358
|
def _resolve_llm(config: AgentForgeConfig) -> LLMClient | str | None:
|
|
263
359
|
"""Pick the LLM definition out of `config.agent.model` /
|
|
264
360
|
`config.providers["default"]`.
|
|
@@ -317,6 +413,7 @@ __all__ = [
|
|
|
317
413
|
"build_evaluators_from_config",
|
|
318
414
|
"build_memory_from_config",
|
|
319
415
|
"build_pipeline_from_config",
|
|
416
|
+
"build_protocols_from_config",
|
|
320
417
|
"build_retriever_from_config",
|
|
321
418
|
"build_tools_from_config",
|
|
322
419
|
"load_and_build",
|
|
@@ -150,7 +150,9 @@ def _framework_version() -> str:
|
|
|
150
150
|
from importlib.metadata import PackageNotFoundError, version # noqa: PLC0415
|
|
151
151
|
|
|
152
152
|
try:
|
|
153
|
-
|
|
153
|
+
# Distribution name is `agentforge-py`, not the import name
|
|
154
|
+
# `agentforge` (bug-008). Do NOT change this back to "agentforge".
|
|
155
|
+
return version("agentforge-py")
|
|
154
156
|
except PackageNotFoundError: # pragma: no cover
|
|
155
157
|
return "0.0.0+unknown"
|
|
156
158
|
|
|
@@ -17,9 +17,11 @@ import sys
|
|
|
17
17
|
from collections.abc import Sequence
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
|
|
20
|
+
import yaml
|
|
20
21
|
from agentforge_core.production.exceptions import ModuleError
|
|
21
22
|
|
|
22
23
|
from agentforge.cli._scaffold_state import (
|
|
24
|
+
answers_path,
|
|
23
25
|
prepend_markers,
|
|
24
26
|
write_managed_files_lock,
|
|
25
27
|
)
|
|
@@ -98,6 +100,19 @@ def _run_new(args: argparse.Namespace) -> int:
|
|
|
98
100
|
)
|
|
99
101
|
prepend_markers(dst, template_name=args.template, template_version=template_version)
|
|
100
102
|
|
|
103
|
+
# bug-007 fix: persist the resolved scaffold answers ourselves.
|
|
104
|
+
# Copier's `_answers_file` directive doesn't write reliably for
|
|
105
|
+
# in-package templates; without `answers.yml`, `agentforge upgrade`
|
|
106
|
+
# has nothing to re-render from. Must precede inject_shared_scaffold
|
|
107
|
+
# because that step reads answers.yml for its Jinja context.
|
|
108
|
+
_write_answers_file(
|
|
109
|
+
dst,
|
|
110
|
+
template_name=args.template,
|
|
111
|
+
template_version=template_version,
|
|
112
|
+
project_slug=args.project_slug,
|
|
113
|
+
llm_provider=args.provider,
|
|
114
|
+
)
|
|
115
|
+
|
|
101
116
|
# feat-019: inject shared runbooks + AGENTS.md / CLAUDE.md /
|
|
102
117
|
# .cursorrules / .github/copilot-instructions.md into every
|
|
103
118
|
# scaffolded agent.
|
|
@@ -113,13 +128,55 @@ def _run_new(args: argparse.Namespace) -> int:
|
|
|
113
128
|
return 0
|
|
114
129
|
|
|
115
130
|
|
|
131
|
+
def _write_answers_file(
|
|
132
|
+
dst: Path,
|
|
133
|
+
*,
|
|
134
|
+
template_name: str,
|
|
135
|
+
template_version: str,
|
|
136
|
+
project_slug: str,
|
|
137
|
+
llm_provider: str | None,
|
|
138
|
+
) -> None:
|
|
139
|
+
"""Persist scaffold answers for `agentforge upgrade` to re-render.
|
|
140
|
+
|
|
141
|
+
Copier's `_answers_file` directive in `copier.yml` is supposed to
|
|
142
|
+
write this automatically, but doesn't reliably for in-package
|
|
143
|
+
templates (bug-007). We write it ourselves with the minimum
|
|
144
|
+
fields the upgrade path needs: `_template_name` so we can resolve
|
|
145
|
+
the template root again, plus the four Copier variables
|
|
146
|
+
(`project_name`, `project_slug`, `llm_provider`, `description`)
|
|
147
|
+
so the re-render produces the same shape.
|
|
148
|
+
"""
|
|
149
|
+
target = answers_path(dst)
|
|
150
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
151
|
+
project_name = " ".join(word.capitalize() for word in project_slug.split("-"))
|
|
152
|
+
payload: dict[str, object] = {
|
|
153
|
+
"_template_name": template_name,
|
|
154
|
+
"_template_version": template_version,
|
|
155
|
+
"project_name": project_name,
|
|
156
|
+
"project_slug": project_slug,
|
|
157
|
+
"llm_provider": llm_provider or "bedrock",
|
|
158
|
+
"description": f"An AgentForge agent ({template_name}).",
|
|
159
|
+
}
|
|
160
|
+
target.write_text(
|
|
161
|
+
"# AgentForge scaffold answers — DO NOT EDIT MANUALLY.\n"
|
|
162
|
+
"# Used by `agentforge upgrade` to re-render managed template files.\n"
|
|
163
|
+
+ yaml.safe_dump(payload, sort_keys=False),
|
|
164
|
+
encoding="utf-8",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
116
168
|
def _template_version() -> str:
|
|
117
|
-
"""Resolve the installed
|
|
169
|
+
"""Resolve the installed framework version — used as the
|
|
118
170
|
template's `source_version` in the lock file."""
|
|
119
171
|
from importlib.metadata import PackageNotFoundError, version # noqa: PLC0415
|
|
120
172
|
|
|
121
173
|
try:
|
|
122
|
-
|
|
174
|
+
# The PyPI *distribution* name is `agentforge-py` (the import name
|
|
175
|
+
# `agentforge` is a squatted PyPI project). `version()` keys off the
|
|
176
|
+
# distribution name, so `version("agentforge")` raised on every
|
|
177
|
+
# install and fell through to the sentinel (bug-008). Do NOT change
|
|
178
|
+
# this back to "agentforge".
|
|
179
|
+
return version("agentforge-py")
|
|
123
180
|
except PackageNotFoundError: # pragma: no cover
|
|
124
181
|
return "0.0.0+unknown"
|
|
125
182
|
|