Files
searchi/tools/windows_agent_smoke.py
T

129 lines
5.4 KiB
Python
Raw Normal View History

"""Exercise an extracted Windows CLI's read-only MCP boundary on owned fixtures."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import queue
import subprocess
import threading
import time
def check(condition, message):
if not condition:
raise RuntimeError(message)
def smoke(cli, work):
cli = cli.resolve(strict=True)
work.mkdir(parents=True, exist_ok=False)
corpus = work / "documents"
corpus.mkdir()
(corpus / "contract.txt").write_text(
"Termination clause: sixty days written notice to end the supplier partnership.",
encoding="utf-8",
)
(corpus / "retry.rs").write_text(
"pub fn refreshAccessToken() { /* retry failed requests */ }", encoding="utf-8"
)
(corpus / "symbol-note.txt").write_text("refreshAccessToken", encoding="utf-8")
db = work / "index.sqlite"
environment = dict(os.environ, SEARCHI_FORCE_CPU="1")
subprocess.run(
[str(cli), "index", "--db", str(db), "--root", str(corpus)],
env=environment, check=True, capture_output=True, timeout=60,
)
child = subprocess.Popen(
[str(cli), "mcp", "--db", str(db)], env=environment,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
text=True, encoding="utf-8",
)
output = queue.Queue(maxsize=128)
def reader():
for line in child.stdout:
try:
output.put(line, timeout=1)
except queue.Full:
return
output.put(None, timeout=1)
reading = threading.Thread(target=reader, daemon=True)
reading.start()
def send(value):
child.stdin.write(json.dumps(value) + "\n")
child.stdin.flush()
def request(identifier, method, params):
send({"jsonrpc": "2.0", "id": identifier, "method": method, "params": params})
deadline = time.monotonic() + 15
for _ in range(128):
remaining = deadline - time.monotonic()
check(remaining > 0, "MCP response deadline exceeded")
line = output.get(timeout=remaining)
check(line is not None, "MCP terminated before responding")
response = json.loads(line)
check(response.get("jsonrpc") == "2.0", "Invalid JSON-RPC output")
if response.get("id") == identifier:
check("error" not in response, "MCP protocol error")
return response["result"]
raise RuntimeError("MCP notification ceiling exceeded")
try:
hello = request(1, "initialize", {
"protocolVersion": "2025-11-25", "capabilities": {},
"clientInfo": {"name": "searchi-package-smoke", "version": "1"},
})
check(hello["serverInfo"]["name"] == "searchi", "Wrong MCP server")
send({"jsonrpc": "2.0", "method": "notifications/initialized"})
tools = request(2, "tools/list", {})["tools"]
check({tool["name"] for tool in tools} == {"search", "stats", "read_source"},
"Unexpected tools exposed")
check(all(tool["annotations"]["readOnlyHint"] for tool in tools),
"Missing read-only annotation")
found = request(3, "tools/call", {"name": "search", "arguments": {
"query": "termination", "extension": "txt", "limit": 3,
}})["structuredContent"]
check(found["mode"] == "lexical_only", "Incorrect readiness mode")
check(found["results"][0]["filename"] == "contract.txt", "Wrong document")
source = request(4, "tools/call", {"name": "read_source", "arguments": {
"handle": found["results"][0]["source_handle"],
}})["structuredContent"]
check("sixty days" in source["text"], "Missing cited source passage")
invented = request(5, "tools/call", {"name": "read_source", "arguments": {
"handle": "invented",
}})
check(invented.get("isError") is True, "Invented source handle accepted")
code = request(6, "tools/call", {"name": "search", "arguments": {
"query": "refreshAccessToken", "code_only": True,
}})["structuredContent"]
check([row["filename"] for row in code["results"]] == ["retry.rs"],
"Code filter included ordinary documents")
with cli.open("rb") as stream:
checksum = hashlib.file_digest(stream, "sha256").hexdigest()
report = {"complete": True, "cli_sha256": checksum, "mode": "lexical_only",
"cpu_forced": True, "inference": False, "tool_names": [t["name"] for t in tools],
"search": found, "source": source, "code": code}
with (work / "report.json").open("x", encoding="utf-8") as stream:
json.dump(report, stream, indent=2)
return report
finally:
# Only this subprocess is owned; leave the installed desktop untouched.
child.kill()
child.wait(timeout=15)
reading.join(timeout=2)
child.stdin.close()
child.stdout.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--cli", type=Path, required=True)
parser.add_argument("--work-dir", type=Path, required=True,
help="New owned fixture/evidence directory, retained after the run")
args = parser.parse_args()
result = smoke(args.cli, args.work_dir.resolve())
print(json.dumps({"complete": result["complete"], "mode": result["mode"],
"cli_sha256": result["cli_sha256"]}))