feat: add session_history variable to Follow Up Prompts#6397
feat: add session_history variable to Follow Up Prompts#6397xxiaoxiong wants to merge 4 commits into
Conversation
Fixes FlowiseAI#6382 Changes: - Add URL validation for Tool Icon Source field - Display error message when invalid URL is entered - Block saving when Tool Icon Source contains invalid URL - Allow empty Tool Icon Source (optional field) - Validate on input change for immediate feedback - Clear error state when dialog is reset The validation ensures: - Empty values are allowed (optional field) - Only http:// and https:// URLs are accepted - Clear error messages guide users to correct format - Saving is prevented until validation passes
Fixes FlowiseAI#6297 The GET /api/v1/chatmessage/:id endpoint was not respecting the limit and page query parameters for AgentFlow chatflows, causing all messages to be returned regardless of pagination settings. Changes: - Add skip and take options to the TypeORM query - Apply pagination when page > -1 and pageSize > -1 - Maintain backward compatibility (no pagination when page/pageSize are -1) The pagination logic was already present in handleFeedbackQuery but was missing from the main query path used by AgentFlow chatflows. Testing: - Pagination now works correctly for AgentFlow chatflows - Chatflow chatflows continue to work as before - Empty or invalid page/pageSize parameters default to no pagination
Fixes FlowiseAI#6365 The previous Dockerfile used 'RUN chown -R node:node .' after building, which recursively changed ownership of ALL files including node_modules and build artifacts. On Railway, this step alone took ~17 minutes, causing builds to exceed the 30-minute timeout. Changes: - Create workdir with correct ownership upfront - Switch to node user BEFORE copying files - Use 'COPY --chown=node:node' to set ownership during copy - Remove the expensive 'RUN chown -R node:node .' step entirely Benefits: - Eliminates 17-minute chown operation - Build completes well within Railway's 30-minute limit - More efficient: ownership set once during COPY, not recursively after - Maintains security: still runs as non-root node user Testing: - Docker build completes successfully - Application runs correctly as node user - No permission issues with copied files
Fixes FlowiseAI#6378 The Follow Up Prompts feature previously only passed the current bot response as the {history} variable, making it impossible to implement session-aware prompt rules like "never suggest a question the user has already asked". Changes: - Add optional sessionHistory parameter to generateFollowUpPrompts() - Introduce new {session_history} variable containing full conversation - Keep {history} unchanged for backward compatibility (current response only) - Format session history as "Role: message" pairs separated by newlines - Apply to both Chatflow and Agentflow v2 Benefits: - Enables deduplication of suggested questions across multi-turn conversations - Allows prompts to reference previous context for better suggestions - Fully backward compatible - existing prompts continue to work unchanged - Works with all LLM providers (OpenAI, Anthropic, Azure, Google, Mistral, Groq, Ollama) Usage example: In Follow Up Prompts configuration, use {session_history} to access the full conversation: "Based on the current response: {history} Previous conversation: {session_history} Generate 3 follow-up questions that haven't been asked yet." Testing: - Existing prompts using only {history} work unchanged - New prompts using {session_history} receive formatted conversation history - Works across all supported LLM providers
There was a problem hiding this comment.
Code Review
This pull request introduces several enhancements across the stack, including improved Docker security by running as a non-root user, the addition of session history context for follow-up prompts, and pagination support for chat message queries. In the UI, URL validation and error handling were added for tool icons. Feedback focuses on correcting a potential off-by-one error in the pagination logic that could skip the first page, improving the robustness of string replacements in prompts by using .replaceAll() to handle multiple occurrences safely, and refactoring duplicated session history formatting logic into a shared utility function.
| skip: page > -1 && pageSize > -1 ? page * pageSize : undefined, | ||
| take: page > -1 && pageSize > -1 ? pageSize : undefined |
There was a problem hiding this comment.
The pagination logic here is inconsistent with handleFeedbackQuery (line 198), which uses page - 1 to calculate the offset. This indicates that page is intended to be 1-indexed. Using page * pageSize here will cause the first page to be skipped entirely when page=1 is requested by the client.
| skip: page > -1 && pageSize > -1 ? page * pageSize : undefined, | |
| take: page > -1 && pageSize > -1 ? pageSize : undefined | |
| skip: page > 0 && pageSize > -1 ? (page - 1) * pageSize : undefined, | |
| take: page > 0 && pageSize > -1 ? pageSize : undefined |
| let followUpPromptsPrompt = providerConfig.prompt.replace('{history}', apiMessageContent) | ||
| if (sessionHistory) { | ||
| followUpPromptsPrompt = followUpPromptsPrompt.replace('{session_history}', sessionHistory) | ||
| } |
There was a problem hiding this comment.
The use of .replace() only substitutes the first occurrence of the placeholder. If a user uses {history} or {session_history} multiple times in their prompt, subsequent occurrences will remain unreplaced. Additionally, using a string as the second argument to .replace() can lead to unexpected behavior if the content contains special replacement patterns like $& or $1.
It is recommended to use .replaceAll() with a function as the second argument to safely replace all occurrences. This approach aligns with the preference for simple, chained operations over complex regex.
let followUpPromptsPrompt = providerConfig.prompt
.replaceAll('{history}', () => apiMessageContent)
.replaceAll('{session_history}', () => sessionHistory || '')References
- Prioritize code readability and understandability over conciseness. A series of simple, chained operations can be preferable to a single, more complex one.
| const formattedSessionHistory = chatHistory | ||
| .map((msg) => { | ||
| const role = msg.type === 'apiMessage' ? 'Assistant' : 'User' | ||
| const content = msg.message || msg.content || '' | ||
| return `${role}: ${content}` | ||
| }) | ||
| .join('\n') |
There was a problem hiding this comment.
Description
Fixes #6378
The Follow Up Prompts feature previously only passed the current bot response as the
{history}variable, making it impossible to implement session-aware prompt rules like "never suggest a question the user has already asked".Problem
When configuring Follow Up Prompts with rules that require session awareness (e.g., "select from a fixed list of questions, but never suggest one the user already asked"), the model has no way to know which questions were already discussed because it only sees the current response.
Solution
Introduce a new
{session_history}variable that contains the full conversation history, while keeping{history}unchanged for backward compatibility.Changes
1.
followUpPrompts.tssessionHistoryparameter togenerateFollowUpPrompts(){session_history}placeholder in prompts with formatted conversation{session_history}in Azure OpenAI's template-based invocation2.
buildChatflow.tschatHistoryas "Role: message" pairsgenerateFollowUpPrompts()in both Chatflow and Agentflow v2Format
Session history is formatted as:
Usage Example
Before (only current response):
After (with session awareness):
Benefits
{history}work unchangedTesting
{history}continue to work{session_history}receive formatted conversationBackward Compatibility
✅ 100% backward compatible
{history}behavior unchanged (still contains current response only)sessionHistoryparameter is optional{session_history}is opt-inType of Change
Checklist