src / index.ts
import "dotenv/config";
import { ChatMessage, PluginContext, PromptPreprocessorController } from "@lmstudio/sdk";
import { configSchematics } from "./config/configSchematics";
import { defaultConfigurationService } from "./config/ConfigurationService";
import { buildPreprocessedText, knownPrependProviders } from "./PrependInstructionFormatter";
import { nativeTitlePollutionPreventer } from "./title";
import { toolsProvider } from "./toolsProvider";
import { Logger } from "./utils/Logger";
export async function main(context: PluginContext) {
context.withGlobalConfigSchematics(configSchematics);
context.withToolsProvider(toolsProvider);
context.withPromptPreprocessor(async (ctl: PromptPreprocessorController, userMessage: ChatMessage) => {
try {
const pluginConfig = ctl.getGlobalPluginConfig(configSchematics);
defaultConfigurationService.lmStudioSource.setPluginConfig(pluginConfig);
defaultConfigurationService.syncAllProviders();
} catch {
// Fall back to environment configuration source
}
const originalText = userMessage.getText()?.trim() ?? "";
const isFreshChat = await ctl.needsNaming().catch(() => false);
const instructions = knownPrependProviders
.filter(p => p.isEnabled(originalText, { isFreshChat }))
.map(p => p.instruction);
const updatedText = buildPreprocessedText(instructions, originalText);
// Mutate userMessage via replaceText() to preserve all non-text attachments (images, files, PDFs)
if (updatedText !== originalText) {
userMessage.replaceText(updatedText);
}
// Prevent conversation title pollution natively during initial naming turn
await nativeTitlePollutionPreventer.applyInitialConversationTitle({
ctl,
originalUserMessage: originalText,
prependInstructions: instructions,
});
return userMessage;
});
}
export { toolsProvider };
src / index.ts
import "dotenv/config";
import { ChatMessage, PluginContext, PromptPreprocessorController } from "@lmstudio/sdk";
import { configSchematics } from "./config/configSchematics";
import { defaultConfigurationService } from "./config/ConfigurationService";
import { buildPreprocessedText, knownPrependProviders } from "./PrependInstructionFormatter";
import { nativeTitlePollutionPreventer } from "./title";
import { toolsProvider } from "./toolsProvider";
import { Logger } from "./utils/Logger";
export async function main(context: PluginContext) {
context.withGlobalConfigSchematics(configSchematics);
context.withToolsProvider(toolsProvider);
context.withPromptPreprocessor(async (ctl: PromptPreprocessorController, userMessage: ChatMessage) => {
try {
const pluginConfig = ctl.getGlobalPluginConfig(configSchematics);
defaultConfigurationService.lmStudioSource.setPluginConfig(pluginConfig);
defaultConfigurationService.syncAllProviders();
} catch {
// Fall back to environment configuration source
}
const originalText = userMessage.getText()?.trim() ?? "";
const isFreshChat = await ctl.needsNaming().catch(() => false);
const instructions = knownPrependProviders
.filter(p => p.isEnabled(originalText, { isFreshChat }))
.map(p => p.instruction);
const updatedText = buildPreprocessedText(instructions, originalText);
// Mutate userMessage via replaceText() to preserve all non-text attachments (images, files, PDFs)
if (updatedText !== originalText) {
userMessage.replaceText(updatedText);
}
// Prevent conversation title pollution natively during initial naming turn
await nativeTitlePollutionPreventer.applyInitialConversationTitle({
ctl,
originalUserMessage: originalText,
prependInstructions: instructions,
});
return userMessage;
});
}
export { toolsProvider };