parseProfileFields extracts the key/value map from a profile invocation. It accepts {"fields":{...}} as well as a bare object {key:value,...} so the LLM can omit the wrapper.
(inner string)
| 359 | // It accepts {"fields":{...}} as well as a bare object {key:value,...} so |
| 360 | // the LLM can omit the wrapper. |
| 361 | func parseProfileFields(inner string) (map[string]string, error) { |
| 362 | inner = strings.TrimSpace(inner) |
| 363 | if inner == "" { |
| 364 | return nil, nil |
| 365 | } |
| 366 | var wrapped struct { |
| 367 | Fields json.RawMessage `json:"fields"` |
| 368 | } |
| 369 | if err := json.Unmarshal([]byte(inner), &wrapped); err == nil && len(wrapped.Fields) > 0 { |
| 370 | if m := decodeFieldsObject(wrapped.Fields); len(m) > 0 { |
| 371 | return stringifyMap(m), nil |
| 372 | } |
| 373 | } |
| 374 | var bare map[string]interface{} |
| 375 | if err := json.Unmarshal([]byte(inner), &bare); err != nil { |
| 376 | return nil, fmt.Errorf("invalid fields JSON: %w", err) |
| 377 | } |
| 378 | delete(bare, "fields") |
| 379 | return stringifyMap(bare), nil |
| 380 | } |
| 381 | |
| 382 | // decodeFieldsObject reads a JSON object from raw, accepting the direct |
| 383 | // object form and the JSON-encoded string the agent flattener produces when |