Preuve · code, extrait

provider_google.go

Dépôt apteva/core · commit f6989d0d806f6ba2310f4152b1a9fd85a77b7cb6 · plateforme Apteva, cœur, lu sur GitHub le 14 septembre 2026

Extrait tel qu'à ce commit : lignes 159–265, sur 744 (numérotation d'origine, 30 lignes de contexte autour de chaque citation) · fichier intégral sur GitHub (dépôt public)

Lignes citées par l'audit : 189–235

107 lignes reproduites · ← retour à l'audit · catalogue des preuves

159type geminiContent struct {
160	Role  string       `json:"role,omitempty"`
161	Parts []geminiPart `json:"parts"`
162}
163
164type geminiPart struct {
165	Text             string                  `json:"text,omitempty"`
166	InlineData       *geminiInline           `json:"inlineData,omitempty"`
167	FunctionCall     *geminiFunctionCall     `json:"functionCall,omitempty"`
168	FunctionResponse *geminiFunctionResponse `json:"functionResponse,omitempty"`
169	ThoughtSignature string                  `json:"thoughtSignature,omitempty"`
170}
171
172type geminiFunctionCall struct {
173	ID   string         `json:"id,omitempty"`
174	Name string         `json:"name"`
175	Args map[string]any `json:"args"`
176}
177
178type geminiFunctionResponse struct {
179	ID       string         `json:"id,omitempty"`
180	Name     string         `json:"name"`
181	Response map[string]any `json:"response"`
182}
183
184type geminiInline struct {
185	MimeType string `json:"mimeType"`
186	Data     string `json:"data"`
187}
188
189func geminiToolParameters(schema map[string]any) map[string]any {
190	normalized, ok := normalizeGeminiSchema("", schema).(map[string]any)
191	if !ok || len(normalized) == 0 {
192		return map[string]any{"type": "object"}
193	}
194	if _, ok := normalized["type"]; !ok {
195		normalized["type"] = "object"
196	}
197	return normalized
198}
199
200func normalizeGeminiSchema(name string, v any) any {
201	switch x := v.(type) {
202	case map[string]any:
203		out := make(map[string]any, len(x)+1)
204		for k, val := range x {
205			if k == "properties" {
206				props, ok := val.(map[string]any)
207				if !ok {
208					out[k] = normalizeGeminiSchema(k, val)
209					continue
210				}
211				normalizedProps := make(map[string]any, len(props))
212				for propName, propSchema := range props {
213					normalizedProps[propName] = normalizeGeminiSchema(propName, propSchema)
214				}
215				out[k] = normalizedProps
216				continue
217			}
218			out[k] = normalizeGeminiSchema(k, val)
219		}
220		if schemaTypeIncludes(out["type"], "array") {
221			if items, ok := out["items"]; !ok || isEmptyGeminiSchema(items) {
222				out["items"] = defaultGeminiArrayItems(name)
223			}
224		}
225		return out
226	case []any:
227		out := make([]any, len(x))
228		for i, val := range x {
229			out[i] = normalizeGeminiSchema(name, val)
230		}
231		return out
232	default:
233		return v
234	}
235}
236
237func defaultGeminiArrayItems(name string) map[string]any {
238	switch name {
239	case "attributes", "channels", "definition", "filters":
240		return map[string]any{"type": "object"}
241	case "enum_values", "list_ids", "tags":
242		return map[string]any{"type": "string"}
243	default:
244		return map[string]any{"type": "object"}
245	}
246}
247
248func schemaTypeIncludes(raw any, want string) bool {
249	switch x := raw.(type) {
250	case string:
251		return strings.EqualFold(x, want)
252	case []any:
253		for _, val := range x {
254			if s, ok := val.(string); ok && strings.EqualFold(s, want) {
255				return true
256			}
257		}
258	case []string:
259		for _, s := range x {
260			if strings.EqualFold(s, want) {
261				return true
262			}
263		}
264	}
265	return false