feat(engine): the manager — chat orders, team, triage, verdicts, bootstrap
Phase 3 of the AI-workforce engine (TODO-agent-2): - engine/manager.py: ManagerTurns.chat (CREATE_TASK/PAUSE/RESUME/CANCEL, HIRE/UPDATE_EMPLOYEE/FIRE, KNOWLEDGE), triage (ASSIGN/REJECT/ASK_USER), final_review (COMPLETE/REVISE +cycle), error_review (RESOLVE_ERROR/CANCEL), bootstrap_team; post_user_message now delegates to it. - One billing path: call_model/BillingScope in runner.py is the single model entry point (fixes the agybot chat-billing bug). - Team changes capped at 3/turn, employee cap, last manager cannot be fired, hires pick a granted model of the requested tier strictly. - container_engine.py wires the real WorkforceBootstrapPort. - Fixes: REVISE is a body tag (prompt and parser now agree); ASSIGN employee="" means pick-for-me; the runner's protocol-error retry is capped by engine_max_protocol_retries (was unbounded until the turn timeout). - 20 new manager tests + regression tests; report in docs/plan/reports/agent-2-phase-3.md.
This commit is contained in:
@@ -182,24 +182,41 @@ class FakeSandbox:
|
||||
|
||||
|
||||
class FakeGrants:
|
||||
"""A ``ModelGrantPort`` with an explicit allow-list."""
|
||||
"""A ``ModelGrantPort`` with an explicit allow-list.
|
||||
|
||||
def __init__(self, granted: list[str] | None = None) -> None:
|
||||
self._granted = list(granted or ["model-strong", "model-fast"])
|
||||
``granted`` is either a list of model ids (all ``balanced``) or a mapping
|
||||
of id → neutral tier, so a test can have a "strong" and a "fast" model and
|
||||
assert the engine picked the right one.
|
||||
"""
|
||||
|
||||
def __init__(self, granted: list[str] | dict[str, str] | None = None) -> None:
|
||||
if granted is None:
|
||||
self._tiers: dict[str, str] = {
|
||||
"model-strong": "strong",
|
||||
"model-fast": "fast",
|
||||
}
|
||||
elif isinstance(granted, dict):
|
||||
self._tiers = dict(granted)
|
||||
else:
|
||||
self._tiers = dict.fromkeys(granted, "balanced")
|
||||
self.checks: list[str] = []
|
||||
|
||||
@property
|
||||
def granted(self) -> list[str]:
|
||||
return list(self._tiers)
|
||||
|
||||
async def granted_models(self, *, organization_id: str) -> list[GrantedModel]:
|
||||
return [
|
||||
GrantedModel(ai_model_id=model_id, tier="balanced")
|
||||
for model_id in self._granted
|
||||
GrantedModel(ai_model_id=model_id, tier=tier)
|
||||
for model_id, tier in self._tiers.items()
|
||||
]
|
||||
|
||||
async def is_granted(self, *, organization_id: str, ai_model_id: str) -> bool:
|
||||
self.checks.append(ai_model_id)
|
||||
return ai_model_id in self._granted
|
||||
return ai_model_id in self._tiers
|
||||
|
||||
def grant(self, model_id: str) -> None:
|
||||
self._granted.append(model_id)
|
||||
def grant(self, model_id: str, tier: str = "balanced") -> None:
|
||||
self._tiers[model_id] = tier
|
||||
|
||||
|
||||
class RecordingMemory:
|
||||
|
||||
Reference in New Issue
Block a user