mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
4b533608b6
* Update sample validation scripts * Adjust prompt * Update autogen-migration samples * Add fix suggestion * Split jobs * Add .env * Create trend report * Add timestamp * Add more env vars * Comments * force node24 * force node24 * force node22
162 lines
4.3 KiB
Python
162 lines
4.3 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
|
|
"""Data models for the sample validation system."""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from pathlib import Path
|
|
|
|
from agent_framework import Workflow
|
|
from agent_framework.github import GitHubCopilotAgent
|
|
|
|
|
|
@dataclass
|
|
class ValidationConfig:
|
|
"""Configuration for the validation workflow."""
|
|
|
|
samples_dir: Path
|
|
python_root: Path
|
|
subdir: str | None = None
|
|
exclude: list[str] | None = None
|
|
max_parallel_workers: int = 10
|
|
|
|
|
|
@dataclass
|
|
class SampleInfo:
|
|
"""Information about a discovered sample file."""
|
|
|
|
path: Path
|
|
relative_path: str
|
|
code: str
|
|
|
|
@classmethod
|
|
def from_path(cls, path: Path, samples_dir: Path) -> "SampleInfo":
|
|
"""Create SampleInfo from a file path."""
|
|
return cls(
|
|
path=path,
|
|
relative_path=str(path.relative_to(samples_dir)),
|
|
code=path.read_text(encoding="utf-8"),
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class DiscoveryResult:
|
|
"""Result of sample discovery."""
|
|
|
|
samples: list[SampleInfo]
|
|
|
|
|
|
@dataclass
|
|
class WorkflowCreationResult:
|
|
"""Result of creating a nested per-sample concurrent workflow."""
|
|
|
|
samples: list[SampleInfo]
|
|
workflow: Workflow | None
|
|
agents: list[GitHubCopilotAgent]
|
|
|
|
|
|
class RunStatus(Enum):
|
|
"""Status of a sample run."""
|
|
|
|
SUCCESS = "success"
|
|
FAILURE = "failure"
|
|
MISSING_SETUP = "missing_setup"
|
|
|
|
|
|
@dataclass
|
|
class RunResult:
|
|
"""Result of running a single sample."""
|
|
|
|
sample: SampleInfo
|
|
status: RunStatus
|
|
output: str
|
|
error: str
|
|
fix: str
|
|
|
|
|
|
@dataclass
|
|
class ExecutionResult:
|
|
"""Result of sample execution."""
|
|
|
|
results: list[RunResult]
|
|
|
|
|
|
@dataclass
|
|
class Report:
|
|
"""Final validation report."""
|
|
|
|
timestamp: datetime
|
|
total_samples: int
|
|
success_count: int
|
|
failure_count: int
|
|
missing_setup_count: int
|
|
results: list[RunResult] = field(default_factory=list) # type: ignore
|
|
|
|
def to_markdown(self) -> str:
|
|
"""Generate a markdown report."""
|
|
lines = [
|
|
"# Sample Validation Report",
|
|
"",
|
|
f"**Generated:** {self.timestamp.isoformat()}",
|
|
"",
|
|
"## Summary",
|
|
"",
|
|
"| Metric | Count |",
|
|
"|--------|-------|",
|
|
f"| Total Samples | {self.total_samples} |",
|
|
f"| [PASS] Success | {self.success_count} |",
|
|
f"| [FAIL] Failure | {self.failure_count} |",
|
|
f"| [MISSING_SETUP] Missing Setup | {self.missing_setup_count} |",
|
|
"",
|
|
"## Detailed Results",
|
|
"",
|
|
]
|
|
|
|
# Group by status
|
|
for status in [RunStatus.FAILURE, RunStatus.MISSING_SETUP, RunStatus.SUCCESS]:
|
|
status_results = [r for r in self.results if r.status == status]
|
|
if not status_results:
|
|
continue
|
|
|
|
status_label = {
|
|
RunStatus.SUCCESS: "[PASS]",
|
|
RunStatus.FAILURE: "[FAIL]",
|
|
RunStatus.MISSING_SETUP: "[MISSING_SETUP]",
|
|
}
|
|
|
|
lines.append(f"### {status_label[status]} {status.value.title()} ({len(status_results)})")
|
|
lines.append("")
|
|
|
|
for result in status_results:
|
|
lines.append(f"- **{result.sample.relative_path}**")
|
|
if result.error:
|
|
# Truncate long errors
|
|
error_preview = result.error[:200] + "..." if len(result.error) > 200 else result.error
|
|
lines.append(f" - Error: `{error_preview}`")
|
|
lines.append("")
|
|
|
|
return "\n".join(lines)
|
|
|
|
def to_dict(self) -> dict[str, object]:
|
|
"""Convert report to dictionary for JSON serialization."""
|
|
return {
|
|
"timestamp": self.timestamp.isoformat(),
|
|
"summary": {
|
|
"total_samples": self.total_samples,
|
|
"success_count": self.success_count,
|
|
"failure_count": self.failure_count,
|
|
"missing_setup_count": self.missing_setup_count,
|
|
},
|
|
"results": [
|
|
{
|
|
"path": r.sample.relative_path,
|
|
"status": r.status.value,
|
|
"output": r.output,
|
|
"error": r.error,
|
|
"fix": r.fix,
|
|
}
|
|
for r in self.results
|
|
],
|
|
}
|