feat: add Android task file evidence and finalize plugin design
This commit is contained in:
1 parent
96fedc816f
commit
72ff342605
20 files changed
+1005
-35
No files matched your search
@@ -18,6 +18,10 @@ from urllib.parse import urlsplit
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
class McpSyncValidationError(ValueError):
|
||||
"""The synchronizer could not safely update an already parsed configuration."""
|
||||
|
||||
|
||||
def launch_text(english: str, chinese: str) -> str:
|
||||
return chinese if os.environ.get("ARTEMIS_LAUNCH_LANG") == "zh-CN" else english
|
||||
|
||||
@@ -170,11 +174,10 @@ def _updated_entry(config: dict, template: dict, root: Path, names: tuple[str, .
|
||||
updated["env"] = {**environment, **template["env"]}
|
||||
if "enabled_tools" in template or "enabled_tools" in config:
|
||||
updated["enabled_tools"] = list(names)
|
||||
if "tools" in template or "tools" in config:
|
||||
current_tools = config.get("tools", {})
|
||||
if not isinstance(current_tools, dict):
|
||||
raise ValueError("The existing Artemis MCP tools setting is not an object")
|
||||
updated["tools"] = {name: {"eager": True, **current_tools.get(name, {})} for name in names}
|
||||
# Per-tool approval/enablement policies belong to the user. Leave `tools`
|
||||
# untouched, including entries outside the current exported tool list.
|
||||
# Rebuilding it both changes policy and sends nested tables to the scalar
|
||||
# serializer, which produces JSON syntax rather than valid TOML.
|
||||
for key in ("type", "required", "startup_timeout_sec", "connectionTimeoutMs"):
|
||||
if key in template and key not in updated:
|
||||
updated[key] = template[key]
|
||||
@@ -300,12 +303,17 @@ def refresh_codex(
|
||||
assignments[env_header] = env_updates
|
||||
if not top and not env_updates:
|
||||
return False
|
||||
result = _replace_toml_tables(raw, assignments)
|
||||
actual = tomllib.loads(result)["mcp_servers"]["artemis"]
|
||||
if any(actual.get(key) != value for key, value in top.items()) or any(
|
||||
actual.get("env", {}).get(key) != value for key, value in env_updates.items()
|
||||
):
|
||||
raise ValueError("Could not safely refresh the Artemis MCP table")
|
||||
try:
|
||||
result = _replace_toml_tables(raw, assignments)
|
||||
actual = tomllib.loads(result)["mcp_servers"]["artemis"]
|
||||
if any(actual.get(key) != value for key, value in top.items()) or any(
|
||||
actual.get("env", {}).get(key) != value for key, value in env_updates.items()
|
||||
):
|
||||
raise ValueError("Updated MCP settings did not match the requested values")
|
||||
except (ValueError, KeyError, TypeError) as exc:
|
||||
raise McpSyncValidationError(
|
||||
"Could not safely generate the MCP configuration update"
|
||||
) from exc
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
_atomic_write(path, result)
|
||||
return result != raw
|
||||
@@ -339,6 +347,11 @@ def refresh_mcp(root: Path) -> int:
|
||||
"Cannot read/write the configuration; check file permissions.",
|
||||
"无法读写配置,请检查文件权限。",
|
||||
)
|
||||
elif isinstance(exc, McpSyncValidationError):
|
||||
reason = launch_text(
|
||||
"The synchronizer generated an invalid update from a readable configuration. This is an ARTEMIS sync error; do not delete your Codex configuration.",
|
||||
"原配置可正常解析,但同步程序生成的更新未通过校验。这是 ARTEMIS 同步错误,请勿删除 Codex 配置。",
|
||||
)
|
||||
else:
|
||||
reason = launch_text(
|
||||
"Invalid TOML or Artemis configuration structure; check the file in Codex.",
|
||||
|
||||
Reference in new issue
Block a user