import { z } from 'zod';
import { createConfigSchematics } from '@lmstudio/sdk';
// ==================== Zod Schema (validation) ====================
export const ConfigSchema = z.object({
// Tool Gating (enable/disable individual tools)
fileSystem: z.boolean().default(true),
webSearch: z.boolean().default(true),
browserAutomation: z.boolean().default(false),
gitOperations: z.boolean().default(false),
databaseQueries: z.boolean().default(false),
documentParsing: z.boolean().default(true),
backgroundCommands: z.boolean().default(false),
// ββ π NEW TOOL CATEGORIES ββββββββββββββββββββββββββββββββββββββ
imageProcessing: z.boolean().default(true).describe('Enable image OCR, screenshot, and comparison tools'),
httpClient: z.boolean().default(false).describe('Enable generic HTTP client for REST API calls'),
vectorRAG: z.boolean().default(true).describe('Enable semantic search with vector embeddings'),
uiGeneration: z.boolean().default(false).describe('Enable interactive UI generation and rendering tools'),
contextManagement: z.boolean().default(true).describe('Enable automatic context tracking and memory management'),
// ββ β οΈ GOD MODE (Enable ALL tools at once) ββββββββββββββββββββββ
godMode: z.boolean().default(false).describe('β οΈ WARNING: Enables every tool category. Use with caution.'),
// ββ π DOCUMENT RAG / CHAT WITH FILES βββββββββββββββββββββββββββ
documentRAG: z.boolean().default(true).describe('Enable file indexing and semantic search for chat'),
retrievalLimit: z.number().min(1).max(20).default(5).describe('Maximum number of relevant chunks to retrieve'),
retrievalAffinityThreshold: z.number().min(0.0).max(1.0).default(0.5).describe('Minimum similarity score for a chunk to be considered relevant (0-1)'),
// Execution tools β individual toggles (granular control)
executionJavaScript: z.boolean().default(false).describe('Allow run_javascript tool'),
executionPython: z.boolean().default(false).describe('Allow run_python tool'),
executionTerminal: z.boolean().default(false).describe('Allow run_in_terminal tool'),
executionShell: z.boolean().default(true).describe('Allow execute_command tool'),
// ββ Web Search Settings βββββββββββββββββββββββββββββββββββββββ
searchFallbackChain: z.enum(['ddg-api', 'ddg-fetch', 'google', 'bing']).default('ddg-api').describe('Primary search engine (auto-fallback to others)'),
maxSearchResults: z.number().min(1).max(50).default(10),
safesearch: z.enum(['0', '1', '2']).default('1'),
// ββ Browser Settings ββββββββββββββββββββββββββββββββββββββββββ
browserTimeout: z.number().min(1000).max(30000).default(5000),
headlessMode: z.boolean().default(false).describe('Run browser without GUI'),
// Git Settings
gitAutoCommit: z.boolean().default(false),
defaultBranch: z.string().default('main'),
// Security Settings
pathValidationEnabled: z.boolean().default(true),
binaryFileDetection: z.boolean().default(true),
regexReDoSProtection: z.boolean().default(true),
maxRegexLength: z.number().min(1).max(1000).default(500),
// State Management
statePersistenceEnabled: z.boolean().default(true),
stateMaxSize: z.number().min(1024).max(1048576).default(10240),
// i18n Settings
language: z.enum(['en', 'de', 'zh-CN', 'zh-TW']).default('en'),
// Notification Settings
notificationsEnabled: z.boolean().default(true),
// Temporal Awareness (merged from up_to_date)
temporalAwareness: z.boolean().default(true).describe('Enable automatic date/time injection into prompts'),
dateFormatStyle: z.enum(['standard', 'heuteIst']).default('standard').describe('Date format style for temporal awareness'),
// ββ π§ CONTEXT GUARD SETTINGS βββββββββββββββββββββββββββββββββββ
contextGuardEnabled: z.boolean().default(true).describe('Enable ContextGuard token management and history compression'),
contextGuardTokenLimit: z.number().min(1000).max(200000).default(80000).describe('Token limit before history compression triggers (90% threshold)'),
contextGuardSmartReading: z.boolean().default(true).describe('Enable keyword-based smart file reading'),
contextGuardSummaryModel: z.string().default('').describe('LM Studio model name for summarization (leave empty to use current chat model)'),
contextGuardTerminalFilterEnabled: z.boolean().default(true).describe('Enable terminal output filtering'),
contextGuardTerminalFilterLength: z.number().min(100).max(20000).default(2000).describe('Max chars before terminal output is filtered'),
// ββ π€ AUTO-TRACKING SETTINGS ββββββββββββββββββββββββββββββββββββ
autoTrackingEnabled: z.boolean().default(true).describe('Enable automatic tracking of important events in conversation'),
autoTrackDecisions: z.boolean().default(true).describe('Auto-track decisions and conclusions ("I decided", "conclusion")'),
autoTrackCompletions: z.boolean().default(true).describe('Auto-track task completions ("successfully completed", "finished")'),
autoTrackErrors: z.boolean().default(true).describe('Auto-track bug fixes and error resolutions ("fixed the bug")'),
autoSummaryInterval: z.number().min(10).max(200).default(50).describe('Messages between automatic session summaries'),
});
export type PluginConfig = z.infer<typeof ConfigSchema>;
/**
* Default configuration object
*/
export const DEFAULT_CONFIG: PluginConfig = {
fileSystem: true,
webSearch: true,
browserAutomation: false,
gitOperations: false,
databaseQueries: false,
documentParsing: true,
backgroundCommands: false,
// β οΈ GOD MODE (Enable ALL tools at once) β οΈ
godMode: false,
// ββ π NEW TOOL CATEGORIES ββββββββββββββββββββββββββββββββββββββ
imageProcessing: true,
httpClient: false,
vectorRAG: true,
uiGeneration: false,
contextManagement: true,
// β οΈ GOD MODE (Enable ALL tools at once) β οΈ
documentRAG: true,
retrievalLimit: 5,
retrievalAffinityThreshold: 0.5,
// Execution tools β all disabled by default (dangerous!)
executionJavaScript: false,
executionPython: false,
executionTerminal: false,
executionShell: true,
searchFallbackChain: 'ddg-api',
maxSearchResults: 10,
safesearch: '1',
browserTimeout: 5000,
headlessMode: false,
gitAutoCommit: false,
defaultBranch: 'main',
pathValidationEnabled: true,
binaryFileDetection: true,
regexReDoSProtection: true,
maxRegexLength: 500,
statePersistenceEnabled: true,
stateMaxSize: 10240,
language: 'en',
notificationsEnabled: true,
// Temporal Awareness (merged from up_to_date)
temporalAwareness: true,
dateFormatStyle: 'standard',
// ββ π§ CONTEXT GUARD SETTINGS βββββββββββββββββββββββββββββββββββ
contextGuardEnabled: true,
contextGuardTokenLimit: 80000, // ~80k tokens before compression (90% = 72k threshold)
contextGuardSmartReading: true,
contextGuardSummaryModel: '', // Empty = use current chat model
contextGuardTerminalFilterEnabled: true,
contextGuardTerminalFilterLength: 2000, // Filter terminal output > 2KB
// ββ π€ AUTO-TRACKING SETTINGS βββββββββββββββββββββββββββββββββββ
autoTrackingEnabled: false, // OFF BY DEFAULT β user must opt-in
autoTrackDecisions: true,
autoTrackCompletions: true,
autoTrackErrors: true,
autoSummaryInterval: 50, // Summary every 50 messages
};
/**
* Validate and sanitize config inp
*/
export function validateConfig(input: unknown): PluginConfig {
const result = ConfigSchema.safeParse(input);
if (!result.success) {
throw new Error(`Invalid configuration: ${result.error.message}`);
}
return result.data;
}
/**
* Check if a tool category is enabled in config
*/
export function isToolEnabled(config: PluginConfig, category: keyof Pick<PluginConfig, 'fileSystem' | 'webSearch' | 'browserAutomation' | 'gitOperations' | 'databaseQueries' | 'documentParsing' | 'backgroundCommands' | 'imageProcessing' | 'httpClient' | 'vectorRAG' | 'uiGeneration' | 'contextManagement'>): boolean {
return config[category] === true;
}
/**
* Check if a specific execution tool is enabled (granular)
*/
export function isExecutionToolEnabled(config: PluginConfig, tool: 'javascript' | 'python' | 'terminal' | 'shell'): boolean {
switch (tool) {
case 'javascript': return config.executionJavaScript === true;
case 'python': return config.executionPython === true;
case 'terminal': return config.executionTerminal === true;
case 'shell': return config.executionShell === true;
}
}
/**
* Get the execution tool key from a tool name
*/
export function getExecutionToolKey(toolName: string): 'javascript' | 'python' | 'terminal' | 'shell' | null {
switch (toolName) {
case 'run_javascript': return 'javascript';
case 'run_python': return 'python';
case 'run_in_terminal': return 'terminal';
case 'execute_command': return 'shell';
default: return null;
}
}
/**
* Check if ANY execution tool is enabled (legacy compatibility)
*/
export function hasAnyExecutionTool(config: PluginConfig): boolean {
return config.executionJavaScript || config.executionPython ||
config.executionTerminal || config.executionShell;
}
// ==================== LM Studio UI Schematics ====================
// These define the toggle switches that appear in LM Studio's settings panel.
export const configSchematics = createConfigSchematics()
// β οΈ GOD MODE - TOP PRIORITY WARNING TOGGLE β οΈ
.field('godMode', 'boolean', {
displayName: 'β‘β οΈ GOD MODE - Enable ALL Tools β οΈβ‘',
subtitle: 'WARNING: Activates every tool category instantly. Use with caution.',
hint: 'When enabled, ALL individual toggles are bypassed and every tool is activated regardless of settings.',
}, DEFAULT_CONFIG.godMode)
// ποΈ TOOL GATING (Hauptschalter) ποΈ
.field('fileSystem', 'boolean', { displayName: 'π File System Tools', hint: 'Enable file read/write/search operations' }, DEFAULT_CONFIG.fileSystem)
.field('webSearch', 'boolean', { displayName: 'π Web & Research Tools', hint: 'Enable DuckDuckGo/Wikipedia search' }, DEFAULT_CONFIG.webSearch)
// π GIT & GITHUB TOOLS (visuelle Gruppierung) π
.field('gitOperations', 'boolean', {
displayName: 'π Git & GitHub Tools',
subtitle: 'Version Control & API',
hint: 'Enable git operations and GitHub API access.',
}, DEFAULT_CONFIG.gitOperations)
.field('gitAutoCommit', 'boolean', {
displayName: 'πΎ Git Auto-Commit',
subtitle: 'βοΈ Teil der Git & GitHub Tools',
hint: 'Automatically commit changes after operations',
}, DEFAULT_CONFIG.gitAutoCommit)
.field('defaultBranch', 'string', {
displayName: 'πΏ Default Branch',
placeholder: 'main',
subtitle: 'βοΈ Teil der Git & GitHub Tools',
hint: 'Branch name for new repositories and git operations',
}, DEFAULT_CONFIG.defaultBranch)
.field('databaseQueries', 'boolean', { displayName: 'ποΈ Database Queries', hint: 'Enable read-only SQLite queries' }, DEFAULT_CONFIG.databaseQueries)
.field('documentParsing', 'boolean', { displayName: 'π Document Parsing', hint: 'Enable PDF/DOCX document reading' }, DEFAULT_CONFIG.documentParsing)
.field('backgroundCommands', 'boolean', { displayName: 'β³ Background Commands', hint: 'Enable long-running process tracking' }, DEFAULT_CONFIG.backgroundCommands)
// πββ NEW TOOL CATEGORIES πββ
.field('imageProcessing', 'boolean', {
displayName: 'πΌοΈ Image Processing Tools',
subtitle: 'OCR, Screenshots & Comparison',
hint: 'Enable image OCR (Tesseract.js), screenshot capture, and image comparison tools.',
}, DEFAULT_CONFIG.imageProcessing)
.field('httpClient', 'boolean', {
displayName: 'π HTTP Client Tools',
subtitle: 'Generic REST API Client',
hint: 'Enable generic HTTP client for making requests to any REST API (GET, POST, PUT, DELETE).',
}, DEFAULT_CONFIG.httpClient)
.field('vectorRAG', 'boolean', {
displayName: 'π Vector RAG / Semantic Search',
subtitle: 'Semantic Document Search',
hint: 'Enable semantic search with vector embeddings for intelligent document retrieval.',
}, DEFAULT_CONFIG.vectorRAG)
.field('uiGeneration', 'boolean', {
displayName: 'π¨ Interactive UI Generation Tools',
subtitle: 'Generate and render interactive UI components',
hint: 'Enable tools for generating HTML/CSS/JS components (buttons, forms, charts, dashboards) and rendering them in the browser.',
}, DEFAULT_CONFIG.uiGeneration)
.field('contextManagement', 'boolean', {
displayName: 'π§ Auto-Context Management Tools',
subtitle: 'Automatic session tracking and memory management',
hint: 'Enable tools for automatically saving important decisions, patterns, and configurations to persistent memory.',
}, DEFAULT_CONFIG.contextManagement)
// π DOCUMENT RAG / CHAT WITH FILES π
.field('documentRAG', 'boolean', {
displayName: 'π Document RAG / Chat with Files',
subtitle: 'Enable file indexing and semantic search for chat',
hint: 'Attach documents to your chat messages. The plugin will automatically retrieve relevant content from attached files using semantic search.',
}, DEFAULT_CONFIG.documentRAG)
.field('retrievalLimit', 'numeric', {
displayName: 'π’ Retrieval Limit',
subtitle: 'Max chunks to return per query',
min: 1, max: 20, int: true,
hint: 'Maximum number of relevant document chunks to retrieve for each query.',
}, DEFAULT_CONFIG.retrievalLimit)
.field('retrievalAffinityThreshold', 'numeric', {
displayName: 'π― Retrieval Affinity Threshold',
subtitle: 'Minimum relevance score (0-1)',
min: 0.0, max: 1.0, step: 0.01,
hint: 'Chunks below this similarity score will be filtered out. Lower = more results but potentially less relevant.',
}, DEFAULT_CONFIG.retrievalAffinityThreshold)
// β‘ EXECUTION TOOLS (GefΓ€hrlich!) β‘
.field('executionJavaScript', 'boolean', {
displayName: 'β‘ JavaScript-AusfΓΌhrung erlauben',
subtitle: "Aktiviert das 'run_javascript'-Tool",
hint: 'GEFAHR: Code lΓ€uft auf Ihrem Rechner.',
}, DEFAULT_CONFIG.executionJavaScript)
.field('executionPython', 'boolean', {
displayName: 'π Python-AusfΓΌhrung erlauben',
subtitle: "Aktiviert das 'run_python'-Tool",
hint: 'GEFAHR: Code lΓ€uft auf Ihrem Rechner.',
}, DEFAULT_CONFIG.executionPython)
.field('executionTerminal', 'boolean', {
displayName: 'π» Terminal-AusfΓΌhrung erlauben',
subtitle: "Aktiviert das 'run_in_terminal'-Tool",
hint: 'Γffnet echte Terminal-Fenster.',
}, DEFAULT_CONFIG.executionTerminal)
.field('executionShell', 'boolean', {
displayName: 'π§ Shell-BefehlsausfΓΌhrung erlauben',
subtitle: "Aktiviert das 'execute_command'-Tool",
hint: 'GEFAHR: Befehle laufen auf Ihrem Rechner.',
}, DEFAULT_CONFIG.executionShell)
// π SEARCH SETTINGS π
.field('searchFallbackChain', 'select', {
displayName: 'π Search Fallback Chain',
hint: 'Primary search engine. Auto-falls back to others if unavailable.',
options: [
{ value: 'ddg-api', displayName: 'DuckDuckGo API' },
{ value: 'ddg-fetch', displayName: 'DuckDuckGo Fetch' },
{ value: 'google', displayName: 'Google' },
{ value: 'bing', displayName: 'Bing' },
],
}, DEFAULT_CONFIG.searchFallbackChain)
.field('maxSearchResults', 'numeric', { min: 1, max: 50, int: true }, DEFAULT_CONFIG.maxSearchResults)
.field('safesearch', 'select', {
displayName: 'π‘οΈ Safe Search',
options: [
{ value: '0', displayName: 'Off' },
{ value: '1', displayName: 'Moderate' },
{ value: '2', displayName: 'Strict' },
],
}, DEFAULT_CONFIG.safesearch)
// π₯οΈ BROWSER AUTOMATION TOOLS π₯οΈ
.field('browserAutomation', 'boolean', {
displayName: 'π₯οΈ Browser Automation Tools',
subtitle: 'Headless browser control & automation',
hint: 'Enable Puppeteer-based headless browser automation for web scraping, testing, and UI interaction.',
}, DEFAULT_CONFIG.browserAutomation)
.field('browserTimeout', 'numeric', {
displayName: 'β±οΈ Browser Timeout',
subtitle: 'βοΈ Teil der Browser Automation Tools',
min: 1000, max: 30000, int: true,
hint: 'Maximum time (ms) to wait for browser operations before timing out.',
}, DEFAULT_CONFIG.browserTimeout)
.field('headlessMode', 'boolean', {
displayName: 'π» Headless Mode',
subtitle: 'βοΈ Teil der Browser Automation Tools',
hint: 'Run browser without GUI (recommended for automation).',
}, DEFAULT_CONFIG.headlessMode)
// π SECURITY SETTINGS π
.field('pathValidationEnabled', 'boolean', { displayName: 'π Path Validation', hint: 'Prevent directory traversal attacks' }, DEFAULT_CONFIG.pathValidationEnabled)
.field('binaryFileDetection', 'boolean', { displayName: 'π Binary File Detection', hint: 'Detect binary files via null byte check' }, DEFAULT_CONFIG.binaryFileDetection)
.field('regexReDoSProtection', 'boolean', { displayName: 'π‘οΈ ReDoS Protection', hint: 'Protect against regex denial-of-service' }, DEFAULT_CONFIG.regexReDoSProtection)
.field('maxRegexLength', 'numeric', { min: 1, max: 1000, int: true }, DEFAULT_CONFIG.maxRegexLength)
// π½ STATE MANAGEMENT π½
.field('statePersistenceEnabled', 'boolean', { displayName: 'π½ State Persistence', hint: 'Persist tool execution state between sessions' }, DEFAULT_CONFIG.statePersistenceEnabled)
.field('stateMaxSize', 'numeric', { min: 1024, max: 1048576, int: true }, DEFAULT_CONFIG.stateMaxSize)
// π LANGUAGE & NOTIFICATIONS π
.field('language', 'select', {
displayName: 'π Language',
options: [
{ value: 'en', displayName: 'English' },
{ value: 'de', displayName: 'Deutsch (German)' },
{ value: 'zh-CN', displayName: 'Simplified Chinese' },
{ value: 'zh-TW', displayName: 'Traditional Chinese' },
],
}, DEFAULT_CONFIG.language)
.field('notificationsEnabled', 'boolean', { displayName: 'π Desktop Notifications', hint: 'Show system notifications' }, DEFAULT_CONFIG.notificationsEnabled)
// β° TEMPORAL AWARENESS (from up_to_date)
.field('temporalAwareness', 'boolean', {
displayName: 'β° Temporal Awareness',
subtitle: 'Injects current date/time into every message',
hint: 'Enables the AI to know the current time.',
}, DEFAULT_CONFIG.temporalAwareness)
.field('dateFormatStyle', 'select', {
displayName: 'π
Date Format Style',
options: [
{ value: 'standard', displayName: 'Standard ([Zeit: ...])' },
{ value: 'heuteIst', displayName: 'HEUTE IST Mode (Prominent)' },
],
}, DEFAULT_CONFIG.dateFormatStyle)
// ββ π§ CONTEXT GUARD SETTINGS βββββββββββββββββββββββββββββββββββ
.field('contextGuardEnabled', 'boolean', {
displayName: 'π§ ContextGuard Token Management',
subtitle: 'Automatic history compression & smart reading',
hint: 'Automatically compresses chat history when token limit is reached. Enables smart file reading and terminal output filtering.',
}, DEFAULT_CONFIG.contextGuardEnabled)
.field('contextGuardTokenLimit', 'numeric', {
displayName: 'π Token Limit Before Compression',
subtitle: 'βοΈ ContextGuard Setting',
min: 1000, max: 200000, int: true,
hint: 'Compression triggers at 90% of this limit. Higher = more context retained but slower responses.',
}, DEFAULT_CONFIG.contextGuardTokenLimit)
.field('contextGuardSmartReading', 'boolean', {
displayName: 'π Smart File Reading',
subtitle: 'βοΈ ContextGuard Setting',
hint: 'Extracts keywords from user queries to read only relevant portions of files. Saves tokens and speeds up responses.',
}, DEFAULT_CONFIG.contextGuardSmartReading)
.field('contextGuardSummaryModel', 'string', {
displayName: 'π€ Summary Model Name',
subtitle: 'βοΈ ContextGuard Setting',
placeholder: '(leave empty for current chat model)',
hint: 'LM Studio model name used for history summarization. Leave empty to use your current chat model.',
}, DEFAULT_CONFIG.contextGuardSummaryModel)
.field('contextGuardTerminalFilterEnabled', 'boolean', {
displayName: 'π Terminal Output Filtering',
subtitle: 'βοΈ ContextGuard Setting',
hint: 'Automatically truncates long terminal outputs to save tokens.',
}, DEFAULT_CONFIG.contextGuardTerminalFilterEnabled)
.field('contextGuardTerminalFilterLength', 'numeric', {
displayName: 'π Max Terminal Output Length',
subtitle: 'βοΈ ContextGuard Setting',
min: 100, max: 20000, int: true,
hint: 'Maximum characters before terminal output is truncated and summarized.',
}, DEFAULT_CONFIG.contextGuardTerminalFilterLength)
// ββ π€ AUTO-TRACKING SETTINGS βββββββββββββββββββββββββββββββββββ
.field('autoTrackingEnabled', 'boolean', {
displayName: 'π€ Auto-Tracking Enabled',
subtitle: 'Automatically remember important events',
hint: 'When enabled, the plugin will silently track decisions, completions, and fixes without user prompts. OFF by default for privacy.',
}, DEFAULT_CONFIG.autoTrackingEnabled)
.field('autoTrackDecisions', 'boolean', {
displayName: 'π Track Decisions Automatically',
subtitle: 'βοΈ Auto-Tracking Setting',
hint: 'Detects phrases like "I decided", "conclusion", "going with".',
}, DEFAULT_CONFIG.autoTrackDecisions)
.field('autoTrackCompletions', 'boolean', {
displayName: 'β
Track Completions Automatically',
subtitle: 'βοΈ Auto-Tracking Setting',
hint: 'Detects phrases like "successfully completed", "finished implementing".',
}, DEFAULT_CONFIG.autoTrackCompletions)
.field('autoTrackErrors', 'boolean', {
displayName: 'π Track Bug Fixes Automatically',
subtitle: 'βοΈ Auto-Tracking Setting',
hint: 'Detects phrases like "fixed the bug", "resolved the issue".',
}, DEFAULT_CONFIG.autoTrackErrors)
.field('autoSummaryInterval', 'numeric', {
displayName: 'π Session Summary Interval',
subtitle: 'βοΈ Auto-Tracking Setting',
min: 10, max: 200, int: true,
hint: 'Number of messages between automatic session summaries. Higher = less frequent.',
}, DEFAULT_CONFIG.autoSummaryInterval)
.build();