mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 00:23:17 +00:00
Compare commits
1 Commits
main
...
improve-va
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a9d512679 |
@@ -56,9 +56,10 @@ class GetTools(Resource):
|
||||
tools = user_tools_collection.find({"user": user})
|
||||
user_tools = []
|
||||
for tool in tools:
|
||||
tool["id"] = str(tool["_id"])
|
||||
tool.pop("_id")
|
||||
user_tools.append(tool)
|
||||
tool_copy = {**tool}
|
||||
tool_copy["id"] = str(tool["_id"])
|
||||
tool_copy.pop("_id", None)
|
||||
user_tools.append(tool_copy)
|
||||
except Exception as err:
|
||||
current_app.logger.error(f"Error getting user tools: {err}", exc_info=True)
|
||||
return make_response(jsonify({"success": False}), 400)
|
||||
|
||||
@@ -225,6 +225,16 @@ layer(base);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
.prompt-variable-highlight {
|
||||
background-color: rgba(106, 77, 244, 0.18);
|
||||
border-radius: 0.375rem;
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
|
||||
.dark .prompt-variable-highlight {
|
||||
background-color: rgba(106, 77, 244, 0.32);
|
||||
}
|
||||
|
||||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
|
||||
@@ -396,6 +396,18 @@
|
||||
"variablesDescription": "Click to insert into prompt",
|
||||
"systemVariables": "Click to insert into prompt",
|
||||
"toolVariables": "Tool Variables",
|
||||
"systemVariablesDropdownLabel": "System Variables",
|
||||
"systemVariableOptions": {
|
||||
"sourceContent": "Sources content",
|
||||
"sourceSummaries": "Alias for content (backward compatible)",
|
||||
"sourceDocuments": "Document objects list",
|
||||
"sourceCount": "Number of retrieved documents",
|
||||
"systemDate": "Current date (YYYY-MM-DD)",
|
||||
"systemTime": "Current time (HH:MM:SS)",
|
||||
"systemTimestamp": "ISO 8601 timestamp",
|
||||
"systemRequestId": "Unique request identifier",
|
||||
"systemUserId": "Current user ID"
|
||||
},
|
||||
"learnAboutPrompts": "Learn about Prompts →",
|
||||
"publicPromptEditDisabled": "Public prompts cannot be edited",
|
||||
"promptTypePublic": "public",
|
||||
|
||||
@@ -396,6 +396,18 @@
|
||||
"variablesDescription": "Haz clic para insertar en el prompt",
|
||||
"systemVariables": "Variables del sistema",
|
||||
"toolVariables": "Variables de herramientas",
|
||||
"systemVariablesDropdownLabel": "Variables del sistema",
|
||||
"systemVariableOptions": {
|
||||
"sourceContent": "Contenido de las fuentes",
|
||||
"sourceSummaries": "Alias del contenido (compatibilidad retroactiva)",
|
||||
"sourceDocuments": "Lista de objetos de documentos",
|
||||
"sourceCount": "Número de documentos recuperados",
|
||||
"systemDate": "Fecha actual (YYYY-MM-DD)",
|
||||
"systemTime": "Hora actual (HH:MM:SS)",
|
||||
"systemTimestamp": "Marca de tiempo ISO 8601",
|
||||
"systemRequestId": "Identificador único de solicitud",
|
||||
"systemUserId": "ID del usuario actual"
|
||||
},
|
||||
"learnAboutPrompts": "Aprende sobre los Prompts →",
|
||||
"publicPromptEditDisabled": "Los prompts públicos no se pueden editar",
|
||||
"promptTypePublic": "público",
|
||||
|
||||
@@ -396,6 +396,18 @@
|
||||
"variablesDescription": "クリックしてプロンプトに挿入",
|
||||
"systemVariables": "システム変数",
|
||||
"toolVariables": "ツール変数",
|
||||
"systemVariablesDropdownLabel": "System Variables",
|
||||
"systemVariableOptions": {
|
||||
"sourceContent": "Sources content",
|
||||
"sourceSummaries": "Alias for content (backward compatible)",
|
||||
"sourceDocuments": "Document objects list",
|
||||
"sourceCount": "Number of retrieved documents",
|
||||
"systemDate": "Current date (YYYY-MM-DD)",
|
||||
"systemTime": "Current time (HH:MM:SS)",
|
||||
"systemTimestamp": "ISO 8601 timestamp",
|
||||
"systemRequestId": "Unique request identifier",
|
||||
"systemUserId": "Current user ID"
|
||||
},
|
||||
"learnAboutPrompts": "プロンプトについて学ぶ →",
|
||||
"publicPromptEditDisabled": "公開プロンプトは編集できません",
|
||||
"promptTypePublic": "公開",
|
||||
|
||||
@@ -396,6 +396,18 @@
|
||||
"variablesDescription": "Нажмите, чтобы вставить в промпт",
|
||||
"systemVariables": "Системные переменные",
|
||||
"toolVariables": "Переменные инструментов",
|
||||
"systemVariablesDropdownLabel": "Системные переменные",
|
||||
"systemVariableOptions": {
|
||||
"sourceContent": "Содержимое источников",
|
||||
"sourceSummaries": "Псевдоним содержимого (обратная совместимость)",
|
||||
"sourceDocuments": "Список объектов документов",
|
||||
"sourceCount": "Количество полученных документов",
|
||||
"systemDate": "Текущая дата (ГГГГ-ММ-ДД)",
|
||||
"systemTime": "Текущее время (ЧЧ:ММ:СС)",
|
||||
"systemTimestamp": "Отметка времени ISO 8601",
|
||||
"systemRequestId": "Уникальный идентификатор запроса",
|
||||
"systemUserId": "Идентификатор текущего пользователя"
|
||||
},
|
||||
"learnAboutPrompts": "Узнать о промптах →",
|
||||
"publicPromptEditDisabled": "Публичные промпты нельзя редактировать",
|
||||
"promptTypePublic": "публичный",
|
||||
|
||||
@@ -396,6 +396,18 @@
|
||||
"variablesDescription": "點擊以插入到提示中",
|
||||
"systemVariables": "點擊以插入提示中",
|
||||
"toolVariables": "工具變數",
|
||||
"systemVariablesDropdownLabel": "系統變數",
|
||||
"systemVariableOptions": {
|
||||
"sourceContent": "來源內容",
|
||||
"sourceSummaries": "內容別名(向後相容)",
|
||||
"sourceDocuments": "文件物件列表",
|
||||
"sourceCount": "擷取的文件數量",
|
||||
"systemDate": "目前日期 (YYYY-MM-DD)",
|
||||
"systemTime": "目前時間 (HH:MM:SS)",
|
||||
"systemTimestamp": "ISO 8601 時間戳記",
|
||||
"systemRequestId": "唯一請求識別碼",
|
||||
"systemUserId": "目前使用者 ID"
|
||||
},
|
||||
"learnAboutPrompts": "了解提示 →",
|
||||
"publicPromptEditDisabled": "公共提示無法編輯",
|
||||
"promptTypePublic": "公共",
|
||||
|
||||
@@ -396,6 +396,18 @@
|
||||
"variablesDescription": "點擊以插入到提示中",
|
||||
"systemVariables": "點擊以插入提示中",
|
||||
"toolVariables": "工具變數",
|
||||
"systemVariablesDropdownLabel": "系統變數",
|
||||
"systemVariableOptions": {
|
||||
"sourceContent": "來源內容",
|
||||
"sourceSummaries": "內容別名(向後相容)",
|
||||
"sourceDocuments": "文件物件列表",
|
||||
"sourceCount": "擷取的文件數量",
|
||||
"systemDate": "目前日期 (YYYY-MM-DD)",
|
||||
"systemTime": "目前時間 (HH:MM:SS)",
|
||||
"systemTimestamp": "ISO 8601 時間戳記",
|
||||
"systemRequestId": "唯一請求識別碼",
|
||||
"systemUserId": "目前使用者 ID"
|
||||
},
|
||||
"learnAboutPrompts": "了解提示 →",
|
||||
"publicPromptEditDisabled": "公共提示無法編輯",
|
||||
"promptTypePublic": "公共",
|
||||
|
||||
@@ -12,6 +12,141 @@ import userService from '../api/services/userService';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { UserToolType } from '../settings/types';
|
||||
|
||||
const variablePattern = /(\{\{\s*[^{}]+\s*\}\}|\{(?!\{)[^{}]+\})/g;
|
||||
|
||||
const escapeHtml = (value: string) =>
|
||||
value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
|
||||
const highlightPromptVariables = (text: string) => {
|
||||
if (!text) {
|
||||
return '​';
|
||||
}
|
||||
variablePattern.lastIndex = 0;
|
||||
let result = '';
|
||||
let lastIndex = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
while ((match = variablePattern.exec(text)) !== null) {
|
||||
const precedingText = text.slice(lastIndex, match.index);
|
||||
if (precedingText) {
|
||||
result += escapeHtml(precedingText);
|
||||
}
|
||||
result += `<span class="prompt-variable-highlight">${escapeHtml(match[0])}</span>`;
|
||||
lastIndex = match.index + match[0].length;
|
||||
}
|
||||
|
||||
const remainingText = text.slice(lastIndex);
|
||||
if (remainingText) {
|
||||
result += escapeHtml(remainingText);
|
||||
}
|
||||
|
||||
return result || '​';
|
||||
};
|
||||
|
||||
const systemVariableOptionDefinitions = [
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.sourceContent',
|
||||
value: 'source.content',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.sourceSummaries',
|
||||
value: 'source.summaries',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.sourceDocuments',
|
||||
value: 'source.documents',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.sourceCount',
|
||||
value: 'source.count',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.systemDate',
|
||||
value: 'system.date',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.systemTime',
|
||||
value: 'system.time',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.systemTimestamp',
|
||||
value: 'system.timestamp',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.systemRequestId',
|
||||
value: 'system.request_id',
|
||||
},
|
||||
{
|
||||
labelKey: 'modals.prompts.systemVariableOptions.systemUserId',
|
||||
value: 'system.user_id',
|
||||
},
|
||||
];
|
||||
|
||||
const buildSystemVariableOptions = (translate: (key: string) => string) =>
|
||||
systemVariableOptionDefinitions.map(({ value, labelKey }) => ({
|
||||
value,
|
||||
label: translate(labelKey),
|
||||
}));
|
||||
|
||||
type PromptTextareaProps = {
|
||||
id: string;
|
||||
value: string;
|
||||
onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
||||
ariaLabel: string;
|
||||
};
|
||||
|
||||
function PromptTextarea({
|
||||
id,
|
||||
value,
|
||||
onChange,
|
||||
ariaLabel,
|
||||
}: PromptTextareaProps) {
|
||||
const [scrollOffsets, setScrollOffsets] = React.useState({ top: 0, left: 0 });
|
||||
const highlightedValue = React.useMemo(
|
||||
() => highlightPromptVariables(value),
|
||||
[value],
|
||||
);
|
||||
|
||||
const handleScroll = (event: React.UIEvent<HTMLTextAreaElement>) => {
|
||||
const { scrollTop, scrollLeft } = event.currentTarget;
|
||||
setScrollOffsets({
|
||||
top: scrollTop,
|
||||
left: scrollLeft,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="pointer-events-none absolute inset-0 z-0 overflow-hidden rounded bg-white px-3 py-2 dark:bg-[#26272E]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className="min-h-full text-base leading-[1.5] break-words whitespace-pre-wrap text-transparent"
|
||||
style={{
|
||||
transform: `translate(${-scrollOffsets.left}px, ${-scrollOffsets.top}px)`,
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: highlightedValue }}
|
||||
/>
|
||||
</div>
|
||||
<textarea
|
||||
id={id}
|
||||
className="peer border-silver dark:border-silver/40 relative z-10 h-48 w-full resize-none rounded border-2 bg-transparent px-3 py-2 text-base text-gray-800 outline-none dark:bg-transparent dark:text-white"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onScroll={handleScroll}
|
||||
placeholder=" "
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Custom hook for fetching tool variables
|
||||
const useToolVariables = () => {
|
||||
const token = useSelector(selectToken);
|
||||
@@ -50,9 +185,13 @@ const useToolVariables = () => {
|
||||
);
|
||||
|
||||
if (canUseAction) {
|
||||
const toolIdentifier = tool.id ?? tool.name;
|
||||
if (!toolIdentifier) {
|
||||
return;
|
||||
}
|
||||
filteredActions.push({
|
||||
label: `${action.name} (${tool.displayName || tool.name})`,
|
||||
value: `tools.${tool.name}.${action.name}`,
|
||||
value: `tools.${toolIdentifier}.${action.name}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -91,6 +230,10 @@ function AddPrompt({
|
||||
disableSave: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const systemVariableOptions = React.useMemo(
|
||||
() => buildSystemVariableOptions(t),
|
||||
[t],
|
||||
);
|
||||
const toolVariables = useToolVariables();
|
||||
|
||||
return (
|
||||
@@ -115,17 +258,15 @@ function AddPrompt({
|
||||
/>
|
||||
|
||||
<div className="relative w-full">
|
||||
<textarea
|
||||
<PromptTextarea
|
||||
id="new-prompt-content"
|
||||
className="peer border-silver dark:border-silver/40 h-48 w-full resize-none rounded border-2 bg-white px-3 py-2 text-base text-gray-800 outline-none dark:bg-[#26272E] dark:text-white"
|
||||
value={newPromptContent}
|
||||
onChange={(e) => setNewPromptContent(e.target.value)}
|
||||
placeholder=" "
|
||||
aria-label={t('prompts.textAriaLabel')}
|
||||
ariaLabel={t('prompts.textAriaLabel')}
|
||||
/>
|
||||
<label
|
||||
htmlFor="new-prompt-content"
|
||||
className={`absolute select-none ${
|
||||
className={`absolute z-20 select-none ${
|
||||
newPromptContent ? '-top-2.5 left-3 text-xs' : ''
|
||||
} text-gray-4000 pointer-events-none max-w-[calc(100%-24px)] cursor-none overflow-hidden bg-white px-2 text-ellipsis whitespace-nowrap transition-all peer-placeholder-shown:top-2.5 peer-placeholder-shown:left-3 peer-placeholder-shown:text-base peer-focus:-top-2.5 peer-focus:left-3 peer-focus:text-xs dark:bg-[#26272E] dark:text-gray-400`}
|
||||
>
|
||||
@@ -146,8 +287,8 @@ function AddPrompt({
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2 sm:gap-3">
|
||||
<Dropdown
|
||||
options={[{ label: 'Summaries', value: 'summaries' }]}
|
||||
selectedValue={'System Variables'}
|
||||
options={systemVariableOptions}
|
||||
selectedValue={t('modals.prompts.systemVariablesDropdownLabel')}
|
||||
onSelect={(option) => {
|
||||
const textarea = document.getElementById(
|
||||
'new-prompt-content',
|
||||
@@ -165,7 +306,7 @@ function AddPrompt({
|
||||
const newText =
|
||||
textBefore +
|
||||
(needsSpace ? ' ' : '') +
|
||||
`{${option.value}}` +
|
||||
`{{ ${option.value} }}` +
|
||||
textAfter;
|
||||
setNewPromptContent(newText);
|
||||
|
||||
@@ -174,17 +315,17 @@ function AddPrompt({
|
||||
textarea.setSelectionRange(
|
||||
cursorPosition +
|
||||
option.value.length +
|
||||
2 +
|
||||
6 +
|
||||
(needsSpace ? 1 : 0),
|
||||
cursorPosition +
|
||||
option.value.length +
|
||||
2 +
|
||||
6 +
|
||||
(needsSpace ? 1 : 0),
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
}}
|
||||
placeholder="System Variables"
|
||||
placeholder={t('modals.prompts.systemVariablesDropdownLabel')}
|
||||
size="w-[140px] sm:w-[185px]"
|
||||
rounded="3xl"
|
||||
border="border"
|
||||
@@ -298,6 +439,10 @@ function EditPrompt({
|
||||
disableSave: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const systemVariableOptions = React.useMemo(
|
||||
() => buildSystemVariableOptions(t),
|
||||
[t],
|
||||
);
|
||||
const toolVariables = useToolVariables();
|
||||
|
||||
return (
|
||||
@@ -322,17 +467,15 @@ function EditPrompt({
|
||||
/>
|
||||
|
||||
<div className="relative w-full">
|
||||
<textarea
|
||||
<PromptTextarea
|
||||
id="edit-prompt-content"
|
||||
className="peer border-silver dark:border-silver/40 h-48 w-full resize-none rounded border-2 bg-white px-3 py-2 text-base text-gray-800 outline-none dark:bg-[#26272E] dark:text-white"
|
||||
value={editPromptContent}
|
||||
onChange={(e) => setEditPromptContent(e.target.value)}
|
||||
placeholder=" "
|
||||
aria-label={t('prompts.textAriaLabel')}
|
||||
ariaLabel={t('prompts.textAriaLabel')}
|
||||
/>
|
||||
<label
|
||||
htmlFor="edit-prompt-content"
|
||||
className={`absolute select-none ${
|
||||
className={`absolute z-20 select-none ${
|
||||
editPromptContent ? '-top-2.5 left-3 text-xs' : ''
|
||||
} text-gray-4000 pointer-events-none max-w-[calc(100%-24px)] cursor-none overflow-hidden bg-white px-2 text-ellipsis whitespace-nowrap transition-all peer-placeholder-shown:top-2.5 peer-placeholder-shown:left-3 peer-placeholder-shown:text-base peer-focus:-top-2.5 peer-focus:left-3 peer-focus:text-xs dark:bg-[#26272E] dark:text-gray-400`}
|
||||
>
|
||||
@@ -353,8 +496,8 @@ function EditPrompt({
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2 sm:gap-3">
|
||||
<Dropdown
|
||||
options={[{ label: 'Summaries', value: 'summaries' }]}
|
||||
selectedValue={'System Variables'}
|
||||
options={systemVariableOptions}
|
||||
selectedValue={t('modals.prompts.systemVariablesDropdownLabel')}
|
||||
onSelect={(option) => {
|
||||
const textarea = document.getElementById(
|
||||
'edit-prompt-content',
|
||||
@@ -372,7 +515,7 @@ function EditPrompt({
|
||||
const newText =
|
||||
textBefore +
|
||||
(needsSpace ? ' ' : '') +
|
||||
`{${option.value}}` +
|
||||
`{{ ${option.value} }}` +
|
||||
textAfter;
|
||||
setEditPromptContent(newText);
|
||||
|
||||
@@ -381,17 +524,17 @@ function EditPrompt({
|
||||
textarea.setSelectionRange(
|
||||
cursorPosition +
|
||||
option.value.length +
|
||||
2 +
|
||||
6 +
|
||||
(needsSpace ? 1 : 0),
|
||||
cursorPosition +
|
||||
option.value.length +
|
||||
2 +
|
||||
6 +
|
||||
(needsSpace ? 1 : 0),
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
}}
|
||||
placeholder="System Variables"
|
||||
placeholder={t('modals.prompts.systemVariablesDropdownLabel')}
|
||||
size="w-[140px] sm:w-[185px]"
|
||||
rounded="3xl"
|
||||
border="border"
|
||||
|
||||
Reference in New Issue
Block a user