diff --git a/src/cli/App.tsx b/src/cli/App.tsx index 6afe942..15af1e0 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -2712,6 +2712,7 @@ export default function App({ input, output: event.output, success: event.success, + agentHint: event.agentHint, }); }, []); @@ -8160,6 +8161,7 @@ export default function App({ await client.agents.update(agentId, { name: newValue }); updateAgentName(newValue); + cmd.agentHint = `Your name is now "${newValue}" — acknowledge this and save your new name to memory.`; cmd.finish(`Agent renamed to "${newValue}"`, true); } catch (error) { const errorDetails = formatErrorDetails(error, agentId); @@ -13838,6 +13840,9 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa settingsManager.pinGlobal(agentId); } + if (newName && newName !== agentName) { + cmd.agentHint = `Your name is now "${newName}" — acknowledge this and save your new name to memory.`; + } cmd.finish( `Pinned "${newName || agentName || agentId.slice(0, 12)}" ${scopeText}.`, true, diff --git a/src/cli/commands/runner.ts b/src/cli/commands/runner.ts index edaeeac..ec49c38 100644 --- a/src/cli/commands/runner.ts +++ b/src/cli/commands/runner.ts @@ -22,6 +22,8 @@ export type CommandHandle = { preformatted?: boolean, ) => void; fail: (output: string) => void; + /** Extra context included only in the agent-facing reminder, not shown in the UI. */ + agentHint?: string; }; export type CommandFinishedEvent = { @@ -31,6 +33,8 @@ export type CommandFinishedEvent = { success: boolean; dimOutput?: boolean; preformatted?: boolean; + /** Extra context included only in the agent-facing reminder, not shown in the UI. */ + agentHint?: string; }; type CreateId = (prefix: string) => string; @@ -69,6 +73,14 @@ export function createCommandRunner({ onCommandFinished, }: RunnerDeps) { function getHandle(id: string, input: string): CommandHandle { + const handle: CommandHandle = { + id, + input, + update: null!, + finish: null!, + fail: null!, + }; + const update = (updateData: CommandUpdate) => { const previous = buffersRef.current.byId.get(id); const wasFinished = @@ -90,13 +102,16 @@ export function createCommandRunner({ success: next.success !== false, dimOutput: next.dimOutput, preformatted: next.preformatted, + agentHint: handle.agentHint, }); } refreshDerived(); }; - const finish = ( + handle.update = update; + + handle.finish = ( finalOutput: string, success = true, dimOutput?: boolean, @@ -110,14 +125,14 @@ export function createCommandRunner({ preformatted, }); - const fail = (finalOutput: string) => + handle.fail = (finalOutput: string) => update({ output: finalOutput, phase: "finished", success: false, }); - return { id, input, update, finish, fail }; + return handle; } function start(input: string, output: string): CommandHandle { diff --git a/src/reminders/engine.ts b/src/reminders/engine.ts index f0f22f9..e39cadd 100644 --- a/src/reminders/engine.ts +++ b/src/reminders/engine.ts @@ -308,13 +308,20 @@ async function buildCommandIoReminder( `; }); + const agentHints = recent + .filter((entry) => entry.agentHint) + .map((entry) => `- ${entry.agentHint}`); + const droppedLine = dropped > 0 ? `\nOmitted ${dropped} older command event(s).` : ""; + const hintsBlock = + agentHints.length > 0 ? `\n\n${agentHints.join("\n")}` : ""; + return `${SYSTEM_REMINDER_OPEN} The following slash commands were executed in the Letta Code harness since your last user message. Treat these as execution context from the CLI, not new user requests.${droppedLine} -${commandBlocks.join("\n")} +${commandBlocks.join("\n")}${hintsBlock} ${SYSTEM_REMINDER_CLOSE} `; diff --git a/src/reminders/state.ts b/src/reminders/state.ts index e6db35d..b0800e4 100644 --- a/src/reminders/state.ts +++ b/src/reminders/state.ts @@ -7,6 +7,8 @@ export interface CommandIoReminder { input: string; output: string; success: boolean; + /** Extra context appended only in the agent-facing reminder, not shown in the UI. */ + agentHint?: string; } export interface ToolsetChangeReminder {