fix: pin existing default agents and rename --new to --new-agent (#556)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2026-01-15 18:08:31 -08:00
committed by GitHub
parent 3753dfe18d
commit 72f172d9d9
9 changed files with 45 additions and 11 deletions

View File

@@ -105,6 +105,8 @@ export async function ensureDefaultAgents(
const existingMemo = await findDefaultAgent(client, MEMO_TAG);
if (existingMemo) {
memoAgent = existingMemo;
// Ensure it's pinned (might not be if settings were cleared or new machine)
settingsManager.pinGlobal(existingMemo.id);
} else {
const { agent } = await createAgent(DEFAULT_AGENT_CONFIGS.memo);
await addTagToAgent(client, agent.id, MEMO_TAG);
@@ -114,7 +116,10 @@ export async function ensureDefaultAgents(
// Check/create Incognito
const existingIncognito = await findDefaultAgent(client, INCOGNITO_TAG);
if (!existingIncognito) {
if (existingIncognito) {
// Ensure it's pinned (might not be if settings were cleared or new machine)
settingsManager.pinGlobal(existingIncognito.id);
} else {
const { agent } = await createAgent(DEFAULT_AGENT_CONFIGS.incognito);
await addTagToAgent(client, agent.id, INCOGNITO_TAG);
settingsManager.pinGlobal(agent.id);

View File

@@ -7414,6 +7414,7 @@ Plan file path: ${planFilePath}`;
{activeOverlay === "conversations" && (
<ConversationSelector
agentId={agentId}
agentName={agentName ?? undefined}
currentConversationId={conversationId}
onSelect={async (convId) => {
closeOverlay();

View File

@@ -13,6 +13,7 @@ const SOLID_LINE = "─";
interface ConversationSelectorProps {
agentId: string;
agentName?: string;
currentConversationId: string;
onSelect: (conversationId: string) => void;
onNewConversation: () => void;
@@ -186,6 +187,7 @@ function getMessageStats(messages: Message[]): {
export function ConversationSelector({
agentId,
agentName,
currentConversationId,
onSelect,
onNewConversation,
@@ -511,7 +513,9 @@ export function ConversationSelector({
{/* Empty state */}
{!loading && !error && conversations.length === 0 && (
<Box flexDirection="column">
<Text dimColor>No conversations found</Text>
<Text dimColor>
No conversations for {agentName || agentId.slice(0, 12)}
</Text>
<Text dimColor>Press N to start a new conversation</Text>
</Box>
)}

View File

@@ -68,7 +68,8 @@ export async function handleHeadlessCommand(
continue: { type: "boolean", short: "c" },
resume: { type: "boolean", short: "r" },
conversation: { type: "string" },
new: { type: "boolean" },
"new-agent": { type: "boolean" },
new: { type: "boolean" }, // Deprecated - kept for helpful error message
agent: { type: "string", short: "a" },
model: { type: "string", short: "m" },
system: { type: "string", short: "s" },
@@ -180,12 +181,21 @@ export async function handleHeadlessCommand(
process.exit(1);
}
// Check for deprecated --new flag
if (values.new) {
console.error(
"Error: --new has been renamed to --new-agent\n" +
'Usage: letta -p "..." --new-agent',
);
process.exit(1);
}
// Resolve agent (same logic as interactive mode)
let agent: AgentState | null = null;
const specifiedAgentId = values.agent as string | undefined;
const specifiedConversationId = values.conversation as string | undefined;
const shouldContinue = values.continue as boolean | undefined;
const forceNew = values.new as boolean | undefined;
const forceNew = values["new-agent"] as boolean | undefined;
const systemPromptPreset = values.system as string | undefined;
const systemCustom = values["system-custom"] as string | undefined;
const systemAppend = values["system-append"] as string | undefined;

View File

@@ -344,7 +344,8 @@ async function main(): Promise<void> {
continue: { type: "boolean" }, // Deprecated - kept for error message
resume: { type: "boolean", short: "r" }, // Resume last session (or specific conversation with --conversation)
conversation: { type: "string", short: "C" }, // Specific conversation ID to resume (--conv alias supported)
new: { type: "boolean" },
"new-agent": { type: "boolean" }, // Force create a new agent
new: { type: "boolean" }, // Deprecated - kept for helpful error message
"init-blocks": { type: "string" },
"base-tools": { type: "string" },
agent: { type: "string", short: "a" },
@@ -426,7 +427,17 @@ async function main(): Promise<void> {
const shouldResume = (values.resume as boolean | undefined) ?? false;
const specifiedConversationId =
(values.conversation as string | undefined) ?? null; // Specific conversation to resume
const forceNew = (values.new as boolean | undefined) ?? false;
const forceNew = (values["new-agent"] as boolean | undefined) ?? false;
// Check for deprecated --new flag
if (values.new) {
console.error(
"Error: --new has been renamed to --new-agent\n" +
"Usage: letta --new-agent",
);
process.exit(1);
}
const initBlocksRaw = values["init-blocks"] as string | undefined;
const baseToolsRaw = values["base-tools"] as string | undefined;
let specifiedAgentId = (values.agent as string | undefined) ?? null;
@@ -838,6 +849,7 @@ async function main(): Promise<void> {
>(null);
// Track agent and conversation for conversation selector (--resume flag)
const [resumeAgentId, setResumeAgentId] = useState<string | null>(null);
const [resumeAgentName, setResumeAgentName] = useState<string | null>(null);
const [selectedConversationId, setSelectedConversationId] = useState<
string | null
>(null);
@@ -969,8 +981,9 @@ async function main(): Promise<void> {
if (lastAgentId) {
// Verify agent exists
try {
await client.agents.retrieve(lastAgentId);
const agent = await client.agents.retrieve(lastAgentId);
setResumeAgentId(lastAgentId);
setResumeAgentName(agent.name ?? null);
setLoadingState("selecting_conversation");
return;
} catch {
@@ -1493,6 +1506,7 @@ async function main(): Promise<void> {
if (loadingState === "selecting_conversation" && resumeAgentId) {
return React.createElement(ConversationSelector, {
agentId: resumeAgentId,
agentName: resumeAgentName ?? undefined,
currentConversationId: "", // No current conversation yet
onSelect: (conversationId: string) => {
setSelectedConversationId(conversationId);

View File

@@ -38,7 +38,7 @@ async function runBidirectional(
"stream-json",
"--output-format",
"stream-json",
"--new",
"--new-agent",
"-m",
"haiku",
"--yolo",

View File

@@ -70,7 +70,7 @@ async function runCLI(
"-p",
scenarioPrompt(),
"--yolo",
"--new",
"--new-agent",
"--output-format",
output,
"-m",

View File

@@ -22,7 +22,7 @@ async function runHeadlessCommand(
[
"run",
"dev",
"--new",
"--new-agent",
"-p",
prompt,
"--output-format",

View File

@@ -61,7 +61,7 @@ async function runCLI(
"-p",
windowsScenarioPrompt(),
"--yolo",
"--new",
"--new-agent",
"--output-format",
"text",
"-m",