feat(agent): redesign project_cli with module/method/input protocol
- Replace command/subcommand/args with module/method/input envelope - Calendar handler uses discriminated union (mode) for read operations - Strict Pydantic models with extra='forbid' for all calendar methods - Worker max_iters=7, router prompt simplified (removed project_cli_defaults) - Skill index cards + per-action files for progressive disclosure - Frontend/AG-UI aligned to module/method dispatch - Protocol docs updated to module/method/input contract WIP: action cards need envelope fix, 2 tests need update, memory handler needs Pydantic models.
This commit is contained in:
@@ -39,7 +39,9 @@ from schemas.agent.forwarded_props import (
|
||||
parse_forwarded_props_runtime_mode,
|
||||
)
|
||||
from schemas.agent.runtime_models import (
|
||||
ErrorInfo,
|
||||
RouterAgentOutput,
|
||||
RunStatus,
|
||||
WorkerAgentOutputLite,
|
||||
)
|
||||
from schemas.agent.skill_config import ProjectCliCommand, SkillName
|
||||
@@ -74,6 +76,8 @@ class AgentScopeRunner:
|
||||
self._active_agent: JsonReActAgent | None = None
|
||||
self._active_agent_lock = asyncio.Lock()
|
||||
|
||||
_WORKER_MAX_ITERS = 7
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
*,
|
||||
@@ -442,6 +446,11 @@ class AgentScopeRunner:
|
||||
if self._active_agent is agent:
|
||||
self._active_agent = None
|
||||
worker_payload = worker_output_model.model_validate(response_msg.metadata or {})
|
||||
worker_payload = self._enforce_tool_evidence_contract(
|
||||
worker_output=worker_payload,
|
||||
requires_tool_evidence=requires_tool_evidence,
|
||||
has_successful_tool_result=emitter.has_successful_tool_result,
|
||||
)
|
||||
response_metadata = self._llm_pricing_service.build_usage_metadata(
|
||||
model=stage_config.model_code,
|
||||
usage_summary=tracking_model.usage_summary(),
|
||||
@@ -458,6 +467,28 @@ class AgentScopeRunner:
|
||||
finally:
|
||||
reset_tool_credential(credential_token)
|
||||
|
||||
@staticmethod
|
||||
def _enforce_tool_evidence_contract(
|
||||
*,
|
||||
worker_output: WorkerAgentOutputLite,
|
||||
requires_tool_evidence: bool,
|
||||
has_successful_tool_result: bool,
|
||||
) -> WorkerAgentOutputLite:
|
||||
if not requires_tool_evidence or has_successful_tool_result:
|
||||
return worker_output
|
||||
return worker_output.model_copy(
|
||||
update={
|
||||
"status": RunStatus.FAILED,
|
||||
"answer": "无法确认结果:所需工具调用未成功完成。",
|
||||
"suggested_actions": [],
|
||||
"error": ErrorInfo(
|
||||
code="TOOL_EVIDENCE_MISSING",
|
||||
message="requires_tool_evidence=true but no tool call completed successfully in this run",
|
||||
retryable=False,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
def _build_worker_input_messages(
|
||||
self,
|
||||
*,
|
||||
@@ -501,6 +532,7 @@ class AgentScopeRunner:
|
||||
model: TrackingChatModel,
|
||||
emitter: PipelineStageEmitter | None = None,
|
||||
force_tool_on_first_reasoning: bool = False,
|
||||
max_iters: int = _WORKER_MAX_ITERS,
|
||||
) -> JsonReActAgent:
|
||||
return JsonReActAgent(
|
||||
name=agent_name,
|
||||
@@ -511,6 +543,7 @@ class AgentScopeRunner:
|
||||
memory=InMemoryMemory(),
|
||||
emitter=emitter,
|
||||
force_tool_on_first_reasoning=force_tool_on_first_reasoning,
|
||||
max_iters=max_iters,
|
||||
)
|
||||
|
||||
async def _emit_step_event(
|
||||
|
||||
Reference in New Issue
Block a user