SIGN IN SIGN UP

chat: recover from V8 max-string-length when persisting session state (#319183)

* ObjectMutationLog: recover from V8 max-string-length on stringify

JSON.stringify on the full session state (every 1024 mutations during
compaction) could exceed V8's ~512 MiB max string length when extensions
stored very large content in IChatAgentResult.metadata.toolCallResults
(notably Copilot's read_page tool can produce ~60 MiB browser dumps).
The thrown RangeError propagated up and lost the entire chat session.

Wrap the JSON.stringify(entry) calls in ObjectMutationLog with a catch
for RangeError that retries with a replacer truncating strings over
1 MiB and capping total at 100 MiB. The common path is a single
JSON.stringify with zero overhead; only failures pay the recovery cost.
Generic across the whole schema, so any future field that grows is
also protected.

Fixes #308843.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

(Written by Copilot)

* Address review: rename _BYTES -> _CHARS, tighten total-budget check

Copilot reviewer noted:
- Constants were named _BYTES but track string.length (UTF-16 code units),
  and the 'guaranteed to succeed' claim ignored JSON escaping and keys.
  Renamed to _CHARS and clarified that the budget is approximate.
- makeTruncatingReplacer checked total >= maxTotalChars *before* counting
  the current string, so one extra under-cap string could overshoot the
  cap. Now projects (total + val.length + 2) and emits the truncation
  marker if it would exceed the budget.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

(Written by Copilot)
R
Rob Lourens committed
eb308be4f9d2ce27a4117d84b7a789d90dd6cd62
Parent: 4918ed6
Committed by GitHub <noreply@github.com> on 6/1/2026, 12:03:32 AM