Initial commit
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
"""Helpers for company runtime output-root contracts.
|
||||
|
||||
The runtime may receive a user-requested absolute output path that is not
|
||||
writable inside an external-agent sandbox. These helpers keep the writable
|
||||
canonical output root separate from requested path aliases.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
OUTPUT_CONTRACT_KEYS: tuple[str, ...] = (
|
||||
"workspace_root",
|
||||
"output_root",
|
||||
"target_output_dir",
|
||||
"requested_output_root",
|
||||
"output_root_aliases",
|
||||
"output_root_alias_map",
|
||||
)
|
||||
|
||||
|
||||
PATH_BLOCKER_TOKENS: tuple[str, ...] = (
|
||||
"operation not permitted",
|
||||
"permission denied",
|
||||
"sandbox",
|
||||
"not writable",
|
||||
"read-only",
|
||||
"readonly",
|
||||
"missing required path",
|
||||
"required root",
|
||||
"required path",
|
||||
)
|
||||
|
||||
|
||||
def normalize_path_text(value: Any) -> str:
|
||||
raw = str(value or "").strip()
|
||||
if not raw:
|
||||
return ""
|
||||
try:
|
||||
return str(Path(raw).expanduser().resolve(strict=False))
|
||||
except Exception:
|
||||
return raw
|
||||
|
||||
|
||||
def is_path_relative_to(path: str | Path, root: str | Path) -> bool:
|
||||
try:
|
||||
Path(path).expanduser().resolve(strict=False).relative_to(
|
||||
Path(root).expanduser().resolve(strict=False)
|
||||
)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def output_contract_metadata(source: dict[str, Any] | None) -> dict[str, Any]:
|
||||
data = dict(source or {})
|
||||
output_root = normalize_path_text(data.get("output_root") or data.get("target_output_dir"))
|
||||
target_output_dir = normalize_path_text(data.get("target_output_dir") or output_root)
|
||||
workspace_root = normalize_path_text(data.get("workspace_root") or data.get("comms_workspace_root"))
|
||||
raw_requested_output_root = str(data.get("requested_output_root") or "").strip()
|
||||
requested_output_root = normalize_path_text(raw_requested_output_root)
|
||||
|
||||
aliases: list[str] = []
|
||||
for item in list(data.get("output_root_aliases", []) or []):
|
||||
raw_alias = str(item or "").strip()
|
||||
normalized_alias = normalize_path_text(raw_alias)
|
||||
if normalized_alias:
|
||||
aliases.append(normalized_alias)
|
||||
if raw_alias and raw_alias != normalized_alias:
|
||||
aliases.append(raw_alias)
|
||||
if requested_output_root and requested_output_root not in aliases and requested_output_root != output_root:
|
||||
aliases.append(requested_output_root)
|
||||
if raw_requested_output_root and raw_requested_output_root not in aliases and raw_requested_output_root != output_root:
|
||||
aliases.append(raw_requested_output_root)
|
||||
|
||||
alias_map: dict[str, str] = {}
|
||||
raw_map = data.get("output_root_alias_map", {})
|
||||
if isinstance(raw_map, dict):
|
||||
for key, value in raw_map.items():
|
||||
raw_alias = str(key or "").strip()
|
||||
alias = normalize_path_text(key)
|
||||
target = normalize_path_text(value)
|
||||
if raw_alias and target:
|
||||
alias_map[raw_alias] = target
|
||||
if alias and target:
|
||||
alias_map[alias] = target
|
||||
if output_root:
|
||||
for alias in aliases:
|
||||
if alias and alias != output_root:
|
||||
alias_map.setdefault(alias, output_root)
|
||||
|
||||
contract: dict[str, Any] = {}
|
||||
if workspace_root:
|
||||
contract["workspace_root"] = workspace_root
|
||||
if output_root:
|
||||
contract["output_root"] = output_root
|
||||
contract["target_output_dir"] = target_output_dir or output_root
|
||||
elif target_output_dir:
|
||||
contract["target_output_dir"] = target_output_dir
|
||||
if requested_output_root:
|
||||
contract["requested_output_root"] = requested_output_root
|
||||
if aliases:
|
||||
contract["output_root_aliases"] = list(dict.fromkeys(aliases))
|
||||
if alias_map:
|
||||
contract["output_root_alias_map"] = alias_map
|
||||
return contract
|
||||
|
||||
|
||||
def output_alias_map(source: dict[str, Any] | None) -> dict[str, str]:
|
||||
data = dict(source or {})
|
||||
contract = output_contract_metadata(data)
|
||||
aliases = dict(contract.get("output_root_alias_map", {}) or {})
|
||||
output_root = str(contract.get("output_root") or contract.get("target_output_dir") or "").strip()
|
||||
if not output_root:
|
||||
return aliases
|
||||
|
||||
raw_requested = str(data.get("requested_output_root") or "").strip()
|
||||
if raw_requested and raw_requested != output_root:
|
||||
aliases.setdefault(raw_requested, output_root)
|
||||
|
||||
raw_aliases = data.get("output_root_aliases", []) or []
|
||||
if isinstance(raw_aliases, (list, tuple, set)):
|
||||
for item in raw_aliases:
|
||||
raw_alias = str(item or "").strip()
|
||||
if raw_alias and raw_alias != output_root:
|
||||
aliases.setdefault(raw_alias, output_root)
|
||||
|
||||
raw_map = data.get("output_root_alias_map", {})
|
||||
if isinstance(raw_map, dict):
|
||||
for key, value in raw_map.items():
|
||||
raw_alias = str(key or "").strip()
|
||||
raw_target = str(value or "").strip()
|
||||
target = normalize_path_text(raw_target) or output_root
|
||||
if raw_alias and target:
|
||||
aliases.setdefault(raw_alias, target)
|
||||
return aliases
|
||||
|
||||
|
||||
def replace_output_aliases(value: Any, source: dict[str, Any] | None) -> Any:
|
||||
aliases = output_alias_map(source)
|
||||
if not aliases:
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
updated = value
|
||||
for alias, target in sorted(aliases.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
if alias and target and alias != target:
|
||||
updated = updated.replace(alias, target)
|
||||
return updated
|
||||
if isinstance(value, list):
|
||||
return [replace_output_aliases(item, source) for item in value]
|
||||
if isinstance(value, tuple):
|
||||
return tuple(replace_output_aliases(item, source) for item in value)
|
||||
if isinstance(value, dict):
|
||||
return {
|
||||
key: replace_output_aliases(item, source)
|
||||
for key, item in value.items()
|
||||
}
|
||||
return value
|
||||
|
||||
|
||||
def text_has_path_blocker(value: Any) -> bool:
|
||||
text = str(value or "").strip().lower()
|
||||
if not text:
|
||||
return False
|
||||
return any(token in text for token in PATH_BLOCKER_TOKENS)
|
||||
|
||||
|
||||
def render_output_contract_context(
|
||||
source: dict[str, Any] | None,
|
||||
*,
|
||||
heading: str = "## Runtime Output Contract",
|
||||
include_workspace_root: bool = True,
|
||||
) -> str:
|
||||
contract = output_contract_metadata(source)
|
||||
output_root = str(contract.get("output_root", "") or "").strip()
|
||||
workspace_root = str(contract.get("workspace_root", "") or "").strip()
|
||||
requested = str(contract.get("requested_output_root", "") or "").strip()
|
||||
alias_map = dict(contract.get("output_root_alias_map", {}) or {})
|
||||
visible_workspace_root = workspace_root if include_workspace_root else ""
|
||||
if not any([output_root, visible_workspace_root, requested, alias_map]):
|
||||
return ""
|
||||
|
||||
lines: list[str] = [heading]
|
||||
if output_root:
|
||||
lines.append(f"Canonical writable output root: {output_root}")
|
||||
if visible_workspace_root:
|
||||
lines.append(f"Workspace root: {visible_workspace_root}")
|
||||
if requested and requested != output_root:
|
||||
lines.append(f"Requested output alias: {requested}")
|
||||
if alias_map:
|
||||
lines.append("Path aliases:")
|
||||
for alias, target in list(alias_map.items())[:6]:
|
||||
lines.append(f"- {alias} -> {target}")
|
||||
lines.append("When old instructions mention an alias path, write and verify against the canonical output root.")
|
||||
return "\n".join(lines).strip()
|
||||
Reference in New Issue
Block a user