Files
MoviePilot/app/agent/code/result.py
DDSRem 2de976f6b3 Merge pull request #7050 from DDSRem-Dev/codex-comment-migration
docs: 统一全项目中文注释和结构化契约说明
2026-10-17 19:26:29 +08:00

54 lines
2.8 KiB
Python

"""
代码执行的模型输出投影,工具失败与内核状态各自如实报告。
"""
import re
from pathlib import Path
from typing import Any
from app.adapters.system.code.output import SPILL_BYTES, STDERR_BYTES, project_stdout, read_cell_stdout
from app.agent.policy.sanitizer import sanitize_archived_text
_ANSI = re.compile(r'\x1b(?:\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1b\\))')
def render_result(payload: dict[str, Any], *, directory: Path, output_directory: Path,
reused: bool, state_reset: bool, elapsed: float) -> dict[str, Any]:
"""
完整 stdout 脱敏后才落盘,内核退出后仍能从独立输出目录继续读取。
"""
source = read_cell_stdout(payload, directory) + str(payload.get('raw_stdout') or '')
source_captured = len(source.encode('utf-8'))
stdout = sanitize_archived_text(_ANSI.sub('', source))
preview, metadata = project_stdout(stdout, output_directory)
stderr = sanitize_archived_text(_ANSI.sub('', str(payload.get('stderr') or '') + str(payload.get('raw_stderr') or '')))
trace = sanitize_archived_text(str(payload.get('traceback') or ''))
status = payload.get('status', 'error')
result: dict[str, Any] = {
'status': 'error' if status == 'error' else 'success',
'output': preview,
'exit_code': 1 if status == 'error' else 0,
'duration_seconds': round(elapsed, 2),
'kernel': {'mode': 'session', 'reused': reused, 'state_reset': state_reset,
'execution_count': int(payload.get('execution_count', 0)), 'ended': status == 'exit'},
**metadata,
}
if stderr or trace:
errors = (stderr + trace).encode('utf-8', errors='replace')
raw_errors = str(payload.get('raw_stderr') or '').encode('utf-8')
truncated = (len(errors) > STDERR_BYTES or bool(payload.get('stderr_clipped'))
or int(payload.get('raw_stderr_bytes', 0)) > len(raw_errors))
result.update(stderr=errors[:STDERR_BYTES].decode('utf-8', errors='ignore'), stderr_truncated=truncated)
result['output'] += '\n[stderr]\n' + result['stderr']
if status == 'error':
result['error'] = result.get('stderr') or 'Python cell 执行异常。'
captured_total = int(payload.get('stdout_bytes_total', 0)) + int(payload.get('raw_stdout_bytes', 0))
if payload.get('stdout_clipped') or captured_total > source_captured:
result['stdout_source_bytes_total'] = captured_total
result['stdout_spill_capped'] = captured_total > SPILL_BYTES
result['stdout_capture_incomplete'] = captured_total > source_captured
if result['stdout_capture_incomplete']:
result['stdout_truncated'] = True
result['warning'] = '部分输出超过捕获预算,无法恢复全部正文;现有 spill 仅包含已保留部分。'
return result