feat: gitea issue integration, refs NOISSUE
This commit is contained in:
@@ -173,12 +173,16 @@ async def _run_generation(
|
||||
db: Session,
|
||||
prompt_text: str | None = None,
|
||||
prompt_actor: str = 'api',
|
||||
prompt_source_context: dict | None = None,
|
||||
prompt_routing: dict | None = None,
|
||||
preferred_project_id: str | None = None,
|
||||
related_issue: dict | None = None,
|
||||
) -> dict:
|
||||
"""Run the shared generation pipeline for a structured request."""
|
||||
database_module.init_db()
|
||||
|
||||
manager = DatabaseManager(db)
|
||||
reusable_history = manager.get_latest_project_by_name(request.name)
|
||||
reusable_history = manager.get_project_by_id(preferred_project_id) if preferred_project_id else manager.get_latest_project_by_name(request.name)
|
||||
if reusable_history and database_module.settings.gitea_url and database_module.settings.gitea_token:
|
||||
try:
|
||||
from .agents.gitea import GiteaAPI
|
||||
@@ -193,7 +197,9 @@ async def _run_generation(
|
||||
),
|
||||
project_id=reusable_history.project_id,
|
||||
)
|
||||
if reusable_history and manager.get_open_pull_request(project_id=reusable_history.project_id):
|
||||
if preferred_project_id and reusable_history is not None:
|
||||
project_id = reusable_history.project_id
|
||||
elif reusable_history and manager.get_open_pull_request(project_id=reusable_history.project_id):
|
||||
project_id = reusable_history.project_id
|
||||
else:
|
||||
project_id = _build_project_id(request.name)
|
||||
@@ -209,6 +215,9 @@ async def _run_generation(
|
||||
prompt_text=resolved_prompt_text,
|
||||
prompt_actor=prompt_actor,
|
||||
existing_history=reusable_history,
|
||||
prompt_source_context=prompt_source_context,
|
||||
prompt_routing=prompt_routing,
|
||||
related_issue_hint=related_issue,
|
||||
)
|
||||
result = await orchestrator.run()
|
||||
|
||||
@@ -229,6 +238,7 @@ async def _run_generation(
|
||||
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')
|
||||
response_data['related_issue'] = result.get('related_issue') or (result.get('ui_data') or {}).get('related_issue')
|
||||
response_data['pull_request'] = result.get('pull_request') or manager.get_open_pull_request(project_id=project_id)
|
||||
summary_context = {
|
||||
'name': response_data['name'],
|
||||
@@ -245,6 +255,7 @@ async def _run_generation(
|
||||
'repository_status': (response_data.get('repository') or {}).get('status') if isinstance(response_data.get('repository'), dict) else None,
|
||||
'pull_request_url': (response_data.get('pull_request') or {}).get('pr_url') if isinstance(response_data.get('pull_request'), dict) else None,
|
||||
'pull_request_state': (response_data.get('pull_request') or {}).get('pr_state') if isinstance(response_data.get('pull_request'), dict) else None,
|
||||
'related_issue': response_data.get('related_issue'),
|
||||
'message': response_data.get('message'),
|
||||
'logs': [log.get('message', '') for log in response_data.get('logs', []) if isinstance(log, dict)],
|
||||
}
|
||||
@@ -320,6 +331,7 @@ def read_api_info():
|
||||
'/audit/system/logs',
|
||||
'/audit/prompts',
|
||||
'/audit/changes',
|
||||
'/audit/issues',
|
||||
'/audit/commit-context',
|
||||
'/audit/timeline',
|
||||
'/audit/llm-traces',
|
||||
@@ -373,13 +385,30 @@ async def generate_software_from_text(request: FreeformSoftwareRequest, db: DbSe
|
||||
},
|
||||
}
|
||||
|
||||
interpreted, interpretation_trace = await RequestInterpreter().interpret_with_trace(request.prompt_text)
|
||||
manager = DatabaseManager(db)
|
||||
interpreter_context = manager.get_interpreter_context(chat_id=request.chat_id, source=request.source)
|
||||
interpreted, interpretation_trace = await RequestInterpreter().interpret_with_trace(
|
||||
request.prompt_text,
|
||||
context=interpreter_context,
|
||||
)
|
||||
routing = interpretation_trace.get('routing') or {}
|
||||
selected_history = manager.get_project_by_id(routing.get('project_id')) if routing.get('project_id') else None
|
||||
if selected_history is not None and routing.get('intent') != 'new_project':
|
||||
interpreted['name'] = selected_history.project_name
|
||||
interpreted['description'] = selected_history.description or interpreted['description']
|
||||
structured_request = SoftwareRequest(**interpreted)
|
||||
response = await _run_generation(
|
||||
structured_request,
|
||||
db,
|
||||
prompt_text=request.prompt_text,
|
||||
prompt_actor=request.source,
|
||||
prompt_source_context={
|
||||
'chat_id': request.chat_id,
|
||||
'chat_type': request.chat_type,
|
||||
},
|
||||
prompt_routing=routing,
|
||||
preferred_project_id=routing.get('project_id') if routing.get('intent') != 'new_project' else None,
|
||||
related_issue={'number': routing.get('issue_number')} if routing.get('issue_number') is not None else None,
|
||||
)
|
||||
project_data = response.get('data', {})
|
||||
if project_data.get('history_id') is not None:
|
||||
@@ -400,6 +429,7 @@ async def generate_software_from_text(request: FreeformSoftwareRequest, db: DbSe
|
||||
fallback_used=interpretation_trace.get('fallback_used', False),
|
||||
)
|
||||
response['interpreted_request'] = interpreted
|
||||
response['routing'] = routing
|
||||
response['llm_trace'] = interpretation_trace
|
||||
response['source'] = {
|
||||
'type': request.source,
|
||||
@@ -456,6 +486,20 @@ def get_code_change_audit(db: DbSession, project_id: str | None = Query(default=
|
||||
return {'changes': [_serialize_audit_item(item) for item in manager.get_code_changes(project_id=project_id)]}
|
||||
|
||||
|
||||
@app.get('/audit/issues')
|
||||
def get_issue_audit(
|
||||
db: DbSession,
|
||||
project_id: str | None = Query(default=None),
|
||||
state: str | None = Query(default=None),
|
||||
):
|
||||
"""Return tracked repository issues and issue-work events."""
|
||||
manager = DatabaseManager(db)
|
||||
return {
|
||||
'issues': manager.get_repository_issues(project_id=project_id, state=state),
|
||||
'issue_work': manager.get_issue_work_events(project_id=project_id),
|
||||
}
|
||||
|
||||
|
||||
@app.get('/audit/commit-context')
|
||||
def get_commit_context_audit(
|
||||
db: DbSession,
|
||||
@@ -538,9 +582,11 @@ async def undo_prompt_changes(project_id: str, prompt_id: int, db: DbSession):
|
||||
def sync_project_repository(project_id: str, db: DbSession, commit_limit: int = Query(default=25, ge=1, le=200)):
|
||||
"""Import recent repository activity from Gitea for a tracked project."""
|
||||
manager = DatabaseManager(db)
|
||||
result = manager.sync_repository_activity(project_id=project_id, gitea_api=_create_gitea_api(), commit_limit=commit_limit)
|
||||
gitea_api = _create_gitea_api()
|
||||
result = manager.sync_repository_activity(project_id=project_id, gitea_api=gitea_api, commit_limit=commit_limit)
|
||||
if result.get('status') == 'error':
|
||||
raise HTTPException(status_code=400, detail=result.get('message', 'Repository sync failed'))
|
||||
manager.sync_repository_issues(project_id=project_id, gitea_api=gitea_api, state='open')
|
||||
return result
|
||||
|
||||
|
||||
@@ -582,6 +628,7 @@ async def onboard_gitea_repository(request: GiteaRepositoryOnboardRequest, db: D
|
||||
raise HTTPException(status_code=404, detail=repo.get('error'))
|
||||
manager = DatabaseManager(db)
|
||||
onboarded = manager.onboard_repository(owner=owner, repo_name=request.repo_name, repository_data=repo)
|
||||
manager.sync_repository_issues(project_id=onboarded['project_id'], gitea_api=gitea_api, state='open')
|
||||
sync_result = None
|
||||
if request.sync_commits:
|
||||
sync_result = manager.sync_repository_activity(
|
||||
|
||||
Reference in New Issue
Block a user