Skip to content

Commit d6dc9d0

Browse files
committed
refactor: fix 19 remaining audit issues β€” SRP splits, error handling, dedup, type safety
- mcp/handlers.py: Extract _SearchParams dataclass, _preprocess_search_query(), _postprocess_search_text(), _build_status_data() shared helper; narrow bare except patterns to specific types with logging - p2p/node.py: Decompose _trio_main (~200 lines) into _prepare_identity(), _init_subsystems(), _post_bootstrap_setup(), _run_main_loop(); extract module constants for magic numbers; remove duplicate/unused imports - mcp/server.py: Move _CORS_HEADERS to module level; clean nested getattr - search/query.py: Fix _sanitize_fts_query fallback to strip non-alphanumeric chars instead of returning unsanitized special characters - cli/serve.py: Extract _render_p2p_status(), _render_bootstrap_hints(), _render_credit_status() from status command; fix mypy type annotations All checks pass: ruff lint βœ…, ruff format βœ…, mypy 0 errors βœ…, 1512 tests βœ…, uv build βœ…
1 parent 05f2c83 commit d6dc9d0

13 files changed

Lines changed: 971 additions & 519 deletions

File tree

β€Žinfomesh/cli/crawl.pyβ€Ž

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,14 +244,38 @@ def _trunc(text: str, max_len: int) -> str:
244244
def mcp_cmd(http: bool, host: str, port: int) -> None:
245245
"""Run the MCP server (stdio or HTTP mode)."""
246246
config = load_config()
247-
if http:
248-
from infomesh.mcp.server import run_mcp_http_server
249247

250-
asyncio.run(run_mcp_http_server(config, host=host, port=port))
251-
else:
252-
from infomesh.mcp.server import run_mcp_server
248+
# ── Best-effort P2P bootstrap for distributed search ──
249+
from infomesh.services import bootstrap_p2p
250+
251+
p2p_node, distributed_index = bootstrap_p2p(config)
252+
253+
try:
254+
if http:
255+
from infomesh.mcp.server import run_mcp_http_server
253256

254-
asyncio.run(run_mcp_server(config))
257+
asyncio.run(
258+
run_mcp_http_server(
259+
config,
260+
host=host,
261+
port=port,
262+
distributed_index=distributed_index,
263+
p2p_node=p2p_node,
264+
)
265+
)
266+
else:
267+
from infomesh.mcp.server import run_mcp_server
268+
269+
asyncio.run(
270+
run_mcp_server(
271+
config,
272+
distributed_index=distributed_index,
273+
p2p_node=p2p_node,
274+
)
275+
)
276+
finally:
277+
if p2p_node is not None and hasattr(p2p_node, "stop"):
278+
p2p_node.stop()
255279

256280

257281
@click.command()

β€Žinfomesh/cli/serve.pyβ€Ž

Lines changed: 106 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ async def _crawl_batch() -> int:
279279
asyncio.run(_crawl_batch())
280280
elapsed = time.monotonic() - start_time
281281
click.echo(f"\n Initial crawl: {crawled} pages indexed in {elapsed:.1f}s")
282+
ctx.close()
282283

283284

284285
# ---------------------------------------------------------------------------
@@ -314,9 +315,9 @@ def stop() -> None:
314315

315316
def _kill_bgm_processes() -> None:
316317
"""Find and kill BGM player processes spawned by infomesh."""
317-
from infomesh.dashboard.bgm import _kill_orphaned_bgm
318+
from infomesh.dashboard.bgm import kill_orphaned_bgm
318319

319-
_kill_orphaned_bgm()
320+
kill_orphaned_bgm()
320321

321322

322323
# ---------------------------------------------------------------------------
@@ -391,16 +392,24 @@ def serve(seeds: str | None, role: str | None) -> None:
391392
_serve_logger.debug("credit_sync_init_skipped")
392393

