| 276 | if (LEAKED_PAYLOAD_NAME_RE.test(text.slice(at, at + LEAKED_PAYLOAD_NAME_WINDOW))) { |
| 277 | const shape = afterProse |
| 278 | ? isPlausibleAfterProsePayload(text.slice(at, at + AFTER_PROSE_PAYLOAD_MAX + 1)) |
| 279 | : isLeakedToolPayloadShape(text.slice(at)); |
| 280 | if (shape) return at; |
| 281 | } |
| 282 | at = nextLineStartBrace(text, at + 1, false, limit); |
| 283 | } |
| 284 | return -1; |
| 285 | }; |
| 286 | |
| 287 | /** |
| 288 | * index 处是否处在**行首**:上一个换行(或文本开头)到 index 之间只有空白。两条路径 |
| 289 | * 共用同一个谓词(review loop 2):整段路径在每个扫描位置与残片切点之后的恢复点上问它 |
| 290 | * (`fullText[position-1] === '\n'` 会把缩进过的 ` {"name":…}` 拒之门外);流式解析器 |
| 291 | * 用它在每个放行点更新 lineStart —— 放行的文本没有换行时沿用之前的状态(prior), |
| 292 | * 于是切在前导空白中间的 chunk 边界也不会让下一个 '{' 失去行首身份。 |
| 293 | * 代价是 index 之前那一串空白的长度,遇到第一个非空白就停。 |
| 294 | * @param {string} text |