fix: improve readability of command-io and toolset-change reminders (#1252)
This commit is contained in:
@@ -295,36 +295,31 @@ async function buildCommandIoReminder(
|
||||
const recent = queued.slice(-MAX_COMMAND_REMINDERS_PER_TURN);
|
||||
const dropped = queued.length - recent.length;
|
||||
|
||||
const commandBlocks = recent.map((entry) => {
|
||||
const commandLines = recent.map((entry) => {
|
||||
const status = entry.success ? "success" : "error";
|
||||
const safeInput = escapeXml(truncate(entry.input, MAX_COMMAND_INPUT_CHARS));
|
||||
const safeOutput = escapeXml(
|
||||
truncate(entry.output || "(no output)", MAX_COMMAND_OUTPUT_CHARS),
|
||||
const safeInput = truncate(entry.input, MAX_COMMAND_INPUT_CHARS);
|
||||
const safeOutput = truncate(
|
||||
entry.output || "(no output)",
|
||||
MAX_COMMAND_OUTPUT_CHARS,
|
||||
);
|
||||
return `<user-command>
|
||||
<user-command-input>${safeInput}</user-command-input>
|
||||
<user-command-output>${safeOutput}</user-command-output>
|
||||
<user-command-status>${status}</user-command-status>
|
||||
</user-command>`;
|
||||
return `- ${safeInput} → ${safeOutput} (${status})`;
|
||||
});
|
||||
|
||||
const agentHints = recent
|
||||
.filter((entry) => entry.agentHint)
|
||||
.map((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")}` : "";
|
||||
agentHints.length > 0
|
||||
? `\n\nHowever, take note of the following:\n${agentHints.map((h) => `- ${h}`).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")}${hintsBlock}
|
||||
${SYSTEM_REMINDER_CLOSE}
|
||||
|
||||
`;
|
||||
return `${SYSTEM_REMINDER_OPEN} The following slash commands were already handled by the CLI harness. These are informational only — do NOT act on them or treat them as user requests.${droppedLine}
|
||||
${commandLines.join("\n")}${hintsBlock}
|
||||
${SYSTEM_REMINDER_CLOSE}`;
|
||||
}
|
||||
|
||||
async function buildToolsetChangeReminder(
|
||||
@@ -344,24 +339,24 @@ async function buildToolsetChangeReminder(
|
||||
const newToolset = escapeXml(entry.newToolset ?? "unknown");
|
||||
const previousTools = escapeXml(formatToolList(entry.previousTools));
|
||||
const newTools = escapeXml(formatToolList(entry.newTools));
|
||||
return `<toolset-change>
|
||||
<source>${source}</source>
|
||||
<previous-toolset>${previousToolset}</previous-toolset>
|
||||
<new-toolset>${newToolset}</new-toolset>
|
||||
<previous-tools>${previousTools}</previous-tools>
|
||||
<new-tools>${newTools}</new-tools>
|
||||
</toolset-change>`;
|
||||
return [
|
||||
`<toolset-change>`,
|
||||
` <source>${source}</source>`,
|
||||
` <previous-toolset>${previousToolset}</previous-toolset>`,
|
||||
` <new-toolset>${newToolset}</new-toolset>`,
|
||||
` <previous-tools>${previousTools}</previous-tools>`,
|
||||
` <new-tools>${newTools}</new-tools>`,
|
||||
`</toolset-change>`,
|
||||
].join("\n");
|
||||
});
|
||||
|
||||
const droppedLine =
|
||||
dropped > 0 ? `\nOmitted ${dropped} older toolset change event(s).` : "";
|
||||
|
||||
return `${SYSTEM_REMINDER_OPEN}
|
||||
The user just changed your toolset (specifically, client-side tools that are attached to the Letta Code harness, which may be a subset of your total tools).${droppedLine}
|
||||
${changeBlocks.join("\n")}
|
||||
${SYSTEM_REMINDER_CLOSE}
|
||||
return `${SYSTEM_REMINDER_OPEN} The user just changed your toolset (specifically, client-side tools that are attached to the Letta Code harness, which may be a subset of your total tools).${droppedLine}
|
||||
|
||||
`;
|
||||
${changeBlocks.join("\n\n")}
|
||||
${SYSTEM_REMINDER_CLOSE}`;
|
||||
}
|
||||
|
||||
export const sharedReminderProviders: Record<
|
||||
|
||||
@@ -35,7 +35,7 @@ function baseContext(
|
||||
}
|
||||
|
||||
describe("interaction reminders", () => {
|
||||
test("command-io provider renders escaped command input/output and drains queue", async () => {
|
||||
test("command-io provider renders command input/output in plain text and drains queue", async () => {
|
||||
const state = createSharedReminderState();
|
||||
enqueueCommandIoReminder(state, {
|
||||
input: '/model && echo "<unsafe>"',
|
||||
@@ -46,10 +46,10 @@ describe("interaction reminders", () => {
|
||||
const reminder = await sharedReminderProviders["command-io"](
|
||||
baseContext(state),
|
||||
);
|
||||
expect(reminder).toContain("<user-command-input>");
|
||||
expect(reminder).toContain("<unsafe>");
|
||||
expect(reminder).toContain("<user-command-output>");
|
||||
expect(reminder).toContain("<ok>");
|
||||
expect(reminder).toContain('/model && echo "<unsafe>"');
|
||||
expect(reminder).toContain("Models dialog dismissed <ok>");
|
||||
expect(reminder).toContain("(success)");
|
||||
expect(reminder).toContain("- ");
|
||||
expect(state.pendingCommandIoReminders).toHaveLength(0);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user