Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/byok/common/geminiFunctionDeclarationConverter.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { FunctionDeclaration, Schema, Type } from '@google/genai';
7
8
export type ToolJsonSchema = {
9
type?: string;
10
description?: string;
11
properties?: Record<string, ToolJsonSchema>;
12
items?: ToolJsonSchema;
13
required?: string[];
14
enum?: string[];
15
16
// Add support for JSON Schema composition keywords
17
anyOf?: ToolJsonSchema[];
18
oneOf?: ToolJsonSchema[];
19
allOf?: ToolJsonSchema[];
20
};
21
22
// Map JSON schema types to Gemini Type enum
23
function mapType(jsonType: string): Type {
24
switch (jsonType) {
25
case 'object':
26
return Type.OBJECT;
27
case 'array':
28
return Type.ARRAY;
29
case 'string':
30
return Type.STRING;
31
case 'number':
32
return Type.NUMBER;
33
case 'integer':
34
return Type.INTEGER;
35
case 'boolean':
36
return Type.BOOLEAN;
37
case 'null':
38
return Type.NULL;
39
default:
40
throw new Error(`Unsupported type: ${jsonType}`);
41
}
42
}
43
44
// Convert JSON schema → Gemini function declaration
45
export function toGeminiFunction(name: string, description: string, schema: ToolJsonSchema): FunctionDeclaration {
46
// If schema root is array, we use its items for function parameters
47
const target = schema.type === 'array' && schema.items ? schema.items : schema;
48
49
const parameters: Schema = {
50
type: Type.OBJECT,
51
properties: transformProperties(target.properties || {}),
52
required: Array.isArray(target.required) ? target.required : []
53
};
54
55
return {
56
name,
57
description: description || 'No description provided.',
58
parameters
59
};
60
}
61
62
// Recursive transformation for nested properties
63
function transformProperties(props: Record<string, ToolJsonSchema>): Record<string, any> {
64
const result: Record<string, any> = {};
65
66
for (const [key, value] of Object.entries(props)) {
67
68
// Handle anyOf, oneOf, allOf by picking the first valid entry
69
const effectiveValue =
70
(value.anyOf?.[0] || value.oneOf?.[0] || value.allOf?.[0] || value) as ToolJsonSchema;
71
72
73
const transformed: any = {
74
// If type is undefined, throw an error to avoid incorrect assumptions
75
type: effectiveValue.type
76
? mapType(effectiveValue.type)
77
: Type.OBJECT
78
};
79
80
if (effectiveValue.description) {
81
transformed.description = effectiveValue.description;
82
}
83
84
// Enum support
85
if (effectiveValue.enum) {
86
transformed.enum = effectiveValue.enum;
87
}
88
89
if (effectiveValue.type === 'object' && effectiveValue.properties) {
90
transformed.properties = transformProperties(effectiveValue.properties);
91
if (effectiveValue.required) {
92
transformed.required = effectiveValue.required;
93
}
94
} else if (effectiveValue.type === 'array' && effectiveValue.items) {
95
const itemType = effectiveValue.items.type === 'object' ? Type.OBJECT : mapType(effectiveValue.items.type ?? 'object');
96
const itemSchema: any = { type: itemType };
97
98
if (effectiveValue.items.description) {
99
itemSchema.description = effectiveValue.items.description;
100
}
101
102
if (effectiveValue.items.enum) {
103
itemSchema.enum = effectiveValue.items.enum;
104
}
105
106
if (effectiveValue.items.properties) {
107
itemSchema.properties = transformProperties(effectiveValue.items.properties);
108
if (effectiveValue.items.required) {
109
itemSchema.required = effectiveValue.items.required;
110
}
111
}
112
113
transformed.items = itemSchema;
114
}
115
116
result[key] = transformed;
117
}
118
119
return result;
120
}
121