feat(precedent-library): auto-trigger CEO wakeup on manual extract requests
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9s

The "חלץ מטא-דאטה" / "חלץ הלכות" buttons in the UI used to only stamp
the queue (set metadata_extraction_requested_at / halacha_extraction_requested_at)
and rely on a human running `mcp__legal-ai__precedent_process_pending` from
local Claude Code to drain it.

That left the user with an unintuitive two-step flow: click button → run
local MCP tool. Meanwhile, the upload endpoint already does the right
thing — after ingest succeeds it calls `pc_wake_for_precedent_extraction`,
which creates a Paperclip issue, assigns it to the CEO, and wakes them
to run `precedent_process_pending` automatically.

Add the same wakeup call to the manual request-metadata / request-halachot
endpoints. Now clicking the button is sufficient — the CEO picks it up
and drains the queue without manual intervention.

Best-effort: matches the upload flow's failure semantics. The queue stamp
still happens even if the wakeup fails, so the user can fall back to the
manual MCP tool when needed. The wakeup outcome is included in the
response under `wakeup` for observability.

Coolify deploy required for the FastAPI container to pick this up.
This commit is contained in:
2026-05-07 06:48:51 +00:00
parent 171da84680
commit c7132ba0d2

View File

@@ -4389,18 +4389,41 @@ async def precedent_library_delete(case_law_id: str):
# drain the queue. # drain the queue.
async def _wake_ceo_for_precedent(case_law_id: UUID, kind: str) -> dict:
"""Trigger Paperclip CEO to drain the precedent extraction queue, mirroring
the upload flow (see ``precedent_library_upload`` → ``pc_wake_for_precedent_extraction``).
Best-effort — any failure is logged but doesn't surface to the user, who
can still invoke ``mcp__legal-ai__precedent_process_pending`` manually.
Returns a dict with the wakeup outcome for inclusion in the API response.
"""
record = await db.get_case_law(case_law_id)
if not record:
return {"ok": False, "skipped": "record_missing"}
try:
return await pc_wake_for_precedent_extraction(
case_law_id=str(case_law_id),
citation=str(record.get("case_number") or ""),
practice_area=str(record.get("practice_area") or ""),
)
except Exception:
logger.exception("precedent-extraction wakeup failed (non-fatal, kind=%s)", kind)
return {"ok": False, "error": "wakeup_failed"}
@app.post("/api/precedent-library/{case_law_id}/request-metadata") @app.post("/api/precedent-library/{case_law_id}/request-metadata")
async def precedent_request_metadata(case_law_id: str): async def precedent_request_metadata(case_law_id: str):
"""Stamp the case_law row as needing metadata extraction. The local """Stamp the case_law row as needing metadata extraction AND wake the
MCP worker (`precedent_process_pending_metadata`) will pick it up.""" Paperclip CEO so extraction runs automatically — same flow as upload."""
try: try:
cid = UUID(case_law_id) cid = UUID(case_law_id)
except ValueError: except ValueError:
raise HTTPException(400, "case_law_id לא תקין") raise HTTPException(400, "case_law_id לא תקין")
ok = await db.request_metadata_extraction(cid) ok = await db.request_metadata_extraction(cid)
if not ok: if not ok:
raise HTTPException(404, "פסיקה לא נמצאה (או לא מסוג external_upload)") raise HTTPException(404, "פסיקה לא נמצאה")
return {"queued": True, "case_law_id": case_law_id, "kind": "metadata"} wakeup = await _wake_ceo_for_precedent(cid, kind="metadata")
return {"queued": True, "case_law_id": case_law_id, "kind": "metadata", "wakeup": wakeup}
@app.post("/api/precedent-library/{case_law_id}/request-halachot") @app.post("/api/precedent-library/{case_law_id}/request-halachot")
@@ -4412,8 +4435,9 @@ async def precedent_request_halachot(case_law_id: str):
raise HTTPException(400, "case_law_id לא תקין") raise HTTPException(400, "case_law_id לא תקין")
ok = await db.request_halacha_extraction(cid) ok = await db.request_halacha_extraction(cid)
if not ok: if not ok:
raise HTTPException(404, "פסיקה לא נמצאה (או לא מסוג external_upload)") raise HTTPException(404, "פסיקה לא נמצאה")
return {"queued": True, "case_law_id": case_law_id, "kind": "halacha"} wakeup = await _wake_ceo_for_precedent(cid, kind="halacha")
return {"queued": True, "case_law_id": case_law_id, "kind": "halacha", "wakeup": wakeup}
@app.get("/api/precedent-library/queue/pending") @app.get("/api/precedent-library/queue/pending")