From ebac19ba6ef49578c0f6af2a762fbe0de06f877d Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Thu, 11 Dec 2025 21:31:05 +0100 Subject: [PATCH] docs: add library-desk integration requirements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Document required endpoints for wiki write operations - Include implementation guide for smart-create endpoint - Decision flow for when to use each write tool πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- docs/library-desk-requirements.md | 424 ++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 docs/library-desk-requirements.md diff --git a/docs/library-desk-requirements.md b/docs/library-desk-requirements.md new file mode 100644 index 0000000..e4298af --- /dev/null +++ b/docs/library-desk-requirements.md @@ -0,0 +1,424 @@ +# Library-Desk API Requirements for Tatlock Integration + +## Overview + +The Librarian agent in Tatlock needs additional endpoints in library-desk to support wiki page editing and content management. Currently, the API provides read operations but The Librarian needs write capabilities for: + +- Creating new wiki pages +- Updating existing wiki pages (content, title, tags, description) + +## Required Endpoints + +### 1. Create Wiki Page (Already Exists) + +**Endpoint:** `POST /wiki/pages` + +This endpoint already exists and works correctly. + +### 2. Update Wiki Page (Needs Enhancement) + +**Endpoint:** `PUT /wiki/pages/{page_id}` + +**Current Status:** May exist but needs verification that it supports partial updates. + +**Required Behavior:** +- Accept partial updates (only provided fields should be updated) +- Support updating: `content`, `title`, `tags`, `description` +- Auto-update vector embeddings after content changes +- Auto-update knowledge graph after content changes + +**Request Body:** +```json +{ + "content": "# New Content\n\nOptional - only if changing content", + "title": "Optional - only if renaming", + "tags": ["optional", "list", "of", "new", "tags"], + "description": "Optional new description" +} +``` + +**Query Parameters:** +- `user`: User identifier for multi-tenancy (required) + +**Response:** +```json +{ + "id": 42, + "path": "/projects/example", + "title": "Updated Title", + "description": "Updated description", + "content": "# New Content...", + "tags": ["updated", "tags"], + "updated_at": "2024-01-15T10:30:00Z" +} +``` + +**Notes:** +- Should trigger background tasks to re-index vectors and refresh graph entities +- Should validate that user has access to the page (namespace check) +- Should preserve fields that are not provided in the request + +## Use Cases for The Librarian + +### Adding New Knowledge +When a user says "Add this to the wiki" or "Create a page about X": +- Librarian uses `POST /wiki/pages` to create the page +- Tags are assigned based on context (dossiers) + +### Correcting Information +When a user says "Update the page about X" or "Fix this fact": +1. Librarian searches for the page with `GET /wiki/search` +2. Fetches full content with `GET /wiki/pages/{id}` +3. Updates with corrected content via `PUT /wiki/pages/{id}` + +### Organizing Knowledge +When a user says "Add this page to the projects dossier": +- Librarian updates just the tags field via `PUT /wiki/pages/{id}` + +## Integration Notes + +- The Librarian will call these endpoints via HTTP from Tatlock +- Authentication uses Bearer token (LIBRARY_DESK_API_KEY) +- All operations are scoped to the user's namespace +- Background processing (vectors, graph) should not block the response + +## Testing Checklist + +- [ ] `PUT /wiki/pages/{page_id}` accepts partial updates +- [ ] Updating content triggers vector re-indexing +- [ ] Updating content triggers graph entity extraction +- [ ] Tags can be updated independently of content +- [ ] Description can be updated independently +- [ ] Title can be updated (with path remaining the same) +- [ ] User namespace validation works correctly + + +===== IMPLEMENTATION INSTRUCTIONS ========= +# Librarian Wiki Integration Guide + +This document provides implementation instructions for integrating the library-desk wiki endpoints into the Librarian agent (Tatlock). + +## Available Endpoints + +### 1. Create Wiki Page + +**Endpoint:** `POST /wiki/pages` + +Use this for simple page creation when the Librarian already has the content. + +```python +async def create_wiki_page( + title: str, + path: str, + content: str, + tags: list[str], + description: str = "", + user: str = "default" +) -> dict: + """Create a new wiki page.""" + response = await http_client.post( + f"{LIBRARY_DESK_URL}/wiki/pages", + headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"}, + json={ + "title": title, + "path": path, + "content": content, + "tags": tags, + "description": description, + "user": user + } + ) + return response.json() +``` + +**When to use:** +- User provides specific content to add +- Librarian has already composed the content +- Simple note-taking or quick additions + +--- + +### 2. Smart Create Wiki Page (Recommended for Research) + +**Endpoint:** `POST /wiki/pages/smart-create` + +Use this when the Librarian should research a topic before creating the page. This endpoint: +1. Searches existing wiki, knowledge graph, and web for context +2. Uses LLM to synthesize findings into structured content +3. Creates the page with proper attribution +4. Automatically links entities bidirectionally + +```python +async def smart_create_wiki_page( + topic: str, + tags: list[str], + user: str = "default", + path: str | None = None, + include_web_research: bool = True, + include_wiki_search: bool = True +) -> dict: + """Create a wiki page with HybridRAG research.""" + response = await http_client.post( + f"{LIBRARY_DESK_URL}/wiki/pages/smart-create", + headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"}, + json={ + "topic": topic, + "path": path, # Optional - auto-generated from topic if not provided + "tags": tags, + "user": user, + "include_web_research": include_web_research, + "include_wiki_search": include_wiki_search + } + ) + return response.json() +``` + +**Response includes:** +```json +{ + "page": { + "id": 123, + "path": "/users/jpmschweitzer/technology/docker-orchestration", + "title": "Docker orchestration", + "content": "# Docker Orchestration\n\n...", + "tags": ["technology", "devops"], + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + }, + "research_summary": { + "wiki_results": 3, + "web_results": 8, + "graph_entities": 5, + "keywords_extracted": 12, + "timing_ms": 4500 + }, + "sources_used": 11, + "search_id": "uuid-for-reference", + "entity_linking": { + "forward_links": 5, + "backward_links": 3, + "pages_updated": 2 + } +} +``` + +**When to use:** +- User says "Create a page about X" +- User says "Add information about X to the wiki" +- Librarian needs to research before writing +- Topic benefits from context from existing knowledge + +--- + +### 3. Update Wiki Page + +**Endpoint:** `PUT /wiki/pages/{page_id}` + +Use this for modifying existing pages. Supports partial updates. + +```python +async def update_wiki_page( + page_id: int, + user: str = "default", + content: str | None = None, + title: str | None = None, + tags: list[str] | None = None, + description: str | None = None +) -> dict: + """Update an existing wiki page (partial updates supported).""" + # Only include fields that are being updated + update_data = {} + if content is not None: + update_data["content"] = content + if title is not None: + update_data["title"] = title + if tags is not None: + update_data["tags"] = tags + if description is not None: + update_data["description"] = description + + response = await http_client.put( + f"{LIBRARY_DESK_URL}/wiki/pages/{page_id}?user={user}", + headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"}, + json=update_data + ) + return response.json() +``` + +**When to use:** +- User says "Update the page about X" +- User says "Fix this information" +- User says "Add this page to the projects dossier" (update tags only) +- Correcting or enhancing existing content + +--- + +### 4. Search Wiki Pages + +**Endpoint:** `GET /wiki/search` + +Use this to find existing pages before updating. + +```python +async def search_wiki( + query: str, + user: str = "default" +) -> dict: + """Search wiki pages.""" + response = await http_client.get( + f"{LIBRARY_DESK_URL}/wiki/search", + headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"}, + params={"q": query, "user": user} + ) + return response.json() +``` + +--- + +### 5. Get Wiki Page + +**Endpoint:** `GET /wiki/pages/{page_id}` + +Use this to fetch full page content before editing. + +```python +async def get_wiki_page( + page_id: int, + user: str = "default" +) -> dict: + """Get a wiki page by ID.""" + response = await http_client.get( + f"{LIBRARY_DESK_URL}/wiki/pages/{page_id}", + headers={"Authorization": f"Bearer {LIBRARY_DESK_API_KEY}"}, + params={"user": user} + ) + return response.json() +``` + +--- + +## Decision Flow for Librarian + +``` +User Request + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Does user want to CREATE or UPDATE a page? β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β–Ό β–Ό + CREATE UPDATE + β”‚ β”‚ + β–Ό β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Does Librarian β”‚ β”‚ Search for the page β”‚ +β”‚ need to researchβ”‚ β”‚ GET /wiki/search β”‚ +β”‚ the topic? β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ β–Ό + β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + YES NO β”‚ Get full page contentβ”‚ + β”‚ β”‚ β”‚ GET /wiki/pages/{id} β”‚ + β–Ό β–Ό β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ smart- β”‚ β”‚ POST β”‚ β–Ό +β”‚ create β”‚ β”‚ /wiki/ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ β”‚ pages β”‚ β”‚ Update the page β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ PUT /wiki/pages/{id} β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Common Use Cases + +### 1. "Create a page about Docker Compose" + +```python +# Use smart-create for research-backed content +result = await smart_create_wiki_page( + topic="Docker Compose", + tags=["technology", "devops", "containers"], + user="jpmschweitzer" +) +# Returns page with synthesized content from wiki + web research +``` + +### 2. "Add this note to the wiki: Remember to renew SSL cert on Jan 15" + +```python +# Use simple create for user-provided content +result = await create_wiki_page( + title="SSL Certificate Renewal Reminder", + path="/reminders/ssl-renewal", + content="# SSL Certificate Renewal\n\nRemember to renew SSL cert on Jan 15", + tags=["reminders", "infrastructure"], + user="jpmschweitzer" +) +``` + +### 3. "Update the page about my home server to add the new IP" + +```python +# 1. Search for the page +search_results = await search_wiki("home server", user="jpmschweitzer") +page_id = search_results["results"][0]["id"] + +# 2. Get current content +page = await get_wiki_page(page_id, user="jpmschweitzer") + +# 3. Modify content (Librarian edits the markdown) +new_content = page["content"] + "\n\n## Updated IP\n\nNew IP: 192.168.1.100" + +# 4. Update the page +result = await update_wiki_page( + page_id=page_id, + content=new_content, + user="jpmschweitzer" +) +``` + +### 4. "Add this page to the projects dossier" + +```python +# Update only tags (partial update) +result = await update_wiki_page( + page_id=page_id, + tags=["projects", "existing-tag"], # Add "projects" tag + user="jpmschweitzer" +) +``` + +--- + +## Background Processing + +All write operations trigger background tasks that: + +1. **Vector Indexing:** Chunks content and generates embeddings in Qdrant +2. **Graph Extraction:** Extracts entities and creates Neo4j relationships +3. **Entity Linking:** (smart-create only) Links entities bidirectionally + +These run asynchronously and don't block the API response. + +--- + +## Authentication + +All endpoints require Bearer token authentication: + +``` +Authorization: Bearer {LIBRARY_DESK_API_KEY} +``` + +--- + +## Multi-Tenancy + +All operations are scoped to the user's namespace: +- Pages are stored under `/users/{user}/...` +- Vector collections are per-user: `library_desk_{user}` +- Graph nodes are labeled per-user: `User_{User}_Document` + +Always pass the `user` parameter to ensure proper isolation.