diff --git a/apps/server/src/assets/openapi.json b/apps/server/src/assets/openapi.json index 3034c7e13..36f152909 100644 --- a/apps/server/src/assets/openapi.json +++ b/apps/server/src/assets/openapi.json @@ -1 +1 @@ -{"openapi":"3.1.1","info":{"title":"Trilium Notes - Sync server API","version":"0.96.6","description":"This is the internal sync server API used by Trilium Notes / TriliumNext Notes.\n\n_If you're looking for the officially supported External Trilium API, see [here](https://triliumnext.github.io/Docs/Wiki/etapi.html)._\n\nThis page does not yet list all routes. For a full list, see the [route controller](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/routes.ts).","contact":{"name":"TriliumNext issue tracker","url":"https://github.com/TriliumNext/Notes/issues"},"license":{"name":"GNU Free Documentation License 1.3 (or later)","url":"https://www.gnu.org/licenses/fdl-1.3"}},"paths":{"/api/setup/sync-seed":{"get":{"tags":["auth"],"summary":"Sync documentSecret value","description":"First step to logging in.","operationId":"setup-sync-seed","responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"syncVersion":{"type":"integer","example":34},"options":{"type":"object","properties":{"documentSecret":{"type":"string"}}}}}}}}},"security":[{"user-password":[]}]}},"/api/app-info":{"get":{"summary":"Get installation info","operationId":"app-info","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/app_info.ts"},"responses":{"200":{"description":"Installation info","content":{"application/json":{"schema":{"type":"object","properties":{"appVersion":{"type":"string","example":"0.91.6"},"dbVersion":{"type":"integer","example":228},"nodeVersion":{"type":"string","description":"value of process.version"},"syncVersion":{"type":"integer","example":34},"buildDate":{"type":"string","example":"2024-09-07T18:36:34Z"},"buildRevision":{"type":"string","example":"7c0d6930fa8f20d269dcfbcbc8f636a25f6bb9a7"},"dataDirectory":{"type":"string","example":"/var/lib/trilium"},"clipperProtocolVersion":{"type":"string","example":"1.0"},"utcDateTime":{"$ref":"#/components/schemas/UtcDateTime"}}}}}}},"security":[{"session":[]}]}},"/api/branches/{branchId}":{"delete":{"summary":"Delete branch (note clone)","operationId":"branches-delete","parameters":[{"name":"branchId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/BranchId"}},{"name":"taskId","in":"query","required":true,"schema":{"type":"string"},"description":"Task group identifier"},{"name":"eraseNotes","in":"query","schema":{"type":"boolean"},"required":false,"description":"Whether to erase the note immediately"},{"name":"last","in":"query","schema":{"type":"boolean"},"required":true,"description":"Whether this is the last request of this task group"}],"responses":{"200":{"description":"Branch successfully deleted","content":{"application/json":{"schema":{"type":"object","properties":{"noteDeleted":{"type":"boolean","description":"Whether the last note clone was deleted"}}}}}}},"security":[{"session":[]}],"tags":["data"]}},"/api/login/sync":{"post":{"tags":["auth"],"summary":"Log in using documentSecret","description":"The `hash` parameter is computed using a HMAC of the `documentSecret` and `timestamp`.","operationId":"login-sync","externalDocs":{"description":"HMAC calculation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66"},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"timestamp":{"$ref":"#/components/schemas/UtcDateTime"},"hash":{"type":"string"},"syncVersion":{"type":"integer","example":34}}}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"syncVersion":{"type":"integer","example":34},"options":{"type":"object","properties":{"documentSecret":{"type":"string"}}}}}}}},"400":{"description":"Sync version / document secret mismatch","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Non-matching sync versions, local is version ${server syncVersion}, remote is ${requested syncVersion}. It is recommended to run same version of Trilium on both sides of sync"}}}}}},"401":{"description":"Timestamp mismatch","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Auth request time is out of sync, please check that both client and server have correct time. The difference between clocks has to be smaller than 5 minutes"}}}}}}}}},"/api/notes/{noteId}":{"get":{"summary":"Retrieve note metadata","operationId":"notes-get","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}}],"responses":{"200":{"description":"Note metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Note"},{"$ref":"#/components/schemas/Timestamps"}]}}}}},"security":[{"session":[]}],"tags":["data"]},"delete":{"summary":"Delete note","operationId":"notes-delete","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}},{"name":"taskId","in":"query","required":true,"schema":{"type":"string"},"description":"Task group identifier"},{"name":"eraseNotes","in":"query","schema":{"type":"boolean"},"required":false,"description":"Whether to erase the note immediately"},{"name":"last","in":"query","schema":{"type":"boolean"},"required":true,"description":"Whether this is the last request of this task group"}],"responses":{"200":{"description":"Note successfully deleted"}},"security":[{"session":[]}],"tags":["data"]}},"/api/notes/{noteId}/blob":{"get":{"summary":"Retrieve note content","operationId":"notes-blob","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}}],"responses":{"304":{"description":"Note content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Blob"}}}}},"security":[{"session":[]}],"tags":["data"]}},"/api/notes/{noteId}/metadata":{"get":{"summary":"Retrieve note metadata (limited to timestamps)","operationId":"notes-metadata","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}}],"responses":{"200":{"description":"Note metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Timestamps"}}}}},"security":[{"session":[]}],"tags":["data"]}},"/api/sync/changed":{"get":{"summary":"Pull sync changes","operationId":"sync-changed","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts"},"parameters":[{"in":"query","name":"instanceId","required":true,"schema":{"type":"string"},"description":"Local instance ID"},{"in":"query","name":"lastEntityChangeId","required":true,"schema":{"type":"integer"},"description":"Last locally present change ID"},{"in":"query","name":"logMarkerId","required":true,"schema":{"type":"string"},"description":"Marker to identify this request in server log"}],"responses":{"200":{"description":"Sync changes, limited to approximately one megabyte.","content":{"application/json":{"schema":{"type":"object","properties":{"entityChanges":{"type":"list","items":{"$ref":"#/components/schemas/EntityChange"}},"lastEntityChangeId":{"type":"integer","description":"If `outstandingPullCount > 0`, pass this as parameter in your next request to continue."},"outstandingPullCount":{"type":"int","example":42,"description":"Number of changes not yet returned by the remote."}}}}}}},"security":[{"session":[]}],"tags":["sync"]}},"/api/sync/update":{"put":{"summary":"Push sync changes","description":"Basic usage: set `pageCount = 1`, `pageIndex = 0`, and omit `requestId`. Supply your entity changes in the request body.","operationId":"sync-update","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts"},"parameters":[{"in":"header","name":"pageCount","required":true,"schema":{"type":"integer"}},{"in":"header","name":"pageIndex","required":true,"schema":{"type":"integer"}},{"in":"header","name":"requestId","schema":{"type":"string","description":"ID to identify paginated requests"}},{"in":"query","name":"logMarkerId","required":true,"schema":{"type":"string"},"description":"Marker to identify this request in server log"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"instanceId":{"type":"string","description":"Local instance ID"},"entities":{"type":"list","items":{"$ref":"#/components/schemas/EntityChange"}}}}}}},"responses":{"200":{"description":"Changes processed successfully"}},"security":[{"session":[]}],"tags":["sync"]}},"/api/tree":{"get":{"summary":"Retrieve tree data","operationId":"tree","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/tree.ts"},"parameters":[{"in":"query","name":"subTreeNoteId","required":false,"schema":{"type":"string"},"description":"Limit tree data to this note and descendants"}],"responses":{"200":{"description":"Notes, branches and attributes","content":{"application/json":{"schema":{"type":"object","properties":{"branches":{"type":"list","items":{"$ref":"#/components/schemas/Branch"}},"notes":{"type":"list","items":{"$ref":"#/components/schemas/Note"}},"attributes":{"type":"list","items":{"$ref":"#/components/schemas/Attribute"}}}}}}}},"security":[{"session":[]}],"tags":["data"]}}},"components":{},"tags":[]} \ No newline at end of file +{"openapi":"3.1.1","info":{"title":"Trilium Notes - Sync server API","version":"0.94.0","description":"This is the internal sync server API used by Trilium Notes / TriliumNext Notes.\n\n_If you're looking for the officially supported External Trilium API, see [here](https://triliumnext.github.io/Docs/Wiki/etapi.html)._\n\nThis page does not yet list all routes. For a full list, see the [route controller](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/routes.ts).","contact":{"name":"TriliumNext issue tracker","url":"https://github.com/TriliumNext/Notes/issues"},"license":{"name":"GNU Free Documentation License 1.3 (or later)","url":"https://www.gnu.org/licenses/fdl-1.3"}},"paths":{"/api/setup/sync-seed":{"get":{"tags":["auth"],"summary":"Sync documentSecret value","description":"First step to logging in.","operationId":"setup-sync-seed","responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"syncVersion":{"type":"integer","example":34},"options":{"type":"object","properties":{"documentSecret":{"type":"string"}}}}}}}}},"security":[{"user-password":[]}]}},"/api/anthropic/models":{"post":{"summary":"List available models from Anthropic","operationId":"anthropic-list-models","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"baseUrl":{"type":"string","description":"Optional custom Anthropic API base URL"}}}}}},"responses":{"200":{"description":"List of available Anthropic models","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"chatModels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"}}}},"embeddingModels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"}}}}}}}}},"500":{"description":"Error listing models"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/app-info":{"get":{"summary":"Get installation info","operationId":"app-info","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/app_info.ts"},"responses":{"200":{"description":"Installation info","content":{"application/json":{"schema":{"type":"object","properties":{"appVersion":{"type":"string","example":"0.91.6"},"dbVersion":{"type":"integer","example":228},"nodeVersion":{"type":"string","description":"value of process.version"},"syncVersion":{"type":"integer","example":34},"buildDate":{"type":"string","example":"2024-09-07T18:36:34Z"},"buildRevision":{"type":"string","example":"7c0d6930fa8f20d269dcfbcbc8f636a25f6bb9a7"},"dataDirectory":{"type":"string","example":"/var/lib/trilium"},"clipperProtocolVersion":{"type":"string","example":"1.0"},"utcDateTime":{"$ref":"#/components/schemas/UtcDateTime"}}}}}}},"security":[{"session":[]}]}},"/api/branches/{branchId}":{"delete":{"summary":"Delete branch (note clone)","operationId":"branches-delete","parameters":[{"name":"branchId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/BranchId"}},{"name":"taskId","in":"query","required":true,"schema":{"type":"string"},"description":"Task group identifier"},{"name":"eraseNotes","in":"query","schema":{"type":"boolean"},"required":false,"description":"Whether to erase the note immediately"},{"name":"last","in":"query","schema":{"type":"boolean"},"required":true,"description":"Whether this is the last request of this task group"}],"responses":{"200":{"description":"Branch successfully deleted","content":{"application/json":{"schema":{"type":"object","properties":{"noteDeleted":{"type":"boolean","description":"Whether the last note clone was deleted"}}}}}}},"security":[{"session":[]}],"tags":["data"]}},"/api/llm/embeddings/similar/{noteId}":{"get":{"summary":"Find similar notes based on a given note ID","operationId":"embeddings-similar-by-note","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"type":"string"}},{"name":"providerId","in":"query","required":false,"schema":{"type":"string"},"default":"openai","description":"Embedding provider ID"},{"name":"modelId","in":"query","required":false,"schema":{"type":"string"},"default":"text-embedding-3-small","description":"Embedding model ID"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"default":10,"description":"Maximum number of similar notes to return"},{"name":"threshold","in":"query","required":false,"schema":{"type":"number","format":"float"},"default":0.7,"description":"Similarity threshold (0.0-1.0)"}],"responses":{"200":{"description":"List of similar notes","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"similarNotes":{"type":"array","items":{"type":"object","properties":{"noteId":{"type":"string"},"title":{"type":"string"},"similarity":{"type":"number","format":"float"}}}}}}}}},"400":{"description":"Invalid request parameters"},"404":{"description":"Note not found"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/search":{"post":{"summary":"Search for notes similar to provided text","operationId":"embeddings-search-by-text","parameters":[{"name":"providerId","in":"query","required":false,"schema":{"type":"string"},"default":"openai","description":"Embedding provider ID"},{"name":"modelId","in":"query","required":false,"schema":{"type":"string"},"default":"text-embedding-3-small","description":"Embedding model ID"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"default":10,"description":"Maximum number of similar notes to return"},{"name":"threshold","in":"query","required":false,"schema":{"type":"number","format":"float"},"default":0.7,"description":"Similarity threshold (0.0-1.0)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"Text to search with"}}}}}},"responses":{"200":{"description":"List of similar notes","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"similarNotes":{"type":"array","items":{"type":"object","properties":{"noteId":{"type":"string"},"title":{"type":"string"},"similarity":{"type":"number","format":"float"}}}}}}}}},"400":{"description":"Invalid request parameters"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/providers":{"get":{"summary":"Get available embedding providers","operationId":"embeddings-get-providers","responses":{"200":{"description":"List of available embedding providers","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"isEnabled":{"type":"boolean"},"priority":{"type":"integer"},"config":{"type":"object"}}}}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/providers/{providerId}":{"patch":{"summary":"Update embedding provider configuration","operationId":"embeddings-update-provider","parameters":[{"name":"providerId","in":"path","required":true,"schema":{"type":"string"},"description":"Provider ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether provider is enabled"},"priority":{"type":"integer","description":"Priority order (lower is higher priority)"},"config":{"type":"object","description":"Provider-specific configuration"}}}}}},"responses":{"200":{"description":"Provider updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Invalid provider ID or configuration"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/reprocess":{"post":{"summary":"Reprocess embeddings for all notes","operationId":"embeddings-reprocess-all","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"providerId":{"type":"string","description":"Provider ID to use for reprocessing"},"modelId":{"type":"string","description":"Model ID to use for reprocessing"},"forceReprocess":{"type":"boolean","description":"Whether to reprocess notes that already have embeddings"}}}}}},"responses":{"200":{"description":"Reprocessing started","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"description":"Invalid provider ID or configuration"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/queue-status":{"get":{"summary":"Get status of the embedding processing queue","operationId":"embeddings-queue-status","parameters":[{"name":"jobId","in":"query","required":false,"schema":{"type":"string"},"description":"Optional job ID to get status for a specific processing job"}],"responses":{"200":{"description":"Queue status information","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"status":{"type":"string","enum":["idle","processing","paused"]},"progress":{"type":"number","format":"float","description":"Progress percentage (0-100)"},"details":{"type":"object"}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/stats":{"get":{"summary":"Get embedding statistics","operationId":"embeddings-stats","responses":{"200":{"description":"Embedding statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"stats":{"type":"object","properties":{"totalEmbeddings":{"type":"integer"},"providers":{"type":"object"},"modelCounts":{"type":"object"},"lastUpdated":{"type":"string","format":"date-time"}}}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/failed":{"get":{"summary":"Get list of notes that failed embedding generation","operationId":"embeddings-failed-notes","responses":{"200":{"description":"List of failed notes","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"failedNotes":{"type":"array","items":{"type":"object","properties":{"noteId":{"type":"string"},"title":{"type":"string"},"error":{"type":"string"},"failedAt":{"type":"string","format":"date-time"}}}}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/retry/{noteId}":{"post":{"summary":"Retry generating embeddings for a failed note","operationId":"embeddings-retry-note","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"type":"string"},"description":"Note ID to retry"},{"name":"providerId","in":"query","required":false,"schema":{"type":"string"},"description":"Provider ID to use (defaults to configured default)"},{"name":"modelId","in":"query","required":false,"schema":{"type":"string"},"description":"Model ID to use (defaults to provider default)"}],"responses":{"200":{"description":"Retry result","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"400":{"description":"Invalid request"},"404":{"description":"Note not found"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/retry-all-failed":{"post":{"summary":"Retry generating embeddings for all failed notes","operationId":"embeddings-retry-all-failed","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"providerId":{"type":"string","description":"Provider ID to use (defaults to configured default)"},"modelId":{"type":"string","description":"Model ID to use (defaults to provider default)"}}}}}},"responses":{"200":{"description":"Retry started","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"jobId":{"type":"string"}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/rebuild-index":{"post":{"summary":"Rebuild the vector store index","operationId":"embeddings-rebuild-index","responses":{"200":{"description":"Rebuild started","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"jobId":{"type":"string"}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/embeddings/index-rebuild-status":{"get":{"summary":"Get status of the vector index rebuild operation","operationId":"embeddings-rebuild-status","parameters":[{"name":"jobId","in":"query","required":false,"schema":{"type":"string"},"description":"Optional job ID to get status for a specific rebuild job"}],"responses":{"200":{"description":"Rebuild status information","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"status":{"type":"string","enum":["idle","in_progress","completed","failed"]},"progress":{"type":"number","format":"float","description":"Progress percentage (0-100)"},"message":{"type":"string"},"details":{"type":"object","properties":{"startTime":{"type":"string","format":"date-time"},"processed":{"type":"integer"},"total":{"type":"integer"}}}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/sessions":{"post":{"summary":"Create a new LLM chat session","operationId":"llm-create-session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Title for the chat session"},"systemPrompt":{"type":"string","description":"System message to set the behavior of the assistant"},"temperature":{"type":"number","description":"Temperature parameter for the LLM (0.0-1.0)"},"maxTokens":{"type":"integer","description":"Maximum tokens to generate in responses"},"model":{"type":"string","description":"Specific model to use (depends on provider)"},"provider":{"type":"string","description":"LLM provider to use (e.g., 'openai', 'anthropic', 'ollama')"},"contextNoteId":{"type":"string","description":"Note ID to use as context for the session"}}}}}},"responses":{"200":{"description":"Successfully created session","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"title":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}},"security":[{"session":[]}],"tags":["llm"]},"get":{"summary":"List all chat sessions","operationId":"llm-list-sessions","responses":{"200":{"description":"List of chat sessions","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"lastActive":{"type":"string","format":"date-time"},"messageCount":{"type":"integer"}}}}}}}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/sessions/{sessionId}":{"get":{"summary":"Retrieve a specific chat session","operationId":"llm-get-session","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chat session details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"},"lastActive":{"type":"string","format":"date-time"}}}}}},"404":{"description":"Session not found"}},"security":[{"session":[]}],"tags":["llm"]},"delete":{"summary":"Delete a chat session","operationId":"llm-delete-session","parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Session successfully deleted"},"404":{"description":"Session not found"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/chat/{chatNoteId}":{"patch":{"summary":"Update a chat's settings","operationId":"llm-update-chat","parameters":[{"name":"chatNoteId","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the chat note (formerly sessionId)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Updated title for the session"},"systemPrompt":{"type":"string","description":"Updated system prompt"},"temperature":{"type":"number","description":"Updated temperature setting"},"maxTokens":{"type":"integer","description":"Updated maximum tokens setting"},"model":{"type":"string","description":"Updated model selection"},"provider":{"type":"string","description":"Updated provider selection"},"contextNoteId":{"type":"string","description":"Updated note ID for context"}}}}}},"responses":{"200":{"description":"Session successfully updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}}}}}},"404":{"description":"Session not found"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/chat/{chatNoteId}/messages":{"post":{"summary":"Send a message to an LLM and get a response","operationId":"llm-send-message","parameters":[{"name":"chatNoteId","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the chat note (formerly sessionId)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"The user message to send to the LLM"},"options":{"type":"object","description":"Optional parameters for this specific message","properties":{"temperature":{"type":"number"},"maxTokens":{"type":"integer"},"model":{"type":"string"},"provider":{"type":"string"}}},"includeContext":{"type":"boolean","description":"Whether to include relevant notes as context"},"useNoteContext":{"type":"boolean","description":"Whether to use the session's context note"}}}}}},"responses":{"200":{"description":"LLM response","content":{"application/json":{"schema":{"type":"object","properties":{"response":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"noteId":{"type":"string"},"title":{"type":"string"},"similarity":{"type":"number"}}}},"sessionId":{"type":"string"}}}}}},"404":{"description":"Session not found"},"500":{"description":"Error processing request"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/indexes/stats":{"get":{"summary":"Get stats about the LLM knowledge base indexing status","operationId":"llm-index-stats","responses":{"200":{"description":"Index stats successfully retrieved"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/indexes":{"post":{"summary":"Start or continue indexing the knowledge base","operationId":"llm-start-indexing","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean","description":"Whether to force reindexing of all notes"}}}}}},"responses":{"200":{"description":"Indexing started successfully"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/indexes/failed":{"get":{"summary":"Get list of notes that failed to index","operationId":"llm-failed-indexes","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"Failed indexes successfully retrieved"}},"security":[{"session":[]}],"tags":["llm"]},"put":{"summary":"Retry indexing all failed notes","operationId":"llm-retry-all-indexes","responses":{"200":{"description":"Retry of all failed indexes successfully initiated"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/indexes/notes/{noteId}":{"put":{"summary":"Retry indexing a specific note that previously failed","operationId":"llm-retry-index","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Index retry successfully initiated"}},"security":[{"session":[]}],"tags":["llm"]},"post":{"summary":"Index a specific note for LLM knowledge base","operationId":"llm-index-note","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Note indexed successfully"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/indexes/notes/similar":{"get":{"summary":"Find notes similar to a query string","operationId":"llm-find-similar-notes","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string"}},{"name":"contextNoteId","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":5}}],"responses":{"200":{"description":"Similar notes found successfully"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/indexes/context":{"get":{"summary":"Generate context for an LLM query based on the knowledge base","operationId":"llm-generate-context","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string"}},{"name":"contextNoteId","in":"query","required":false,"schema":{"type":"string"}},{"name":"depth","in":"query","required":false,"schema":{"type":"integer","default":2}}],"responses":{"200":{"description":"Context generated successfully"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/llm/chat/{chatNoteId}/messages/stream":{"post":{"summary":"Stream a message to an LLM via WebSocket","operationId":"llm-stream-message","parameters":[{"name":"chatNoteId","in":"path","required":true,"schema":{"type":"string"},"description":"The ID of the chat note to stream messages to (formerly sessionId)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","description":"The user message to send to the LLM"},"useAdvancedContext":{"type":"boolean","description":"Whether to use advanced context extraction"},"showThinking":{"type":"boolean","description":"Whether to show thinking process in the response"}}}}}},"responses":{"200":{"description":"Streaming started successfully"},"404":{"description":"Session not found"},"500":{"description":"Error processing request"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/login/sync":{"post":{"tags":["auth"],"summary":"Log in using documentSecret","description":"The `hash` parameter is computed using a HMAC of the `documentSecret` and `timestamp`.","operationId":"login-sync","externalDocs":{"description":"HMAC calculation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66"},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"timestamp":{"$ref":"#/components/schemas/UtcDateTime"},"hash":{"type":"string"},"syncVersion":{"type":"integer","example":34}}}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"syncVersion":{"type":"integer","example":34},"options":{"type":"object","properties":{"documentSecret":{"type":"string"}}}}}}}},"400":{"description":"Sync version / document secret mismatch","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Non-matching sync versions, local is version ${server syncVersion}, remote is ${requested syncVersion}. It is recommended to run same version of Trilium on both sides of sync"}}}}}},"401":{"description":"Timestamp mismatch","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Auth request time is out of sync, please check that both client and server have correct time. The difference between clocks has to be smaller than 5 minutes"}}}}}}}}},"/api/notes/{noteId}":{"get":{"summary":"Retrieve note metadata","operationId":"notes-get","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}}],"responses":{"200":{"description":"Note metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Note"},{"$ref":"#/components/schemas/Timestamps"}]}}}}},"security":[{"session":[]}],"tags":["data"]},"delete":{"summary":"Delete note","operationId":"notes-delete","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}},{"name":"taskId","in":"query","required":true,"schema":{"type":"string"},"description":"Task group identifier"},{"name":"eraseNotes","in":"query","schema":{"type":"boolean"},"required":false,"description":"Whether to erase the note immediately"},{"name":"last","in":"query","schema":{"type":"boolean"},"required":true,"description":"Whether this is the last request of this task group"}],"responses":{"200":{"description":"Note successfully deleted"}},"security":[{"session":[]}],"tags":["data"]}},"/api/notes/{noteId}/blob":{"get":{"summary":"Retrieve note content","operationId":"notes-blob","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}}],"responses":{"304":{"description":"Note content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Blob"}}}}},"security":[{"session":[]}],"tags":["data"]}},"/api/notes/{noteId}/metadata":{"get":{"summary":"Retrieve note metadata (limited to timestamps)","operationId":"notes-metadata","parameters":[{"name":"noteId","in":"path","required":true,"schema":{"$ref":"#/components/schemas/NoteId"}}],"responses":{"200":{"description":"Note metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Timestamps"}}}}},"security":[{"session":[]}],"tags":["data"]}},"/api/llm/providers/ollama/models":{"get":{"summary":"List available models from Ollama","operationId":"ollama-list-models","parameters":[{"name":"baseUrl","in":"query","required":false,"schema":{"type":"string"},"description":"Optional custom Ollama API base URL"}],"responses":{"200":{"description":"List of available Ollama models","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"models":{"type":"array","items":{"type":"object"}}}}}}},"500":{"description":"Error listing models"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/openai/models":{"post":{"summary":"List available models from OpenAI","operationId":"openai-list-models","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"baseUrl":{"type":"string","description":"Optional custom OpenAI API base URL"}}}}}},"responses":{"200":{"description":"List of available OpenAI models","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"chatModels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"}}}},"embeddingModels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"}}}}}}}}},"500":{"description":"Error listing models"}},"security":[{"session":[]}],"tags":["llm"]}},"/api/sync/changed":{"get":{"summary":"Pull sync changes","operationId":"sync-changed","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts"},"parameters":[{"in":"query","name":"instanceId","required":true,"schema":{"type":"string"},"description":"Local instance ID"},{"in":"query","name":"lastEntityChangeId","required":true,"schema":{"type":"integer"},"description":"Last locally present change ID"},{"in":"query","name":"logMarkerId","required":true,"schema":{"type":"string"},"description":"Marker to identify this request in server log"}],"responses":{"200":{"description":"Sync changes, limited to approximately one megabyte.","content":{"application/json":{"schema":{"type":"object","properties":{"entityChanges":{"type":"array","items":{"$ref":"#/components/schemas/EntityChange"}},"lastEntityChangeId":{"type":"integer","description":"If `outstandingPullCount > 0`, pass this as parameter in your next request to continue."},"outstandingPullCount":{"type":"integer","example":42,"description":"Number of changes not yet returned by the remote."}}}}}}},"security":[{"session":[]}],"tags":["sync"]}},"/api/sync/update":{"put":{"summary":"Push sync changes","description":"Basic usage: set `pageCount = 1`, `pageIndex = 0`, and omit `requestId`. Supply your entity changes in the request body.","operationId":"sync-update","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts"},"parameters":[{"in":"header","name":"pageCount","required":true,"schema":{"type":"integer"}},{"in":"header","name":"pageIndex","required":true,"schema":{"type":"integer"}},{"in":"header","name":"requestId","schema":{"type":"string","description":"ID to identify paginated requests"}},{"in":"query","name":"logMarkerId","required":true,"schema":{"type":"string"},"description":"Marker to identify this request in server log"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"instanceId":{"type":"string","description":"Local instance ID"},"entities":{"type":"array","items":{"$ref":"#/components/schemas/EntityChange"}}}}}}},"responses":{"200":{"description":"Changes processed successfully"}},"security":[{"session":[]}],"tags":["sync"]}},"/api/tree":{"get":{"summary":"Retrieve tree data","operationId":"tree","externalDocs":{"description":"Server implementation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/tree.ts"},"parameters":[{"in":"query","name":"subTreeNoteId","required":false,"schema":{"type":"string"},"description":"Limit tree data to this note and descendants"}],"responses":{"200":{"description":"Notes, branches and attributes","content":{"application/json":{"schema":{"type":"object","properties":{"branches":{"type":"array","items":{"$ref":"#/components/schemas/Branch"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/Attribute"}}}}}}}},"security":[{"session":[]}],"tags":["data"]}},"/login":{"post":{"tags":["auth"],"summary":"Log in using password","description":"This will give you a Trilium session, which is required for some other API endpoints. `totpToken` is only required if the user configured TOTP authentication.","operationId":"login-normal","externalDocs":{"description":"HMAC calculation","url":"https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66"},"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["password"],"properties":{"password":{"type":"string"},"totpToken":{"type":"string"}}}}}},"responses":{"200":{"description":"Successful operation"},"401":{"description":"Password / TOTP mismatch"}}}}},"components":{"schemas":{"Attribute":{"type":"object","properties":{"attributeId":{"type":"string","example":"4G1DPrI58PAb"},"noteId":{"$ref":"#/components/schemas/NoteId"},"type":{"type":"string","enum":["label","relation"]},"name":{"type":"string","example":"internalLink"},"value":{"type":"string","example":"hA8aHSpTRdZ6","description":"If type = \"relation\", a note ID. Otherwise, the attribute content."},"position":{"type":"integer","example":20},"isInheritable":{"type":"boolean"}}},"Blob":{"type":"object","properties":{"blobId":{"type":"string","example":"8iqMIB8eiY1tPYmElfjm"},"content":{"type":["string","null"],"description":"`null` if not text."},"contentLength":{"type":"integer"},"dateModified":{"$ref":"#/components/schemas/DateTime"},"utcDateModified":{"$ref":"#/components/schemas/UtcDateTime"}}},"Branch":{"type":"object","required":["branchId","noteId","parentNoteId","notePosition"],"properties":{"branchId":{"$ref":"#/components/schemas/BranchId"},"noteId":{"$ref":"#/components/schemas/NoteId"},"parentNoteId":{"$ref":"#/components/schemas/NoteId"},"notePosition":{"type":"integer","example":20},"prefix":{"type":["string","null"]},"isExpanded":{"type":"boolean"}}},"BranchId":{"type":"string","example":"WUjhaGp4EKah_ur11rSfHkzeV","description":"Equal to `{parentNoteId}_{noteId}`"},"DateTime":{"type":"string","example":"2025-02-14 08:19:59.203+0100"},"EntityChange":{"type":"object","properties":{"entityChange":{"type":"object","properties":{"entityName":{"type":"string","example":"notes","description":"Database table for this entity."},"changeId":{"type":"string","example":"changeId9630","description":"ID, referenced in `entity_changes` table."}}},"entity":{"type":"object","description":"Encoded entity data. Object has one property for each database column."}}},"Note":{"type":"object","required":["noteId","title","isProtected","type","mime","blobId"],"properties":{"noteId":{"$ref":"#/components/schemas/NoteId"},"title":{"type":"string"},"isProtected":{"type":"boolean"},"type":{"type":"string","example":"text","enum":["text","code","render","file","image","search","relationMap","book","noteMap","mermaid","canvas","webView","launcher","doc","contentWidget","mindMap","geoMap"],"description":"[Reference list](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/note_types.ts)"},"mime":{"type":"string","example":"text/html"},"blobId":{"type":"string","example":"z4PhNX7vuL3xVChQ1m2A"}}},"NoteId":{"type":"string","example":"ur11rSfHkzeV","description":"12-character note ID. Special values: \"none\"`, `\"root\"."},"Timestamps":{"type":"object","properties":{"dateCreated":{"$ref":"#/components/schemas/DateTime"},"dateModified":{"$ref":"#/components/schemas/DateTime"},"utcDateCreated":{"$ref":"#/components/schemas/UtcDateTime"},"utcDateModified":{"$ref":"#/components/schemas/UtcDateTime"}}},"UtcDateTime":{"type":"string","example":"2025-02-13T07:42:47.698Z","description":"Result of `new Date().toISOString().replace('T', ' ')`"}},"securitySchemes":{"user-password":{"type":"apiKey","name":"trilium-cred","in":"header","description":"Username and password, formatted as `user:password`"},"session":{"type":"apiKey","in":"cookie","name":"trilium.sid"}}},"tags":[{"name":"auth","description":"Authentication"},{"name":"sync","description":"Synchronization"},{"name":"data"}]} \ No newline at end of file diff --git a/package.json b/package.json index c62d15db3..4ab602416 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "server:start-prod": "nx run server:start-prod", "electron:build": "nx build desktop", "chore:ci-update-nightly-version": "tsx ./scripts/update-nightly-version.ts", + "chore:generate-openapi": "tsx ./scripts/generate-openapi.ts", "chore:update-build-info": "tsx ./scripts/update-build-info.ts", "chore:update-version": "tsx ./scripts/update-version.ts", diff --git a/_regroup/bin/generate-openapi.ts b/scripts/generate-openapi.ts similarity index 92% rename from _regroup/bin/generate-openapi.ts rename to scripts/generate-openapi.ts index c422f93ab..3e1953d9e 100644 --- a/_regroup/bin/generate-openapi.ts +++ b/scripts/generate-openapi.ts @@ -5,18 +5,23 @@ import fs from "fs"; /* * Usage: npm run chore:generate-openapi - * Output: ./src/routes/api/openapi.json + * Output: ./apps/server/src/assets/openapi.json * * Inspect generated file by opening it in https://editor-next.swagger.io/ * */ +const scriptDir = dirname(fileURLToPath(import.meta.url)); +const outputPath = join(scriptDir, "..", "apps", "server", "src", "assets", "openapi.json"); + +const packageJson = JSON.parse(fs.readFileSync(join(scriptDir, "..", "package.json"), 'utf8')); + const options = { definition: { openapi: "3.1.1", info: { title: "Trilium Notes - Sync server API", - version: "0.93.0", + version: packageJson["version"], description: "This is the internal sync server API used by Trilium Notes / TriliumNext Notes.\n\n_If you're looking for the officially supported External Trilium API, see [here](https://triliumnext.github.io/Docs/Wiki/etapi.html)._\n\nThis page does not yet list all routes. For a full list, see the [route controller](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/routes.ts).", contact: { @@ -31,19 +36,17 @@ const options = { }, apis: [ // Put individual files here to have them ordered first. - "./src/routes/api/setup.ts", + "./apps/server/src/routes/api/setup.ts", // all other files - "./src/routes/api/*.ts", - "./src/routes/*.ts", - "./bin/generate-openapi.ts" + "./apps/server/src/routes/api/*.ts", + "./apps/server/src/routes/*.ts", + "./scripts/generate-openapi.ts" ] }; const openapiSpecification = swaggerJsdoc(options); -const scriptDir = dirname(fileURLToPath(import.meta.url)); -const outputPath = join(scriptDir, "..", "src", "routes", "api", "openapi.json"); fs.writeFileSync(outputPath, JSON.stringify(openapiSpecification)); -console.log("Saved to ", outputPath); +console.log("Saved to", outputPath); /** * @swagger