diff --git a/src/agent/promptAssets.ts b/src/agent/promptAssets.ts index a531653..41602c5 100644 --- a/src/agent/promptAssets.ts +++ b/src/agent/promptAssets.ts @@ -279,6 +279,18 @@ export async function validateSystemPromptPreset( ); } +/** + * Returns true if the agent is not on the current default preset + * and would benefit from switching to `/system default`. + */ +export function shouldRecommendDefaultPrompt( + currentPrompt: string, + memoryMode: MemoryPromptMode, +): boolean { + const defaultPrompt = buildSystemPrompt("default", memoryMode); + return currentPrompt !== defaultPrompt; +} + /** * Resolve a prompt ID and build the full system prompt with memory addon. * Known presets are rebuilt deterministically; unknown IDs (subagent names) diff --git a/src/cli/App.tsx b/src/cli/App.tsx index 4cdd308..f948a09 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -59,7 +59,10 @@ import { getModelShortName, type ModelReasoningEffort, } from "../agent/model"; -import { INTERRUPT_RECOVERY_ALERT } from "../agent/promptAssets"; +import { + INTERRUPT_RECOVERY_ALERT, + shouldRecommendDefaultPrompt, +} from "../agent/promptAssets"; import { recordSessionEnd } from "../agent/sessionHistory"; import { SessionStats } from "../agent/stats"; import { @@ -1022,6 +1025,15 @@ export default function App({ setAgentState((prev) => (prev ? { ...prev, name } : prev)); }, []); + // Check if the current agent would benefit from switching to the default prompt + const shouldShowDefaultPromptTip = useCallback(() => { + if (!agentState?.id || !agentState.system) return false; + const memMode = settingsManager.isMemfsEnabled(agentState.id) + ? "memfs" + : ("standard" as const); + return shouldRecommendDefaultPrompt(agentState.system, memMode); + }, [agentState]); + const projectDirectory = process.cwd(); // Track current conversation (always created fresh on startup) @@ -3093,6 +3105,8 @@ export default function App({ ? `Resuming conversation with **${agentName}**` : `Starting new conversation with **${agentName}**`; + const showPromptTip = shouldShowDefaultPromptTip(); + // Command hints - vary based on agent state: // - Resuming: show /new (they may want a fresh conversation) // - New session + unpinned: show /pin (they should save their agent) @@ -3104,6 +3118,9 @@ export default function App({ "→ **/new** start a new conversation", "→ **/init** initialize your agent's memory", "→ **/remember** teach your agent", + ...(showPromptTip + ? ["→ **/system** upgrade to the latest default prompt"] + : []), ] : isPinned ? [ @@ -3112,6 +3129,9 @@ export default function App({ "→ **/memory** view your agent's memory", "→ **/init** initialize your agent's memory", "→ **/remember** teach your agent", + ...(showPromptTip + ? ["→ **/system** upgrade to the latest default prompt"] + : []), ] : [ "→ **/agents** list all agents", @@ -3119,6 +3139,9 @@ export default function App({ "→ **/pin** save + name your agent", "→ **/init** initialize your agent's memory", "→ **/remember** teach your agent", + ...(showPromptTip + ? ["→ **/system** upgrade to the latest default prompt"] + : []), ]; // Build status lines with optional release notes above header @@ -3154,6 +3177,7 @@ export default function App({ agentProvenance, resumedExistingConversation, releaseNotes, + shouldShowDefaultPromptTip, ]); // Fetch llmConfig when agent is ready @@ -12840,6 +12864,9 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa ? `Starting new conversation with **${agentName}**` : "Creating a new agent"; + // Only show prompt tip for existing agents, not brand new ones + const showPromptTip = continueSession && shouldShowDefaultPromptTip(); + // Command hints - for pinned agents show /memory, for unpinned show /pin const commandHints = isPinned ? [ @@ -12848,6 +12875,9 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa "→ **/memory** view your agent's memory", "→ **/init** initialize your agent's memory", "→ **/remember** teach your agent", + ...(showPromptTip + ? ["→ **/system** upgrade to the latest default prompt"] + : []), ] : [ "→ **/agents** list all agents", @@ -12855,6 +12885,9 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa "→ **/pin** save + name your agent", "→ **/init** initialize your agent's memory", "→ **/remember** teach your agent", + ...(showPromptTip + ? ["→ **/system** upgrade to the latest default prompt"] + : []), ]; // Build status lines with optional release notes above header @@ -12889,6 +12922,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa agentState, refreshDerived, releaseNotes, + shouldShowDefaultPromptTip, ]); const liveTrajectorySnapshot = diff --git a/src/tests/agent/memoryPrompt.test.ts b/src/tests/agent/memoryPrompt.test.ts index 606106d..e072ed1 100644 --- a/src/tests/agent/memoryPrompt.test.ts +++ b/src/tests/agent/memoryPrompt.test.ts @@ -5,6 +5,7 @@ import { isKnownPreset, SYSTEM_PROMPT_MEMFS_ADDON, SYSTEM_PROMPT_MEMORY_ADDON, + shouldRecommendDefaultPrompt, swapMemoryAddon, } from "../../agent/promptAssets"; @@ -151,3 +152,32 @@ describe("swapMemoryAddon", () => { expect(countOccurrences(twice, "# See what changed")).toBe(1); }); }); + +describe("shouldRecommendDefaultPrompt", () => { + test("returns false when prompt matches current default (standard)", () => { + const current = buildSystemPrompt("default", "standard"); + expect(shouldRecommendDefaultPrompt(current, "standard")).toBe(false); + }); + + test("returns false when prompt matches current default (memfs)", () => { + const current = buildSystemPrompt("default", "memfs"); + expect(shouldRecommendDefaultPrompt(current, "memfs")).toBe(false); + }); + + test("returns true for a different preset", () => { + const current = buildSystemPrompt("letta-claude", "standard"); + expect(shouldRecommendDefaultPrompt(current, "standard")).toBe(true); + }); + + test("returns true for a fully custom prompt", () => { + expect( + shouldRecommendDefaultPrompt("You are a custom agent.", "standard"), + ).toBe(true); + }); + + test("returns true for a modified default prompt", () => { + const current = buildSystemPrompt("default", "standard"); + const modified = `${current}\n\nExtra instructions added by user.`; + expect(shouldRecommendDefaultPrompt(modified, "standard")).toBe(true); + }); +});