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 recent = queued.slice(-MAX_COMMAND_REMINDERS_PER_TURN);
|
||||||
const dropped = queued.length - recent.length;
|
const dropped = queued.length - recent.length;
|
||||||
|
|
||||||
const commandBlocks = recent.map((entry) => {
|
const commandLines = recent.map((entry) => {
|
||||||
const status = entry.success ? "success" : "error";
|
const status = entry.success ? "success" : "error";
|
||||||
const safeInput = escapeXml(truncate(entry.input, MAX_COMMAND_INPUT_CHARS));
|
const safeInput = truncate(entry.input, MAX_COMMAND_INPUT_CHARS);
|
||||||
const safeOutput = escapeXml(
|
const safeOutput = truncate(
|
||||||
truncate(entry.output || "(no output)", MAX_COMMAND_OUTPUT_CHARS),
|
entry.output || "(no output)",
|
||||||
|
MAX_COMMAND_OUTPUT_CHARS,
|
||||||
);
|
);
|
||||||
return `<user-command>
|
return `- ${safeInput} → ${safeOutput} (${status})`;
|
||||||
<user-command-input>${safeInput}</user-command-input>
|
|
||||||
<user-command-output>${safeOutput}</user-command-output>
|
|
||||||
<user-command-status>${status}</user-command-status>
|
|
||||||
</user-command>`;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const agentHints = recent
|
const agentHints = recent
|
||||||
.filter((entry) => entry.agentHint)
|
.filter((entry) => entry.agentHint)
|
||||||
.map((entry) => `- ${entry.agentHint}`);
|
.map((entry) => entry.agentHint);
|
||||||
|
|
||||||
const droppedLine =
|
const droppedLine =
|
||||||
dropped > 0 ? `\nOmitted ${dropped} older command event(s).` : "";
|
dropped > 0 ? `\nOmitted ${dropped} older command event(s).` : "";
|
||||||
|
|
||||||
const hintsBlock =
|
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}
|
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}
|
||||||
The following slash commands were executed in the Letta Code harness since your last user message.
|
${commandLines.join("\n")}${hintsBlock}
|
||||||
Treat these as execution context from the CLI, not new user requests.${droppedLine}
|
${SYSTEM_REMINDER_CLOSE}`;
|
||||||
${commandBlocks.join("\n")}${hintsBlock}
|
|
||||||
${SYSTEM_REMINDER_CLOSE}
|
|
||||||
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildToolsetChangeReminder(
|
async function buildToolsetChangeReminder(
|
||||||
@@ -344,24 +339,24 @@ async function buildToolsetChangeReminder(
|
|||||||
const newToolset = escapeXml(entry.newToolset ?? "unknown");
|
const newToolset = escapeXml(entry.newToolset ?? "unknown");
|
||||||
const previousTools = escapeXml(formatToolList(entry.previousTools));
|
const previousTools = escapeXml(formatToolList(entry.previousTools));
|
||||||
const newTools = escapeXml(formatToolList(entry.newTools));
|
const newTools = escapeXml(formatToolList(entry.newTools));
|
||||||
return `<toolset-change>
|
return [
|
||||||
<source>${source}</source>
|
`<toolset-change>`,
|
||||||
<previous-toolset>${previousToolset}</previous-toolset>
|
` <source>${source}</source>`,
|
||||||
<new-toolset>${newToolset}</new-toolset>
|
` <previous-toolset>${previousToolset}</previous-toolset>`,
|
||||||
<previous-tools>${previousTools}</previous-tools>
|
` <new-toolset>${newToolset}</new-toolset>`,
|
||||||
<new-tools>${newTools}</new-tools>
|
` <previous-tools>${previousTools}</previous-tools>`,
|
||||||
</toolset-change>`;
|
` <new-tools>${newTools}</new-tools>`,
|
||||||
|
`</toolset-change>`,
|
||||||
|
].join("\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
const droppedLine =
|
const droppedLine =
|
||||||
dropped > 0 ? `\nOmitted ${dropped} older toolset change event(s).` : "";
|
dropped > 0 ? `\nOmitted ${dropped} older toolset change event(s).` : "";
|
||||||
|
|
||||||
return `${SYSTEM_REMINDER_OPEN}
|
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}
|
||||||
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}
|
|
||||||
|
|
||||||
`;
|
${changeBlocks.join("\n\n")}
|
||||||
|
${SYSTEM_REMINDER_CLOSE}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sharedReminderProviders: Record<
|
export const sharedReminderProviders: Record<
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function baseContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("interaction reminders", () => {
|
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();
|
const state = createSharedReminderState();
|
||||||
enqueueCommandIoReminder(state, {
|
enqueueCommandIoReminder(state, {
|
||||||
input: '/model && echo "<unsafe>"',
|
input: '/model && echo "<unsafe>"',
|
||||||
@@ -46,10 +46,10 @@ describe("interaction reminders", () => {
|
|||||||
const reminder = await sharedReminderProviders["command-io"](
|
const reminder = await sharedReminderProviders["command-io"](
|
||||||
baseContext(state),
|
baseContext(state),
|
||||||
);
|
);
|
||||||
expect(reminder).toContain("<user-command-input>");
|
expect(reminder).toContain('/model && echo "<unsafe>"');
|
||||||
expect(reminder).toContain("<unsafe>");
|
expect(reminder).toContain("Models dialog dismissed <ok>");
|
||||||
expect(reminder).toContain("<user-command-output>");
|
expect(reminder).toContain("(success)");
|
||||||
expect(reminder).toContain("<ok>");
|
expect(reminder).toContain("- ");
|
||||||
expect(state.pendingCommandIoReminders).toHaveLength(0);
|
expect(state.pendingCommandIoReminders).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user