fix: better n8n workflow, refs NOISSUE
This commit is contained in:
@@ -28,6 +28,7 @@ try:
|
||||
from . import __version__, frontend
|
||||
from . import database as database_module
|
||||
from .agents.database_manager import DatabaseManager
|
||||
from .agents.request_interpreter import RequestInterpreter
|
||||
from .agents.orchestrator import AgentOrchestrator
|
||||
from .agents.n8n_setup import N8NSetupAgent
|
||||
from .agents.ui_manager import UIManager
|
||||
@@ -36,6 +37,7 @@ except ImportError:
|
||||
import frontend
|
||||
import database as database_module
|
||||
from agents.database_manager import DatabaseManager
|
||||
from agents.request_interpreter import RequestInterpreter
|
||||
from agents.orchestrator import AgentOrchestrator
|
||||
from agents.n8n_setup import N8NSetupAgent
|
||||
from agents.ui_manager import UIManager
|
||||
@@ -79,6 +81,15 @@ class N8NSetupRequest(BaseModel):
|
||||
force_update: bool = False
|
||||
|
||||
|
||||
class FreeformSoftwareRequest(BaseModel):
|
||||
"""Request body for free-form software generation."""
|
||||
|
||||
prompt_text: str = Field(min_length=1)
|
||||
source: str = 'telegram'
|
||||
chat_id: str | None = None
|
||||
chat_type: str | None = None
|
||||
|
||||
|
||||
def _build_project_id(name: str) -> str:
|
||||
"""Create a stable project id from the requested name."""
|
||||
slug = PROJECT_ID_PATTERN.sub("-", name.strip().lower()).strip("-") or "project"
|
||||
@@ -144,6 +155,49 @@ def _compose_prompt_text(request: SoftwareRequest) -> str:
|
||||
)
|
||||
|
||||
|
||||
async def _run_generation(
|
||||
request: SoftwareRequest,
|
||||
db: Session,
|
||||
prompt_text: str | None = None,
|
||||
prompt_actor: str = 'api',
|
||||
) -> dict:
|
||||
"""Run the shared generation pipeline for a structured request."""
|
||||
database_module.init_db()
|
||||
|
||||
project_id = _build_project_id(request.name)
|
||||
resolved_prompt_text = prompt_text or _compose_prompt_text(request)
|
||||
orchestrator = AgentOrchestrator(
|
||||
project_id=project_id,
|
||||
project_name=request.name,
|
||||
description=request.description,
|
||||
features=request.features,
|
||||
tech_stack=request.tech_stack,
|
||||
db=db,
|
||||
prompt_text=resolved_prompt_text,
|
||||
prompt_actor=prompt_actor,
|
||||
)
|
||||
result = await orchestrator.run()
|
||||
|
||||
manager = DatabaseManager(db)
|
||||
manager.log_system_event(
|
||||
component='api',
|
||||
level='INFO' if result['status'] == 'completed' else 'ERROR',
|
||||
message=f"Generated project {project_id} with {len(result.get('changed_files', []))} artifact(s)",
|
||||
)
|
||||
|
||||
history = manager.get_project_by_id(project_id)
|
||||
project_logs = manager.get_project_logs(history.id)
|
||||
response_data = _serialize_project(history)
|
||||
response_data['logs'] = [_serialize_project_log(log) for log in project_logs]
|
||||
response_data['ui_data'] = result.get('ui_data')
|
||||
response_data['features'] = request.features
|
||||
response_data['tech_stack'] = request.tech_stack
|
||||
response_data['project_root'] = result.get('project_root', str(_project_root(project_id)))
|
||||
response_data['changed_files'] = result.get('changed_files', [])
|
||||
response_data['repository'] = result.get('repository')
|
||||
return {'status': result['status'], 'data': response_data}
|
||||
|
||||
|
||||
def _project_root(project_id: str) -> Path:
|
||||
"""Resolve the filesystem location for a generated project."""
|
||||
return database_module.settings.projects_root / project_id
|
||||
@@ -172,6 +226,7 @@ def read_api_info():
|
||||
'/api',
|
||||
'/health',
|
||||
'/generate',
|
||||
'/generate/text',
|
||||
'/projects',
|
||||
'/status/{project_id}',
|
||||
'/audit/projects',
|
||||
@@ -202,40 +257,43 @@ def health_check():
|
||||
@app.post('/generate')
|
||||
async def generate_software(request: SoftwareRequest, db: DbSession):
|
||||
"""Create and record a software-generation request."""
|
||||
database_module.init_db()
|
||||
return await _run_generation(request, db)
|
||||
|
||||
project_id = _build_project_id(request.name)
|
||||
prompt_text = _compose_prompt_text(request)
|
||||
orchestrator = AgentOrchestrator(
|
||||
project_id=project_id,
|
||||
project_name=request.name,
|
||||
description=request.description,
|
||||
features=request.features,
|
||||
tech_stack=request.tech_stack,
|
||||
db=db,
|
||||
prompt_text=prompt_text,
|
||||
|
||||
@app.post('/generate/text')
|
||||
async def generate_software_from_text(request: FreeformSoftwareRequest, db: DbSession):
|
||||
"""Interpret a free-form request and run generation."""
|
||||
if (
|
||||
request.source == 'telegram'
|
||||
and database_module.settings.telegram_chat_id
|
||||
and request.chat_id
|
||||
and str(request.chat_id) != str(database_module.settings.telegram_chat_id)
|
||||
):
|
||||
return {
|
||||
'status': 'ignored',
|
||||
'message': f"Ignoring Telegram message from chat {request.chat_id}",
|
||||
'source': {
|
||||
'type': request.source,
|
||||
'chat_id': request.chat_id,
|
||||
'chat_type': request.chat_type,
|
||||
},
|
||||
}
|
||||
|
||||
interpreted = await RequestInterpreter().interpret(request.prompt_text)
|
||||
structured_request = SoftwareRequest(**interpreted)
|
||||
response = await _run_generation(
|
||||
structured_request,
|
||||
db,
|
||||
prompt_text=request.prompt_text,
|
||||
prompt_actor=request.source,
|
||||
)
|
||||
result = await orchestrator.run()
|
||||
|
||||
manager = DatabaseManager(db)
|
||||
manager.log_system_event(
|
||||
component='api',
|
||||
level='INFO' if result['status'] == 'completed' else 'ERROR',
|
||||
message=f"Generated project {project_id} with {len(result.get('changed_files', []))} artifact(s)",
|
||||
)
|
||||
|
||||
history = manager.get_project_by_id(project_id)
|
||||
project_logs = manager.get_project_logs(history.id)
|
||||
response_data = _serialize_project(history)
|
||||
response_data['logs'] = [_serialize_project_log(log) for log in project_logs]
|
||||
response_data['ui_data'] = result.get('ui_data')
|
||||
response_data['features'] = request.features
|
||||
response_data['tech_stack'] = request.tech_stack
|
||||
response_data['project_root'] = result.get('project_root', str(_project_root(project_id)))
|
||||
response_data['changed_files'] = result.get('changed_files', [])
|
||||
response_data['repository'] = result.get('repository')
|
||||
|
||||
return {'status': result['status'], 'data': response_data}
|
||||
response['interpreted_request'] = interpreted
|
||||
response['source'] = {
|
||||
'type': request.source,
|
||||
'chat_id': request.chat_id,
|
||||
'chat_type': request.chat_type,
|
||||
}
|
||||
return response
|
||||
|
||||
|
||||
@app.get('/projects')
|
||||
@@ -348,7 +406,7 @@ async def setup_n8n_workflow(request: N8NSetupRequest, db: DbSession):
|
||||
)
|
||||
result = await agent.setup(
|
||||
webhook_path=request.webhook_path,
|
||||
backend_url=request.backend_url or f"{database_module.settings.backend_public_url}/generate",
|
||||
backend_url=request.backend_url or f"{database_module.settings.backend_public_url}/generate/text",
|
||||
force_update=request.force_update,
|
||||
telegram_bot_token=database_module.settings.telegram_bot_token,
|
||||
telegram_credential_name=database_module.settings.n8n_telegram_credential_name,
|
||||
|
||||
Reference in New Issue
Block a user