refactor: unload model on errors + success

This commit is contained in:
2026-05-31 16:57:03 -05:00
parent 11dc00b2b8
commit 192c9e85ff
+22 -20
View File
@@ -87,14 +87,28 @@ function pruneToolMessages(messages: Message[], keepRecent = 6): Message[] {
let pruned = 0; let pruned = 0;
const result = messages.map((msg, i) => { const result = messages.map((msg, i) => {
if (!toPrune.has(i)) return msg; if (!toPrune.has(i)) return msg;
const originalLen = typeof msg.content === "string" ? msg.content.length : 0; const originalLen =
typeof msg.content === "string" ? msg.content.length : 0;
pruned++; pruned++;
return { ...msg, content: `[pruned: was ${originalLen} chars — context limit approached]` }; return {
...msg,
content: `[pruned: was ${originalLen} chars — context limit approached]`,
};
}); });
log.info(`» pruned ${pruned} old tool message(s) to reduce context`); log.info(`» pruned ${pruned} old tool message(s) to reduce context`);
return result; return result;
} }
async function unloadModel(ollama: Ollama, model: string): Promise<void> {
try {
await ollama.generate({ model, keep_alive: 0, prompt: "" });
log.info(`» unloaded model ${model} from Ollama`);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
log.warning(`» failed to unload model ${model}: ${msg}`);
}
}
async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> { async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
const ollamaHost = process.env.OLLAMA_HOST ?? ""; const ollamaHost = process.env.OLLAMA_HOST ?? "";
if (!ollamaHost) { if (!ollamaHost) {
@@ -162,6 +176,8 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
}, },
); );
} catch (err) { } catch (err) {
await unloadModel(ollama, model);
const lastError = err instanceof Error ? err.message : String(err); const lastError = err instanceof Error ? err.message : String(err);
log.error(`Ollama error: ${lastError}`); log.error(`Ollama error: ${lastError}`);
return { success: false, error: `Ollama request failed: ${lastError}` }; return { success: false, error: `Ollama request failed: ${lastError}` };
@@ -208,21 +224,14 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
continue; continue;
} }
await unloadModel(ollama, model);
if (pendingModeNudge) { if (pendingModeNudge) {
log.info("» agent finished after mode nudge (no tool calls)"); log.info("» agent finished after mode nudge (no tool calls)");
} else { } else {
log.info("» agent finished (no tool calls)"); log.info("» agent finished (no tool calls)");
} }
// unload the model from memory immediately since we're done with it, to free up resources for future runs. see #829.
try {
await ollama.generate({ model, keep_alive: 0, prompt: "" });
log.info(`» unloaded model ${model} from Ollama`);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
log.warning(`» failed to unload model ${model}: ${msg}`);
}
return { return {
success: true, success: true,
output: assistantMessage.content || undefined, output: assistantMessage.content || undefined,
@@ -299,16 +308,9 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
} }
} }
log.warning(`» agent hit max iterations (${MAX_ITERATIONS})`); await unloadModel(ollama, model);
// unload the model from memory immediately since we're done with it, to free up resources for future runs. see #829. log.warning(`» agent hit max iterations (${MAX_ITERATIONS})`);
try {
await ollama.generate({ model, keep_alive: 0, prompt: "" });
log.info(`» unloaded model ${model} from Ollama`);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
log.warning(`» failed to unload model ${model}: ${msg}`);
}
return { return {
success: false, success: false,