File size: 4,361 Bytes
f0743f4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | import { SystemCategories } from 'librechat-data-provider';
import type { IPromptGroupDocument as IPromptGroup } from '@librechat/data-schemas';
import type { Types } from 'mongoose';
import type { PromptGroupsListResponse } from '~/types';
import { escapeRegExp } from '~/utils/common';
/**
* Formats prompt groups for the paginated /groups endpoint response
*/
export function formatPromptGroupsResponse({
promptGroups = [],
pageNumber,
pageSize,
actualLimit,
hasMore = false,
after = null,
}: {
promptGroups: IPromptGroup[];
pageNumber?: string;
pageSize?: string;
actualLimit?: string | number;
hasMore?: boolean;
after?: string | null;
}): PromptGroupsListResponse {
const currentPage = parseInt(pageNumber || '1');
// Calculate total pages based on whether there are more results
// If hasMore is true, we know there's at least one more page
// We use a high number (9999) to indicate "many pages" since we don't know the exact count
const totalPages = hasMore ? '9999' : currentPage.toString();
return {
promptGroups,
pageNumber: pageNumber || '1',
pageSize: pageSize || String(actualLimit) || '10',
pages: totalPages,
has_more: hasMore,
after,
};
}
/**
* Creates an empty response for the paginated /groups endpoint
*/
export function createEmptyPromptGroupsResponse({
pageNumber,
pageSize,
actualLimit,
}: {
pageNumber?: string;
pageSize?: string;
actualLimit?: string | number;
}): PromptGroupsListResponse {
return {
promptGroups: [],
pageNumber: pageNumber || '1',
pageSize: pageSize || String(actualLimit) || '10',
pages: '0',
has_more: false,
after: null,
};
}
/**
* Marks prompt groups as public based on the publicly accessible IDs
*/
export function markPublicPromptGroups(
promptGroups: IPromptGroup[],
publiclyAccessibleIds: Types.ObjectId[],
): IPromptGroup[] {
if (!promptGroups.length) {
return [];
}
return promptGroups.map((group) => {
const isPublic = publiclyAccessibleIds.some((id) => id.equals(group._id?.toString()));
return isPublic ? ({ ...group, isPublic: true } as IPromptGroup) : group;
});
}
/**
* Builds filter object for prompt group queries
*/
export function buildPromptGroupFilter({
name,
category,
...otherFilters
}: {
name?: string;
category?: string;
[key: string]: string | number | boolean | RegExp | undefined;
}): {
filter: Record<string, string | number | boolean | RegExp | undefined>;
searchShared: boolean;
searchSharedOnly: boolean;
} {
const filter: Record<string, string | number | boolean | RegExp | undefined> = {
...otherFilters,
};
let searchShared = true;
let searchSharedOnly = false;
// Handle name filter - convert to regex for case-insensitive search
if (name) {
filter.name = new RegExp(escapeRegExp(name), 'i');
}
// Handle category filters with special system categories
if (category === SystemCategories.MY_PROMPTS) {
searchShared = false;
} else if (category === SystemCategories.NO_CATEGORY) {
filter.category = '';
} else if (category === SystemCategories.SHARED_PROMPTS) {
searchSharedOnly = true;
} else if (category) {
filter.category = category;
}
return { filter, searchShared, searchSharedOnly };
}
/**
* Filters accessible IDs based on shared/public prompts logic
*/
export async function filterAccessibleIdsBySharedLogic({
accessibleIds,
searchShared,
searchSharedOnly,
publicPromptGroupIds,
}: {
accessibleIds: Types.ObjectId[];
searchShared: boolean;
searchSharedOnly: boolean;
publicPromptGroupIds?: Types.ObjectId[];
}): Promise<Types.ObjectId[]> {
const publicIdStrings = new Set((publicPromptGroupIds || []).map((id) => id.toString()));
if (!searchShared) {
// For MY_PROMPTS - exclude public prompts to show only user's own prompts
return accessibleIds.filter((id) => !publicIdStrings.has(id.toString()));
}
if (searchSharedOnly) {
// Handle SHARED_PROMPTS filter - only return public prompts that user has access to
if (!publicPromptGroupIds?.length) {
return [];
}
const accessibleIdStrings = new Set(accessibleIds.map((id) => id.toString()));
return publicPromptGroupIds.filter((id) => accessibleIdStrings.has(id.toString()));
}
return [...accessibleIds, ...(publicPromptGroupIds || [])];
}
|