Presets & Prompts
APIs for managing presets and assembling prompt messages with character cards and World Info.
Preset API
context.presets provides a unified preset management interface, replacing direct imports of the PresetManager internal module.
presets.list
presets.list(collection?: string): Array<PresetRef>Lists all saved presets in the specified collection. collection is the preset collection name (e.g., 'openai').
presets.getSelected
presets.getSelected(collection?: string): PresetRef | nullGets the currently selected preset reference. Returns null if the current selection is a runtime preset bound to a Character Card.
presets.getLive
presets.getLive(collection?: string): PresetBody | nullGets the preset content currently being edited in the UI (including unsaved changes). Useful when you need to read the currently effective configuration.
presets.getStored
presets.getStored(ref: { collection: string, name: string }): PresetBody | nullGets the saved content of a specific preset. Useful for cross-preset comparison or copying content.
presets.save
presets.save(
ref: { collection: string, name: string },
body: PresetBody
): Promise<void>Saves preset content.
presets.resolve
presets.resolve(
target?: PresetRef | string,
options?: { collection?: string, defaultCollection?: string, allowMissingName?: boolean }
): { collection: string, name: string } | nullNormalizes a preset reference into a canonical { collection, name } object. This is purely a name-resolution helper — it does not return connection information. Pass an existing PresetRef, a collection name as a string (resolves to that collection's currently selected preset), or null (resolves to the current preset of options.collection). Returns null when the collection or name can't be determined.
Looking for connection profile resolution?
This function does not return API endpoint, model, or secret information. To resolve a Connection Manager profile into the connection settings that sendOpenAIRequest consumes, use context.connectionProfiles.resolve instead.
presets.state
presets.state.update(
namespace: string,
updater: (current: any) => any,
options?: { target: PresetRef }
): Promise<void>Manages plugin runtime/session data bound to a preset. This data is not exported with the preset and is only used for plugin runtime state.
Usage Rules
list()andgetSelected()only return saved presets- Use
getLive()for the preset currently being edited - Runtime presets bound to a Character Card are not considered "saved" —
getSelected()returnsnull, butgetLive()can still read them - Do not stuff plugin runtime data into the preset body; use
presets.state.*instead
Prompt and World Info Assembly
buildPresetAwarePromptMessages
buildPresetAwarePromptMessages(options: {
messages: Array<{ role: string, content: string }>,
envelopeOptions?: {
includeCharacterCard?: boolean,
api?: string,
promptPresetName?: string,
},
promptPresetName?: string,
runtimeWorldInfo?: object,
}): PromptMessage[]Assembles plugin messages into a prompt message list ready to be sent to an API, arranged according to the prompt preset's ordering. This is an optional assembly tool — simple LLM calls don't need it. You only need it when you want to reuse character cards, world info, or prompt templates.
Parameters:
| Parameter | Description |
|---|---|
messages | Array of messages to send, each containing role ('system'/'user'/'assistant') and content |
envelopeOptions.includeCharacterCard | Whether to include the current Character Card's definitions in the prompt (default true) |
envelopeOptions.api | Specifies the API type to use (e.g., 'openai'); uses the current connection if not specified |
envelopeOptions.promptPresetName | Specifies the preset name to use; uses the current preset if not specified |
promptPresetName | Same as envelopeOptions.promptPresetName; top-level shortcut |
runtimeWorldInfo | Pre-resolved World Info activation results (obtained via resolveWorldInfoForMessages) |
Key Behaviors:
- Preserves content from the active preset outside of chat history (system prompt, character description, etc.)
- Only replaces the chat history portion with the
messagesyou provide - If
runtimeWorldInfois provided, World Info entries are injected at the corresponding positions - If
promptPresetNameis specified, that preset's prompt template is used instead of the current preset
Practical Example (based on the Memory Graph plugin's recall flow):
// 1. First resolve World Info activation results
const runtimeWorldInfo = await context.resolveWorldInfoForMessages(
resolverMessages,
{
type: 'quiet',
fallbackToCurrentChat: false,
postActivationHook: rewriteDepthWorldInfoToAfter, // Rewrite directive: move depth-type World Info entries to the after position
}
);
// 2. Assemble the prompt
const promptMessages = context.buildPresetAwarePromptMessages({
messages: [
{ role: 'system', content: 'You are a memory analysis assistant...' },
{ role: 'user', content: 'Please analyze the key information in the following conversation...' },
],
envelopeOptions: {
includeCharacterCard: true,
api: envelopeApi,
promptPresetName: selectedPromptPresetName,
},
promptPresetName: selectedPromptPresetName,
runtimeWorldInfo: runtimeWorldInfo,
});
// 3. Send to the LLM
import { sendOpenAIRequest } from '../../../openai.js';
const response = await sendOpenAIRequest('quiet', promptMessages, signal, {
requestScope: 'extension_internal',
});About the Post-Activation Hook (postActivationHook)
The postActivationHook parameter of resolveWorldInfoForMessages allows you to make arbitrary modifications to entries after World Info activation but before injection — including modifying content, adjusting injection positions and depth, or even adding/removing entries. The hook receives the fully normalized World Info payload and returns the modified version. For example, the Memory Graph plugin uses this hook to rewrite depth-type World Info entries to the after position, preventing them from being inserted into the chat depth and interfering with the plugin's own instructions.
resolveWorldInfoForMessages
resolveWorldInfoForMessages(
messages: Array<{ role: string, content: string }>,
options?: {
type?: string,
fallbackToCurrentChat?: boolean,
postActivationHook?: (entries: object) => object,
}
): Promise<object>Performs a World Info activation scan against the specified messages and returns the activation results. This is essentially a World Info "rescan" against custom messages.
Parameters:
| Parameter | Description |
|---|---|
messages | Message list used to trigger World Info keyword matching |
options.type | Activation type (e.g., 'quiet' for silent scan that does not affect the main conversation) |
options.fallbackToCurrentChat | Whether to fall back to current chat messages if messages is empty |
options.postActivationHook | Post-activation hook function that receives the full World Info payload; can modify entry content, positions, depth, or add/remove entries |
The returned object contains fields such as worldInfoBeforeEntries, worldInfoAfterEntries, and worldInfoDepth, which can be passed directly to the runtimeWorldInfo parameter of buildPresetAwarePromptMessages.
World Info Rescan
resolveWorldInfoForMessages is essentially a World Info rescan against custom messages. Plugins can use it to:
- Obtain relevant World Info entries for independent LLM calls
- Test which World Info entries a specific message would trigger
- Simulate World Info activation without affecting the main conversation
Recommended Independent LLM Call Pattern
When a plugin needs to make independent LLM calls (e.g., AI-assisted features in a popup), the following pattern is recommended:
import { sendOpenAIRequest } from '../../../openai.js';
const context = Luker.getContext();
// 1. Resolve World Info activation results
const wi = await context.resolveWorldInfoForMessages(myCustomMessages, {
type: 'quiet',
fallbackToCurrentChat: false,
});
// 2. Assemble the prompt (inject character card, world info, arrange by prompt_order)
const requestMessages = context.buildPresetAwarePromptMessages({
messages: myCustomMessages,
runtimeWorldInfo: wi,
});
// 3. Send the request
const result = await sendOpenAIRequest('quiet', requestMessages, signal, {
requestScope: 'extension_internal',
});If you don't need character cards or world info, you can skip steps 1-2 and pass messages directly to sendOpenAIRequest. See Generation for sendOpenAIRequest details.
Prompt Envelope Inspection
For diagnostic UIs and "preview what would be sent" tooling, plugins can read the assembled prompt envelope and layout without dispatching a request.
getActivePromptPresetEnvelope
getActivePromptPresetEnvelope(options?: {
includeCharacterCard?: boolean,
api?: string,
promptPresetName?: string,
completionPresetName?: string,
contextPresetName?: string,
instructPresetName?: string,
syspromptPresetName?: string,
reasoningPresetName?: string,
}): PromptPresetEnvelopeReturns a snapshot of the resolved prompt configuration including:
mainApi/completionApi— active API identifierspresetRefs— names of resolved completion / context / instruct / sysprompt / reasoning presetspromptCore— extracted prompt-affecting fields per presetpromptLayout— the merged Luker layout (fromextensions.luker.prompt_layout)promptCatalog— map ofprompt.identifier→{ name, role, content, marker, systemPrompt }characterCard— current character fields (whenincludeCharacterCard !== false)
This is the same data that buildPresetAwarePromptMessages consumes internally. Useful for showing users what their plugin's request will look like before sending.
getActivePromptLayout
getActivePromptLayout(options?: object): PromptLayoutEntry[]Convenience accessor returning just the merged prompt layout. Each entry has id, enabled, order, role, phase, source, content, path, promptIdentifier, tags.
formatPromptPresetEnvelope
formatPromptPresetEnvelope(envelope?: object, options?: { label?: string }): stringFormats an envelope as [[LABEL]]\n<json> for embedding into another prompt (e.g., when delegating to a meta-LLM that needs to reason about the user's prompt config). Defaults to the current envelope when none is supplied.
const ctx = Luker.getContext();
const envelope = ctx.getActivePromptPresetEnvelope({ includeCharacterCard: true });
const serialized = ctx.formatPromptPresetEnvelope(envelope);
console.log(serialized);Reasoning
Reasoning helpers parse and render the <thinking>...</thinking> style blocks emitted by reasoning models (Claude reasoning, DeepSeek-R1, o1, etc.).
parseReasoningFromString
parseReasoningFromString(
text: string,
options?: { strict?: boolean },
template?: ReasoningTemplate | null,
): { reasoning: string, content: string } | nullSplits a model output string into reasoning and content based on the prefix and suffix of a reasoning template (or the active power_user.reasoning template). Returns null if the template lacks prefix/suffix or the parse fails.
| Option | Description |
|---|---|
strict | When true (default), the prefix must appear at the start (after whitespace). When false, finds it anywhere |
getReasoningTemplateByName
getReasoningTemplateByName(name: string): ReasoningTemplateLooks up a reasoning template by name. Throws Error('Unknown reasoning template name: "<name>"') when not found. The returned template should be treated as read-only.
updateReasoningUI
updateReasoningUI(
messageIdOrElement: number | HTMLElement | JQuery,
options?: { reset?: boolean },
): voidTriggers a UI refresh of the reasoning block on a message. Pass a chat index, a raw DOM element, or a JQuery wrapper. reset: true skips reading the message's current reasoning state — used during swipes when the new reasoning hasn't been written yet.
const ctx = Luker.getContext();
const parsed = ctx.parseReasoningFromString(modelOutput);
if (parsed) {
console.log('Reasoning:', parsed.reasoning);
console.log('Final answer:', parsed.content);
}Settings Views (Read-Only)
The following properties expose live settings objects. They are mutable references — write through them only through their canonical APIs (presets.save, saveSettingsDebounced, etc.). Direct mutation may not persist correctly.
chatCompletionSettings
context.chatCompletionSettings: objectReference to oai_settings. Read-only views useful for inspecting the active chat completion source, model, and parameters.
textCompletionSettings
context.textCompletionSettings: objectReference to textgenerationwebui_settings. Read-only views for the active text completion backend.
powerUserSettings
context.powerUserSettings: objectReference to power_user. Holds tokenizer choice, reasoning template selection, message-display preferences, and other user-level configuration.
Mutate via APIs, not directly
These views are exposed for inspection only. Writing to them directly may bypass debounced save logic. To change connection or model, use the user-facing UI or presets.save. To change generation parameters, use a chat completion preset.