chore: sync local changes, add Chinese docs and opencode config
This commit is contained in:
+26
-8
@@ -207,9 +207,17 @@ class TestLongRunningToolsAreAsync:
|
||||
)
|
||||
|
||||
def test_heavy_tool_source_uses_to_thread(self):
|
||||
"""Defense in depth: the source of every heavy tool wrapper must
|
||||
literally call asyncio.to_thread so we don't accidentally turn
|
||||
a tool async without offloading the blocking work."""
|
||||
"""Defense in depth: every heavy tool wrapper must offload its
|
||||
blocking work via ``asyncio.to_thread`` — either directly or through
|
||||
the shared ``_run_with_progress`` helper — so we don't accidentally
|
||||
turn a tool async without offloading the work; that would hang the
|
||||
stdio event loop on Windows. See #46, #136."""
|
||||
helper = inspect.getsource(crg_main._run_with_progress)
|
||||
assert "asyncio.to_thread" in helper, (
|
||||
"_run_with_progress must call asyncio.to_thread to offload "
|
||||
"blocking work; otherwise Windows MCP clients will hang. "
|
||||
"See #46, #136."
|
||||
)
|
||||
for tool_name in self.HEAVY_TOOLS:
|
||||
fn = getattr(crg_main, tool_name, None)
|
||||
assert fn is not None, f"{tool_name} not found on module"
|
||||
@@ -217,10 +225,12 @@ class TestLongRunningToolsAreAsync:
|
||||
# through the wrapper to find the underlying source.
|
||||
underlying = getattr(fn, "fn", None) or fn
|
||||
source = inspect.getsource(underlying)
|
||||
assert "asyncio.to_thread" in source, (
|
||||
f"{tool_name} must call asyncio.to_thread to offload its "
|
||||
f"blocking work; otherwise Windows MCP clients will hang. "
|
||||
f"See #46, #136."
|
||||
assert (
|
||||
"asyncio.to_thread" in source or "_run_with_progress" in source
|
||||
), (
|
||||
f"{tool_name} must offload its blocking work via "
|
||||
f"asyncio.to_thread or _run_with_progress; otherwise Windows "
|
||||
f"MCP clients will hang. See #46, #136."
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("tool_name,impl_name", HEAVY_TOOL_IMPLS.items())
|
||||
@@ -361,11 +371,19 @@ class TestGraphBackedToolProvenanceCoverage:
|
||||
self, category, tool_names,
|
||||
):
|
||||
assert tool_names, f"{category} must name at least one tool"
|
||||
helper = inspect.getsource(crg_main._run_with_progress)
|
||||
assert "with_provenance" in helper, (
|
||||
"_run_with_progress must attach graph provenance for tools that "
|
||||
"route through it"
|
||||
)
|
||||
for tool_name in tool_names:
|
||||
tool = getattr(crg_main, tool_name, None)
|
||||
assert tool is not None, f"{category}: missing {tool_name}"
|
||||
underlying = getattr(tool, "fn", None) or tool
|
||||
assert "with_provenance" in inspect.getsource(underlying), (
|
||||
source = inspect.getsource(underlying)
|
||||
assert (
|
||||
"with_provenance" in source or "_run_with_progress" in source
|
||||
), (
|
||||
f"{category}: {tool_name} does not attach graph provenance"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user