feat: prepare 2.2.0 with UI and execution fixes

Add dark theme, richer Markdown and readable plugin results.
Improve Android input evidence, response integrity and diagnostics.
Unify lifecycle, guidance receipts and evidence sources across clients.
Keep direct action dispatch without an added AI quota approval layer.
Align version metadata at 2.2.0 and bundle Helper 1.2.2.

Validation: 3063 backend tests before the version bump; 44 after.
Frontend: 317 tests and production build passed.
This commit is contained in:
chenmingxuan committed 2026-10-26 00:44:13 +08:00
1 parent 83bcfd54d5
commit fac4ccb760
146 files changed
+5689 -2033

No files matched your search

+31 -1
View File
@@ -1,12 +1,39 @@
"""Keep ARTEMIS tool descriptions stable across supported Python versions."""
import json
from textwrap import dedent
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.exceptions import ToolError
from mcp.types import TextContent
class ArtemisFastMCP(FastMCP):
"""Normalize docstring indentation before FastMCP publishes tool metadata."""
"""Publish strict inputs and preserve structured legacy JSON results."""
def __init__(self, *args, strict_inputs=False, **kwargs):
super().__init__(*args, **kwargs)
self.strict_inputs = strict_inputs
async def call_tool(self, name, arguments):
tool = self._tool_manager.get_tool(name)
if tool is not None and self.strict_inputs:
unknown = set(arguments) - set(tool.parameters.get("properties", {}))
if unknown:
raise ToolError(
f"未知参数 {sorted(unknown)};请按 {name} 的输入 schema 提交,未执行工具。"
)
result = await super().call_tool(name, arguments)
if isinstance(result, list) and len(result) == 1 and isinstance(result[0], TextContent):
try:
value = json.loads(result[0].text)
except (ValueError, TypeError):
return result
if isinstance(value, dict):
return result, value
if isinstance(value, list):
return result, {"items": value}
return result
def add_tool(
self,
@@ -35,3 +62,6 @@ class ArtemisFastMCP(FastMCP):
meta=meta,
structured_output=structured_output,
)
tool = self._tool_manager.get_tool(name or fn.__name__)
if tool is not None and self.strict_inputs:
tool.parameters["additionalProperties"] = False