Files
mnemosyne/mnemosyne/library/api/urls.py
Robert Helewka f2af28d96d feat(api): add workspace + ingest REST endpoints for Daedalus
Adds the REST API surface that Daedalus calls to manage workspace
lifecycle and dispatch file ingestion. All endpoints under /library/api/:

  POST   /workspaces/                   create workspace (idempotent on
                                        workspace_id; library_type frozen)
  GET    /workspaces/{workspace_id}/    workspace status with item/chunk
                                        counts
  DELETE /workspaces/{workspace_id}/    delete workspace + reachable
                                        content; concept-safe (orphan-only
                                        Concept GC; concepts referenced
                                        elsewhere are preserved)

  POST   /ingest/                       queue a file for ingest. Idempotent
                                        on (library, source_ref, hash):
                                        same triple → return existing job;
                                        new hash → supersede.
  GET    /jobs/{job_id}/                poll job status
  POST   /jobs/{job_id}/retry/          re-dispatch a failed job
  GET    /jobs/?status=&library_uid=    list recent jobs

Workspace-Library lookup uses the unique workspace_id index added in the
schema commit. Concept GC runs as a separate transaction after item/chunk
delete so partial failures don't leave the global graph corrupted.

Tests cover serializer validation, IngestJob ORM behavior, the
(library, source_ref, hash) idempotency query pattern, and auth
boundaries on every new endpoint. Cypher correctness is validated by
manual end-to-end testing — no live Neo4j in unit tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 06:27:08 -04:00

44 lines
1.8 KiB
Python

"""
URL patterns for the library DRF API.
"""
from django.urls import path
from . import views, workspaces
app_name = "library-api"
urlpatterns = [
# Libraries
path("libraries/", views.library_list_create, name="library-list"),
path("libraries/<str:uid>/", views.library_detail, name="library-detail"),
# Collections
path("collections/", views.collection_list_create, name="collection-list"),
path("collections/<str:uid>/", views.collection_detail, name="collection-detail"),
# Items
path("items/", views.item_list_create, name="item-list"),
path("items/upload/", views.item_upload, name="item-upload"),
path("items/<str:uid>/", views.item_detail, name="item-detail"),
path("items/<str:uid>/reembed/", views.item_reembed, name="item-reembed"),
path("items/<str:uid>/status/", views.item_status, name="item-status"),
# Search (Phase 3)
path("search/", views.search, name="search"),
path("search/vector/", views.search_vector, name="search-vector"),
path("search/fulltext/", views.search_fulltext, name="search-fulltext"),
# Concepts (Phase 3)
path("concepts/", views.concept_list, name="concept-list"),
path("concepts/<str:uid>/graph/", views.concept_graph, name="concept-graph"),
# Workspaces (Daedalus integration)
path("workspaces/", workspaces.workspace_create, name="workspace-create"),
path(
"workspaces/<str:workspace_id>/",
workspaces.workspace_detail_or_delete,
name="workspace-detail",
),
# Ingest (Daedalus integration)
path("ingest/", views.ingest_create, name="ingest-create"),
path("jobs/", views.ingest_job_list, name="ingest-job-list"),
path("jobs/<str:job_id>/", views.ingest_job_detail, name="ingest-job-detail"),
path("jobs/<str:job_id>/retry/", views.ingest_job_retry, name="ingest-job-retry"),
]