Record parses the tools array from a raw JSON request body and stores each tool's name and schema. format must be "openai" or "claude".
(rawJSON []byte, format string)
| 34 | // Record parses the tools array from a raw JSON request body and stores |
| 35 | // each tool's name and schema. format must be "openai" or "claude". |
| 36 | func (s *Store) Record(rawJSON []byte, format string) { |
| 37 | tools := gjson.GetBytes(rawJSON, "tools") |
| 38 | if !tools.Exists() || !tools.IsArray() { |
| 39 | return |
| 40 | } |
| 41 | |
| 42 | now := time.Now() |
| 43 | s.mu.Lock() |
| 44 | defer s.mu.Unlock() |
| 45 | |
| 46 | tools.ForEach(func(_, tool gjson.Result) bool { |
| 47 | var name string |
| 48 | var schemaRaw gjson.Result |
| 49 | |
| 50 | switch format { |
| 51 | case "openai": |
| 52 | // Chat Completions: {"type":"function","function":{"name":"...","parameters":{...}}} |
| 53 | name = tool.Get("function.name").String() |
| 54 | schemaRaw = tool.Get("function.parameters") |
| 55 | case "openai-responses": |
| 56 | // Responses API: {"type":"function","name":"...","parameters":{...}} |
| 57 | name = tool.Get("name").String() |
| 58 | schemaRaw = tool.Get("parameters") |
| 59 | default: // claude |
| 60 | name = tool.Get("name").String() |
| 61 | schemaRaw = tool.Get("input_schema") |
| 62 | } |
| 63 | |
| 64 | if name == "" { |
| 65 | return true |
| 66 | } |
| 67 | |
| 68 | var schema map[string]any |
| 69 | if schemaRaw.Exists() && schemaRaw.Raw != "" { |
| 70 | _ = json.Unmarshal([]byte(schemaRaw.Raw), &schema) |
| 71 | } |
| 72 | |
| 73 | key := format + ":" + name |
| 74 | s.tools[key] = ObservedTool{ |
| 75 | Name: name, |
| 76 | Schema: schema, |
| 77 | Format: format, |
| 78 | UpdatedAt: now, |
| 79 | } |
| 80 | return true |
| 81 | }) |
| 82 | } |
| 83 | |
| 84 | // List returns all observed tools sorted by format then name. |
| 85 | func (s *Store) List() []ObservedTool { |