src / promptPreprocessor.ts
import {
type ChatMessage,
type PromptPreprocessorController,
} from "@lmstudio/sdk";
const SYSTEM_RULES = `\
[System: Skills Plugin]
You have access to a library of skills — reusable procedures stored as SKILL.md files. Use them to follow established, proven workflows instead of improvising.
== TOOL ROUTING ==
- User asks what skills are available / what you can do -> list_skills
- User names a skill and wants its full procedure -> read_skill
- User has a task that matches a skill's purpose -> apply_skill (loads the skill and follows it for the task)
- A skill references one of its own files -> list_skill_files to see them, read_skill_file to load one
== LINKED FILES ==
A skill directory may contain references/, scripts/, and assets/ alongside SKILL.md.
read_skill and apply_skill return a linkedFiles listing. Load an auxiliary file with
read_skill_file only when the procedure calls for it (progressive disclosure — don't
load everything up front).
== BEST PRACTICE ==
- Before starting a task, check list_skills for a matching skill.
- When a skill matches, read/apply it and follow its numbered procedure exactly.
- If no skill matches, say so and proceed with general knowledge.
`;
export async function promptPreprocessor(
ctl: PromptPreprocessorController,
userMessage: ChatMessage,
): Promise<string | ChatMessage> {
const history = await ctl.pullHistory();
if (history.length === 0) {
if (await ctl.needsNaming()) {
const text = userMessage.getText().trim();
const name = text.length > 0 ? text.slice(0, 60).replace(/\s+/g, " ") : "Session";
ctl.suggestName(name);
}
return `${SYSTEM_RULES}\n\n${userMessage.getText()}`;
}
return userMessage;
}
src / promptPreprocessor.ts
import {
type ChatMessage,
type PromptPreprocessorController,
} from "@lmstudio/sdk";
const SYSTEM_RULES = `\
[System: Skills Plugin]
You have access to a library of skills — reusable procedures stored as SKILL.md files. Use them to follow established, proven workflows instead of improvising.
== TOOL ROUTING ==
- User asks what skills are available / what you can do -> list_skills
- User names a skill and wants its full procedure -> read_skill
- User has a task that matches a skill's purpose -> apply_skill (loads the skill and follows it for the task)
- A skill references one of its own files -> list_skill_files to see them, read_skill_file to load one
== LINKED FILES ==
A skill directory may contain references/, scripts/, and assets/ alongside SKILL.md.
read_skill and apply_skill return a linkedFiles listing. Load an auxiliary file with
read_skill_file only when the procedure calls for it (progressive disclosure — don't
load everything up front).
== BEST PRACTICE ==
- Before starting a task, check list_skills for a matching skill.
- When a skill matches, read/apply it and follow its numbered procedure exactly.
- If no skill matches, say so and proceed with general knowledge.
`;
export async function promptPreprocessor(
ctl: PromptPreprocessorController,
userMessage: ChatMessage,
): Promise<string | ChatMessage> {
const history = await ctl.pullHistory();
if (history.length === 0) {
if (await ctl.needsNaming()) {
const text = userMessage.getText().trim();
const name = text.length > 0 ? text.slice(0, 60).replace(/\s+/g, " ") : "Session";
ctl.suggestName(name);
}
return `${SYSTEM_RULES}\n\n${userMessage.getText()}`;
}
return userMessage;
}