From 36449a2cae99de122200442f0545cc7b3efa6b45 Mon Sep 17 00:00:00 2001 From: Charles Packer Date: Thu, 5 Feb 2026 14:51:50 -0800 Subject: [PATCH] fix: reset loaded_skills block on new conversation (#837) Co-authored-by: Letta --- src/agent/loadedSkills.ts | 52 +++++++++++++++++++++++++++++++++++++++ src/cli/App.tsx | 3 +++ src/index.ts | 2 ++ 3 files changed, 57 insertions(+) create mode 100644 src/agent/loadedSkills.ts diff --git a/src/agent/loadedSkills.ts b/src/agent/loadedSkills.ts new file mode 100644 index 0000000..56633e0 --- /dev/null +++ b/src/agent/loadedSkills.ts @@ -0,0 +1,52 @@ +import { getClient } from "./client"; +import { setHasLoadedSkills } from "./context"; +import { parseMdxFrontmatter } from "./memory"; +import { MEMORY_PROMPTS } from "./promptAssets"; + +const DEFAULT_LOADED_SKILLS_VALUE = (() => { + const content = MEMORY_PROMPTS["loaded_skills.mdx"]; + if (!content) { + return "No skills currently loaded."; + } + return parseMdxFrontmatter(content).body; +})(); + +type Client = Awaited>; + +export async function clearLoadedSkillsForConversation( + conversationId: string, + clientOverride?: Client, +): Promise { + if (!conversationId || conversationId === "default") { + return; + } + + try { + const client = clientOverride ?? (await getClient()); + const conversation = await client.conversations.retrieve(conversationId); + const isolatedBlockIds = conversation.isolated_block_ids || []; + + for (const blockId of isolatedBlockIds) { + try { + const block = await client.blocks.retrieve(blockId); + if (block.label !== "loaded_skills") { + continue; + } + + const value = typeof block.value === "string" ? block.value.trim() : ""; + if (value !== DEFAULT_LOADED_SKILLS_VALUE) { + await client.blocks.update(blockId, { + value: DEFAULT_LOADED_SKILLS_VALUE, + }); + } + + setHasLoadedSkills(false); + return; + } catch { + // Ignore block errors; continue searching. + } + } + } catch { + // Best-effort cleanup; ignore errors. + } +} diff --git a/src/cli/App.tsx b/src/cli/App.tsx index 0ced0f8..f244b10 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -40,6 +40,7 @@ import { getClient } from "../agent/client"; import { getCurrentAgentId, setCurrentAgentId } from "../agent/context"; import { type AgentProvenance, createAgent } from "../agent/create"; import { getLettaCodeHeaders } from "../agent/http-headers"; +import { clearLoadedSkillsForConversation } from "../agent/loadedSkills"; import { ISOLATED_BLOCK_LABELS } from "../agent/memory"; import { checkMemoryFilesystemStatus, @@ -6061,6 +6062,7 @@ export default function App({ // Update conversationId state setConversationId(conversation.id); + clearLoadedSkillsForConversation(conversation.id, client); // Save the new session to settings settingsManager.setLocalLastSession( @@ -11068,6 +11070,7 @@ Plan file path: ${planFilePath}`; isolated_block_labels: [...ISOLATED_BLOCK_LABELS], }); setConversationId(conversation.id); + clearLoadedSkillsForConversation(conversation.id, client); settingsManager.setLocalLastSession( { agentId, conversationId: conversation.id }, process.cwd(), diff --git a/src/index.ts b/src/index.ts index 9a3eca8..e0f16cd 100755 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ import { } from "./agent/context"; import type { AgentProvenance } from "./agent/create"; import { getLettaCodeHeaders } from "./agent/http-headers"; +import { clearLoadedSkillsForConversation } from "./agent/loadedSkills"; import { ensureSkillsBlocks, ISOLATED_BLOCK_LABELS } from "./agent/memory"; import { LETTA_CLOUD_API_URL } from "./auth/oauth"; import { ConversationSelector } from "./cli/components/ConversationSelector"; @@ -1855,6 +1856,7 @@ async function main(): Promise { isolated_block_labels: [...ISOLATED_BLOCK_LABELS], }); conversationIdToUse = conversation.id; + clearLoadedSkillsForConversation(conversation.id, client); } else { // Default (including --new-agent): use the agent's "default" conversation conversationIdToUse = "default";