1
0
Fork 0

System instruction override

This commit is contained in:
Pabloader 2026-04-07 07:52:59 +00:00
parent 64b913374e
commit d93e3c812e
3 changed files with 26 additions and 4 deletions

View File

@ -11,7 +11,7 @@ import { LoreEditor } from "./lore-editor";
import { Menu } from "./menu"; import { Menu } from "./menu";
import { useInputCallback } from "@common/hooks/useInputCallback"; import { useInputCallback } from "@common/hooks/useInputCallback";
import Prompt from "../utils/prompt"; import Prompt from "../utils/prompt";
import { BookOpen, List, Users, MapPin, BookMarked, FileText, Code, Layers, MessageSquare, Globe, type LucideIcon } from "lucide-preact"; import { BookOpen, List, Users, MapPin, BookMarked, FileText, Code, Layers, MessageSquare, Globe, BrainCircuit, type LucideIcon } from "lucide-preact";
// Tabs available when a story is selected // Tabs available when a story is selected
const STORY_TABS: { id: Tab; label: string; icon: LucideIcon; right?: boolean }[] = [ const STORY_TABS: { id: Tab; label: string; icon: LucideIcon; right?: boolean }[] = [
@ -31,6 +31,7 @@ const WORLD_TABS: { id: Tab; label: string; icon: LucideIcon; right?: boolean }[
{ id: "lore", label: "Lore", icon: BookMarked }, { id: "lore", label: "Lore", icon: BookMarked },
{ id: "characters", label: "Characters", icon: Users }, { id: "characters", label: "Characters", icon: Users },
{ id: "locations", label: "Locations", icon: MapPin }, { id: "locations", label: "Locations", icon: MapPin },
{ id: "system", label: "System", icon: BrainCircuit },
]; ];
export const Editor = () => { export const Editor = () => {
@ -47,6 +48,11 @@ export const Editor = () => {
dispatch({ type: 'EDIT_SCRATCHPAD', worldId: currentWorld.id, id: currentStory.id, text }); dispatch({ type: 'EDIT_SCRATCHPAD', worldId: currentWorld.id, id: currentStory.id, text });
}, [currentStory?.id, currentWorld?.id]); }, [currentStory?.id, currentWorld?.id]);
const handleSystemOverrideInput = useInputCallback((text: string) => {
if (!currentWorld) return;
dispatch({ type: 'SET_WORLD_SYSTEM_INSTRUCTION_OVERRIDE', worldId: currentWorld.id, systemInstructionOverride: text || undefined });
}, [currentWorld?.id]);
const handleTabChange = (tab: Tab) => { const handleTabChange = (tab: Tab) => {
dispatch({ type: 'SET_CURRENT_TAB', tab }); dispatch({ type: 'SET_CURRENT_TAB', tab });
}; };
@ -150,6 +156,14 @@ export const Editor = () => {
{currentTab === "prompt" && currentStory && ( {currentTab === "prompt" && currentStory && (
<div class={styles.promptPreview} dangerouslySetInnerHTML={{ __html: promptPreview }} /> <div class={styles.promptPreview} dangerouslySetInnerHTML={{ __html: promptPreview }} />
)} )}
{currentTab === "system" && currentWorld && (
<ContentEditable
class={styles.editable}
value={currentWorld.systemInstructionOverride ?? ''}
onInput={handleSystemOverrideInput}
placeholder="Override the global system instruction for this world. Leave empty to use the global setting."
/>
)}
</div> </div>
<div class={styles.tabs}> <div class={styles.tabs}>
{tabs.filter(tab => hasSelection || tab.id === 'menu').map((tab) => ( {tabs.filter(tab => hasSelection || tab.id === 'menu').map((tab) => (

View File

@ -11,7 +11,7 @@ export type ChatMessage = LLM.ChatMessage & {
id: string; id: string;
} }
export type Tab = "story" | "lore" | "characters" | "locations" | "chapters" | "scratchpad" | "prompt" | "menu"; export type Tab = "story" | "lore" | "characters" | "locations" | "chapters" | "scratchpad" | "prompt" | "menu" | "system";
export enum CharacterRole { export enum CharacterRole {
Protagonist = 'protagonist', Protagonist = 'protagonist',
@ -84,6 +84,7 @@ export interface World {
characters: Character[]; characters: Character[];
locations: Location[]; locations: Location[];
stories: Story[]; stories: Story[];
systemInstructionOverride?: string;
} }
// ─── State ─────────────────────────────────────────────────────────────────── // ─── State ───────────────────────────────────────────────────────────────────
@ -124,6 +125,7 @@ type Action =
| { type: 'REORDER_LORE_ENTRIES'; worldId: string; storyId: string | null; entryIds: string[] } | { type: 'REORDER_LORE_ENTRIES'; worldId: string; storyId: string | null; entryIds: string[] }
// Settings // Settings
| { type: 'SET_SYSTEM_INSTRUCTION'; systemInstruction: string } | { type: 'SET_SYSTEM_INSTRUCTION'; systemInstruction: string }
| { type: 'SET_WORLD_SYSTEM_INSTRUCTION_OVERRIDE'; worldId: string; systemInstructionOverride: string | undefined }
| { type: 'SET_CURRENT_TAB'; tab: Tab } | { type: 'SET_CURRENT_TAB'; tab: Tab }
| { type: 'SET_CHAT_OPEN'; open: boolean } | { type: 'SET_CHAT_OPEN'; open: boolean }
// Chat // Chat
@ -357,6 +359,9 @@ function reducer(state: IState, action: Action): IState {
case 'SET_SYSTEM_INSTRUCTION': { case 'SET_SYSTEM_INSTRUCTION': {
return { ...state, systemInstruction: action.systemInstruction }; return { ...state, systemInstruction: action.systemInstruction };
} }
case 'SET_WORLD_SYSTEM_INSTRUCTION_OVERRIDE': {
return updateWorld(state, action.worldId, w => ({ ...w, systemInstructionOverride: action.systemInstructionOverride }));
}
case 'SET_CURRENT_TAB': { case 'SET_CURRENT_TAB': {
return { ...state, currentTab: action.tab }; return { ...state, currentTab: action.tab };
} }
@ -513,6 +518,8 @@ export interface AppState {
enableThinking: boolean; enableThinking: boolean;
bannedTokens: string[]; bannedTokens: string[];
systemInstruction: string; systemInstruction: string;
/** Effective system instruction: world override if set, otherwise global */
effectiveSystemInstruction: string;
dispatch: (action: Action) => void; dispatch: (action: Action) => void;
} }
@ -557,6 +564,7 @@ export const StateContextProvider = ({ children }: { children?: any }) => {
enableThinking: state.enableThinking, enableThinking: state.enableThinking,
bannedTokens: state.bannedTokens ?? [], bannedTokens: state.bannedTokens ?? [],
systemInstruction: state.systemInstruction ?? '', systemInstruction: state.systemInstruction ?? '',
effectiveSystemInstruction: currentWorld?.systemInstructionOverride ?? state.systemInstruction ?? '',
dispatch, dispatch,
}; };
}, [state]); }, [state]);

View File

@ -277,10 +277,10 @@ namespace Prompt {
export function formatSystemPrompt(state: AppState, storyTokenBudget: number = 0): string { export function formatSystemPrompt(state: AppState, storyTokenBudget: number = 0): string {
const { currentStory } = state; const { currentStory } = state;
if (!currentStory) { if (!currentStory) {
return state.systemInstruction; return state.effectiveSystemInstruction;
} }
const parts: string[] = [state.systemInstruction]; const parts: string[] = [state.effectiveSystemInstruction];
parts.push(`# Story Title: ${currentStory.title}`); parts.push(`# Story Title: ${currentStory.title}`);