mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-03-16 18:33:08 +00:00
feat: add "blocked for human input" feature across full stack
Agents can now request structured human input when they encounter genuine blockers (API keys, design choices, external configs). The request is displayed in the UI with a dynamic form, and the human's response is stored and made available when the agent resumes. Changes span 21 files + 1 new component: - Database: 3 new columns (needs_human_input, human_input_request, human_input_response) with migration - MCP: new feature_request_human_input tool + guards on existing tools - API: new resolve-human-input endpoint, 4th feature bucket - Orchestrator: skip needs_human_input features in scheduling - Progress: 4-tuple return from count_passing_tests - WebSocket: needs_human_input count in progress messages - UI: conditional 4th Kanban column, HumanInputForm component, amber status indicators, dependency graph support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,10 +43,10 @@ class Feature(Base):
|
||||
|
||||
__tablename__ = "features"
|
||||
|
||||
# Composite index for common status query pattern (passes, in_progress)
|
||||
# Composite index for common status query pattern (passes, in_progress, needs_human_input)
|
||||
# Used by feature_get_stats, get_ready_features, and other status queries
|
||||
__table_args__ = (
|
||||
Index('ix_feature_status', 'passes', 'in_progress'),
|
||||
Index('ix_feature_status', 'passes', 'in_progress', 'needs_human_input'),
|
||||
)
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
@@ -61,6 +61,11 @@ class Feature(Base):
|
||||
# NULL/empty = no dependencies (backwards compatible)
|
||||
dependencies = Column(JSON, nullable=True, default=None)
|
||||
|
||||
# Human input: agent can request structured input from a human
|
||||
needs_human_input = Column(Boolean, nullable=False, default=False, index=True)
|
||||
human_input_request = Column(JSON, nullable=True, default=None) # Agent's structured request
|
||||
human_input_response = Column(JSON, nullable=True, default=None) # Human's response
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Convert feature to dictionary for JSON serialization."""
|
||||
return {
|
||||
@@ -75,6 +80,10 @@ class Feature(Base):
|
||||
"in_progress": self.in_progress if self.in_progress is not None else False,
|
||||
# Dependencies: NULL/empty treated as empty list for backwards compat
|
||||
"dependencies": self.dependencies if self.dependencies else [],
|
||||
# Human input fields
|
||||
"needs_human_input": self.needs_human_input if self.needs_human_input is not None else False,
|
||||
"human_input_request": self.human_input_request,
|
||||
"human_input_response": self.human_input_response,
|
||||
}
|
||||
|
||||
def get_dependencies_safe(self) -> list[int]:
|
||||
@@ -302,6 +311,21 @@ def _is_network_path(path: Path) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _migrate_add_human_input_columns(engine) -> None:
|
||||
"""Add human input columns to existing databases that don't have them."""
|
||||
with engine.connect() as conn:
|
||||
result = conn.execute(text("PRAGMA table_info(features)"))
|
||||
columns = [row[1] for row in result.fetchall()]
|
||||
|
||||
if "needs_human_input" not in columns:
|
||||
conn.execute(text("ALTER TABLE features ADD COLUMN needs_human_input BOOLEAN DEFAULT 0"))
|
||||
if "human_input_request" not in columns:
|
||||
conn.execute(text("ALTER TABLE features ADD COLUMN human_input_request TEXT DEFAULT NULL"))
|
||||
if "human_input_response" not in columns:
|
||||
conn.execute(text("ALTER TABLE features ADD COLUMN human_input_response TEXT DEFAULT NULL"))
|
||||
conn.commit()
|
||||
|
||||
|
||||
def _migrate_add_schedules_tables(engine) -> None:
|
||||
"""Create schedules and schedule_overrides tables if they don't exist."""
|
||||
from sqlalchemy import inspect
|
||||
@@ -425,6 +449,7 @@ def create_database(project_dir: Path) -> tuple:
|
||||
_migrate_fix_null_boolean_fields(engine)
|
||||
_migrate_add_dependencies_column(engine)
|
||||
_migrate_add_testing_columns(engine)
|
||||
_migrate_add_human_input_columns(engine)
|
||||
|
||||
# Migrate to add schedules tables
|
||||
_migrate_add_schedules_tables(engine)
|
||||
|
||||
Reference in New Issue
Block a user