Project Files
promptPreprocessor.js
"use strict";
/**
* Prompt preprocessor.
*
* On the first turn: prepends a hidden system block with tool-call rules so the
* model knows how to handle errors. On subsequent turns: passes through unchanged.
*
* The heavy lifting for error feedback is done by safe_impl() in toolsProvider,
* which wraps every tool and returns a structured { tool_error, error, hint } JSON
* object the model can read and retry from.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.promptPreprocessor = promptPreprocessor;
const peers_1 = require("./peers");
const TOOL_RULES = `\
[System: Tool call rules]
• Output valid JSON only — no HTML, no markdown, no trailing commas.
• Booleans: use true/false, never "true"/"false".
• Numbers: plain numbers only, never quoted.
• Always include required parameters (check the tool description).
• For large file content, use multiple write_file calls — long JSON args get truncated.
• When a tool returns { "tool_error": true }, read the "error" and "hint" fields, correct the issue, and retry immediately.
== WRITE SAFETY ==
Before overwriting an existing file with write_file, or making a large replace_in_file substitution:
→ call diff_preview(path, mode="write"|"replace", ...) first
This shows exactly what will change without touching the file. Always do this when the user hasn't seen the current file content.
== GIT STAGING ==
git_stage accepts glob patterns — e.g. files="src/**/*.py" or files="*.ts *.js".
No need to enumerate every file explicitly.`;
async function promptPreprocessor(ctl, userMessage) {
const history = await ctl.pullHistory();
// Inject rules on the first turn by prepending them to the user message.
// history.append() operates on a local copy and is never sent back to LM Studio,
// so the only way to inject content is through the return value.
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);
}
const peerTip = (0, peers_1.webPeerStatus)() === false
? `\n\n[Tip: Install the "altra/web-search" plugin for richer web search and page reading. Without it, fetch_url and search_web are active as built-in fallbacks.]`
: "";
return `${TOOL_RULES}${peerTip}\n\n${userMessage.getText()}`;
}
return userMessage;
}