From fea0c5ff0738fc249f4531fa52f26347e6e69583 Mon Sep 17 00:00:00 2001 From: Devansh Jain <31609257+devanshrj@users.noreply.github.com> Date: Mon, 16 Mar 2026 16:23:05 -0700 Subject: [PATCH] refactor(cli): move /system upgrade hint into thinking tips (#1411) Co-authored-by: Letta Code --- src/cli/App.tsx | 28 ++++---------------------- src/cli/components/InputRich.tsx | 16 +++++++-------- src/cli/helpers/thinkingMessages.ts | 27 ++++++++++++++++++------- src/tests/cli/thinkingMessages.test.ts | 9 +++++++++ 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/cli/App.tsx b/src/cli/App.tsx index 47b964c..76443d6 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -981,8 +981,9 @@ 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(() => { + // Check if the current agent would benefit from switching to the default prompt. + // Used to conditionally include the /system tip in streaming tip rotation. + const includeSystemPromptUpgradeTip = useMemo(() => { if (!agentState?.id || !agentState.system) return false; const memMode = settingsManager.isMemfsEnabled(agentState.id) ? "memfs" @@ -3079,8 +3080,6 @@ 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) @@ -3092,9 +3091,6 @@ 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 ? [ @@ -3103,9 +3099,6 @@ 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", @@ -3113,9 +3106,6 @@ 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 @@ -3151,7 +3141,6 @@ export default function App({ agentProvenance, resumedExistingConversation, releaseNotes, - shouldShowDefaultPromptTip, ]); // Fetch llmConfig when agent is ready @@ -13075,9 +13064,6 @@ 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 ? [ @@ -13086,9 +13072,6 @@ 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", @@ -13096,9 +13079,6 @@ 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 @@ -13133,7 +13113,6 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa agentState, refreshDerived, releaseNotes, - shouldShowDefaultPromptTip, ]); const liveTrajectorySnapshot = @@ -13511,6 +13490,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa tokenCount={trajectoryTokenDisplay} elapsedBaseMs={liveTrajectoryElapsedBaseMs} thinkingMessage={thinkingMessage} + includeSystemPromptUpgradeTip={includeSystemPromptUpgradeTip} onSubmit={onSubmit} onBashSubmit={handleBashSubmit} bashRunning={bashRunning} diff --git a/src/cli/components/InputRich.tsx b/src/cli/components/InputRich.tsx index f5a802e..576e12c 100644 --- a/src/cli/components/InputRich.tsx +++ b/src/cli/components/InputRich.tsx @@ -477,6 +477,7 @@ const StreamingStatus = memo(function StreamingStatus({ tokenCount, elapsedBaseMs, thinkingMessage, + includeSystemPromptUpgradeTip, agentName, interruptRequested, networkPhase, @@ -488,6 +489,7 @@ const StreamingStatus = memo(function StreamingStatus({ tokenCount: number; elapsedBaseMs: number; thinkingMessage: string; + includeSystemPromptUpgradeTip: boolean; agentName: string | null | undefined; interruptRequested: boolean; networkPhase: "upload" | "download" | "error" | null; @@ -529,7 +531,6 @@ const StreamingStatus = memo(function StreamingStatus({ const [shimmerOffset, setShimmerOffset] = useState(-3); const [elapsedMs, setElapsedMs] = useState(0); const [tipMessage, setTipMessage] = useState(""); - const tipInitializedRef = useRef(false); const streamStartRef = useRef(null); useEffect(() => { @@ -583,15 +584,9 @@ const StreamingStatus = memo(function StreamingStatus({ useEffect(() => { if (streaming && visible) { - if (!tipInitializedRef.current) { - setTipMessage(getRandomThinkingTip()); - tipInitializedRef.current = true; - } - return; + setTipMessage(getRandomThinkingTip({ includeSystemPromptUpgradeTip })); } - - tipInitializedRef.current = false; - }, [streaming, visible]); + }, [streaming, visible, includeSystemPromptUpgradeTip]); const estimatedTokens = charsToTokens(tokenCount); const totalElapsedMs = elapsedBaseMs + elapsedMs; @@ -724,6 +719,7 @@ export function Input({ tokenCount, elapsedBaseMs = 0, thinkingMessage, + includeSystemPromptUpgradeTip = true, onSubmit, onBashSubmit, bashRunning = false, @@ -766,6 +762,7 @@ export function Input({ tokenCount: number; elapsedBaseMs?: number; thinkingMessage: string; + includeSystemPromptUpgradeTip?: boolean; onSubmit: (message?: string) => Promise<{ submitted: boolean }>; onBashSubmit?: (command: string) => Promise; bashRunning?: boolean; @@ -1713,6 +1710,7 @@ export function Input({ tokenCount={tokenCount} elapsedBaseMs={elapsedBaseMs} thinkingMessage={thinkingMessage} + includeSystemPromptUpgradeTip={includeSystemPromptUpgradeTip} agentName={agentName} interruptRequested={interruptRequested} networkPhase={networkPhase} diff --git a/src/cli/helpers/thinkingMessages.ts b/src/cli/helpers/thinkingMessages.ts index af8072e..5114439 100644 --- a/src/cli/helpers/thinkingMessages.ts +++ b/src/cli/helpers/thinkingMessages.ts @@ -43,6 +43,9 @@ const THINKING_VERBS = [ "internalizing", ] as const; +export const SYSTEM_PROMPT_UPGRADE_TIP = + "Use /system to upgrade to the latest default prompt."; + export const THINKING_TIPS = [ "Use /remember [instructions] to remember something from the conversation.", "Use /palace to inspect your agent's memory palace.", @@ -51,6 +54,11 @@ export const THINKING_TIPS = [ "Use /init to initialize (or re-init) your agent's memory.", ] as const; +const THINKING_TIPS_WITH_SYSTEM_UPGRADE = [ + ...THINKING_TIPS, + SYSTEM_PROMPT_UPGRADE_TIP, +]; + type ThinkingVerb = (typeof THINKING_VERBS)[number]; const PAST_TENSE_VERBS: Record = { @@ -103,11 +111,6 @@ function getRandomVerb(): string { return THINKING_VERBS[index] ?? "thinking"; } -function getRandomTip(): string { - const index = Math.floor(Math.random() * THINKING_TIPS.length); - return THINKING_TIPS[index] ?? ""; -} - // Get a random thinking verb phrase (e.g., "is thinking", "is processing") export function getRandomThinkingVerb(): string { return `is ${getRandomVerb()}`; @@ -131,6 +134,16 @@ export function getRandomThinkingMessage(agentName?: string | null): string { return verb.charAt(0).toUpperCase() + verb.slice(1); } -export function getRandomThinkingTip(): string { - return getRandomTip(); +export function getRandomThinkingTip(options?: { + includeSystemPromptUpgradeTip?: boolean; +}): string { + const tipPool = + (options?.includeSystemPromptUpgradeTip ?? true) + ? THINKING_TIPS_WITH_SYSTEM_UPGRADE + : THINKING_TIPS; + if (tipPool.length === 0) { + return ""; + } + const index = Math.floor(Math.random() * tipPool.length); + return tipPool[index] ?? ""; } diff --git a/src/tests/cli/thinkingMessages.test.ts b/src/tests/cli/thinkingMessages.test.ts index 853322e..ad73687 100644 --- a/src/tests/cli/thinkingMessages.test.ts +++ b/src/tests/cli/thinkingMessages.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"; import { getRandomThinkingMessage, getRandomThinkingTip, + SYSTEM_PROMPT_UPGRADE_TIP, THINKING_TIPS, } from "../../cli/helpers/thinkingMessages"; @@ -54,4 +55,12 @@ describe("Thinking messages", () => { expect(tip.length).toBeGreaterThan(0); expect((THINKING_TIPS as readonly string[]).includes(tip)).toBe(true); }); + + test("can exclude /system upgrade tip from the selection pool", () => { + const tips = Array.from({ length: 50 }, () => + getRandomThinkingTip({ includeSystemPromptUpgradeTip: false }), + ); + + expect(tips.every((tip) => tip !== SYSTEM_PROMPT_UPGRADE_TIP)).toBe(true); + }); });