TryConsumeJSON attempts to consume a JSON value from the current position Returns the parsed JSON (can be object, array, or any JSON type), whether it's partial, and the jsonDumpMarker (non-empty if JSON was healed) Matches llama.cpp's try_consume_json() which returns common_json containing any JSON
()
| 320 | // and the jsonDumpMarker (non-empty if JSON was healed) |
| 321 | // Matches llama.cpp's try_consume_json() which returns common_json containing any JSON type and healing_marker |
| 322 | func (p *ChatMsgParser) TryConsumeJSON() (any, bool, string, error) { |
| 323 | // Skip whitespace |
| 324 | p.ConsumeSpaces() |
| 325 | |
| 326 | if p.pos >= len(p.input) { |
| 327 | return nil, false, "", errors.New("end of input") |
| 328 | } |
| 329 | |
| 330 | // Try to parse JSON starting from current position |
| 331 | jsonStart := p.pos |
| 332 | if p.input[p.pos] != '{' && p.input[p.pos] != '[' { |
| 333 | return nil, false, "", errors.New("not a JSON object or array") |
| 334 | } |
| 335 | |
| 336 | // Try parsing complete JSON first using decoder to get exact position |
| 337 | // Use any to support objects, arrays, and other JSON types (matching llama.cpp) |
| 338 | decoder := json.NewDecoder(strings.NewReader(p.input[jsonStart:])) |
| 339 | var jsonValue any |
| 340 | if err := decoder.Decode(&jsonValue); err == nil { |
| 341 | // Complete JSON parsed successfully |
| 342 | // Calculate position after JSON using decoder's input offset |
| 343 | p.pos = jsonStart + int(decoder.InputOffset()) |
| 344 | return jsonValue, false, "", nil |
| 345 | } |
| 346 | |
| 347 | // If parsing failed, try to find where JSON might end |
| 348 | // Find matching brace/bracket |
| 349 | depth := 0 |
| 350 | inString := false |
| 351 | escape := false |
| 352 | jsonEnd := -1 |
| 353 | |
| 354 | for i := p.pos; i < len(p.input); i++ { |
| 355 | ch := p.input[i] |
| 356 | |
| 357 | if escape { |
| 358 | escape = false |
| 359 | continue |
| 360 | } |
| 361 | |
| 362 | if ch == '\\' { |
| 363 | escape = true |
| 364 | continue |
| 365 | } |
| 366 | |
| 367 | if ch == '"' { |
| 368 | inString = !inString |
| 369 | continue |
| 370 | } |
| 371 | |
| 372 | if inString { |
| 373 | continue |
| 374 | } |
| 375 | |
| 376 | if ch == '{' || ch == '[' { |
| 377 | depth++ |
| 378 | } else if ch == '}' || ch == ']' { |
| 379 | depth-- |
no test coverage detected