@inceptionstack/roundhouse 0.5.25 → 0.5.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/gateway/gateway.ts +20 -0
- package/src/memory/lifecycle.ts +13 -3
package/package.json
CHANGED
package/src/gateway/gateway.ts
CHANGED
|
@@ -439,6 +439,26 @@ export class Gateway {
|
|
|
439
439
|
|
|
440
440
|
stopTyping = startTypingLoop(thread);
|
|
441
441
|
|
|
442
|
+
// Pre-turn recovery: if a prior turn failed to compact (state has
|
|
443
|
+
// pendingCompact === "emergency"), the live session is almost certainly
|
|
444
|
+
// still over the model's context limit, so calling agent.prompt() now
|
|
445
|
+
// will throw with "prompt is too long" before our post-turn pressure
|
|
446
|
+
// handler ever runs — perpetuating the loop. Run the pressure handler
|
|
447
|
+
// BEFORE the agent call to recover. Best-effort: if it fails, fall
|
|
448
|
+
// through to the normal turn (which will then post the error and let
|
|
449
|
+
// the user see something is wrong).
|
|
450
|
+
if (memoryPrepared?.pendingCompact === "emergency") {
|
|
451
|
+
console.log(`[roundhouse] pre-turn recovery: pendingCompact=emergency, compacting before agent.prompt for thread=${agentThreadId}`);
|
|
452
|
+
try {
|
|
453
|
+
await this.handleContextPressure(thread, agentThreadId, agent, memoryRoot, "emergency");
|
|
454
|
+
// Clear the pending flag in our prepared snapshot so the post-turn
|
|
455
|
+
// pressure logic doesn't double-up on a redundant emergency pass.
|
|
456
|
+
memoryPrepared.pendingCompact = undefined;
|
|
457
|
+
} catch (err) {
|
|
458
|
+
console.error(`[roundhouse] pre-turn emergency compact failed:`, (err as Error).message);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
442
462
|
let deferredSoftFlush: { thread: any; agentThreadId: string; agent: AgentAdapter; memoryRoot: string } | undefined;
|
|
443
463
|
try {
|
|
444
464
|
let turnUsedTools = false;
|
package/src/memory/lifecycle.ts
CHANGED
|
@@ -239,7 +239,15 @@ export async function flushMemoryThenCompact(
|
|
|
239
239
|
// NOT require the live session to fit under the limit — so skipping flush
|
|
240
240
|
// lets us recover. Facts-to-MEMORY.md (the whole point of flush) is a
|
|
241
241
|
// best-effort nicety that the next soft/hard flush can catch up on.
|
|
242
|
-
|
|
242
|
+
//
|
|
243
|
+
// We also skip flush when state already has pendingCompact === "emergency":
|
|
244
|
+
// a prior turn detected emergency pressure and could not complete (e.g. the
|
|
245
|
+
// current call was triggered by /compact while stuck). Even at "hard" or
|
|
246
|
+
// "manual" level, attempting the flush in that condition will hit the same
|
|
247
|
+
// 200k rejection. Deferring flush to a later (successful) turn is the safe
|
|
248
|
+
// recovery path.
|
|
249
|
+
const stuckInEmergency = (await loadThreadMemoryState(threadId)).pendingCompact === "emergency";
|
|
250
|
+
const skipFlush = effectiveLevel === "emergency" || stuckInEmergency;
|
|
243
251
|
|
|
244
252
|
try {
|
|
245
253
|
let flushMs = 0;
|
|
@@ -255,10 +263,12 @@ export async function flushMemoryThenCompact(
|
|
|
255
263
|
}
|
|
256
264
|
|
|
257
265
|
// Step 2: compact (use flush model if compactWithModel is available)
|
|
258
|
-
const flushNote = skipFlush
|
|
266
|
+
const flushNote = skipFlush
|
|
267
|
+
? (effectiveLevel === "emergency" ? "flush skipped (emergency)" : "flush skipped (recovery from prior emergency)")
|
|
268
|
+
: `flush took ${flushMs}ms`;
|
|
259
269
|
console.log(`[memory] compacting ${threadId} (${flushNote})`);
|
|
260
270
|
const progressNote = skipFlush
|
|
261
|
-
?
|
|
271
|
+
? `✂️ Compacting context... (${effectiveLevel === "emergency" ? "emergency — " : "recovery — "}skipping flush)`
|
|
262
272
|
: `✂️ Compacting context... (flush took ${(flushMs / 1000).toFixed(1)}s)`;
|
|
263
273
|
await onProgress?.(progressNote);
|
|
264
274
|
const t1 = Date.now();
|