graphlit-client 1.0.20260627002 → 1.0.20260628002

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.
@@ -6,6 +6,7 @@ export interface GooglePromptCache {
6
6
  entries: Map<string, string>;
7
7
  maxEntries?: number;
8
8
  }
9
+ export declare function buildGoogleTools(tools: ToolDefinitionInput[] | undefined): any[] | undefined;
9
10
  /**
10
11
  * Stream with OpenAI SDK
11
12
  */
@@ -44,35 +44,19 @@ function simplifySchemaForGroq(schema) {
44
44
  }
45
45
  return JSON.stringify(simplified);
46
46
  }
47
- /**
48
- * Clean schema for Google Gemini by removing unsupported fields
49
- */
50
- function cleanSchemaForGoogle(schema) {
51
- if (typeof schema !== "object" || schema === null) {
52
- return schema;
53
- }
54
- if (Array.isArray(schema)) {
55
- return schema.map((item) => cleanSchemaForGoogle(item));
56
- }
57
- const cleaned = {};
58
- for (const [key, value] of Object.entries(schema)) {
59
- // Skip fields that Google doesn't support
60
- if (key === "$schema" || key === "additionalProperties") {
61
- continue;
62
- }
63
- // Handle format field for string types - Google only supports 'enum' and 'date-time'
64
- if (key === "format" && typeof value === "string") {
65
- // Only keep supported formats
66
- if (value === "enum" || value === "date-time") {
67
- cleaned[key] = value;
68
- }
69
- // Skip unsupported formats like "date", "time", "email", etc.
70
- continue;
71
- }
72
- // Recursively clean nested objects
73
- cleaned[key] = cleanSchemaForGoogle(value);
47
+ export function buildGoogleTools(tools) {
48
+ if (!tools || tools.length === 0) {
49
+ return undefined;
74
50
  }
75
- return cleaned;
51
+ return [
52
+ {
53
+ functionDeclarations: tools.map((tool) => ({
54
+ name: tool.name,
55
+ description: tool.description,
56
+ parametersJsonSchema: tool.schema ? JSON.parse(tool.schema) : {},
57
+ })),
58
+ },
59
+ ];
76
60
  }
77
61
  function shortHash(value) {
78
62
  return createHash("sha256").update(value).digest("hex").slice(0, 16);
@@ -1084,36 +1068,7 @@ promptCache, onEvent, onComplete, abortSignal, thinkingConfig, toolConfig) {
1084
1068
  if (systemPrompt) {
1085
1069
  streamConfig.system = systemPrompt;
1086
1070
  }
1087
- // Add tools if provided
1088
- if (tools && tools.length > 0) {
1089
- streamConfig.tools = tools.map((tool) => ({
1090
- name: tool.name,
1091
- description: tool.description,
1092
- input_schema: tool.schema ? JSON.parse(tool.schema) : {},
1093
- }));
1094
- }
1095
- // Configure tools for Google - expects a single array of function declarations
1096
- const googleTools = tools && tools.length > 0
1097
- ? [
1098
- {
1099
- functionDeclarations: tools.map((tool) => {
1100
- const rawSchema = tool.schema ? JSON.parse(tool.schema) : {};
1101
- const cleanedSchema = cleanSchemaForGoogle(rawSchema);
1102
- if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
1103
- const hadCleanup = JSON.stringify(rawSchema) !== JSON.stringify(cleanedSchema);
1104
- if (hadCleanup) {
1105
- console.log(`[Google] Cleaned schema for tool ${tool.name} - removed unsupported fields`);
1106
- }
1107
- }
1108
- return {
1109
- name: tool.name,
1110
- description: tool.description,
1111
- parameters: cleanedSchema,
1112
- };
1113
- }),
1114
- },
1115
- ]
1116
- : undefined;
1071
+ const googleTools = buildGoogleTools(tools);
1117
1072
  // Add thinking configuration if provided
1118
1073
  // Note: Google's thinking API is still in preview and may require specific model support
1119
1074
  const generationConfig = {
@@ -1155,10 +1110,18 @@ promptCache, onEvent, onComplete, abortSignal, thinkingConfig, toolConfig) {
1155
1110
  // Build the config object for the new SDK
1156
1111
  const config = {
1157
1112
  ...generationConfig,
1158
- ...(toolConfig ? { toolConfig } : {}),
1159
1113
  };
1160
1114
  const systemInstructionParts = getGoogleSystemInstructionParts(systemPrompt);
1161
- const stableCacheKey = promptCache && systemInstructionParts.length > 0
1115
+ // Google rejects any GenerateContent request that combines `cachedContent`
1116
+ // with request-level `system_instruction`, `tools`, or `tool_config`:
1117
+ // "CachedContent can not be used with GenerateContent request setting
1118
+ // system_instruction, tools or tool_config."
1119
+ // A forced tool choice (`toolConfig`) is a per-round directive — it cannot be
1120
+ // baked into the shared cache without breaking reuse across rounds — so when
1121
+ // it is present we skip the cache entirely and send the system instruction,
1122
+ // tools, and tool config inline instead.
1123
+ const canUseCache = !!promptCache && systemInstructionParts.length > 0 && !toolConfig;
1124
+ const stableCacheKey = canUseCache
1162
1125
  ? shortHash(JSON.stringify({
1163
1126
  model: modelName,
1164
1127
  systemInstructionParts,
@@ -1193,16 +1156,22 @@ promptCache, onEvent, onComplete, abortSignal, thinkingConfig, toolConfig) {
1193
1156
  }
1194
1157
  }
1195
1158
  if (cachedContentName) {
1159
+ // System instruction, tools, and tool config live inside the cache; sending
1160
+ // any of them at request level alongside `cachedContent` is a 400 from Google.
1196
1161
  config.cachedContent = cachedContentName;
1197
1162
  }
1198
- else if (systemInstructionParts.length > 0) {
1199
- config.systemInstruction = {
1200
- parts: systemInstructionParts.map((text) => ({ text })),
1201
- };
1202
- }
1203
- // Add tools to config if provided and not already attached to cachedContent.
1204
- if (googleTools && !cachedContentName) {
1205
- config.tools = googleTools;
1163
+ else {
1164
+ if (systemInstructionParts.length > 0) {
1165
+ config.systemInstruction = {
1166
+ parts: systemInstructionParts.map((text) => ({ text })),
1167
+ };
1168
+ }
1169
+ if (googleTools) {
1170
+ config.tools = googleTools;
1171
+ }
1172
+ if (toolConfig) {
1173
+ config.toolConfig = toolConfig;
1174
+ }
1206
1175
  }
1207
1176
  const createStreamResponse = () => googleClient.models.generateContentStream({
1208
1177
  model: modelName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphlit-client",
3
- "version": "1.0.20260627002",
3
+ "version": "1.0.20260628002",
4
4
  "description": "Graphlit API Client for TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/client.js",