Initial commit
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
"""Prompt harness builder for NativeAgent."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from opc.layer2_organization.prompt_contract import is_report_prompt_turn
|
||||
from opc.layer2_organization.session_scoping import is_top_level_company_session
|
||||
|
||||
from .artifacts import build_runtime_artifact_manifest, render_runtime_artifact_messages
|
||||
from .tool_strategy import NativeToolStrategyBuilder
|
||||
from .types import PromptHarnessOutput, RuntimeArtifact
|
||||
|
||||
|
||||
def _final_decider_role_id(task: Any) -> str:
|
||||
metadata = dict(getattr(task, "metadata", {}) or {})
|
||||
final_role = str(metadata.get("final_decider_role_id", "") or "").strip()
|
||||
if final_role:
|
||||
return final_role
|
||||
top_level = [str(item).strip() for item in list(metadata.get("top_level_role_ids", []) or []) if str(item).strip()]
|
||||
if len(top_level) == 1:
|
||||
return top_level[0]
|
||||
return ""
|
||||
|
||||
|
||||
def _memory_skill_user_facing(task: Any, role_id: str) -> bool:
|
||||
metadata = dict(getattr(task, "metadata", {}) or {})
|
||||
execution_mode = str(metadata.get("execution_mode", "") or "").strip()
|
||||
if execution_mode != "company_mode":
|
||||
return True
|
||||
if is_report_prompt_turn(metadata):
|
||||
return False
|
||||
current_role = str(role_id or getattr(task, "assigned_to", "") or metadata.get("work_item_role_id", "") or "").strip()
|
||||
if not current_role or current_role != _final_decider_role_id(task):
|
||||
return False
|
||||
return bool(metadata.get("user_visible", False) or is_top_level_company_session(task))
|
||||
|
||||
|
||||
def _execution_mode(task: Any) -> str | None:
|
||||
return str(getattr(task, "metadata", {}).get("execution_mode", "") or "").strip() or None
|
||||
|
||||
|
||||
def _resume_content(runtime_resume: dict[str, Any]) -> str:
|
||||
lines = [
|
||||
f"- Runtime session: {str(runtime_resume.get('runtime_session_id', '') or '').strip()}",
|
||||
f"- Resume cursor: {runtime_resume.get('resume_cursor', '')}",
|
||||
f"- Active subagents: {len(runtime_resume.get('active_subagents', []) or [])}",
|
||||
f"- Permission requests: {len(runtime_resume.get('permission_requests', []) or [])}",
|
||||
f"- Task ledger items: {len(runtime_resume.get('task_ledger', []) or [])}",
|
||||
]
|
||||
worktree_path = str(runtime_resume.get("worktree_path", "") or "").strip()
|
||||
if worktree_path:
|
||||
lines.append(f"- Worktree path: {worktree_path}")
|
||||
verification_verdict = str(runtime_resume.get("verification_verdict", "") or "").strip()
|
||||
if verification_verdict:
|
||||
lines.append(f"- Last verification: {verification_verdict}")
|
||||
return "Resume envelope:\n" + "\n".join(lines)
|
||||
|
||||
|
||||
def _runtime_resume_payload(task: Any) -> dict[str, Any]:
|
||||
context_snapshot = getattr(task, "context_snapshot", {}) or {}
|
||||
if not isinstance(context_snapshot, dict):
|
||||
return {}
|
||||
raw_resume = context_snapshot.get("runtime_resume", {})
|
||||
return dict(raw_resume) if isinstance(raw_resume, dict) else {}
|
||||
|
||||
|
||||
class PromptHarnessBuilder:
|
||||
"""Build dynamic sections and boot artifact messages for NativeAgent."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
task: Any,
|
||||
role_id: str,
|
||||
config: Any,
|
||||
context_assembler: Any,
|
||||
preferences: Any,
|
||||
skills: Any,
|
||||
) -> None:
|
||||
self.task = task
|
||||
self.role_id = role_id
|
||||
self.config = config
|
||||
self.context_assembler = context_assembler
|
||||
self.preferences = preferences
|
||||
self.skills = skills
|
||||
|
||||
async def build(
|
||||
self,
|
||||
*,
|
||||
system_prompt: str,
|
||||
allowed_tools: list[str] | None = None,
|
||||
runtime_policy_messages: list[dict[str, Any]] | None = None,
|
||||
) -> PromptHarnessOutput:
|
||||
runtime_policy_messages = list(runtime_policy_messages or [])
|
||||
cfg = self.config.system.native_runtime.prompt_harness
|
||||
if not cfg.enabled:
|
||||
return PromptHarnessOutput(
|
||||
system_prompt=system_prompt,
|
||||
runtime_policy_messages=runtime_policy_messages,
|
||||
)
|
||||
|
||||
workspace_context_messages: list[dict[str, str]] = []
|
||||
dynamic_section_ids: list[str] = []
|
||||
if cfg.split_static_dynamic:
|
||||
assembled_ctx = await self.context_assembler.build_system_context(self.task, role_id=self.role_id)
|
||||
if assembled_ctx:
|
||||
workspace_context_messages.append({"role": "system", "content": assembled_ctx})
|
||||
dynamic_section_ids.append("assembled_context")
|
||||
# employee_delta_context is already rendered inside the
|
||||
# unified Self section produced by
|
||||
# ``ContextAssembler._build_self_section`` (which is
|
||||
# included in ``assembled_ctx`` above). Emitting it a
|
||||
# second time here would duplicate the delta profile in
|
||||
# the prompt, so we rely solely on the assembled context.
|
||||
|
||||
artifacts: list[RuntimeArtifact] = []
|
||||
if cfg.artifact_messages_enabled:
|
||||
execution_mode = _execution_mode(self.task)
|
||||
tool_surface = NativeToolStrategyBuilder(
|
||||
list(allowed_tools or []),
|
||||
company_mode=execution_mode == "company_mode",
|
||||
).render()
|
||||
artifacts.append(RuntimeArtifact(
|
||||
artifact_type="tool_surface_delta",
|
||||
title="Tool Strategy",
|
||||
content=tool_surface,
|
||||
metadata={"allowed_tools": sorted(list(allowed_tools or []))},
|
||||
))
|
||||
skills_summary = str(
|
||||
self.skills.build_skills_summary(
|
||||
self.task.project_id,
|
||||
execution_mode=execution_mode,
|
||||
role_id=self.role_id,
|
||||
user_facing=_memory_skill_user_facing(self.task, self.role_id),
|
||||
final_decider_role_id=_final_decider_role_id(self.task),
|
||||
)
|
||||
or ""
|
||||
).strip()
|
||||
if skills_summary:
|
||||
artifacts.append(RuntimeArtifact(
|
||||
artifact_type="skills_delta",
|
||||
title="Skills",
|
||||
content=skills_summary,
|
||||
metadata={"project_id": self.task.project_id or "default"},
|
||||
))
|
||||
resident_assignment = dict(self.task.context_snapshot.get("resident_assignment", {}) or self.task.metadata.get("resident_assignment", {}) or {})
|
||||
team_memory_digest = str(resident_assignment.get("team_memory_digest", "") or "").strip()
|
||||
if team_memory_digest:
|
||||
artifacts.append(RuntimeArtifact(
|
||||
artifact_type="team_memory_delta",
|
||||
title="Team Memory",
|
||||
content=team_memory_digest,
|
||||
metadata={"assignment_id": resident_assignment.get("assignment_id", "")},
|
||||
))
|
||||
runtime_resume = _runtime_resume_payload(self.task)
|
||||
if runtime_resume:
|
||||
artifacts.append(RuntimeArtifact(
|
||||
artifact_type="resume_state",
|
||||
title="Resume State",
|
||||
content=_resume_content(runtime_resume),
|
||||
metadata={"runtime_session_id": runtime_resume.get("runtime_session_id", "")},
|
||||
))
|
||||
|
||||
previous_hashes = dict((self.task.metadata.get("prompt_harness", {}) or {}).get("artifact_hashes", {}) or {})
|
||||
artifact_messages = render_runtime_artifact_messages(
|
||||
artifacts,
|
||||
previous_hashes=previous_hashes,
|
||||
emit_delta_messages=cfg.emit_delta_messages,
|
||||
)
|
||||
artifact_manifest, artifact_hashes = build_runtime_artifact_manifest(artifacts)
|
||||
return PromptHarnessOutput(
|
||||
system_prompt=system_prompt,
|
||||
runtime_policy_messages=runtime_policy_messages,
|
||||
workspace_context_messages=workspace_context_messages,
|
||||
dynamic_messages=workspace_context_messages,
|
||||
artifact_messages=artifact_messages,
|
||||
static_section_ids=["system_prompt"],
|
||||
dynamic_section_ids=dynamic_section_ids,
|
||||
artifact_manifest=artifact_manifest,
|
||||
artifact_hashes=artifact_hashes,
|
||||
)
|
||||
Reference in New Issue
Block a user