393394
# ── P2P node (best-effort) ─────────────────────────────────
394-
p2p_node = _try_start_p2p(
395+
# Build local_search_fn so peers can query our local index.
396+
from infomesh.services import bootstrap_p2p, create_local_search_fn
397+
398+
_local_search_fn = create_local_search_fn(config)
399+
400+
p2p_node, _distributed_index = bootstrap_p2p(
395401
config,
396-
_serve_logger,
397402
credit_sync_manager=_credit_sync_mgr,
403+
local_search_fn=_local_search_fn,
398404
)
399405

400406
async def _run() -> None:
401407
from infomesh.services import AppContext, seed_and_crawl_loop
402408

403409
ctx = AppContext(config)
410+
# Attach P2P components so MCP and search can use them
411+
ctx.distributed_index = _distributed_index
412+
ctx.p2p_node = p2p_node
404413

405414
if config.node.role == NodeRole.SEARCH:
406415
# Search-only nodes don't crawl β€” wait for index submissions
@@ -427,63 +436,105 @@ async def _run() -> None:
427436
_serve_logger.info("serve_stopped")
428437

429438

430-
def _try_start_p2p(
439+
# ---------------------------------------------------------------------------
440+
# infomesh status
441+
# ---------------------------------------------------------------------------
442+
443+
444+
def _render_p2p_status(
431445
config: Config,
432-
log: structlog.stdlib.BoundLogger,
433-
*,
434-
credit_sync_manager: object | None = None,
435-
) -> object | None:
436-
"""Try to start the P2P node. Returns the node or None on failure.
446+
running: bool,
447+
) -> None:
448+
"""Render P2P status lines for the ``status`` command."""
449+
from infomesh.dashboard.utils import read_p2p_status
450+
451+
p2p = read_p2p_status(config)
452+
p2p_state = p2p.get("state", "stopped")
453+
p2p_peers = p2p.get("peers", 0)
454+
455+
if p2p_state == "running":
456+
click.echo(f"P2P: running ({p2p_peers} peers)")
457+
addrs = p2p.get("listen_addrs", [])
458+
if addrs and isinstance(addrs, list):
459+
click.echo("P2P addrs: " + ", ".join(str(a) for a in addrs))
460+
bs = p2p.get("bootstrap", {})
461+
if isinstance(bs, dict) and p2p_peers == 0:
462+
_render_bootstrap_hints(bs)
463+
elif p2p_state == "error":
464+
click.echo("P2P: " + click.style("error", fg="red"))
465+
err = p2p.get("error", "")
466+
if err:
467+
click.echo(f"P2P error: {err}")
468+
elif running:
469+
click.echo("P2P: " + click.style("not connected", fg="yellow"))
470+
click.echo(" (libp2p not installed or no bootstrap nodes)")
471+
else:
472+
click.echo("P2P: stopped")
437473

438-
Failures are logged as warnings β€” the node continues in local-only mode.
439-
"""
440-
try:
441-
from infomesh.p2p.node import InfoMeshNode # noqa: F811
442-
except ImportError:
443-
log.warning(
444-
"p2p_unavailable",
445-
reason="libp2p not installed",
446-
hint="pip install 'infomesh[p2p]'",
447-
)
448-
return None
449474

450-
try:
451-
node = InfoMeshNode(
452-
config,
453-
credit_sync_manager=credit_sync_manager,
454-
)
455-
node.start(blocking=False)
456-
log.info(
457-
"p2p_started",
458-
peer_id=node.peer_id,
459-
listen_port=config.node.listen_port,
460-
bootstrap_nodes=len(config.network.bootstrap_nodes),
475+
def _render_bootstrap_hints(
476+
bs: dict[str, object],
477+
) -> None:
478+
"""Render bootstrap troubleshooting hints."""
479+
bs_conf = bs.get("configured", 0)
480+
bs_conn = bs.get("connected", 0)
481+
bs_fail = bs.get("failed", 0)
482+
483+
if bs_conf == 0:
484+
click.echo("Bootstrap: " + click.style("none configured", fg="yellow"))
485+
click.echo(" Add bootstrap nodes in ~/.infomesh/config.toml:")
486+
click.echo(" [network]")
487+
click.echo(
488+
' bootstrap_nodes = ["/ip4/<IP>/tcp/4001/p2p/<PEER_ID>"]'
461489
)
462-
if not config.network.bootstrap_nodes:
463-
log.warning(
464-
"p2p_no_bootstrap",
465-
msg=(
466-
"No bootstrap nodes configured. "
467-
"Add [network] bootstrap_nodes in "
468-
"~/.infomesh/config.toml to connect to peers."
469-
),
490+
elif isinstance(bs_fail, int) and bs_fail > 0 and bs_conn == 0:
491+
click.echo(
492+
"Bootstrap: "
493+
+ click.style(
494+
f"all {bs_fail} nodes unreachable",
495+
fg="red",
470496
)
471-
return node
472-
except Exception as exc:
473-
log.warning(
474-
"p2p_start_failed",
475-
error=str(exc),
476-
msg=(
477-
"P2P node failed to start β€” running in local-only mode. "
478-
"Crawling, indexing, and local search still work."
479-
),
480497
)
481-
return None
498+
failed = bs.get("failed_addrs", [])
499+
if isinstance(failed, list):
500+
for fa in failed:
501+
click.echo(f" βœ— {fa}")
502+
click.echo(
503+
" Check: (1) node running?"
504+
" (2) port 4001 open?"
505+
" (3) correct IP?"
506+
)
507+
click.echo(" Test: nc -zv <IP> 4001")
508+
509+
510+
def _render_credit_status(ledger: object) -> None:
511+
"""Render credit status lines for the ``status`` command."""
512+
if ledger is None:
513+
click.echo("Credits: N/A (ledger unavailable)")
514+
return
515+
ls = ledger.stats() # type: ignore[attr-defined]
516+
click.echo(
517+
f"Credits: {ls.balance:.1f}"
518+
f" (earned {ls.total_earned:.1f}"
519+
f" / spent {ls.total_spent:.1f})"
520+
)
521+
click.echo(
522+
f"Tier: {ls.tier.value}"
523+
f" (score {ls.contribution_score:.1f},"
524+
f" search cost {ls.search_cost:.3f})"
525+
)
526+
if ls.credit_state.value != "normal":
527+
click.echo(f"Credit state: {ls.credit_state.value}")
528+
if ls.owner_email:
529+
click.echo(f"GitHub: {ls.owner_email}")
530+
click.echo(" Credits linked across all nodes.")
531+
else:
532+
click.echo("GitHub: " + click.style("not connected", fg="yellow"))
533+
click.echo(
534+
" Run 'infomesh config github [email protected]' to link."
535+
)
482536

483537

484-
# ---------------------------------------------------------------------------
485-
# infomesh status
486-
# ---------------------------------------------------------------------------
487538
@click.command()
488539
def status() -> None:
489540
"""Show node status."""
@@ -515,95 +566,8 @@ def status() -> None:
515566
click.echo("Vector docs: (chromadb not installed)")
516567
click.echo(f"LLM: {'on' if config.llm.enabled else 'off'}")
517568

518-
# ── P2P status ─────────────────────────────────────────
519-
from infomesh.dashboard.utils import read_p2p_status
520-
521-
p2p = read_p2p_status(config)
522-
p2p_state = p2p.get("state", "stopped")
523-
p2p_peers = p2p.get("peers", 0)
524-
if p2p_state == "running":
525-
click.echo(f"P2P: running ({p2p_peers} peers)")
526-
addrs = p2p.get("listen_addrs", [])
527-
if addrs and isinstance(addrs, list):
528-
click.echo(f"P2P addrs: {', '.join(str(a) for a in addrs)}")
529-
# Show bootstrap status if peers=0
530-
bs = p2p.get("bootstrap", {})
531-
if isinstance(bs, dict) and p2p_peers == 0:
532-
bs_conf = bs.get("configured", 0)
533-
bs_conn = bs.get("connected", 0)
534-
bs_fail = bs.get("failed", 0)
535-
if bs_conf == 0:
536-
click.echo(
537-
"Bootstrap: "
538-
+ click.style("none configured", fg="yellow")
539-
)
540-
click.echo(
541-
" Add bootstrap nodes in"
542-
" ~/.infomesh/config.toml:"
543-
)
544-
click.echo(" [network]")
545-
click.echo(
546-
" bootstrap_nodes"
547-
' = ["/ip4/<IP>/tcp/4001'
548-
'/p2p/<PEER_ID>"]'
549-
)
550-
elif bs_fail > 0 and bs_conn == 0:
551-
click.echo(
552-
"Bootstrap: "
553-
+ click.style(
554-
f"all {bs_fail} nodes unreachable",
555-
fg="red",
556-
)
557-
)
558-
failed = bs.get("failed_addrs", [])
559-
if isinstance(failed, list):
560-
for fa in failed:
561-
click.echo(f" βœ— {fa}")
562-
click.echo(
563-
" Check: (1) node running?"
564-
" (2) port 4001 open?"
565-
" (3) correct IP?"
566-
)
567-
click.echo(" Test: nc -zv <IP> 4001")
568-
elif p2p_state == "error":
569-
click.echo("P2P: " + click.style("error", fg="red"))
570-
err = p2p.get("error", "")
571-
if err:
572-
click.echo(f"P2P error: {err}")
573-
elif running:
574-
click.echo("P2P: " + click.style("not connected", fg="yellow"))
575-
click.echo(" (libp2p not installed or no bootstrap nodes)")
576-
else:
577-
click.echo("P2P: stopped")
578-
579-
# Credits
580-
if ctx.ledger is not None:
581-
ls = ctx.ledger.stats()
582-
click.echo(
583-
f"Credits: {ls.balance:.1f}"
584-
f" (earned {ls.total_earned:.1f}"
585-
f" / spent {ls.total_spent:.1f})"
586-
)
587-
click.echo(
588-
f"Tier: {ls.tier.value}"
589-
f" (score {ls.contribution_score:.1f},"
590-
f" search cost {ls.search_cost:.3f})"
591-
)
592-
if ls.credit_state.value != "normal":
593-
click.echo(f"Credit state: {ls.credit_state.value}")
594-
if ls.owner_email:
595-
click.echo(f"GitHub: {ls.owner_email}")
596-
click.echo(" Credits linked across all nodes.")
597-
else:
598-
click.echo(
599-
"GitHub: " + click.style("not connected", fg="yellow")
600-
)
601-
click.echo(
602-
" Run "
603-
"'infomesh config github [email protected]' to link."
604-
)
605-
else:
606-
click.echo("Credits: N/A (ledger unavailable)")
569+
_render_p2p_status(config, running)
570+
_render_credit_status(ctx.ledger)
607571

608572
keys_dir = config.node.data_dir / "keys"
609573
if (keys_dir / "private.pem").exists():

β€Žinfomesh/credits/sync.pyβ€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,7 @@ def get_same_owner_peers(self) -> list[str]:
490490
def purge_stale(self) -> int:
491491
"""Remove stale peer summaries from the store."""
492492
return self._store.purge_stale()
493+
494+
def close(self) -> None:
495+
"""Release underlying store resources."""
496+
self._store.close()

β€Žinfomesh/dashboard/bgm.pyβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def _find_player() -> tuple[str, list[str]] | None:
100100
return None
101101

102102

103-
def _kill_orphaned_bgm() -> None:
103+
def kill_orphaned_bgm() -> None:
104104
"""Kill any orphaned BGM player processes from previous runs.
105105
106106
Uses ``pgrep`` to find ffplay/mpv processes whose command line
@@ -190,7 +190,7 @@ def play(
190190
self.stop()
191191

192192
# Kill orphaned BGM processes from previous runs
193-
_kill_orphaned_bgm()
193+
kill_orphaned_bgm()
194194

195195
self._volume = max(0, min(100, volume))
196196

0 commit comments

Comments
Β (0)