mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-10-06 02:48:22 +00:00
- Add file_graph import to component registry - Register FILE_GRAPH enum in ComponentEnum - Implement BaseFileGraph integration in LinkedFileParser - Replace FileEdge with FileLink for better semantic clarity - Add lazy resolution of file_graph from app_context - Update file watcher logging to reflect links instead of edges refactor: streamline MCP transport layer architecture - Remove redundant step shells from reme2/mcp/steps/ - Consolidate all @R.register components to reme2.memory package - Update server.py to import reme2.memory directly - Revise README.md to document new architecture - Simplify module dependencies and import structure
76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
"""CLI runner: `python -m reme2.mcp.test`
|
|
|
|
Boots one Application per profile against a fresh temp vault, runs the
|
|
profile's CHECKS list in order, prints a per-check status line plus a
|
|
final summary. Exit code is the number of failed checks across both
|
|
profiles.
|
|
|
|
Per-profile suites are intentionally sequential — later checks rely on
|
|
side-effects from earlier ones (e.g. `sync.append` after `sync.create`).
|
|
Cross-profile work happens in independent vaults.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import shutil
|
|
import sys
|
|
import traceback
|
|
|
|
from . import test_expert, test_service
|
|
from ._helpers import AppContext, make_context
|
|
|
|
|
|
SUITES = {
|
|
"expert": test_expert.CHECKS,
|
|
"service": test_service.CHECKS,
|
|
}
|
|
|
|
|
|
async def _run_suite(profile: str, checks: list[tuple[str, callable]]) -> tuple[int, int]:
|
|
"""Run one suite. Returns (passed, total)."""
|
|
print(f"\n========== profile: {profile} ==========")
|
|
ctx: AppContext | None = None
|
|
tmp = None
|
|
passed = 0
|
|
try:
|
|
ctx, tmp = await make_context(profile)
|
|
print(f" bootstrapped: vault={ctx.vault}, jobs={len(ctx.jobs)}, " f"file_store={len(ctx.file_store)}")
|
|
for label, fn in checks:
|
|
try:
|
|
summary = await fn(ctx)
|
|
print(f" ✓ {label:32s} {summary}")
|
|
passed += 1
|
|
except Exception as e:
|
|
print(f" ✗ {label:32s} {type(e).__name__}: {e}")
|
|
traceback.print_exc()
|
|
except Exception as e:
|
|
print(f" ✗ bootstrap failed: {type(e).__name__}: {e}")
|
|
traceback.print_exc()
|
|
finally:
|
|
if ctx is not None:
|
|
try:
|
|
await ctx.app.close()
|
|
except Exception as e: # noqa: BLE001
|
|
print(f" (warn) app.close failed: {e}")
|
|
if tmp is not None:
|
|
shutil.rmtree(tmp, ignore_errors=True)
|
|
return passed, len(checks)
|
|
|
|
|
|
async def _main() -> int:
|
|
summary: dict[str, tuple[int, int]] = {}
|
|
for profile, checks in SUITES.items():
|
|
summary[profile] = await _run_suite(profile, checks)
|
|
|
|
print("\n========== summary ==========")
|
|
failed = 0
|
|
for profile, (passed, total) in summary.items():
|
|
marker = "✓" if passed == total else "✗"
|
|
print(f" {marker} {profile}: {passed}/{total}")
|
|
failed += total - passed
|
|
return 0 if failed == 0 else failed
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(asyncio.run(_main()))
|