* Extract complete top-level JSON objects from a line without splitting on * braces that appear inside JSON strings.
(line: string)
| 152 | this.handleEvent(event); |
| 153 | return; |
| 154 | } catch { |
| 155 | // 可能是多个 JSON 拼接,尝试拆分 |
| 156 | } |
| 157 | |
| 158 | const segments = this.extractJsonObjects(line); |
| 159 | |
| 160 | for (const segment of segments) { |
| 161 | try { |
| 162 | const event: CodexEvent = JSON.parse(segment); |
| 163 | this.handleEvent(event); |
| 164 | } catch (err) { |
| 165 | if (DEBUG_PARSER) { |
| 166 | console.error('[CodexParser] Failed to parse JSON segment:', segment.substring(0, 200), err); |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | /** |
| 173 | * Extract complete top-level JSON objects from a line without splitting on |
| 174 | * braces that appear inside JSON strings. |
| 175 | */ |
| 176 | private extractJsonObjects(line: string): string[] { |
| 177 | const segments: string[] = []; |
| 178 | let start = -1; |
| 179 | let depth = 0; |
| 180 | let inString = false; |
| 181 | let escaped = false; |
| 182 | |
| 183 | for (let i = 0; i < line.length; i += 1) { |
| 184 | const char = line[i]; |
| 185 | |
| 186 | if (start === -1) { |
| 187 | if (char === '{') { |
| 188 | start = i; |
| 189 | depth = 1; |
| 190 | inString = false; |
| 191 | escaped = false; |
| 192 | } |
| 193 | continue; |
| 194 | } |
| 195 | |
| 196 | if (inString) { |
| 197 | if (escaped) { |
| 198 | escaped = false; |
| 199 | } else if (char === '\\') { |
| 200 | escaped = true; |
| 201 | } else if (char === '"') { |
| 202 | inString = false; |