### Run Frontend Development Server Source: https://github.com/yenche123/liubai/blob/cool/memory-bank/techContext.md Starts the local development server for the liubai web frontend using pnpm. This command installs dependencies and then launches the Vite development server. ```bash cd liubai-frontends/liubai-web pnpm i pnpm dev ``` -------------------------------- ### Install and Deploy Backend Source: https://github.com/yenche123/liubai/blob/cool/memory-bank/techContext.md Installs dependencies for the liubai backend and provides a placeholder for deployment to Laf. This involves setting up the necessary packages before deploying to the cloud environment. ```bash cd liubai-backends/liubai-laf pnpm i # Deploy to Laf ``` -------------------------------- ### Watch and Build VS Code Extension Source: https://github.com/yenche123/liubai/blob/cool/memory-bank/techContext.md Installs dependencies and starts a watch process for the liubai VS Code extension using pnpm. This is useful for iterative development of the extension. ```bash cd liubai-frontends/liubai-vscode-extension pnpm i pnpm watch ``` -------------------------------- ### AI Chat Example Flows (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Provides example TypeScript code snippets demonstrating different AI chat interaction flows, including starting a new chat, continuing an existing conversation, and sending images for analysis. ```typescript // 1. Start new chat const newChatRequest = { operateType: "chat", spaceId: "workspace-id", character: "assistant", prompt: "What's the weather like in Beijing today?", model: "deepseek-chat" } // 2. Continue conversation const continueRequest = { operateType: "chat", chat_id: "existing-chat-id", spaceId: "workspace-id", turn_text: "How about tomorrow?" } // 3. Send image for analysis (vision models) const imageRequest = { operateType: "chat", chat_id: "chat-id", spaceId: "workspace-id", turn_text: "What's in this image?", turn_images: [{ url: "https://cdn.example.com/image.jpg", width: 800, height: 600 }] } ``` -------------------------------- ### AI Tool Definitions and Examples (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Defines the types for AI tool names and the structure for tool definitions, compatible with OpenAI's format. Includes an example of a web search tool definition. ```typescript type AiToolName = | "web_search" // Search the web | "draw_picture" // Generate images via DALL-E/etc | "add_note" // Create a new note/thread | "add_todo" // Create a todo item | "translate" // Translate text | "other" // Custom tools // Tool definition format (OpenAI-compatible) interface OaiTool { type: "function" function: { name: string description: string parameters: { type: "object" properties: Record required: string[] } } } // Example: Web search tool definition const webSearchTool: OaiTool = { type: "function", function: { name: "web_search", description: "Search the web for current information", parameters: { type: "object", properties: { query: { type: "string", description: "The search query" } }, required: ["query"] } } } ``` -------------------------------- ### User Login API Flow Examples (JavaScript) Source: https://context7.com/yenche123/liubai/llms.txt Illustrates JavaScript code snippets for interacting with the User Login API, including initializing the login process, sending email verification codes, and verifying codes for authentication. ```javascript // 1. Initialize login (get public key for encryption) const initResponse = await fetch("/user-login", { method: "POST", body: JSON.stringify({ operateType: "init" }) }) // Returns: { publicKey, state, githubOAuthClientId?, googleOAuthClientId?, wxGzhAppid? } // 2. Email login - Step 1: Send code const sendCode = await fetch("/user-login", { method: "POST", body: JSON.stringify({ operateType: "email", enc_email: encryptWithRSA(email, publicKey), // RSA encrypted state: loginState }) }) // 3. Email login - Step 2: Verify code const verifyCode = await fetch("/user-login", { method: "POST", body: JSON.stringify({ operateType: "email_code", enc_email: encryptWithRSA(email, publicKey), email_code: "123456", enc_client_key: encryptWithRSA(`client_key_${clientKey}`, publicKey), state: loginState }) }) // Response on success interface LoginResponse { code: "0000" data: { userId: string email?: string open_id: string token: string serial_id: string theme: "system" | "light" | "dark" language: "system" | "zh-Hans" | "zh-Hant" | "en" spaceMemberList: LiuSpaceAndMember[] subscription?: UserSubscription } } ``` -------------------------------- ### Fetch Thread List using Sync-Get API (TypeScript & cURL) Source: https://context7.com/yenche123/liubai/llms.txt This example shows how to request a list of threads using the `sync-get` cloud function. It defines the structure for the `SyncGetRequest` and specifically the `SyncGet_ThreadList` atom, demonstrating various filtering and sorting options. A cURL command is provided for making the actual API call. ```typescript // Fetch threads with various view types const threadListAtom: SyncGet_ThreadList = { taskType: "thread_list", taskId: "unique-task-id-1", spaceId: "workspace-id", viewType: "INDEX", // INDEX | PINNED | TRASH | CALENDAR | TODAY_FUTURE | PAST | STATE | TAG | FAVORITE limit: 16, lastItemStamp: 1699999999999, // For pagination sort: "desc", // Optional filters stateId: "state-uuid", // Required when viewType is STATE tagId: "tag-uuid", // Required when viewType is TAG specific_ids: ["id1", "id2"], // Filter to specific IDs excluded_ids: ["id3"] } ``` ```bash curl -X POST "https://your-laf-domain.com/sync-get" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "operateType": "general_sync", "atoms": [{ "taskType": "thread_list", "taskId": "task-001", "spaceId": "ws-123", "viewType": "INDEX", "limit": 20 }] }' ``` -------------------------------- ### Workspace & Member Operations in TypeScript Source: https://context7.com/yenche123/liubai/llms.txt Contains TypeScript examples for updating workspace configurations like tags and state columns, as well as modifying member details such as nicknames and avatars. These are structured as SyncSetAtom tasks. ```typescript // Update workspace tags const updateWorkspaceTags: SyncSetAtom = { taskType: "workspace-tag", taskId: "task-ws-tag-001", operateStamp: Date.now(), workspace: { id: "workspace-id", tagList: [ { tagId: "tag-1", text: "Work", color: "#FF5733" }, { tagId: "tag-2", text: "Personal", color: "#33FF57" } ] } } // Update workspace state config (kanban columns) const updateStateConfig: SyncSetAtom = { taskType: "workspace-state_config", taskId: "task-state-cfg-001", operateStamp: Date.now(), workspace: { id: "workspace-id", stateConfig: { updatedStamp: Date.now(), stateList: [ { id: "state-1", text: "Todo", color: "#FFA500" }, { id: "state-2", text: "In Progress", color: "#0000FF" }, { id: "state-3", text: "Done", color: "#00FF00" } ] } } } // Update member nickname const updateMemberNickname: SyncSetAtom = { taskType: "member-nickname", taskId: "task-nickname-001", operateStamp: Date.now(), member: { id: "member-id", name: "New Display Name" } } // Update member avatar const updateMemberAvatar: SyncSetAtom = { taskType: "member-avatar", taskId: "task-avatar-001", operateStamp: Date.now(), member: { id: "member-id", avatar: { url: "https://cdn.example.com/avatar.jpg", width: 200, height: 200 } } } ``` -------------------------------- ### Create Thread Operation (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Provides a TypeScript example for creating a new thread using the Sync-Set API. It includes essential fields like spaceId, title, content (liuDesc), and optional scheduling and tagging information. ```typescript const createThread: SyncSetAtom = { taskType: "thread-post", taskId: "task-create-001", operateStamp: Date.now(), thread: { first_id: "client-generated-uuid", // Min 20 chars spaceId: "workspace-id", title: "Meeting Notes", liuDesc: [ { type: "paragraph", children: [{ text: "Discussion points..." }] } ], images: [], files: [], oState: "OK", editedStamp: Date.now(), createdStamp: Date.now(), // Optional scheduling calendarStamp: 1700000000000, whenStamp: 1700000000000, remindStamp: 1699999000000, remindMe: { type: "early", early_minute: 30 }, // Tags and states tagIds: ["tag-uuid-1"], tagSearched: ["tag-uuid-1"], stateId: "state-uuid", stateStamp: Date.now(), // AI settings aiReadable: "Y", aiChatId: "ai-chat-id" // Link to AI conversation } } ``` -------------------------------- ### Edit Thread Operation (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Illustrates how to edit an existing thread using the Sync-Set API. This example shows updating fields like title, content, and scheduling information, referencing the thread by its ID. ```typescript const editThread: SyncSetAtom = { taskType: "thread-edit", taskId: "task-edit-001", operateStamp: Date.now(), thread: { id: "existing-thread-id", first_id: "original-first-id", title: "Updated Title", liuDesc: [ { type: "paragraph", children: [{ text: "Updated content..." }] } ], images: [], files: [], editedStamp: Date.now(), // Update scheduling calendarStamp: 1700100000000, whenStamp: 1700100000000, remindStamp: 1700099000000, remindMe: { type: "early", early_minute: 15 }, // Update tags tagIds: ["tag-uuid-2"], tagSearched: ["tag-uuid-2"], stateId: "new-state-uuid", stateStamp: Date.now() } } ``` -------------------------------- ### Retrieve Drafts (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Demonstrates how to retrieve draft data using different parameters like draft ID, thread editing context, or workspace ID. These examples define the structure for fetching draft information. ```typescript const draftById: SyncGet_Draft = { taskType: "draft_data", taskId: "task-006", draft_id: "draft-uuid" } // Get draft for editing a thread const draftForThread: SyncGet_Draft = { taskType: "draft_data", taskId: "task-007", threadEdited: "thread-id" } // Get new thread draft in a workspace const newDraft: SyncGet_Draft = { taskType: "draft_data", taskId: "task-008", spaceId: "workspace-id" } ``` -------------------------------- ### Query Comments using Sync-Get API (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt This snippet illustrates various ways to query comments using the `sync-get` cloud function. It defines different `SyncGet_CommentList` types for fetching comments under a thread, retrieving child comments, getting a parent comment chain, and finding the hottest comments. ```typescript // Get comments under a thread (level 1 comments) const commentsUnderThread: SyncGet_CommentList_A = { taskType: "comment_list", taskId: "task-002", loadType: "under_thread", targetThread: "thread-id", sort: "asc", limit: 9, lastItemStamp: 1699999999999 } // Get child comments (replies to a comment) const childComments: SyncGet_CommentList_B = { taskType: "comment_list", taskId: "task-003", loadType: "find_children", commentId: "parent-comment-id", sort: "asc", limit: 9 } // Get parent comment chain const parentComments: SyncGet_CommentList_C = { taskType: "comment_list", taskId: "task-004", loadType: "find_parent", parentWeWant: "comment-id", grandparent: "grandparent-comment-id", batchNum: 2 } // Get hottest comments (sorted by engagement score) const hottestComments: SyncGet_CommentList_D = { taskType: "comment_list", taskId: "task-005", loadType: "find_hottest", commentId: "thread-or-comment-id" } ``` -------------------------------- ### Draft Retrieval API Source: https://context7.com/yenche123/liubai/llms.txt This section details how to retrieve drafts. You can fetch a draft by its ID, retrieve a draft for editing a specific thread, or get a new draft within a workspace. ```APIDOC ## Draft Retrieval API ### Description Retrieves draft content based on different criteria. ### Method GET ### Endpoint `/api/drafts` (Hypothetical endpoint, actual may vary) ### Query Parameters - **draft_id** (string) - Optional - The unique identifier of the draft to retrieve. - **threadEdited** (string) - Optional - The ID of the thread for which to retrieve the draft for editing. - **spaceId** (string) - Optional - The ID of the workspace to retrieve a new draft for. ### Response #### Success Response (200) - **code** (string) - "0000" for success. - **taskId** (string) - The ID of the task. - **list** (array) - An array of draft objects matching the query. #### Response Example ```json { "code": "0000", "taskId": "task-006", "list": [ { "id": "draft-uuid", "status": "has_data", "parcelType": "content", "content": { "_id": "content-id", "first_id": "first-id", "isMine": true, "author": { "userId": "user-id" }, "spaceId": "workspace-id", "spaceType": "Team", "infoType": "THREAD", "oState": "OK", "title": "Sample Draft Title", "liuDesc": [ { "type": "paragraph", "children": [ { "text": "This is the content of the draft." } ] } ], "createdStamp": 1678886400000, "editedStamp": 1678886400000, "tagIds": [], "emojiData": {}, "levelOne": 0, "levelOneAndTwo": 0 } } ] } ``` ``` -------------------------------- ### Plan Mode Workflow Diagram Source: https://github.com/yenche123/liubai/blob/cool/memory-bank/README.md Mermaid diagram illustrating the Plan Mode workflow. This mode involves reading the Memory Bank, checking file completeness, planning, documenting in chat, verifying context, developing a strategy, and presenting the approach. ```mermaid flowchart TD Start[Start] --> ReadFiles[Read Memory Bank] ReadFiles --> CheckFiles{Files Complete?} CheckFiles -->|No| Plan[Create Plan] Plan --> Document[Document in Chat] CheckFiles -->|Yes| Verify[Verify Context] Verify --> Strategy[Develop Strategy] Strategy --> Present[Present Approach] ``` -------------------------------- ### File Upload Utility (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Frontend utility for uploading files to cloud storage (Qiniu) using the CloudFiler class. It handles both image and general file uploads, returning structured data upon successful upload. Dependencies include the CloudFiler utility and potentially types like Cloud_ImageStore and Cloud_FileStore. ```typescript import CloudFiler from "@/utils/cloud/CloudFiler" // Upload image const imageFile: File = // from input or drag-drop const uploadResult = await CloudFiler.upload({ file: imageFile, prefix: "user-images", type: "image" }) if (uploadResult.code === "0000") { const imageData: Cloud_ImageStore = { id: uploadResult.data.key, url: uploadResult.data.url, width: uploadResult.data.width, height: uploadResult.data.height, blurhash: uploadResult.data.blurhash } } // Upload file/document const docFile: File = // PDF, DOC, etc. const fileResult = await CloudFiler.upload({ file: docFile, prefix: "user-files", type: "file" }) if (fileResult.code === "0000") { const fileData: Cloud_FileStore = { id: fileResult.data.key, url: fileResult.data.url, name: docFile.name, suffix: "pdf", size: docFile.size } } ``` -------------------------------- ### Sync-Set API (Mutations) Source: https://context7.com/yenche123/liubai/llms.txt The `sync-set` API handles all data mutations including creating, updating, and deleting content. It supports general sync operations with multiple atoms or single sync operations. ```APIDOC ## Sync-Set API (`sync-set.ts`) ### Description Handles all data mutations including creating, updating, and deleting content. Supports general sync operations (up to 10 atoms) and single sync operations (1 atom). ### Method POST ### Endpoint `/api/sync-set` (Hypothetical endpoint, actual may vary) ### Request Body - **operateType** (string) - Required - Type of operation: "general_sync" or "single_sync". - **atoms** (array) - Required - An array of `SyncSetAtom` objects. #### SyncSetAtom Object - **taskType** (string) - Required - Type of task (e.g., "thread-post", "thread-edit", "thread-delete"). - **taskId** (string) - Required - Unique identifier for the task. - **operateStamp** (number) - Required - Timestamp of the operation. - **thread** (object) - Optional - Contains thread-related data for the operation. - **comment** (object) - Optional - Contains comment-related data. - **draft** (object) - Optional - Contains draft-related data. - **workspace** (object) - Optional - Contains workspace-related data. - **member** (object) - Optional - Contains member-related data. - **collection** (object) - Optional - Contains collection-related data. ### Create Thread #### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "thread-post", "taskId": "task-create-001", "operateStamp": 1678886400000, "thread": { "first_id": "client-generated-uuid", "spaceId": "workspace-id", "title": "Meeting Notes", "liuDesc": [ { "type": "paragraph", "children": [ { "text": "Discussion points..." } ] } ], "images": [], "files": [], "oState": "OK", "editedStamp": 1678886400000, "createdStamp": 1678886400000, "calendarStamp": 1700000000000, "whenStamp": 1700000000000, "remindStamp": 1699999000000, "remindMe": { "type": "early", "early_minute": 30 }, "tagIds": ["tag-uuid-1"], "tagSearched": ["tag-uuid-1"], "stateId": "state-uuid", "stateStamp": 1678886400000, "aiReadable": "Y", "aiChatId": "ai-chat-id" } } ] } ``` ### Edit Thread #### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "thread-edit", "taskId": "task-edit-001", "operateStamp": 1678886400000, "thread": { "id": "existing-thread-id", "first_id": "original-first-id", "title": "Updated Title", "liuDesc": [ { "type": "paragraph", "children": [ { "text": "Updated content..." } ] } ], "images": [], "files": [], "editedStamp": 1678886400000, "calendarStamp": 1700100000000, "whenStamp": 1700100000000, "remindStamp": 1700099000000, "remindMe": { "type": "early", "early_minute": 15 }, "tagIds": ["tag-uuid-2"], "tagSearched": ["tag-uuid-2"], "stateId": "new-state-uuid", "stateStamp": 1678886400000 } } ] } ``` ### Thread State Operations #### Delete Thread (Move to Trash) ##### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "thread-delete", "taskId": "task-delete-001", "operateStamp": 1678886400000, "thread": { "id": "thread-id", "removedStamp": 1678886400000 } } ] } ``` #### Restore Thread from Trash ##### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "undo_thread-delete", "taskId": "task-restore-001", "operateStamp": 1678886400000, "thread": { "id": "thread-id" } } ] } ``` #### Permanent Delete Thread ##### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "thread-delete_forever", "taskId": "task-perm-delete-001", "operateStamp": 1678886400000, "thread": { "id": "thread-id" } } ] } ``` #### Pin Thread ##### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "thread-pin", "taskId": "task-pin-001", "operateStamp": 1678886400000, "thread": { "id": "thread-id", "pinStamp": 1678886400000 } } ] } ``` #### Unpin Thread ##### Request Example ```json { "operateType": "single_sync", "atoms": [ { "taskType": "undo_thread-pin", "taskId": "task-unpin-001", "operateStamp": 1678886400000, "thread": { "id": "thread-id", "pinStamp": 0 } } ] } ``` ### Response #### Success Response (200) - **code** (string) - "0000" for success. - **taskId** (string) - The ID of the task. - **errMsg** (string) - Error message if operation failed. #### Response Example ```json { "code": "0000", "taskId": "task-create-001" } ``` ``` -------------------------------- ### File Upload (CloudFiler) Source: https://context7.com/yenche123/liubai/llms.txt Utility for uploading files to cloud storage (Qiniu). Supports uploading images and general files/documents. ```APIDOC ## File Upload (CloudFiler) ### Description Frontend utility for uploading files to cloud storage (Qiniu). This function handles both image uploads and general file/document uploads, returning relevant metadata upon successful upload. ### Method POST (Implicit via CloudFiler.upload) ### Endpoint Not directly exposed as an HTTP endpoint; used via the CloudFiler utility. ### Parameters #### Request Body (for CloudFiler.upload) - **file** (File) - Required - The file object to upload. - **prefix** (string) - Required - The storage path prefix (e.g., "user-images", "user-files"). - **type** (string) - Required - The type of file being uploaded ('image' or 'file'). ### Request Example ```typescript // Upload image const imageFile: File = // ... obtained from input or drag-drop const uploadResult = await CloudFiler.upload({ file: imageFile, prefix: "user-images", type: "image" }); // Upload file/document const docFile: File = // ... PDF, DOC, etc. const fileResult = await CloudFiler.upload({ file: docFile, prefix: "user-files", type: "file" }); ``` ### Response #### Success Response (Code '0000') - **code** (string) - "0000" indicates success. - **data** (object) - Contains upload details: - **key** (string) - The unique identifier/key of the uploaded file in cloud storage. - **url** (string) - The accessible URL of the uploaded file. - **width** (number) - (For images) The width of the image. - **height** (number) - (For images) The height of the image. - **blurhash** (string) - (For images) The blurhash representation of the image. - **name** (string) - (For files) The original name of the file. - **suffix** (string) - (For files) The file extension. - **size** (number) - (For files) The size of the file in bytes. #### Response Example (Image) ```json { "code": "0000", "data": { "key": "user-images/abcdef12345.jpg", "url": "https://your-cloud-storage.com/user-images/abcdef12345.jpg", "width": 1920, "height": 1080, "blurhash": "LHLx+X%g00xZ?w%g00xZ?w%g" } } ``` #### Response Example (File) ```json { "code": "0000", "data": { "key": "user-files/document.pdf", "url": "https://your-cloud-storage.com/user-files/document.pdf", "name": "document.pdf", "suffix": "pdf", "size": 102400 } } ``` ``` -------------------------------- ### Act Mode Workflow Diagram Source: https://github.com/yenche123/liubai/blob/cool/memory-bank/README.md Mermaid diagram illustrating the Act Mode workflow. This mode focuses on checking the Memory Bank for context, updating documentation, executing tasks, and documenting any changes made. ```mermaid flowchart TD Start[Start] --> Context[Check Memory Bank] Context --> Update[Update Documentation] Update --> Execute[Execute Task] Execute --> Document[Document Changes] ``` -------------------------------- ### General API Patterns Source: https://context7.com/yenche123/liubai/llms.txt Guidelines for interacting with Liubai's core APIs, including content operations and authentication. ```APIDOC ## General API Patterns ### Description This section outlines the recommended patterns for interacting with Liubai's core content APIs and authentication mechanisms. Adhering to these patterns ensures proper data synchronization, conflict resolution, and secure access. ### Content Operations All content operations (reading, writing, updating) should utilize the `sync-get` and `sync-set` APIs. These APIs are designed for multi-platform synchronization and include mechanisms for conflict resolution. #### `sync-get` API - **Method**: GET - **Endpoint**: `/api/sync/get` - **Description**: Retrieves content based on specified parameters. Supports filtering and pagination. - **Parameters**: Query parameters for filtering, sorting, and pagination. - **Response**: Returns content data along with `operateStamp` for optimistic concurrency. #### `sync-set` API - **Method**: POST - **Endpoint**: `/api/sync/set` - **Description**: Saves or updates content. Requires `operateStamp` for optimistic concurrency control. - **Request Body**: Content data including the `operateStamp`. - **Response**: Confirmation of successful save, potentially returning updated `operateStamp`. ### Conflict Resolution Utilize the `operateStamp` timestamp provided in responses from `sync-get` to ensure optimistic concurrency. When updating content via `sync-set`, include the latest `operateStamp` received. The backend will reject updates if the `operateStamp` does not match the current version, preventing data loss. ### AI System - Custom Tools The AI system supports custom tools through an OpenAI-compatible function calling interface. This allows developers to extend AI capabilities with custom logic, such as: - Automated note creation from external data. - Web search integration for information retrieval. - Image generation via integrated services. ### Authentication - **Token-Based Authentication**: API requests should include authentication tokens in the headers (e.g., `Authorization: Bearer `). - **Multi-Provider OAuth**: The platform supports a unified login flow across various providers (e.g., Google, GitHub). Implementations should follow the standard OAuth 2.0 protocol. ### Data Privacy Liubai employs an encryption-first approach to data privacy. Payloads may be encrypted, requiring appropriate handling on both client and server sides. ``` -------------------------------- ### Sync-Get API Source: https://context7.com/yenche123/liubai/llms.txt The `sync-get` cloud function retrieves various types of data including threads, comments, drafts, and collections. It supports multiple task types for different query patterns and allows for pagination. ```APIDOC ## Sync-Get API (`sync-get.ts`) The `sync-get` cloud function retrieves data including threads, comments, drafts, and collections. It supports multiple task types for different query patterns. ### Method POST ### Endpoint `/sync-get` ### Parameters #### Request Body - **operateType** (string) - Required - Must be `"general_sync"`. - **atoms** (array) - Required - An array of sync get atom objects (1-5 atoms per request). - **atom** (object) - Represents a single data retrieval task. - **taskType** (string) - Required - The type of data to retrieve (e.g., `"thread_list"`, `"comment_list"`). - **taskId** (string) - Required - A unique identifier for the task. - **spaceId** (string) - Required - The ID of the workspace. - **viewType** (string) - Optional - For `thread_list`, specifies the view (e.g., `"INDEX"`, `"PINNED"`, `"TRASH"`). - **limit** (number) - Optional - The maximum number of items to return. - **lastItemStamp** (number) - Optional - Timestamp for pagination. - **sort** (string) - Optional - Sort order (`"asc"` or `"desc"`). - **stateId** (string) - Optional - Filter by state ID (required for `viewType: "STATE"`). - **tagId** (string) - Optional - Filter by tag ID (required for `viewType: "TAG"`). - **specific_ids** (array) - Optional - Array of specific IDs to retrieve. - **excluded_ids** (array) - Optional - Array of IDs to exclude. - **loadType** (string) - Optional - For `comment_list`, specifies how to load comments (e.g., `"under_thread"`, `"find_children"`). - **targetThread** (string) - Optional - For `comment_list`, the ID of the thread to get comments from. - **commentId** (string) - Optional - For `comment_list`, the ID of the comment to get replies to or the base for hottest comments. - **parentWeWant** (string) - Optional - For `comment_list`, specifies the parent comment for chain loading. - **grandparent** (string) - Optional - For `comment_list`, specifies the grandparent comment for chain loading. - **batchNum** (number) - Optional - For `comment_list`, batch number for chain loading. ### Request Example ```json { "operateType": "general_sync", "atoms": [ { "taskType": "thread_list", "taskId": "task-001", "spaceId": "ws-123", "viewType": "INDEX", "limit": 20 }, { "taskType": "comment_list", "taskId": "task-002", "loadType": "under_thread", "targetThread": "thread-id", "sort": "asc", "limit": 9 } ] } ``` ### Response #### Success Response (200) - **code** (string) - "0000" indicates success. - **data** (object) - The encrypted response data containing the results of the sync operations. #### Response Example ```json { "code": "0000", "data": "encrypted_response_payload" } ``` ``` -------------------------------- ### User Login API Source: https://context7.com/yenche123/liubai/llms.txt Handles user authentication through various methods including email, phone, OAuth providers, and IDE extension authentication. ```APIDOC ## POST /user-login ### Description Authenticates users via multiple methods, including email verification, phone verification, OAuth flows (GitHub, Google, WeChat), and IDE extension authentication. ### Method POST ### Endpoint /user-login ### Parameters #### Request Body - **operateType** (string) - Required - Specifies the login operation (e.g., 'init', 'email', 'email_code', 'github_oauth', 'google_oauth', 'users_select', 'auth_request', 'auth_submit'). - **enc_email** (string) - Optional - RSA-encrypted email address (used with 'email' and 'email_code'). - **state** (string) - Optional - State parameter, often used in OAuth flows. - **email_code** (string) - Optional - Verification code sent to the email (used with 'email_code'). - **enc_client_key** (string) - Optional - RSA-encrypted client key (used with 'email_code'). - **redirect_uri** (string) - Optional - Redirect URI for OAuth flows. - **code** (string) - Optional - Authorization code received from OAuth provider. - **credential** (string) - Optional - Google credential for One-Tap sign-in. - **session_key** (string) - Optional - Session key for WeChat Mini Program login. - **auth_request_data** (object) - Optional - Data for IDE extension auth request. - **auth_submit_data** (object) - Optional - Data for IDE extension auth submission. ### Request Example (Email Login - Step 1: Send Code) ```json { "operateType": "email", "enc_email": "encrypted_email_string", "state": "login_state_string" } ``` ### Response #### Success Response (200) - **code** (string) - Response code, typically '0000' for success. - **data** (object) - Response data upon successful login. - **userId** (string) - The unique identifier for the user. - **email** (string) - The user's email address (may be optional). - **open_id** (string) - Open ID for the user. - **token** (string) - Authentication token for subsequent requests. - **serial_id** (string) - Serial ID associated with the user. - **theme** (string) - User's preferred theme ('system', 'light', 'dark'). - **language** (string) - User's preferred language ('system', 'zh-Hans', 'zh-Hant', 'en'). - **spaceMemberList** (array) - List of spaces and member information the user belongs to. - **subscription** (object) - User's subscription details (optional). #### Response Example ```json { "code": "0000", "data": { "userId": "user-123", "email": "user@example.com", "open_id": "openid-abc", "token": "auth_token_xyz", "serial_id": "serial-456", "theme": "dark", "language": "en", "spaceMemberList": [], "subscription": {} } } ``` ``` -------------------------------- ### Dynamically Set Manifest Href Based on User Agent (JavaScript) Source: https://github.com/yenche123/liubai/blob/cool/liubai-frontends/liubai-web/index.html This JavaScript snippet determines the correct manifest file to link based on the user's browser user agent. It checks if the user agent includes 'iphone', 'ipad', or 'ios' to set the manifest href to '/manifest-ios.json'; otherwise, it defaults to '/manifest.json'. The resulting href is then applied to the element with the ID 'manifest'. ```javascript let manifestHref = "/manifest.json" try { const ua = navigator.userAgent.toLowerCase() if(ua.includes("iphone") || ua.includes("ipad") || ua.includes("ios")) { manifestHref = "/manifest-ios.json" } } catch(e) {} document.querySelector("#manifest").setAttribute("href", manifestHref) ``` -------------------------------- ### Thread State Operations (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Demonstrates various thread state management operations using the Sync-Set API, including deleting, restoring, permanently deleting, pinning, and unpinning threads. Each operation uses a specific `taskType` and relevant thread properties. ```typescript // Delete thread (move to trash) const deleteThread: SyncSetAtom = { taskType: "thread-delete", taskId: "task-delete-001", operateStamp: Date.now(), thread: { id: "thread-id", removedStamp: Date.now() } } // Restore from trash const restoreThread: SyncSetAtom = { taskType: "undo_thread-delete", taskId: "task-restore-001", operateStamp: Date.now(), thread: { id: "thread-id" } } // Permanent delete const permanentDelete: SyncSetAtom = { taskType: "thread-delete_forever", taskId: "task-perm-delete-001", operateStamp: Date.now(), thread: { id: "thread-id" } } // Pin thread const pinThread: SyncSetAtom = { taskType: "thread-pin", taskId: "task-pin-001", operateStamp: Date.now(), thread: { id: "thread-id", pinStamp: Date.now() } } // Unpin thread const unpinThread: SyncSetAtom = { taskType: "undo_thread-pin", taskId: "task-unpin-001", operateStamp: Date.now(), thread: { id: "thread-id", pinStamp: 0 } } ``` -------------------------------- ### Documentation Update Process Diagram Source: https://github.com/yenche123/liubai/blob/cool/memory-bank/README.md Mermaid diagram detailing the process for updating Memory Bank documentation. It emphasizes reviewing all files, documenting the current state, clarifying next steps, and recording insights and patterns. ```mermaid flowchart TD Start[Update Process] subgraph Process P1[Review ALL Files] P2[Document Current State] P3[Clarify Next Steps] P4[Document Insights & Patterns] P1 --> P2 --> P3 --> P4 end Start --> Process ``` -------------------------------- ### Sync-Set API Request Structure (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt Defines the core interfaces for the Sync-Set API, which handles data mutations. SyncSetRequest outlines the overall request structure, while SyncSetAtom specifies the individual operations like creating or updating threads. ```typescript interface SyncSetRequest { operateType: "general_sync" | "single_sync" atoms: SyncSetAtom[] // Max 10 for general_sync, 1 for single_sync } interface SyncSetAtom { taskType: LiuUploadTask taskId: string operateStamp: number thread?: LiuUploadThread comment?: LiuUploadComment draft?: LiuUploadDraft workspace?: LiuUploadWorkspace member?: LiuUploadMember collection?: LiuUploadCollection } ``` -------------------------------- ### Webhook - Stripe Integration Source: https://context7.com/yenche123/liubai/llms.txt Handles Stripe payment webhooks for subscription management. This endpoint listens for various Stripe events to update user subscription status. ```APIDOC ## Webhook - Stripe Integration ### Description This endpoint is designed to receive and process webhook events from Stripe, enabling real-time updates for subscription management, including creation, updates, cancellations, and payment status. ### Method POST ### Endpoint `/webhook-stripe` ### Headers - **stripe-signature** (string) - Required - The signature of the webhook event, used for verification. ### Request Body Stripe event payload (structure varies based on the event type). ### Supported Stripe Events - `checkout.session.completed` - `customer.subscription.created` - `customer.subscription.updated` - `customer.subscription.deleted` - `invoice.paid` - `invoice.payment_failed` ### Request Example (Conceptual) ```http POST /webhook-stripe HTTP/1.1 Host: your-api-domain.com Stripe-Signature: t=...',signature='sig_...' Content-Type: application/json { "id": "evt_...", "object": "event", "type": "customer.subscription.created", "data": { "object": { // Subscription details... } } } ``` ### Response #### Success Response (200 OK) Indicates that the webhook event was successfully received and processed. #### Error Response - **400 Bad Request**: If the request body is invalid or signature verification fails. - **500 Internal Server Error**: If there's an issue processing the event. ### Data Structure (User Subscription) ```typescript interface UserSubscription { isOn: "Y" | "N"; plan: "monthly" | "yearly" | "lifetime"; isLifelong: boolean; expireStamp?: number; // Unix timestamp for expiration stripe_subscription_id?: string; stripe_customer_id?: string; createdStamp: number; updatedStamp: number; } ``` ``` -------------------------------- ### Authentication & Token Verification Source: https://context7.com/yenche123/liubai/llms.txt All protected endpoints require token verification. The `verifyToken` function validates requests and returns user data with workspace access permissions. Request and response bodies are encrypted. ```APIDOC ## Authentication & Token Verification All protected endpoints require token verification. The `verifyToken` function validates requests and returns user data with workspace access permissions. Request and response bodies are encrypted using AES. ### Method POST (Implicitly, as it's part of cloud function execution) ### Endpoint `/` (for Laf cloud functions) ### Parameters #### Request Body - **body** (object) - Required - The encrypted request payload containing operation details and potentially user authentication tokens. ### Request Example ```typescript // Token verification pattern used across all cloud functions import { verifyToken, getDecryptedBody, getEncryptedData } from "@/common-util" export async function main(ctx: FunctionContext) { const body = ctx.request?.body ?? {} // Verify token and get user data const vRes = await verifyToken(ctx, body) if (!vRes.pass) return vRes.rqReturn const user = vRes.userData // Table_User const workspaces = vRes.workspaces // string[] - workspace IDs user has access to // Decrypt the encrypted request body const res = getDecryptedBody(body, vRes) if (!res.newBody || res.rqReturn) { return res.rqReturn ?? { code: "E5001" } } // Process decrypted body... const results = await processRequest(res.newBody) // Encrypt response before sending const encRes = getEncryptedData({ results }, vRes) return { code: "0000", data: encRes.data } } ``` ### Response #### Success Response (200) - **code** (string) - "0000" indicates success. - **data** (object) - The encrypted response data. #### Response Example ```json { "code": "0000", "data": "encrypted_response_payload" } ``` ``` -------------------------------- ### Verify Token and Encrypt/Decrypt Data in Cloud Functions (TypeScript) Source: https://context7.com/yenche123/liubai/llms.txt This snippet demonstrates the common pattern for verifying authentication tokens and handling encrypted request/response bodies in Laf cloud functions. It ensures secure communication by decrypting incoming data and encrypting outgoing data using provided user credentials. ```typescript import { verifyToken, getDecryptedBody, getEncryptedData } from "@/common-util" export async function main(ctx: FunctionContext) { const body = ctx.request?.body ?? {} // Verify token and get user data const vRes = await verifyToken(ctx, body) if (!vRes.pass) return vRes.rqReturn const user = vRes.userData // Table_User const workspaces = vRes.workspaces // string[] - workspace IDs user has access to // Decrypt the encrypted request body const res = getDecryptedBody(body, vRes) if (!res.newBody || res.rqReturn) { return res.rqReturn ?? { code: "E5001" } } // Process decrypted body... const results = await processRequest(res.newBody) // Encrypt response before sending const encRes = getEncryptedData({ results }, vRes) return { code: "0000", data: encRes.data } } ```