Parcourir la source

扩展 recursive 任务验收范围

SamLee il y a 19 heures
Parent
commit
5bb96123d8
2 fichiers modifiés avec 41 ajouts et 0 suppressions
  1. 5 0
      cyber_agent/core/context_policy.py
  2. 36 0
      cyber_agent/core/task_protocol.py

+ 5 - 0
cyber_agent/core/context_policy.py

@@ -198,6 +198,11 @@ def normalize_task_brief(
             *brief.constraints,
         ]),
         "context_refs": _stable_unique_refs(brief.context_refs),
+        "validation_scopes": [
+            scope
+            for scope in ("evidence", "hypothesis", "output", "task")
+            if scope in set(brief.validation_scopes)
+        ],
     })
     try:
         encoded_chars = context_chars(normalized.model_dump(mode="json"))

+ 36 - 0
cyber_agent/core/task_protocol.py

@@ -13,6 +13,7 @@ from typing import Any, Literal
 
 from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
 
+from cyber_agent.core.artifacts import ArtifactRef
 from cyber_agent.core.validation import RetryFrom
 
 
@@ -27,6 +28,8 @@ ReviewDecision = Literal[
     "ASCEND",
     "FAIL",
 ]
+TaskValidationScope = Literal["evidence", "hypothesis", "output", "task"]
+_VALIDATION_SCOPE_ORDER = ("evidence", "hypothesis", "output", "task")
 
 
 class StrictProtocolModel(BaseModel):
@@ -78,6 +81,7 @@ class TaskBrief(StrictProtocolModel):
     context: dict[str, Any] = Field(default_factory=dict)
     constraints: list[str] = Field(default_factory=list)
     context_refs: list[ContextRef] = Field(default_factory=list)
+    validation_scopes: list[TaskValidationScope] = Field(default_factory=list)
 
     @field_validator(
         "completion_criteria",
@@ -91,6 +95,15 @@ class TaskBrief(StrictProtocolModel):
             raise ValueError("items must be non-empty strings")
         return items
 
+    @field_validator("validation_scopes")
+    @classmethod
+    def normalize_validation_scopes(
+        cls,
+        scopes: list[TaskValidationScope],
+    ) -> list[TaskValidationScope]:
+        selected = set(scopes)
+        return [scope for scope in _VALIDATION_SCOPE_ORDER if scope in selected]
+
 
 class Validation(StrictProtocolModel):
     """子 Agent 在 TaskReport 中提交的执行者自检。
@@ -140,6 +153,8 @@ class TaskReportSubmission(StrictProtocolModel):
     next_step_suggestion: NextStepSuggestion
     outputs: list[dict[str, Any]] = Field(default_factory=list)
     evidence: list[dict[str, Any]] = Field(default_factory=list)
+    artifact_refs: list[ArtifactRef] = Field(default_factory=list, max_length=20)
+    source_urls: list[str] = Field(default_factory=list, max_length=20)
     remaining_issues: list[str] = Field(default_factory=list)
 
     @field_validator("remaining_issues")
@@ -149,6 +164,20 @@ class TaskReportSubmission(StrictProtocolModel):
             raise ValueError("remaining_issues must contain non-empty strings")
         return items
 
+    @field_validator("source_urls")
+    @classmethod
+    def validate_source_urls(cls, items: list[str]) -> list[str]:
+        normalized: list[str] = []
+        for item in items:
+            value = item.strip()
+            if not value:
+                raise ValueError("source_urls must contain non-empty strings")
+            if not value.lower().startswith(("http://", "https://")):
+                raise ValueError("source_urls only accepts HTTP(S) URLs")
+            if value not in normalized:
+                normalized.append(value)
+        return normalized
+
     @model_validator(mode="after")
     def validate_outcome_consistency(self) -> "TaskReportSubmission":
         if self.outcome == "satisfied" and (
@@ -410,6 +439,13 @@ def format_task_brief(
         )
     if constraints:
         parts.append(f"\n## Constraints\n{constraints}")
+    effective_scopes = [*task_brief.validation_scopes]
+    if "task" not in effective_scopes:
+        effective_scopes.append("task")
+    parts.append(
+        "\n## Validation Scopes\n"
+        + ", ".join(effective_scopes)
+    )
     if available_context_refs:
         parts.append(
             "\n## Available Context References\n"