Wiki spaces¶
Free-form markdown notes per space, with vault import, a directed page graph view, and an embedded Wiki Copilot agent that can read pages and (with wikis:write) upsert them. Toggle: wikiSpaces (default on).
| Feature | Status | Description |
|---|---|---|
| Wiki space CRUD | ✅ | /api/wiki-spaces; list/create/update/delete; optional group data scopes via access_group_wiki_spaces (local mode, same pattern as knowledge bases) |
| Wiki pages | ✅ | Path-per-space (e.g. guides/onboarding); GET/POST/PATCH/DELETE by id; PUT upsert .../pages/by-path/{path} for CLI; markdown body; cached page_index JSONB; GET .../pages/{id}/page-index; GET .../pages optional limit (1–500) + offset + path_prefix — total is full match count; omit limit to return all (e.g. editor tree) |
| Wiki files | ✅ | POST .../files (multipart), GET .../files/{id}/content (presigned redirect), DELETE .../files/{id}; S3/MinIO uses wiki/{space_id}/vault/{relative-path} when the multipart filename is a valid vault-relative path (folder import + CLI), else wiki/{space_id}/files/{file_id}/…; same vault path re-upload updates existing wiki_files row and overwrites the object (no duplicate storage_key) |
| Graph View | ✅ | GET .../graph — directed page graph from [[wikilinks]] and relative markdown links (excluding fenced code blocks); response { nodes, links, source_max_updated_at? }; when S3 is enabled, JSON cache at wiki/{space_id}/link-graph.json — used if object LastModified ≥ max(wiki_pages.updated_at) for the space, else recomputed and uploaded; SPA ?focus= (from the page editor) highlights that node and includes it in the same main-cluster zoomToFit set as the default view — it does not zoom the camera to that node alone |
| Vault import | ✅ | Zip: POST .../import/vault with archive. Folder (UI): Import folder opens an in-app dialog (skip .pdf / Office extensions), then Choose vault folder…; the browser's mandatory upload confirmation appears, then import starts immediately (no extra in-app confirm); paths omit the picked OS folder name (first segment of webkitRelativePath stripped so wiki paths start at vault contents); sequential uploads with progress; same skip rules, limits (~2000 files, 80 MB total, 25 MB/file), and image rewrites as bulk import; binaries require storage; markdown mirrored to wiki/{space_id}/vault/…/*.md (rewritten body) when storage is enabled; NUL bytes stripped from markdown/title/path text before insert (PostgreSQL UTF-8) |
| Permissions | ✅ | wikis:read / wikis:write with default SPA/API patterns; strict pattern middleware coverage via seeded security_permissions |
| UI | ✅ | /wikis, /wikis/:id, /wikis/:id/graph, /wikis/:id/pages/:pageId; Documents tab: GET/POST/DELETE /api/wiki-spaces/{id}/documents (pick from GET /api/documents in modal; persisted in DB), Pages (15 per page, path + page last updated; table-style rows), Documents (linked doc + document last updated); Wiki Copilot (fixed right rail, wide layout): embedded agent /api/agent (LangGraph: list/get pages, linked docs; upsert_wiki_page when the user has wikis:write); while streaming, tool invocations show as compact terminal-style rows interleaved with the assistant text in NDJSON event order; GFM message bodies; auto-scroll while replying; / in the message box opens wiki-skills completion (wiki-init, wiki-ingest, wiki-query, wiki-lint, wiki-update); conversation history (picker, new draft, delete; active id in sessionStorage per space); OPENKMS_AGENT_MODEL_ID or default LLM on Models (/models); Import folder / Import zip; sidebar Wiki Spaces; preview: react-markdown for /api/... images |
| Wiki ↔ documents | ✅ | wiki_space_documents join table; link/unlink/list on /api/wiki-spaces/{id}/documents with scope + wikis:write for mutations; GET list includes each linked document updated_at (in addition to linked_at) |
| Wiki Copilot API | ✅ | POST/GET /api/agent/conversations (list by wiki_space_id + surface), GET/DELETE/PATCH /api/agent/conversations/{id}, /api/agent/conversations/{id}/messages: POST with stream: true returns NDJSON — delta (tokens) plus tool_start / tool_end / tool_error (per-tool run_id, name, and truncated I/O) for a Cursor-style tool rail in the panel; stream: false returns JSON; DELETE .../messages/from/{message_id} — remove that message and all after it (restart from here; SPA: refresh under user bubble); first user message can set title when empty; LangGraph agent system prompt includes vendored wiki-skills under third-party/wiki-skills (git subtree) — see wiki agent prototype |
| openkms-cli | ✅ | openkms-cli wiki put, wiki sync, wiki upload-file (auth: OIDC or local Basic) |