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:
@@ -104,6 +104,7 @@ BODY_TAGS: frozenset[TagName] = frozenset(
|
||||
TagName.EDIT_FILE,
|
||||
TagName.KNOWLEDGE,
|
||||
TagName.ASK_USER,
|
||||
TagName.REVISE,
|
||||
TagName.CREATE_TASK,
|
||||
TagName.SPLIT,
|
||||
TagName.PLAN_SPEC,
|
||||
@@ -282,14 +283,15 @@ _EDIT_BLOCK_RE = re.compile(
|
||||
def assign_of(tag: Tag) -> AssignTag:
|
||||
"""Read an ``ASSIGN`` tag. ``employee=""`` means "pick for me"."""
|
||||
employee = tag.attr("employee", "").strip()
|
||||
if not employee and not tag.attr("task_id", "").strip():
|
||||
task_id = tag.attr("task_id", "").strip()
|
||||
# ``employee=""`` is a deliberate "pick the least busy one"; a tag with
|
||||
# neither attribute at all is a mistake we quote back to the model.
|
||||
if "employee" not in tag.attrs and "task_id" not in tag.attrs:
|
||||
raise ProtocolError("[[ASSIGN]] needs employee=... or task_id=...")
|
||||
pipeline = tag.attr("pipeline", "").strip()
|
||||
if pipeline and pipeline not in ASSIGNABLE_PIPELINES:
|
||||
raise ProtocolError(f"unknown pipeline: {pipeline}")
|
||||
return AssignTag(
|
||||
employee=employee, pipeline=pipeline, task_id=tag.attr("task_id", "").strip()
|
||||
)
|
||||
return AssignTag(employee=employee, pipeline=pipeline, task_id=task_id)
|
||||
|
||||
|
||||
def task_draft_of(tag: Tag) -> TaskDraft:
|
||||
|
||||
Reference in New Issue
Block a user