Files
ObsiGate/backend/tools/duplicates.py
T
bruno 4ce677902a
CI / lint (push) Successful in 2m53s
CI / security (push) Successful in 2m5s
CI / test (push) Successful in 4m52s
CI / build (push) Successful in 2m5s
CI / e2e (push) Successful in 16m14s
feat: agent IA phase 4 — doublons #166, notifications externes #168 (Discord/Telegram/SMTP/webhook), taches planifiees #170
2026-10-04 13:11:25 -04:00

60 lines
2.0 KiB
Python

"""Duplicate detection & merge tools (#166).
* ``find_duplicates`` — READ, vault-scoped: candidate pairs with scores.
* ``merge_duplicate_notes`` — DANGEROUS: confirmed fusion with automatic
backup (service layer), never without an explicit approval.
"""
from __future__ import annotations
from typing import Any
from backend.services import duplicates as _duplicates
from backend.services.errors import ServiceError
from backend.tools.context import ToolContext, ToolError, ToolRisk
from backend.tools.registry import tool
from backend.tools.schemas import FindDuplicatesInput, MergeDuplicatesInput
@tool(
name="find_duplicates",
description="Find candidate duplicate markdown notes in a vault (similarity scores).",
input_model=FindDuplicatesInput,
risk=ToolRisk.READ,
requires_vault=True,
)
def find_duplicates(ctx: ToolContext, params: FindDuplicatesInput) -> dict[str, Any]:
"""List duplicate candidates ordered by descending score."""
try:
return _duplicates.find_duplicate_pairs(
params.vault,
threshold=params.threshold,
limit=params.limit,
subdir=params.subdir,
)
except ServiceError as e:
raise ToolError(e.message, code=e.code, details=e.details) from e
@tool(
name="merge_duplicate_notes",
description=(
"Merge one note into another and delete the source (backup first). "
"Destructive: requires confirmation."
),
input_model=MergeDuplicatesInput,
risk=ToolRisk.DANGEROUS,
requires_vault=True,
)
def merge_duplicate_notes(ctx: ToolContext, params: MergeDuplicatesInput) -> dict[str, Any]:
"""Fuse *source_path* into *target_path* using the chosen strategy."""
try:
return _duplicates.merge_duplicates(
params.vault,
params.source_path,
params.target_path,
strategy=params.strategy,
)
except ServiceError as e:
raise ToolError(e.message, code=e.code, details=e.details) from e