feat: Show command hint for agents with non-default system prompts (#1314)
This commit is contained in:
@@ -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.
|
* Resolve a prompt ID and build the full system prompt with memory addon.
|
||||||
* Known presets are rebuilt deterministically; unknown IDs (subagent names)
|
* Known presets are rebuilt deterministically; unknown IDs (subagent names)
|
||||||
|
|||||||
@@ -59,7 +59,10 @@ import {
|
|||||||
getModelShortName,
|
getModelShortName,
|
||||||
type ModelReasoningEffort,
|
type ModelReasoningEffort,
|
||||||
} from "../agent/model";
|
} from "../agent/model";
|
||||||
import { INTERRUPT_RECOVERY_ALERT } from "../agent/promptAssets";
|
import {
|
||||||
|
INTERRUPT_RECOVERY_ALERT,
|
||||||
|
shouldRecommendDefaultPrompt,
|
||||||
|
} from "../agent/promptAssets";
|
||||||
import { recordSessionEnd } from "../agent/sessionHistory";
|
import { recordSessionEnd } from "../agent/sessionHistory";
|
||||||
import { SessionStats } from "../agent/stats";
|
import { SessionStats } from "../agent/stats";
|
||||||
import {
|
import {
|
||||||
@@ -1022,6 +1025,15 @@ export default function App({
|
|||||||
setAgentState((prev) => (prev ? { ...prev, name } : prev));
|
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();
|
const projectDirectory = process.cwd();
|
||||||
|
|
||||||
// Track current conversation (always created fresh on startup)
|
// Track current conversation (always created fresh on startup)
|
||||||
@@ -3093,6 +3105,8 @@ export default function App({
|
|||||||
? `Resuming conversation with **${agentName}**`
|
? `Resuming conversation with **${agentName}**`
|
||||||
: `Starting new conversation with **${agentName}**`;
|
: `Starting new conversation with **${agentName}**`;
|
||||||
|
|
||||||
|
const showPromptTip = shouldShowDefaultPromptTip();
|
||||||
|
|
||||||
// Command hints - vary based on agent state:
|
// Command hints - vary based on agent state:
|
||||||
// - Resuming: show /new (they may want a fresh conversation)
|
// - Resuming: show /new (they may want a fresh conversation)
|
||||||
// - New session + unpinned: show /pin (they should save their agent)
|
// - New session + unpinned: show /pin (they should save their agent)
|
||||||
@@ -3104,6 +3118,9 @@ export default function App({
|
|||||||
"→ **/new** start a new conversation",
|
"→ **/new** start a new conversation",
|
||||||
"→ **/init** initialize your agent's memory",
|
"→ **/init** initialize your agent's memory",
|
||||||
"→ **/remember** teach your agent",
|
"→ **/remember** teach your agent",
|
||||||
|
...(showPromptTip
|
||||||
|
? ["→ **/system** upgrade to the latest default prompt"]
|
||||||
|
: []),
|
||||||
]
|
]
|
||||||
: isPinned
|
: isPinned
|
||||||
? [
|
? [
|
||||||
@@ -3112,6 +3129,9 @@ export default function App({
|
|||||||
"→ **/memory** view your agent's memory",
|
"→ **/memory** view your agent's memory",
|
||||||
"→ **/init** initialize your agent's memory",
|
"→ **/init** initialize your agent's memory",
|
||||||
"→ **/remember** teach your agent",
|
"→ **/remember** teach your agent",
|
||||||
|
...(showPromptTip
|
||||||
|
? ["→ **/system** upgrade to the latest default prompt"]
|
||||||
|
: []),
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
"→ **/agents** list all agents",
|
"→ **/agents** list all agents",
|
||||||
@@ -3119,6 +3139,9 @@ export default function App({
|
|||||||
"→ **/pin** save + name your agent",
|
"→ **/pin** save + name your agent",
|
||||||
"→ **/init** initialize your agent's memory",
|
"→ **/init** initialize your agent's memory",
|
||||||
"→ **/remember** teach your agent",
|
"→ **/remember** teach your agent",
|
||||||
|
...(showPromptTip
|
||||||
|
? ["→ **/system** upgrade to the latest default prompt"]
|
||||||
|
: []),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Build status lines with optional release notes above header
|
// Build status lines with optional release notes above header
|
||||||
@@ -3154,6 +3177,7 @@ export default function App({
|
|||||||
agentProvenance,
|
agentProvenance,
|
||||||
resumedExistingConversation,
|
resumedExistingConversation,
|
||||||
releaseNotes,
|
releaseNotes,
|
||||||
|
shouldShowDefaultPromptTip,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Fetch llmConfig when agent is ready
|
// 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}**`
|
? `Starting new conversation with **${agentName}**`
|
||||||
: "Creating a new agent";
|
: "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
|
// Command hints - for pinned agents show /memory, for unpinned show /pin
|
||||||
const commandHints = isPinned
|
const commandHints = isPinned
|
||||||
? [
|
? [
|
||||||
@@ -12848,6 +12875,9 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|||||||
"→ **/memory** view your agent's memory",
|
"→ **/memory** view your agent's memory",
|
||||||
"→ **/init** initialize your agent's memory",
|
"→ **/init** initialize your agent's memory",
|
||||||
"→ **/remember** teach your agent",
|
"→ **/remember** teach your agent",
|
||||||
|
...(showPromptTip
|
||||||
|
? ["→ **/system** upgrade to the latest default prompt"]
|
||||||
|
: []),
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
"→ **/agents** list all agents",
|
"→ **/agents** list all agents",
|
||||||
@@ -12855,6 +12885,9 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|||||||
"→ **/pin** save + name your agent",
|
"→ **/pin** save + name your agent",
|
||||||
"→ **/init** initialize your agent's memory",
|
"→ **/init** initialize your agent's memory",
|
||||||
"→ **/remember** teach your agent",
|
"→ **/remember** teach your agent",
|
||||||
|
...(showPromptTip
|
||||||
|
? ["→ **/system** upgrade to the latest default prompt"]
|
||||||
|
: []),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Build status lines with optional release notes above header
|
// 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,
|
agentState,
|
||||||
refreshDerived,
|
refreshDerived,
|
||||||
releaseNotes,
|
releaseNotes,
|
||||||
|
shouldShowDefaultPromptTip,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const liveTrajectorySnapshot =
|
const liveTrajectorySnapshot =
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
isKnownPreset,
|
isKnownPreset,
|
||||||
SYSTEM_PROMPT_MEMFS_ADDON,
|
SYSTEM_PROMPT_MEMFS_ADDON,
|
||||||
SYSTEM_PROMPT_MEMORY_ADDON,
|
SYSTEM_PROMPT_MEMORY_ADDON,
|
||||||
|
shouldRecommendDefaultPrompt,
|
||||||
swapMemoryAddon,
|
swapMemoryAddon,
|
||||||
} from "../../agent/promptAssets";
|
} from "../../agent/promptAssets";
|
||||||
|
|
||||||
@@ -151,3 +152,32 @@ describe("swapMemoryAddon", () => {
|
|||||||
expect(countOccurrences(twice, "# See what changed")).toBe(1);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user