fix: handle prompt-too-long by resetting session and continuing inline directives
parent
3241d81ce5
commit
36b0796976
|
|
@ -251,6 +251,35 @@ describe("runCommandReply (pi)", () => {
|
|||
expect(meta.killed).toBe(true);
|
||||
});
|
||||
|
||||
it("surfaces prompt-too-long and flags meta for session reset", async () => {
|
||||
mockPiRpc({
|
||||
stdout:
|
||||
'{"type":"agent_end","message":{"role":"assistant","content":[],"errorMessage":"400 {\\"type\\":\\"error\\",\\"error\\":{\\"type\\":\\"invalid_request_error\\",\\"message\\":\\"prompt is too long: 200333 tokens > 200000 maximum\\"}}"}}',
|
||||
stderr: "",
|
||||
code: 0,
|
||||
});
|
||||
|
||||
const { payloads, meta } = await runCommandReply({
|
||||
reply: {
|
||||
mode: "command",
|
||||
command: ["pi", "{{Body}}"],
|
||||
agent: { kind: "pi" },
|
||||
},
|
||||
templatingCtx: noopTemplateCtx,
|
||||
sendSystemOnce: false,
|
||||
isNewSession: false,
|
||||
isFirstTurnInSession: false,
|
||||
systemSent: false,
|
||||
timeoutMs: 1000,
|
||||
timeoutSeconds: 1,
|
||||
commandRunner: vi.fn(),
|
||||
enqueue: enqueueImmediate,
|
||||
});
|
||||
|
||||
expect(payloads?.[0]?.text).toMatch(/history is too long/i);
|
||||
expect(meta.agentMeta?.extra?.promptTooLong).toBe(true);
|
||||
});
|
||||
|
||||
it("collapses rpc deltas instead of emitting raw JSON spam", async () => {
|
||||
mockPiRpc({
|
||||
stdout: [
|
||||
|
|
|
|||
|
|
@ -677,18 +677,19 @@ export async function runCommandReply(
|
|||
}
|
||||
},
|
||||
});
|
||||
const rawStdout = stdout.trim();
|
||||
const rpcAssistantText = extractRpcAssistantText(stdout);
|
||||
let mediaFromCommand: string[] | undefined;
|
||||
const trimmed = stripRpcNoise(rawStdout);
|
||||
if (stderr?.trim()) {
|
||||
logVerbose(`Command auto-reply stderr: ${stderr.trim()}`);
|
||||
}
|
||||
const rawStdout = stdout.trim();
|
||||
const rpcAssistantText = extractRpcAssistantText(stdout);
|
||||
let mediaFromCommand: string[] | undefined;
|
||||
const trimmed = stripRpcNoise(rawStdout);
|
||||
if (stderr?.trim()) {
|
||||
logVerbose(`Command auto-reply stderr: ${stderr.trim()}`);
|
||||
}
|
||||
const promptTooLong = rawStdout.includes("prompt is too long");
|
||||
|
||||
const logFailure = () => {
|
||||
const truncate = (s?: string) =>
|
||||
s ? (s.length > 4000 ? `${s.slice(0, 4000)}…` : s) : undefined;
|
||||
logger.warn(
|
||||
const logFailure = () => {
|
||||
const truncate = (s?: string) =>
|
||||
s ? (s.length > 4000 ? `${s.slice(0, 4000)}…` : s) : undefined;
|
||||
logger.warn(
|
||||
{
|
||||
code,
|
||||
signal,
|
||||
|
|
@ -702,6 +703,21 @@ export async function runCommandReply(
|
|||
);
|
||||
};
|
||||
|
||||
if (promptTooLong) {
|
||||
const text =
|
||||
"⚠️ Session history is too long. Starting a fresh session — please resend your last message.";
|
||||
const meta: CommandReplyMeta = {
|
||||
durationMs: Date.now() - started,
|
||||
queuedMs,
|
||||
queuedAhead,
|
||||
exitCode: code,
|
||||
signal,
|
||||
killed,
|
||||
agentMeta: { extra: { promptTooLong: true } },
|
||||
};
|
||||
return { payloads: [{ text }], meta };
|
||||
}
|
||||
|
||||
const parsed = trimmed ? agent.parseOutput(trimmed) : undefined;
|
||||
|
||||
// Collect assistant texts and tool results from parseOutput (tau RPC can emit many).
|
||||
|
|
|
|||
|
|
@ -701,6 +701,26 @@ export async function getReplyFromConfig(
|
|||
});
|
||||
const payloadArray = runResult.payloads ?? [];
|
||||
const meta = runResult.meta;
|
||||
const promptTooLong =
|
||||
meta.agentMeta &&
|
||||
typeof meta.agentMeta.extra === "object" &&
|
||||
(meta.agentMeta.extra as { promptTooLong?: boolean }).promptTooLong;
|
||||
|
||||
if (promptTooLong && sessionCfg && sessionStore && sessionKey) {
|
||||
// Rotate to a new session to avoid hitting context limits again.
|
||||
const newId = crypto.randomUUID();
|
||||
sessionEntry = {
|
||||
sessionId: newId,
|
||||
updatedAt: Date.now(),
|
||||
systemSent,
|
||||
abortedLastRun: false,
|
||||
};
|
||||
sessionStore[sessionKey] = sessionEntry;
|
||||
await saveSessionStore(storePath, sessionStore);
|
||||
sessionId = newId;
|
||||
isNewSession = true;
|
||||
}
|
||||
|
||||
let finalPayloads = payloadArray;
|
||||
if (!finalPayloads || finalPayloads.length === 0) {
|
||||
return undefined;
|
||||
|
|
|
|||
Loading…
Reference in New Issue