transcript: fix close-brace finder to track string boundaries
The backward JSON scanner (JsonlBackwardIter and TailMessages) was matching } characters inside JSON strings — code blocks full of Rust braces being the primary offender. This caused: - Quadratic retry behavior on code-heavy transcripts (wrong object boundaries → serde parse failure → retry from different position) - Inconsistent find_last_compaction_in_file offsets across calls, making detect_new_compaction fire repeatedly → context reload on every hook call → seen set growing without bound Fix: add string-boundary tracking with escaped-quote handling to the close-brace finder loop, matching the existing logic in the depth-tracking loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aa46b1d5a6
commit
38816dc56e
1 changed files with 49 additions and 12 deletions
|
|
@ -32,14 +32,31 @@ impl<'a> Iterator for JsonlBackwardIter<'a> {
|
|||
type Item = &'a [u8];
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Find the closing } of the next object
|
||||
let close = loop {
|
||||
let p = memrchr3(b'{', b'}', b'"', &self.data[..self.pos])?;
|
||||
self.pos = p;
|
||||
if self.data[p] == b'}' {
|
||||
break p;
|
||||
// Find the closing } of the next object, skipping } inside strings
|
||||
let close = {
|
||||
let mut in_string = false;
|
||||
loop {
|
||||
let p = memrchr3(b'{', b'}', b'"', &self.data[..self.pos])?;
|
||||
self.pos = p;
|
||||
let ch = self.data[p];
|
||||
|
||||
if in_string {
|
||||
if ch == b'"' {
|
||||
let mut bs = 0;
|
||||
while p > bs + 1 && self.data[p - 1 - bs] == b'\\' {
|
||||
bs += 1;
|
||||
}
|
||||
if bs % 2 == 0 { in_string = false; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
match ch {
|
||||
b'}' => break p,
|
||||
b'"' => in_string = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Skip past any { or " that aren't our closing brace
|
||||
};
|
||||
|
||||
// Track brace depth to find matching {
|
||||
|
|
@ -164,11 +181,31 @@ impl Iterator for TailMessages {
|
|||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
// Find closing }
|
||||
let close = loop {
|
||||
let p = memrchr3(b'{', b'}', b'"', &self.mmap[..self.pos])?;
|
||||
self.pos = p;
|
||||
if self.mmap[p] == b'}' { break p; }
|
||||
// Find closing }, skipping } inside strings
|
||||
let close = {
|
||||
let mut in_string = false;
|
||||
loop {
|
||||
let p = memrchr3(b'{', b'}', b'"', &self.mmap[..self.pos])?;
|
||||
self.pos = p;
|
||||
let ch = self.mmap[p];
|
||||
|
||||
if in_string {
|
||||
if ch == b'"' {
|
||||
let mut bs = 0;
|
||||
while p > bs + 1 && self.mmap[p - 1 - bs] == b'\\' {
|
||||
bs += 1;
|
||||
}
|
||||
if bs % 2 == 0 { in_string = false; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
match ch {
|
||||
b'}' => break p,
|
||||
b'"' => in_string = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Track brace depth to find matching {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue