mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 22:38:10 -05:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45d06f8854 | ||
|
|
fdc64c8fd6 | ||
|
|
8ae93940f3 | ||
|
|
cc5d232cfe | ||
|
|
a6e9d6ae92 | ||
|
|
e0b70d2d90 | ||
|
|
b3993238d5 | ||
|
|
5f5728ee8e | ||
|
|
6c5487609e |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## v1.4.364 (2025-12-28)
|
||||
|
||||
### PR [#1907](https://github.com/danielmiessler/Fabric/pull/1907) by [majiayu000](https://github.com/majiayu000): feat(gui): add Session Name support for multi-turn conversations
|
||||
|
||||
- Added Session Name support for multi-turn conversations in GUI chat interface, enabling persistent conversations similar to CLI's --session flag
|
||||
- Added SessionName field to PromptRequest and sessionName to ChatPrompt interface for proper session handling
|
||||
- Extracted SessionSelector component with Select component instead of native dropdown for better user experience
|
||||
- Implemented session message loading when selecting existing sessions with proper error handling
|
||||
- Fixed Select component binding and empty input handling to prevent redundant API calls and properly clear sessions
|
||||
|
||||
## v1.4.363 (2025-12-25)
|
||||
|
||||
### PR [#1906](https://github.com/danielmiessler/Fabric/pull/1906) by [ksylvan](https://github.com/ksylvan): Code Quality: Optimize HTTP client reuse + simplify error formatting
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.363"
|
||||
var version = "v1.4.364"
|
||||
|
||||
Binary file not shown.
@@ -29,6 +29,7 @@ type PromptRequest struct {
|
||||
ContextName string `json:"contextName"`
|
||||
PatternName string `json:"patternName"`
|
||||
StrategyName string `json:"strategyName"` // Optional strategy name
|
||||
SessionName string `json:"sessionName"` // Session name for multi-turn conversations
|
||||
Variables map[string]string `json:"variables,omitempty"` // Pattern variables
|
||||
}
|
||||
|
||||
@@ -131,6 +132,7 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
|
||||
},
|
||||
PatternName: p.PatternName,
|
||||
ContextName: p.ContextName,
|
||||
SessionName: p.SessionName, // Pass session name for multi-turn conversations
|
||||
PatternVariables: p.Variables, // Pass pattern variables
|
||||
Language: request.Language, // Pass the language field
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
"1.4.363"
|
||||
"1.4.364"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import Patterns from "./Patterns.svelte";
|
||||
import Models from "./Models.svelte";
|
||||
import ModelConfig from "./ModelConfig.svelte";
|
||||
import SessionSelector from "./SessionSelector.svelte";
|
||||
import { Select } from "$lib/components/ui/select";
|
||||
import { Input } from "$lib/components/ui/input";
|
||||
import { Label } from "$lib/components/ui/label";
|
||||
import { languageStore } from '$lib/store/language-store';
|
||||
import { strategies, selectedStrategy, fetchStrategies } from '$lib/store/strategy-store';
|
||||
@@ -75,6 +75,7 @@
|
||||
{/each}
|
||||
</Select>
|
||||
</div>
|
||||
<SessionSelector />
|
||||
<div>
|
||||
<Label for="pattern-variables" class="text-xs text-white/70 mb-1 block">Pattern Variables (JSON)</Label>
|
||||
<textarea
|
||||
|
||||
82
web/src/lib/components/chat/SessionSelector.svelte
Normal file
82
web/src/lib/components/chat/SessionSelector.svelte
Normal file
@@ -0,0 +1,82 @@
|
||||
<script lang="ts">
|
||||
import { Select } from "$lib/components/ui/select";
|
||||
import { Label } from "$lib/components/ui/label";
|
||||
import { currentSession, setSession, messageStore } from '$lib/store/chat-store';
|
||||
import { sessionAPI, sessions } from '$lib/store/session-store';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let sessionInput = '';
|
||||
|
||||
$: sessionsList = $sessions?.map(s => s.Name) ?? [];
|
||||
|
||||
function handleSessionInput() {
|
||||
const trimmed = sessionInput.trim();
|
||||
if (trimmed) {
|
||||
setSession(trimmed);
|
||||
} else {
|
||||
// Clear session when input is empty
|
||||
sessionInput = '';
|
||||
setSession(null);
|
||||
}
|
||||
}
|
||||
|
||||
let previousSessionInput = '';
|
||||
|
||||
async function handleSessionSelect() {
|
||||
// If the placeholder option (empty value) is selected, restore to previous value
|
||||
if (!sessionInput) {
|
||||
sessionInput = previousSessionInput || $currentSession || '';
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if session hasn't changed
|
||||
if (sessionInput === $currentSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
previousSessionInput = sessionInput;
|
||||
setSession(sessionInput);
|
||||
|
||||
// Load the selected session's message history so the chat reflects prior context
|
||||
try {
|
||||
const messages = await sessionAPI.loadSessionMessages(sessionInput);
|
||||
messageStore.set(messages);
|
||||
} catch (error) {
|
||||
console.error('Failed to load session messages:', error);
|
||||
}
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
await sessionAPI.loadSessions();
|
||||
} catch (error) {
|
||||
console.error('Failed to load sessions:', error);
|
||||
}
|
||||
sessionInput = $currentSession ?? '';
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Label for="session-input" class="text-xs text-white/70 mb-1 block">Session Name</Label>
|
||||
<input
|
||||
id="session-input"
|
||||
type="text"
|
||||
bind:value={sessionInput}
|
||||
on:blur={handleSessionInput}
|
||||
on:keydown={(e) => e.key === 'Enter' && handleSessionInput()}
|
||||
placeholder="Enter session name..."
|
||||
class="w-full px-3 py-2 text-sm bg-primary-800/30 border-none rounded-md hover:bg-primary-800/40 transition-colors text-white placeholder-white/50 focus:ring-1 focus:ring-white/20 focus:outline-none"
|
||||
/>
|
||||
{#if sessionsList.length > 0}
|
||||
<Select
|
||||
bind:value={sessionInput}
|
||||
on:change={handleSessionSelect}
|
||||
class="mt-2 bg-primary-800/30 border-none hover:bg-primary-800/40 transition-colors"
|
||||
>
|
||||
<option value="">Load existing session...</option>
|
||||
{#each sessionsList as session}
|
||||
<option value={session}>{session}</option>
|
||||
{/each}
|
||||
</Select>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -8,6 +8,7 @@ export interface ChatPrompt {
|
||||
model: string;
|
||||
patternName?: string;
|
||||
strategyName?: string; // Optional strategy name to prepend strategy prompt
|
||||
sessionName?: string; // Session name for multi-turn conversations
|
||||
variables?: { [key: string]: string }; // Pattern variables
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
systemPrompt,
|
||||
} from "$lib/store/pattern-store";
|
||||
import { selectedStrategy } from "$lib/store/strategy-store";
|
||||
import { currentSession } from "$lib/store/chat-store";
|
||||
|
||||
class LanguageValidator {
|
||||
constructor(private targetLanguage: string) {}
|
||||
@@ -210,6 +211,7 @@ export class ChatService {
|
||||
model: config.model,
|
||||
patternName: get(selectedPatternName),
|
||||
strategyName: get(selectedStrategy), // Add selected strategy to prompt
|
||||
sessionName: get(currentSession) ?? undefined, // Session name for multi-turn conversations
|
||||
variables: get(patternVariables), // Add pattern variables
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,5 +89,20 @@ export const sessionAPI = {
|
||||
toastService.error(error instanceof Error ? error.message : 'Failed to import session');
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async loadSessionMessages(sessionName: string): Promise<Message[]> {
|
||||
try {
|
||||
const response = await fetch(`/api/sessions/${sessionName}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load session: ${response.statusText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const messages = Array.isArray(data.Message) ? data.Message : [];
|
||||
return messages;
|
||||
} catch (error) {
|
||||
console.error(`Error loading session messages for ${sessionName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user