feat(agent-provider): user plugin discovery, Dockerfile cascade, and provider-owned ca/git provisioning
- Add _load_user_plugin: loads AgentProvider subclass from ~/.bot-bottle/contrib/<name>/agent_provider.py; get_provider() checks there first before falling back to built-ins - Add Dockerfile cascade to docker prepare: per-bottle override → manifest dockerfile → user plugin Dockerfile → provider default - Move provision_ca and provision_git from backend-specific provision/ modules to AgentProvider ABC as overridable defaults; delete docker/provision/ca.py, docker/provision/git.py, smolmachines/provision/ca.py, smolmachines/provision/git.py - Add git_gate_insteadof_host/scheme properties to BottlePlan base; SmolmachinesBottlePlan overrides them to return agent_git_gate_host and "http" so provision_git works correctly on both backends - Move SIGKILL retry from smolmachines provision/ca.py into SmolmachinesBottle.exec via _exec_raw helper — all exec calls on smolmachines now transparently retry once on exit 137 - Relax manifest_agent template validation to allow user-defined template names; keep auth_token/forward_host_credentials guards for built-in-only features - Update tests: rewrite test_docker_provision_git_user and test_smolmachines_provision to call provider methods directly; add TestSmolmachinesBottleExec for SIGKILL retry coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ from datetime import datetime, timezone
|
||||
from dataclasses import replace
|
||||
from pathlib import Path
|
||||
|
||||
from ...agent_provider import agent_provision_plan, runtime_for
|
||||
from ...agent_provider import PROVIDER_TEMPLATES, agent_provision_plan, runtime_for
|
||||
from ...egress import Egress
|
||||
from ...env import ResolvedEnv, resolve_env
|
||||
from ...git_gate import GitGate
|
||||
@@ -100,6 +100,15 @@ def resolve_plan(
|
||||
elif provider_runtime.dockerfile:
|
||||
image_default = provider_runtime.image
|
||||
dockerfile_path = provider_runtime.dockerfile
|
||||
elif provider.template not in PROVIDER_TEMPLATES:
|
||||
user_dockerfile = (
|
||||
Path.home() / ".bot-bottle" / "contrib" / provider.template / "Dockerfile"
|
||||
)
|
||||
if user_dockerfile.is_file():
|
||||
image_default = f"bot-bottle-{provider.template}:{slug}"
|
||||
dockerfile_path = str(user_dockerfile)
|
||||
else:
|
||||
image_default = provider_runtime.image
|
||||
else:
|
||||
image_default = provider_runtime.image
|
||||
image = os.environ.get("BOT_BOTTLE_IMAGE", image_default)
|
||||
|
||||
Reference in New Issue
Block a user