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);
|
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 () => {
|
it("collapses rpc deltas instead of emitting raw JSON spam", async () => {
|
||||||
mockPiRpc({
|
mockPiRpc({
|
||||||
stdout: [
|
stdout: [
|
||||||
|
|
|
||||||
|
|
@ -677,18 +677,19 @@ export async function runCommandReply(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const rawStdout = stdout.trim();
|
const rawStdout = stdout.trim();
|
||||||
const rpcAssistantText = extractRpcAssistantText(stdout);
|
const rpcAssistantText = extractRpcAssistantText(stdout);
|
||||||
let mediaFromCommand: string[] | undefined;
|
let mediaFromCommand: string[] | undefined;
|
||||||
const trimmed = stripRpcNoise(rawStdout);
|
const trimmed = stripRpcNoise(rawStdout);
|
||||||
if (stderr?.trim()) {
|
if (stderr?.trim()) {
|
||||||
logVerbose(`Command auto-reply stderr: ${stderr.trim()}`);
|
logVerbose(`Command auto-reply stderr: ${stderr.trim()}`);
|
||||||
}
|
}
|
||||||
|
const promptTooLong = rawStdout.includes("prompt is too long");
|
||||||
|
|
||||||
const logFailure = () => {
|
const logFailure = () => {
|
||||||
const truncate = (s?: string) =>
|
const truncate = (s?: string) =>
|
||||||
s ? (s.length > 4000 ? `${s.slice(0, 4000)}…` : s) : undefined;
|
s ? (s.length > 4000 ? `${s.slice(0, 4000)}…` : s) : undefined;
|
||||||
logger.warn(
|
logger.warn(
|
||||||
{
|
{
|
||||||
code,
|
code,
|
||||||
signal,
|
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;
|
const parsed = trimmed ? agent.parseOutput(trimmed) : undefined;
|
||||||
|
|
||||||
// Collect assistant texts and tool results from parseOutput (tau RPC can emit many).
|
// 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 payloadArray = runResult.payloads ?? [];
|
||||||
const meta = runResult.meta;
|
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;
|
let finalPayloads = payloadArray;
|
||||||
if (!finalPayloads || finalPayloads.length === 0) {
|
if (!finalPayloads || finalPayloads.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue