@simulacra-ai/google 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/dist/index.cjs +501 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{google-provider.d.ts → index.d.cts} +30 -5
- package/dist/index.d.ts +79 -3
- package/dist/index.js +462 -2
- package/dist/index.js.map +1 -1
- package/package.json +11 -5
- package/dist/google-provider.d.ts.map +0 -1
- package/dist/google-provider.js +0 -400
- package/dist/google-provider.js.map +0 -1
- package/dist/google-tool-code-context-transformer.d.ts +0 -24
- package/dist/google-tool-code-context-transformer.d.ts.map +0 -1
- package/dist/google-tool-code-context-transformer.js +0 -73
- package/dist/google-tool-code-context-transformer.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import * as gemini from '@google/genai';
|
|
2
|
+
import { ModelProvider, ProviderContextTransformer, ModelRequest, StreamReceiver, CancellationToken, AssistantMessage } from '@simulacra-ai/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options for the Google Gemini provider.
|
|
6
|
+
*/
|
|
7
|
+
interface GoogleProviderConfig extends Record<string, unknown> {
|
|
8
|
+
/** The model identifier to use (e.g., "gemini-2.0-flash-exp"). */
|
|
9
|
+
model: string;
|
|
10
|
+
/** The maximum number of tokens to generate in the response. */
|
|
11
|
+
max_tokens?: number;
|
|
12
|
+
/** Configuration for extended thinking mode. */
|
|
13
|
+
thinking?: {
|
|
14
|
+
/** Whether to enable extended thinking. */
|
|
15
|
+
enable: boolean;
|
|
16
|
+
/** The token budget allocated for thinking. */
|
|
17
|
+
budget_tokens?: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Model provider implementation for Google's Gemini models.
|
|
22
|
+
*
|
|
23
|
+
* This provider wraps the Google Generative AI SDK to provide streaming completions
|
|
24
|
+
* with support for tool use, extended thinking, and multimodal content. It handles
|
|
25
|
+
* message formatting, content streaming, and usage tracking according to the
|
|
26
|
+
* ModelProvider interface.
|
|
27
|
+
*/
|
|
28
|
+
declare class GoogleProvider implements ModelProvider {
|
|
29
|
+
#private;
|
|
30
|
+
readonly context_transformers: ProviderContextTransformer[];
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new Google Gemini provider instance.
|
|
33
|
+
*
|
|
34
|
+
* @param sdk - The initialized Google Generative AI SDK client.
|
|
35
|
+
* @param config - Configuration options for the provider.
|
|
36
|
+
* @param context_transformers - Provider-level context transformers. Defaults to GoogleToolCodeContextTransformer.
|
|
37
|
+
*/
|
|
38
|
+
constructor(sdk: gemini.GoogleGenAI, config: GoogleProviderConfig, context_transformers?: ProviderContextTransformer[]);
|
|
39
|
+
/**
|
|
40
|
+
* Executes a model request and streams the response through the provided receiver.
|
|
41
|
+
*
|
|
42
|
+
* @param request - The request containing messages, tools, and system prompt.
|
|
43
|
+
* @param receiver - The receiver that handles streaming events.
|
|
44
|
+
* @param cancellation - Token to signal cancellation of the request.
|
|
45
|
+
* @returns A promise that resolves when the request completes.
|
|
46
|
+
*/
|
|
47
|
+
execute_request(request: ModelRequest, receiver: StreamReceiver, cancellation: CancellationToken): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a clone of this provider with the same configuration.
|
|
50
|
+
*
|
|
51
|
+
* @returns A new provider instance with identical configuration.
|
|
52
|
+
*/
|
|
53
|
+
clone(): ModelProvider;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Provider context transformer that extracts tool calls from Gemini's code execution blocks.
|
|
58
|
+
*
|
|
59
|
+
* Gemini models sometimes return tool calls as executable code in markdown code blocks
|
|
60
|
+
* tagged with "tool_code". This transformer parses those blocks and converts them into
|
|
61
|
+
* standard tool call content that the framework can execute.
|
|
62
|
+
*/
|
|
63
|
+
declare class GoogleToolCodeContextTransformer implements ProviderContextTransformer {
|
|
64
|
+
/**
|
|
65
|
+
* Transforms completion messages by extracting tool calls from code blocks.
|
|
66
|
+
*
|
|
67
|
+
* Scans text content for code blocks tagged as "tool_code" and parses them into
|
|
68
|
+
* proper tool call content. The original code blocks are replaced with newlines
|
|
69
|
+
* in the text content.
|
|
70
|
+
*
|
|
71
|
+
* @param message - The completion message to transform.
|
|
72
|
+
* @returns A promise resolving to the transformed message.
|
|
73
|
+
*/
|
|
74
|
+
transform_completion(message: AssistantMessage): Promise<AssistantMessage>;
|
|
75
|
+
private extract_tool_calls;
|
|
76
|
+
private parse_tool_call;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { GoogleProvider, type GoogleProviderConfig, GoogleToolCodeContextTransformer };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,463 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// src/google-provider.ts
|
|
2
|
+
import crypto2 from "crypto";
|
|
3
|
+
import * as gemini from "@google/genai";
|
|
4
|
+
import { deep_merge, peek_generator, undefined_if_empty } from "@simulacra-ai/core";
|
|
5
|
+
|
|
6
|
+
// src/google-tool-code-context-transformer.ts
|
|
7
|
+
import crypto from "crypto";
|
|
8
|
+
var GoogleToolCodeContextTransformer = class {
|
|
9
|
+
/**
|
|
10
|
+
* Transforms completion messages by extracting tool calls from code blocks.
|
|
11
|
+
*
|
|
12
|
+
* Scans text content for code blocks tagged as "tool_code" and parses them into
|
|
13
|
+
* proper tool call content. The original code blocks are replaced with newlines
|
|
14
|
+
* in the text content.
|
|
15
|
+
*
|
|
16
|
+
* @param message - The completion message to transform.
|
|
17
|
+
* @returns A promise resolving to the transformed message.
|
|
18
|
+
*/
|
|
19
|
+
transform_completion(message) {
|
|
20
|
+
if (message.role !== "assistant") {
|
|
21
|
+
return Promise.resolve(message);
|
|
22
|
+
}
|
|
23
|
+
return Promise.resolve({
|
|
24
|
+
...message,
|
|
25
|
+
content: message.content.flatMap((c) => {
|
|
26
|
+
if (c.type !== "text") {
|
|
27
|
+
return [c];
|
|
28
|
+
}
|
|
29
|
+
return this.extract_tool_calls(c);
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
extract_tool_calls(content) {
|
|
34
|
+
const tool_calls = [];
|
|
35
|
+
const remaining_text = content.text.replaceAll(
|
|
36
|
+
/```(?:tool_code)\n(.*?)\n```/gs,
|
|
37
|
+
(_, tool_code) => {
|
|
38
|
+
const tool_call = this.parse_tool_call(content, tool_code);
|
|
39
|
+
if (tool_call) {
|
|
40
|
+
tool_calls.push(tool_call);
|
|
41
|
+
}
|
|
42
|
+
return "\n";
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
return [{ ...content, text: remaining_text }, ...tool_calls];
|
|
46
|
+
}
|
|
47
|
+
parse_tool_call(content, tool_code) {
|
|
48
|
+
const function_match = tool_code?.match(/^print\((\w+)\((.*)\)\)$/);
|
|
49
|
+
if (!function_match) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const [_, name, params_text] = function_match;
|
|
53
|
+
const params = Object.fromEntries(
|
|
54
|
+
Array.from(
|
|
55
|
+
params_text.matchAll(
|
|
56
|
+
/(\w+)\s*=\s*(("(?:\\"|[^"])*")|(-?[\d.]+)|([Tt]rue|[Ff]alse))\s*(,|$)/g
|
|
57
|
+
)
|
|
58
|
+
).map(([_match, key, _full, str, num, bool]) => {
|
|
59
|
+
if (bool !== void 0) {
|
|
60
|
+
return [key, bool.toLocaleLowerCase() === "true"];
|
|
61
|
+
}
|
|
62
|
+
if (!isNaN(Number(num))) {
|
|
63
|
+
return [key, Number(num)];
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
return [key, JSON.parse(str)];
|
|
67
|
+
} catch {
|
|
68
|
+
return [key, str];
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
);
|
|
72
|
+
return {
|
|
73
|
+
type: "tool",
|
|
74
|
+
tool_request_id: content.id ?? crypto.randomUUID(),
|
|
75
|
+
tool: name,
|
|
76
|
+
params
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// src/google-provider.ts
|
|
82
|
+
var GoogleProvider = class _GoogleProvider {
|
|
83
|
+
#sdk;
|
|
84
|
+
#config;
|
|
85
|
+
context_transformers;
|
|
86
|
+
/**
|
|
87
|
+
* Creates a new Google Gemini provider instance.
|
|
88
|
+
*
|
|
89
|
+
* @param sdk - The initialized Google Generative AI SDK client.
|
|
90
|
+
* @param config - Configuration options for the provider.
|
|
91
|
+
* @param context_transformers - Provider-level context transformers. Defaults to GoogleToolCodeContextTransformer.
|
|
92
|
+
*/
|
|
93
|
+
constructor(sdk, config, context_transformers = [new GoogleToolCodeContextTransformer()]) {
|
|
94
|
+
this.#sdk = sdk;
|
|
95
|
+
this.#config = config;
|
|
96
|
+
this.context_transformers = context_transformers;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Executes a model request and streams the response through the provided receiver.
|
|
100
|
+
*
|
|
101
|
+
* @param request - The request containing messages, tools, and system prompt.
|
|
102
|
+
* @param receiver - The receiver that handles streaming events.
|
|
103
|
+
* @param cancellation - Token to signal cancellation of the request.
|
|
104
|
+
* @returns A promise that resolves when the request completes.
|
|
105
|
+
*/
|
|
106
|
+
async execute_request(request, receiver, cancellation) {
|
|
107
|
+
const { model, max_tokens, thinking, ...api_extras } = this.#config;
|
|
108
|
+
const params = {
|
|
109
|
+
model,
|
|
110
|
+
config: {
|
|
111
|
+
...api_extras,
|
|
112
|
+
systemInstruction: request.system,
|
|
113
|
+
maxOutputTokens: max_tokens,
|
|
114
|
+
thinkingConfig: {
|
|
115
|
+
includeThoughts: thinking?.enable,
|
|
116
|
+
thinkingBudget: thinking?.budget_tokens
|
|
117
|
+
},
|
|
118
|
+
...request.tools.length > 0 ? {
|
|
119
|
+
tools: [
|
|
120
|
+
{
|
|
121
|
+
functionDeclarations: request.tools.map((t) => to_gemini_tool(t))
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
} : {}
|
|
125
|
+
},
|
|
126
|
+
contents: request.messages.map((m) => to_gemini_content(m))
|
|
127
|
+
};
|
|
128
|
+
receiver.before_request({ params });
|
|
129
|
+
receiver.request_raw(params);
|
|
130
|
+
const response = await this.#sdk.models.generateContentStream(params);
|
|
131
|
+
const { peeked_value: _peeked_value, generator } = await peek_generator(response);
|
|
132
|
+
this.#stream_response(generator, receiver, cancellation);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates a clone of this provider with the same configuration.
|
|
136
|
+
*
|
|
137
|
+
* @returns A new provider instance with identical configuration.
|
|
138
|
+
*/
|
|
139
|
+
clone() {
|
|
140
|
+
return new _GoogleProvider(this.#sdk, this.#config, this.context_transformers);
|
|
141
|
+
}
|
|
142
|
+
async #stream_response(stream, receiver, cancellation) {
|
|
143
|
+
try {
|
|
144
|
+
let response;
|
|
145
|
+
const completed_parts = /* @__PURE__ */ new Set();
|
|
146
|
+
for await (const response_chunk of stream) {
|
|
147
|
+
if (cancellation.is_cancellation_requested) {
|
|
148
|
+
receiver.cancel();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
receiver.stream_raw(response_chunk);
|
|
152
|
+
const { candidates: candidates_chunk, ...rest } = response_chunk;
|
|
153
|
+
response = {
|
|
154
|
+
...response,
|
|
155
|
+
...rest,
|
|
156
|
+
candidates: response?.candidates ?? []
|
|
157
|
+
};
|
|
158
|
+
const candidates = response.candidates;
|
|
159
|
+
for (const candidate_chunk of candidates_chunk ?? []) {
|
|
160
|
+
if (!candidates[candidate_chunk.index ?? 0]) {
|
|
161
|
+
candidates[candidate_chunk.index ?? 0] = candidate_chunk;
|
|
162
|
+
const message2 = from_gemini_content(candidate_chunk.content);
|
|
163
|
+
const usage2 = from_gemini_usage(response.usageMetadata);
|
|
164
|
+
for (const content of message2.content) {
|
|
165
|
+
receiver.start_content({ content, message: message2, usage: usage2 });
|
|
166
|
+
}
|
|
167
|
+
receiver.start_message({ message: message2, usage: usage2 });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const { content: content_chunk, ...rest2 } = candidate_chunk;
|
|
171
|
+
const candidate = candidates[candidate_chunk.index ?? 0] = {
|
|
172
|
+
...candidates[candidate_chunk.index ?? 0],
|
|
173
|
+
...rest2,
|
|
174
|
+
content: {
|
|
175
|
+
...candidates[candidate_chunk.index ?? 0]?.content,
|
|
176
|
+
parts: candidates[candidate_chunk.index ?? 0]?.content?.parts ?? []
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
for (const part_chunk of content_chunk?.parts ?? []) {
|
|
180
|
+
const [part] = candidate.content.parts.slice(-1);
|
|
181
|
+
if (!part) {
|
|
182
|
+
candidate.content.parts.push(part_chunk);
|
|
183
|
+
receiver.start_content({
|
|
184
|
+
message: from_gemini_content(candidate.content),
|
|
185
|
+
content: from_gemini_part(part_chunk),
|
|
186
|
+
usage: from_gemini_usage(response.usageMetadata)
|
|
187
|
+
});
|
|
188
|
+
receiver.update_message({
|
|
189
|
+
message: from_gemini_content(candidate.content),
|
|
190
|
+
usage: from_gemini_usage(response?.usageMetadata)
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
if (part_chunk.thought && part.thought) {
|
|
194
|
+
part.text = (part.text ?? "") + (part_chunk.text ?? "");
|
|
195
|
+
} else if (!part_chunk.thought && !part.thought && part_chunk.text && part.text) {
|
|
196
|
+
part.text = (part.text ?? "") + (part_chunk.text ?? "");
|
|
197
|
+
} else if (part_chunk.functionCall && part.functionCall) {
|
|
198
|
+
part.functionCall = deep_merge(part.functionCall, part_chunk.functionCall);
|
|
199
|
+
} else if (part_chunk.executableCode && part.executableCode) {
|
|
200
|
+
if (part_chunk.executableCode.code && part.executableCode.code) {
|
|
201
|
+
part.executableCode.code += part_chunk.executableCode.code;
|
|
202
|
+
delete part_chunk.executableCode.code;
|
|
203
|
+
}
|
|
204
|
+
part.executableCode = deep_merge(part.executableCode, part_chunk.executableCode);
|
|
205
|
+
} else if (part_chunk.videoMetadata && part.videoMetadata) {
|
|
206
|
+
part.videoMetadata = deep_merge(part.videoMetadata, part_chunk.videoMetadata);
|
|
207
|
+
} else if (part_chunk.fileData && part.fileData) {
|
|
208
|
+
part.fileData = deep_merge(part.fileData, part_chunk.fileData);
|
|
209
|
+
} else if (part_chunk.inlineData && part.inlineData) {
|
|
210
|
+
part.inlineData = deep_merge(part.inlineData, part_chunk.inlineData);
|
|
211
|
+
} else {
|
|
212
|
+
receiver.complete_content({
|
|
213
|
+
message: from_gemini_content(candidate.content),
|
|
214
|
+
content: from_gemini_part(part),
|
|
215
|
+
usage: from_gemini_usage(response.usageMetadata)
|
|
216
|
+
});
|
|
217
|
+
completed_parts.add(candidate.content.parts.length - 1);
|
|
218
|
+
candidate.content.parts.push(part_chunk);
|
|
219
|
+
receiver.start_content({
|
|
220
|
+
message: from_gemini_content(candidate.content),
|
|
221
|
+
content: from_gemini_part(part_chunk),
|
|
222
|
+
usage: from_gemini_usage(response.usageMetadata)
|
|
223
|
+
});
|
|
224
|
+
receiver.update_message({
|
|
225
|
+
message: from_gemini_content(candidate.content),
|
|
226
|
+
usage: from_gemini_usage(response?.usageMetadata)
|
|
227
|
+
});
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
receiver.update_content({
|
|
231
|
+
message: from_gemini_content(candidate.content),
|
|
232
|
+
content: from_gemini_part(part),
|
|
233
|
+
usage: from_gemini_usage(response.usageMetadata)
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (!response || !response.candidates?.[0]) {
|
|
240
|
+
throw new Error("no data", { cause: JSON.stringify(response?.promptFeedback ?? response) });
|
|
241
|
+
}
|
|
242
|
+
receiver.response_raw({ ...response });
|
|
243
|
+
const message = from_gemini_content(response.candidates[0].content);
|
|
244
|
+
const usage = from_gemini_usage(response.usageMetadata);
|
|
245
|
+
for (let i = 0; i < message.content.length; i++) {
|
|
246
|
+
if (!completed_parts.has(i)) {
|
|
247
|
+
receiver.complete_content({ content: message.content[i], message, usage });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
receiver.complete_message({ message, usage, ...map_stop_reason(response) });
|
|
251
|
+
} catch (error) {
|
|
252
|
+
receiver.error(error);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
function to_gemini_tool(tool) {
|
|
257
|
+
return {
|
|
258
|
+
name: tool.name,
|
|
259
|
+
description: tool.description,
|
|
260
|
+
parameters: {
|
|
261
|
+
type: gemini.Type.OBJECT,
|
|
262
|
+
properties: undefined_if_empty(
|
|
263
|
+
Object.fromEntries(
|
|
264
|
+
tool.parameters.map((p) => [p.name, to_gemini_tool_schema(p, p.description)])
|
|
265
|
+
)
|
|
266
|
+
),
|
|
267
|
+
required: undefined_if_empty(tool.parameters.filter((p) => p.required).map((p) => p.name))
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function from_gemini_content(content) {
|
|
272
|
+
if (!content) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
role: content.role === "model" ? "assistant" : "user",
|
|
277
|
+
content: content.parts?.map((p) => from_gemini_part(p)).filter(Boolean)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function from_gemini_part(part) {
|
|
281
|
+
if (!part) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (part.thought) {
|
|
285
|
+
return {
|
|
286
|
+
type: "thinking",
|
|
287
|
+
thought: part.text ?? ""
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
if (part.text) {
|
|
291
|
+
return {
|
|
292
|
+
type: "text",
|
|
293
|
+
text: part.text ?? ""
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
if (part.functionCall) {
|
|
297
|
+
return {
|
|
298
|
+
type: "tool",
|
|
299
|
+
tool_request_id: part.functionCall.id ?? crypto2.randomUUID(),
|
|
300
|
+
tool: part.functionCall.name ?? "",
|
|
301
|
+
params: part.functionCall.args ?? {}
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
if (part.functionResponse) {
|
|
305
|
+
return {
|
|
306
|
+
type: "tool_result",
|
|
307
|
+
tool_request_id: part.functionResponse.id ?? "",
|
|
308
|
+
tool: part.functionResponse.name ?? "",
|
|
309
|
+
result: part.functionResponse.response ?? {}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
type: "raw",
|
|
314
|
+
model_kind: "google",
|
|
315
|
+
data: JSON.stringify(part)
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function to_gemini_content(message) {
|
|
319
|
+
return {
|
|
320
|
+
role: message.role === "assistant" ? "model" : "user",
|
|
321
|
+
parts: message.content.map((c) => to_gemini_part(c))
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
function to_gemini_part(content) {
|
|
325
|
+
switch (content.type) {
|
|
326
|
+
case "text":
|
|
327
|
+
return {
|
|
328
|
+
text: content.text
|
|
329
|
+
};
|
|
330
|
+
case "tool":
|
|
331
|
+
return {
|
|
332
|
+
functionCall: {
|
|
333
|
+
id: content.tool_request_id,
|
|
334
|
+
name: content.tool,
|
|
335
|
+
args: content.params
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
case "raw":
|
|
339
|
+
if (content.model_kind === "google") {
|
|
340
|
+
try {
|
|
341
|
+
return {
|
|
342
|
+
...JSON.parse(content.data)
|
|
343
|
+
};
|
|
344
|
+
} catch {
|
|
345
|
+
return {
|
|
346
|
+
text: content.data
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
text: content.data
|
|
352
|
+
};
|
|
353
|
+
case "tool_result":
|
|
354
|
+
return {
|
|
355
|
+
functionResponse: {
|
|
356
|
+
id: content.tool_request_id,
|
|
357
|
+
name: content.tool,
|
|
358
|
+
response: content.result
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
case "thinking":
|
|
362
|
+
return {
|
|
363
|
+
thought: true,
|
|
364
|
+
text: content.thought
|
|
365
|
+
};
|
|
366
|
+
default:
|
|
367
|
+
throw new Error("unexpected content type");
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function to_gemini_tool_schema(parameter_type, description) {
|
|
371
|
+
switch (parameter_type.type) {
|
|
372
|
+
case "string":
|
|
373
|
+
return {
|
|
374
|
+
type: gemini.Type.STRING,
|
|
375
|
+
description,
|
|
376
|
+
enum: parameter_type.enum,
|
|
377
|
+
default: !parameter_type.required ? parameter_type.default : void 0
|
|
378
|
+
};
|
|
379
|
+
case "number":
|
|
380
|
+
return {
|
|
381
|
+
type: gemini.Type.NUMBER,
|
|
382
|
+
description,
|
|
383
|
+
default: !parameter_type.required ? parameter_type.default : void 0
|
|
384
|
+
};
|
|
385
|
+
case "boolean":
|
|
386
|
+
return {
|
|
387
|
+
type: gemini.Type.BOOLEAN,
|
|
388
|
+
description,
|
|
389
|
+
default: !parameter_type.required ? parameter_type.default : void 0
|
|
390
|
+
};
|
|
391
|
+
case "object":
|
|
392
|
+
return {
|
|
393
|
+
type: gemini.Type.OBJECT,
|
|
394
|
+
description,
|
|
395
|
+
properties: Object.fromEntries(
|
|
396
|
+
Object.entries(parameter_type.properties).map(([name, p]) => [
|
|
397
|
+
name,
|
|
398
|
+
to_gemini_tool_schema(p, p.description)
|
|
399
|
+
])
|
|
400
|
+
),
|
|
401
|
+
required: undefined_if_empty(
|
|
402
|
+
Object.entries(parameter_type.properties).filter(([, p]) => p.required).map(([name]) => name)
|
|
403
|
+
)
|
|
404
|
+
};
|
|
405
|
+
case "array":
|
|
406
|
+
return {
|
|
407
|
+
type: gemini.Type.ARRAY,
|
|
408
|
+
description,
|
|
409
|
+
items: to_gemini_tool_schema(parameter_type.items, parameter_type.items.description)
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
function from_gemini_usage(usage) {
|
|
414
|
+
return {
|
|
415
|
+
cache_read_input_tokens: usage?.cachedContentTokenCount,
|
|
416
|
+
input_tokens: usage?.promptTokenCount,
|
|
417
|
+
output_tokens: usage?.candidatesTokenCount
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function map_stop_reason(response) {
|
|
421
|
+
for (const { finishReason, finishMessage } of response?.candidates ?? []) {
|
|
422
|
+
switch (finishReason) {
|
|
423
|
+
case gemini.FinishReason.STOP:
|
|
424
|
+
if (response.candidates?.[0].content?.parts?.some((p) => !!p.functionCall)) {
|
|
425
|
+
return {
|
|
426
|
+
stop_reason: "tool_use",
|
|
427
|
+
stop_details: finishMessage
|
|
428
|
+
};
|
|
429
|
+
} else {
|
|
430
|
+
return {
|
|
431
|
+
stop_reason: "end_turn",
|
|
432
|
+
stop_details: finishMessage
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
case gemini.FinishReason.MAX_TOKENS:
|
|
436
|
+
return {
|
|
437
|
+
stop_reason: "max_tokens",
|
|
438
|
+
stop_details: finishMessage
|
|
439
|
+
};
|
|
440
|
+
case gemini.FinishReason.MALFORMED_FUNCTION_CALL:
|
|
441
|
+
return {
|
|
442
|
+
stop_reason: "error",
|
|
443
|
+
stop_details: finishMessage
|
|
444
|
+
};
|
|
445
|
+
case gemini.FinishReason.FINISH_REASON_UNSPECIFIED:
|
|
446
|
+
case gemini.FinishReason.SAFETY:
|
|
447
|
+
case gemini.FinishReason.RECITATION:
|
|
448
|
+
case gemini.FinishReason.LANGUAGE:
|
|
449
|
+
case gemini.FinishReason.BLOCKLIST:
|
|
450
|
+
case gemini.FinishReason.PROHIBITED_CONTENT:
|
|
451
|
+
case gemini.FinishReason.SPII:
|
|
452
|
+
case gemini.FinishReason.IMAGE_SAFETY:
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
stop_reason: "other"
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
export {
|
|
460
|
+
GoogleProvider,
|
|
461
|
+
GoogleToolCodeContextTransformer
|
|
462
|
+
};
|
|
3
463
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA6B,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,2CAA2C,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../src/google-provider.ts","../src/google-tool-code-context-transformer.ts"],"sourcesContent":["import crypto from \"node:crypto\";\n\nimport * as gemini from \"@google/genai\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n CancellationToken,\n CompletionResponseData,\n Content,\n EnumParameterType,\n Message,\n ModelProvider,\n ModelRequest,\n ParameterType,\n ProviderContextTransformer,\n StreamReceiver,\n ToolDefinition,\n} from \"@simulacra-ai/core\";\nimport { deep_merge, peek_generator, undefined_if_empty } from \"@simulacra-ai/core\";\nimport { GoogleToolCodeContextTransformer } from \"./google-tool-code-context-transformer.ts\";\n\n/**\n * Configuration options for the Google Gemini provider.\n */\nexport interface GoogleProviderConfig extends Record<string, unknown> {\n /** The model identifier to use (e.g., \"gemini-2.0-flash-exp\"). */\n model: string;\n /** The maximum number of tokens to generate in the response. */\n max_tokens?: number;\n /** Configuration for extended thinking mode. */\n thinking?: {\n /** Whether to enable extended thinking. */\n enable: boolean;\n /** The token budget allocated for thinking. */\n budget_tokens?: number;\n };\n}\n\n/**\n * Model provider implementation for Google's Gemini models.\n *\n * This provider wraps the Google Generative AI SDK to provide streaming completions\n * with support for tool use, extended thinking, and multimodal content. It handles\n * message formatting, content streaming, and usage tracking according to the\n * ModelProvider interface.\n */\nexport class GoogleProvider implements ModelProvider {\n readonly #sdk: gemini.GoogleGenAI;\n readonly #config: GoogleProviderConfig;\n\n readonly context_transformers: ProviderContextTransformer[];\n\n /**\n * Creates a new Google Gemini provider instance.\n *\n * @param sdk - The initialized Google Generative AI SDK client.\n * @param config - Configuration options for the provider.\n * @param context_transformers - Provider-level context transformers. Defaults to GoogleToolCodeContextTransformer.\n */\n constructor(\n sdk: gemini.GoogleGenAI,\n config: GoogleProviderConfig,\n context_transformers: ProviderContextTransformer[] = [new GoogleToolCodeContextTransformer()],\n ) {\n this.#sdk = sdk;\n this.#config = config;\n this.context_transformers = context_transformers;\n }\n\n /**\n * Executes a model request and streams the response through the provided receiver.\n *\n * @param request - The request containing messages, tools, and system prompt.\n * @param receiver - The receiver that handles streaming events.\n * @param cancellation - Token to signal cancellation of the request.\n * @returns A promise that resolves when the request completes.\n */\n async execute_request(\n request: ModelRequest,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ): Promise<void> {\n const { model, max_tokens, thinking, ...api_extras } = this.#config;\n const params: gemini.GenerateContentParameters = {\n model,\n\n config: {\n ...api_extras,\n systemInstruction: request.system,\n maxOutputTokens: max_tokens,\n thinkingConfig: {\n includeThoughts: thinking?.enable,\n thinkingBudget: thinking?.budget_tokens,\n },\n ...(request.tools.length > 0\n ? {\n tools: [\n {\n functionDeclarations: request.tools.map((t) => to_gemini_tool(t)),\n },\n ],\n }\n : {}),\n },\n contents: request.messages.map((m) => to_gemini_content(m)),\n };\n receiver.before_request({ params });\n receiver.request_raw(params);\n\n const response = await this.#sdk.models.generateContentStream(params);\n const { peeked_value: _peeked_value, generator } = (await peek_generator(response)) as {\n peeked_value: gemini.GenerateContentResponse;\n generator: AsyncGenerator<gemini.GenerateContentResponse>;\n };\n\n // Intentionally not awaited. Streaming is event-driven through the receiver.\n // The policy wraps only connection establishment; chunk processing flows\n // asynchronously via StreamListener events back to the conversation.\n this.#stream_response(generator, receiver, cancellation);\n }\n\n /**\n * Creates a clone of this provider with the same configuration.\n *\n * @returns A new provider instance with identical configuration.\n */\n clone(): ModelProvider {\n return new GoogleProvider(this.#sdk, this.#config, this.context_transformers);\n }\n\n async #stream_response(\n stream: AsyncGenerator<gemini.GenerateContentResponse>,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ) {\n try {\n let response: Partial<gemini.GenerateContentResponse> | undefined;\n const completed_parts = new Set<number>();\n for await (const response_chunk of stream) {\n if (cancellation.is_cancellation_requested) {\n receiver.cancel();\n return;\n }\n receiver.stream_raw(response_chunk);\n\n const { candidates: candidates_chunk, ...rest } = response_chunk;\n response = {\n ...response,\n ...rest,\n candidates: response?.candidates ?? [],\n };\n const candidates = response.candidates as gemini.Candidate[];\n\n for (const candidate_chunk of candidates_chunk ?? []) {\n if (!candidates[candidate_chunk.index ?? 0]) {\n candidates[candidate_chunk.index ?? 0] = candidate_chunk;\n const message = from_gemini_content(candidate_chunk.content) as AssistantMessage;\n const usage = from_gemini_usage(response.usageMetadata);\n for (const content of message.content) {\n receiver.start_content({ content, message, usage });\n }\n receiver.start_message({ message, usage });\n continue;\n }\n const { content: content_chunk, ...rest } = candidate_chunk;\n const candidate = (candidates[candidate_chunk.index ?? 0] = {\n ...candidates[candidate_chunk.index ?? 0],\n ...rest,\n content: {\n ...candidates[candidate_chunk.index ?? 0]?.content,\n parts: candidates[candidate_chunk.index ?? 0]?.content?.parts ?? [],\n },\n });\n\n for (const part_chunk of content_chunk?.parts ?? []) {\n const [part] = candidate.content.parts.slice(-1);\n if (!part) {\n candidate.content.parts.push(part_chunk);\n receiver.start_content({\n message: from_gemini_content(candidate.content) as AssistantMessage,\n content: from_gemini_part(part_chunk) as AssistantContent,\n usage: from_gemini_usage(response.usageMetadata),\n });\n receiver.update_message({\n message: from_gemini_content(candidate.content) as AssistantMessage,\n usage: from_gemini_usage(response?.usageMetadata),\n });\n } else {\n if (part_chunk.thought && part.thought) {\n part.text = (part.text ?? \"\") + (part_chunk.text ?? \"\");\n } else if (!part_chunk.thought && !part.thought && part_chunk.text && part.text) {\n part.text = (part.text ?? \"\") + (part_chunk.text ?? \"\");\n } else if (part_chunk.functionCall && part.functionCall) {\n part.functionCall = deep_merge(part.functionCall, part_chunk.functionCall);\n } else if (part_chunk.executableCode && part.executableCode) {\n if (part_chunk.executableCode.code && part.executableCode.code) {\n part.executableCode.code += part_chunk.executableCode.code;\n delete part_chunk.executableCode.code;\n }\n part.executableCode = deep_merge(part.executableCode, part_chunk.executableCode);\n } else if (part_chunk.videoMetadata && part.videoMetadata) {\n part.videoMetadata = deep_merge(part.videoMetadata, part_chunk.videoMetadata);\n } else if (part_chunk.fileData && part.fileData) {\n part.fileData = deep_merge(part.fileData, part_chunk.fileData);\n } else if (part_chunk.inlineData && part.inlineData) {\n part.inlineData = deep_merge(part.inlineData, part_chunk.inlineData);\n } else {\n receiver.complete_content({\n message: from_gemini_content(candidate.content) as AssistantMessage,\n content: from_gemini_part(part) as AssistantContent,\n usage: from_gemini_usage(response.usageMetadata),\n });\n completed_parts.add(candidate.content.parts.length - 1);\n candidate.content.parts.push(part_chunk);\n receiver.start_content({\n message: from_gemini_content(candidate.content) as AssistantMessage,\n content: from_gemini_part(part_chunk) as AssistantContent,\n usage: from_gemini_usage(response.usageMetadata),\n });\n receiver.update_message({\n message: from_gemini_content(candidate.content) as AssistantMessage,\n usage: from_gemini_usage(response?.usageMetadata),\n });\n continue;\n }\n receiver.update_content({\n message: from_gemini_content(candidate.content) as AssistantMessage,\n content: from_gemini_part(part) as AssistantContent,\n usage: from_gemini_usage(response.usageMetadata),\n });\n }\n }\n }\n }\n if (!response || !response.candidates?.[0]) {\n throw new Error(\"no data\", { cause: JSON.stringify(response?.promptFeedback ?? response) });\n }\n receiver.response_raw({ ...response });\n\n const message = from_gemini_content(response.candidates[0].content) as AssistantMessage;\n const usage = from_gemini_usage(response.usageMetadata);\n for (let i = 0; i < message.content.length; i++) {\n if (!completed_parts.has(i)) {\n receiver.complete_content({ content: message.content[i], message, usage });\n }\n }\n receiver.complete_message({ message, usage, ...map_stop_reason(response) });\n } catch (error) {\n receiver.error(error);\n }\n }\n}\n\nfunction to_gemini_tool(tool: ToolDefinition): gemini.FunctionDeclaration {\n return {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: gemini.Type.OBJECT,\n properties: undefined_if_empty(\n Object.fromEntries(\n tool.parameters.map((p) => [p.name, to_gemini_tool_schema(p, p.description)]),\n ),\n ),\n required: undefined_if_empty(tool.parameters.filter((p) => p.required).map((p) => p.name)),\n },\n };\n}\n\nfunction from_gemini_content(content?: gemini.Content) {\n if (!content) {\n return;\n }\n return {\n role: content.role === \"model\" ? \"assistant\" : \"user\",\n content: content.parts?.map((p: gemini.Part) => from_gemini_part(p)).filter(Boolean),\n };\n}\n\nfunction from_gemini_part(part: gemini.Part) {\n if (!part) {\n return;\n }\n if (part.thought) {\n return {\n type: \"thinking\",\n thought: part.text ?? \"\",\n };\n }\n if (part.text) {\n return {\n type: \"text\",\n text: part.text ?? \"\",\n };\n }\n if (part.functionCall) {\n return {\n type: \"tool\",\n tool_request_id: part.functionCall.id ?? crypto.randomUUID(),\n tool: part.functionCall.name ?? \"\",\n params: part.functionCall.args ?? {},\n };\n }\n if (part.functionResponse) {\n return {\n type: \"tool_result\",\n tool_request_id: part.functionResponse.id ?? \"\",\n tool: part.functionResponse.name ?? \"\",\n result: part.functionResponse.response ?? {},\n };\n }\n return {\n type: \"raw\",\n model_kind: \"google\",\n data: JSON.stringify(part),\n };\n}\n\nfunction to_gemini_content(message: Message): gemini.Content {\n return {\n role: message.role === \"assistant\" ? \"model\" : \"user\",\n parts: message.content.map((c) => to_gemini_part(c)),\n };\n}\n\nfunction to_gemini_part(content: Readonly<Content>) {\n switch (content.type) {\n case \"text\":\n return {\n text: content.text,\n };\n case \"tool\":\n return {\n functionCall: {\n id: content.tool_request_id,\n name: content.tool,\n args: content.params,\n },\n };\n case \"raw\":\n if (content.model_kind === \"google\") {\n try {\n return {\n ...JSON.parse(content.data),\n };\n } catch {\n return {\n text: content.data,\n };\n }\n }\n return {\n text: content.data,\n };\n case \"tool_result\":\n return {\n functionResponse: {\n id: content.tool_request_id,\n name: content.tool,\n response: content.result,\n },\n };\n case \"thinking\":\n return {\n thought: true,\n text: content.thought,\n };\n default:\n throw new Error(\"unexpected content type\");\n }\n}\n\nfunction to_gemini_tool_schema(parameter_type: ParameterType, description?: string): gemini.Schema {\n switch (parameter_type.type) {\n case \"string\":\n return {\n type: gemini.Type.STRING,\n description,\n enum: (parameter_type as EnumParameterType).enum,\n default: !parameter_type.required ? parameter_type.default : undefined,\n };\n case \"number\":\n return {\n type: gemini.Type.NUMBER,\n description,\n default: !parameter_type.required ? parameter_type.default : undefined,\n };\n case \"boolean\":\n return {\n type: gemini.Type.BOOLEAN,\n description,\n default: !parameter_type.required ? parameter_type.default : undefined,\n };\n case \"object\":\n return {\n type: gemini.Type.OBJECT,\n description,\n properties: Object.fromEntries(\n Object.entries(parameter_type.properties).map(([name, p]) => [\n name,\n to_gemini_tool_schema(p, p.description),\n ]),\n ),\n required: undefined_if_empty(\n Object.entries(parameter_type.properties)\n .filter(([, p]) => p.required)\n .map(([name]) => name),\n ),\n };\n case \"array\":\n return {\n type: gemini.Type.ARRAY,\n description,\n items: to_gemini_tool_schema(parameter_type.items, parameter_type.items.description),\n };\n }\n}\n\nfunction from_gemini_usage(usage: gemini.GenerateContentResponseUsageMetadata | undefined) {\n return {\n cache_read_input_tokens: usage?.cachedContentTokenCount,\n input_tokens: usage?.promptTokenCount,\n output_tokens: usage?.candidatesTokenCount,\n };\n}\n\nfunction map_stop_reason(\n response: Partial<gemini.GenerateContentResponse>,\n): Pick<CompletionResponseData, \"stop_reason\" | \"stop_details\"> {\n for (const { finishReason, finishMessage } of response?.candidates ?? []) {\n switch (finishReason) {\n case gemini.FinishReason.STOP:\n if (response.candidates?.[0].content?.parts?.some((p: gemini.Part) => !!p.functionCall)) {\n return {\n stop_reason: \"tool_use\",\n stop_details: finishMessage,\n };\n } else {\n return {\n stop_reason: \"end_turn\",\n stop_details: finishMessage,\n };\n }\n case gemini.FinishReason.MAX_TOKENS:\n return {\n stop_reason: \"max_tokens\",\n stop_details: finishMessage,\n };\n case gemini.FinishReason.MALFORMED_FUNCTION_CALL:\n return {\n stop_reason: \"error\",\n stop_details: finishMessage,\n };\n case gemini.FinishReason.FINISH_REASON_UNSPECIFIED:\n case gemini.FinishReason.SAFETY:\n case gemini.FinishReason.RECITATION:\n case gemini.FinishReason.LANGUAGE:\n case gemini.FinishReason.BLOCKLIST:\n case gemini.FinishReason.PROHIBITED_CONTENT:\n case gemini.FinishReason.SPII:\n case gemini.FinishReason.IMAGE_SAFETY:\n }\n }\n return {\n stop_reason: \"other\",\n };\n}\n","import crypto from \"node:crypto\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n ProviderContextTransformer,\n TextContent,\n ToolContent,\n} from \"@simulacra-ai/core\";\n\n/**\n * Provider context transformer that extracts tool calls from Gemini's code execution blocks.\n *\n * Gemini models sometimes return tool calls as executable code in markdown code blocks\n * tagged with \"tool_code\". This transformer parses those blocks and converts them into\n * standard tool call content that the framework can execute.\n */\nexport class GoogleToolCodeContextTransformer implements ProviderContextTransformer {\n /**\n * Transforms completion messages by extracting tool calls from code blocks.\n *\n * Scans text content for code blocks tagged as \"tool_code\" and parses them into\n * proper tool call content. The original code blocks are replaced with newlines\n * in the text content.\n *\n * @param message - The completion message to transform.\n * @returns A promise resolving to the transformed message.\n */\n transform_completion(message: AssistantMessage) {\n if (message.role !== \"assistant\") {\n return Promise.resolve(message);\n }\n\n return Promise.resolve({\n ...message,\n content: message.content.flatMap((c) => {\n if (c.type !== \"text\") {\n return [c];\n }\n return this.extract_tool_calls(c);\n }),\n });\n }\n\n private extract_tool_calls(content: TextContent) {\n const tool_calls: ToolContent[] = [];\n const remaining_text = content.text.replaceAll(\n /```(?:tool_code)\\n(.*?)\\n```/gs,\n (_, tool_code) => {\n const tool_call = this.parse_tool_call(content, tool_code);\n if (tool_call) {\n tool_calls.push(tool_call);\n }\n return \"\\n\";\n },\n );\n\n return [{ ...content, text: remaining_text }, ...tool_calls] as AssistantContent[];\n }\n\n private parse_tool_call(content: AssistantContent, tool_code?: string) {\n const function_match = tool_code?.match(/^print\\((\\w+)\\((.*)\\)\\)$/);\n if (!function_match) {\n return;\n }\n const [_, name, params_text] = function_match;\n const params = Object.fromEntries(\n Array.from(\n params_text.matchAll(\n /(\\w+)\\s*=\\s*((\"(?:\\\\\"|[^\"])*\")|(-?[\\d.]+)|([Tt]rue|[Ff]alse))\\s*(,|$)/g,\n ),\n ).map(([_match, key, _full, str, num, bool]: string[]) => {\n if (bool !== undefined) {\n return [key, bool.toLocaleLowerCase() === \"true\"];\n }\n if (!isNaN(Number(num))) {\n return [key, Number(num)];\n }\n try {\n return [key, JSON.parse(str)];\n } catch {\n return [key, str];\n }\n }),\n );\n\n return {\n type: \"tool\",\n tool_request_id: content.id ?? crypto.randomUUID(),\n tool: name,\n params: params,\n } as ToolContent;\n }\n}\n"],"mappings":"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","names":["crypto","message","usage","rest","crypto"]}
|
package/package.json
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simulacra-ai/google",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Google Gemini provider for the Simulacra conversation engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
|
-
"
|
|
9
|
-
|
|
8
|
+
"require": {
|
|
9
|
+
"types": "./dist/index.d.cts",
|
|
10
|
+
"default": "./dist/index.cjs"
|
|
11
|
+
},
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
10
16
|
}
|
|
11
17
|
},
|
|
12
18
|
"files": [
|
|
13
19
|
"dist"
|
|
14
20
|
],
|
|
15
21
|
"scripts": {
|
|
16
|
-
"build": "
|
|
22
|
+
"build": "tsup",
|
|
17
23
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
18
24
|
},
|
|
19
25
|
"peerDependencies": {
|
|
20
|
-
"@simulacra-ai/core": "0.0.
|
|
26
|
+
"@simulacra-ai/core": "0.0.4",
|
|
21
27
|
"@google/genai": ">=0.10.0 <2.0.0"
|
|
22
28
|
},
|
|
23
29
|
"repository": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"google-provider.d.ts","sourceRoot":"","sources":["../src/google-provider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAGV,iBAAiB,EAKjB,aAAa,EACb,YAAY,EAEZ,0BAA0B,EAC1B,cAAc,EAEf,MAAM,oBAAoB,CAAC;AAI5B;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,QAAQ,CAAC,EAAE;QACT,2CAA2C;QAC3C,MAAM,EAAE,OAAO,CAAC;QAChB,+CAA+C;QAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,aAAa;;IAIlD,QAAQ,CAAC,oBAAoB,EAAE,0BAA0B,EAAE,CAAC;IAE5D;;;;;;OAMG;gBAED,GAAG,EAAE,MAAM,CAAC,WAAW,EACvB,MAAM,EAAE,oBAAoB,EAC5B,oBAAoB,GAAE,0BAA0B,EAA6C;IAO/F;;;;;;;OAOG;IACG,eAAe,CACnB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,cAAc,EACxB,YAAY,EAAE,iBAAiB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAwChB;;;;OAIG;IACH,KAAK,IAAI,aAAa;CA6HvB"}
|