Add project-bound OAuth MCP queries and controlled analysis with scoped evidence, limits, timeouts and a nearby-model spatial query using EPSG:4326 inputs. Default nearby searches to 200 meters and five results. Integrate investigation messaging/presentation, health/readiness and typed history; remove duplicate web search and fix online simulation and compressed baseline writes. Include project migrations 023-025; keep local credentials and demo seeding excluded. Validation: 319 focused pytest checks; real PostGIS temporary-table regression; read-only Jinqian bridge radius comparison; cross-language MCP discovery/calls.
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""Server-owned business instructions, selected from the persisted task workflow."""
|
|
|
|
from hashlib import sha256
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
|
|
SKILL_ROOT = Path(__file__).resolve().parents[2] / "resources" / "work-order-skills"
|
|
WORKFLOW_SKILLS = {
|
|
"burst_report": "burst-report",
|
|
"water_quality_complaint": "water-quality-complaint",
|
|
"general": "appointment-follow-up",
|
|
}
|
|
|
|
|
|
def read_work_order_skill(workflow: str | None, *, include_content: bool = False) -> dict[str, Any]:
|
|
"""Read only packaged, allowlisted instructions; never interpret a task path."""
|
|
name = WORKFLOW_SKILLS.get(workflow)
|
|
if name is None:
|
|
return {"available": False, "workflow": workflow, "reason": "No business skill is configured for this workflow"}
|
|
content = (SKILL_ROOT / name / "SKILL.md").read_text(encoding="utf-8")
|
|
_, frontmatter, body = content.split("---", 2)
|
|
header = yaml.safe_load(frontmatter)
|
|
if header["name"] != name:
|
|
raise ValueError("Packaged work-order skill name does not match its directory")
|
|
result = {
|
|
"available": True,
|
|
"kind": "business_instructions",
|
|
"workflow": workflow,
|
|
"name": header["name"],
|
|
"description": header["description"],
|
|
"version": str(header["metadata"]["version"]),
|
|
"content_sha256": sha256(content.encode("utf-8")).hexdigest(),
|
|
"read": {"section": "skill"},
|
|
}
|
|
if include_content:
|
|
result["instructions"] = body.strip()
|
|
return result
|