{"version":3,"sources":["../../src/providers/google.ts","../../src/providers/utils.ts"],"sourcesContent":["import type { ReforgeProvider, Message, ProviderCallOptions } from \"./types.js\";\r\nimport { getMessageText } from \"./utils.js\";\r\n\r\nexport interface GoogleCallOptions extends ProviderCallOptions {\r\n  generationConfig?: Record<string, unknown>;\r\n  safetySettings?: unknown[];\r\n  systemInstruction?: { role?: string; parts?: Array<{ text: string }> };\r\n  modelOptions?: Record<string, unknown>;\r\n  chatOptions?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Minimal subset of the Google Generative AI client used by the adapter.\r\n */\r\ninterface GoogleGenerativeAIClient {\r\n  getGenerativeModel(params: Record<string, unknown>): {\r\n    startChat(params: Record<string, unknown>): {\r\n      sendMessage(\r\n        message: unknown,\r\n      ): Promise<{ response: { text(): string } }>;\r\n    };\r\n  };\r\n}\r\n\r\ntype GeminiPart =\r\n  | { text: string }\r\n  | { functionCall: { name: string; args: unknown } }\r\n  | { functionResponse: { name: string; response: unknown } };\r\n\r\nfunction toGeminiTextParts(message: Message): GeminiPart[] {\r\n  if (typeof message.content === \"string\") {\r\n    return [{ text: message.content }];\r\n  }\r\n\r\n  const parts: GeminiPart[] = [];\r\n  for (const block of message.content) {\r\n    if (block.type === \"text\") {\r\n      parts.push({ text: block.text });\r\n    } else {\r\n      parts.push({ text: `[image_url:${block.image_url.url}]` });\r\n    }\r\n  }\r\n\r\n  return parts.length > 0 ? parts : [{ text: \"\" }];\r\n}\r\n\r\nfunction parseToolArguments(raw: string): unknown {\r\n  try {\r\n    return JSON.parse(raw);\r\n  } catch {\r\n    return { raw };\r\n  }\r\n}\r\n\r\nfunction toGeminiParts(message: Message): GeminiPart[] {\r\n  const parts = toGeminiTextParts(message);\r\n\r\n  if (message.toolCalls && message.toolCalls.length > 0) {\r\n    for (const toolCall of message.toolCalls) {\r\n      parts.push({\r\n        functionCall: {\r\n          name: toolCall.name,\r\n          args: parseToolArguments(toolCall.arguments),\r\n        },\r\n      });\r\n    }\r\n  }\r\n\r\n  if (message.toolResponse) {\r\n    parts.push({\r\n      functionResponse: {\r\n        name: message.toolResponse.name,\r\n        response: {\r\n          toolCallId: message.toolResponse.toolCallId,\r\n          content: getMessageText({ role: \"tool\", content: message.toolResponse.content }),\r\n          isError: message.toolResponse.isError ?? false,\r\n        },\r\n      },\r\n    });\r\n  }\r\n\r\n  return parts;\r\n}\r\n\r\n/**\r\n * Create a `ReforgeProvider` for Google Gemini / Vertex AI.\r\n *\r\n * Only needed for **direct** Google AI access via the `@google/generative-ai`\r\n * SDK. If you're using Gemini through an OpenAI-compatible proxy, use\r\n * `openaiCompatible()` instead.\r\n *\r\n * @param client - A `GoogleGenerativeAI` instance (from `@google/generative-ai`).\r\n * @param model  - The model identifier (e.g. `\"gemini-2.0-flash\"`).\r\n * @returns A `ReforgeProvider` ready to use with `forge()`.\r\n *\r\n * @example\r\n * ```ts\r\n * import { GoogleGenerativeAI } from '@google/generative-ai';\r\n * import { google } from 'reforge-ai/google';\r\n *\r\n * const client = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);\r\n * const provider = google(client, 'gemini-2.0-flash');\r\n * ```\r\n */\r\nexport function google(\r\n  client: GoogleGenerativeAIClient,\r\n  model: string,\r\n): ReforgeProvider<GoogleCallOptions> {\r\n  return {\r\n    id: `google:${model}`,\r\n    async call(\r\n      messages: Message[],\r\n      options?: GoogleCallOptions,\r\n    ): Promise<string> {\r\n      const generationConfig =\r\n        options?.generationConfig && typeof options.generationConfig === \"object\"\r\n          ? (options.generationConfig as Record<string, unknown>)\r\n          : undefined;\r\n      const modelOptions =\r\n        options?.modelOptions && typeof options.modelOptions === \"object\"\r\n          ? (options.modelOptions as Record<string, unknown>)\r\n          : undefined;\r\n\r\n      const genModel = client.getGenerativeModel({\r\n        model,\r\n        ...(generationConfig ? { generationConfig } : {}),\r\n        ...(Array.isArray(options?.safetySettings)\r\n          ? { safetySettings: options.safetySettings }\r\n          : {}),\r\n        ...(modelOptions ?? {}),\r\n      });\r\n\r\n      // Convert messages to Gemini format\r\n      const systemMessages = messages\r\n        .filter((m) => m.role === \"system\")\r\n        .map((m) => getMessageText(m));\r\n      const nonSystemMsgs = messages.filter((m) => m.role !== \"system\");\r\n\r\n      const history = nonSystemMsgs.slice(0, -1).map((m) => ({\r\n        role: m.role === \"assistant\" ? \"model\" : \"user\",\r\n        parts: toGeminiParts(m),\r\n      }));\r\n\r\n      const lastMsg = nonSystemMsgs[nonSystemMsgs.length - 1];\r\n      if (!lastMsg) {\r\n        throw new Error(\"No user message provided\");\r\n      }\r\n\r\n      const chat = genModel.startChat({\r\n        history,\r\n        ...(options?.chatOptions && typeof options.chatOptions === \"object\"\r\n          ? (options.chatOptions as Record<string, unknown>)\r\n          : {}),\r\n        systemInstruction: options?.systemInstruction ??\r\n          (systemMessages.length > 0\r\n            ? {\r\n                role: \"user\",\r\n                parts: [{ text: systemMessages.join(\"\\n\\n\") }],\r\n              }\r\n            : undefined),\r\n      });\r\n\r\n      const lastParts = toGeminiParts(lastMsg);\r\n      const sendPayload =\r\n        lastParts.length === 1 && \"text\" in lastParts[0]!\r\n          ? lastParts[0]!.text\r\n          : lastParts;\r\n      const result = await chat.sendMessage(sendPayload);\r\n      const text = result.response.text();\r\n      if (!text) {\r\n        throw new Error(\"Google returned an empty response\");\r\n      }\r\n      return text;\r\n    },\r\n  };\r\n}\r\n","import type {\r\n  ProviderCallOptions,\r\n  Message,\r\n  MessageContent,\r\n  MessageContentBlock,\r\n  MessageImageUrlBlock,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Keys managed by Reforge that should not be spread into the\r\n * provider-specific options object (they are mapped explicitly).\r\n */\r\nconst REFORGE_KEYS = new Set<string>([]);\r\n\r\n/**\r\n * Strip Reforge-managed keys from a `ProviderCallOptions` object so\r\n * they aren't double-sent when spreading into provider SDK calls.\r\n *\r\n * Returns a plain object with only the pass-through keys, or\r\n * `undefined` if there's nothing left.\r\n */\r\nexport function filterReforgeKeys(\r\n  options?: ProviderCallOptions,\r\n): Record<string, unknown> | undefined {\r\n  if (!options) return undefined;\r\n\r\n  const filtered: Record<string, unknown> = {};\r\n  let hasKeys = false;\r\n\r\n  for (const key of Object.keys(options)) {\r\n    if (!REFORGE_KEYS.has(key)) {\r\n      filtered[key] = options[key];\r\n      hasKeys = true;\r\n    }\r\n  }\r\n\r\n  return hasKeys ? filtered : undefined;\r\n}\r\n\r\nfunction isImageBlock(block: MessageContentBlock): block is MessageImageUrlBlock {\r\n  return block.type === \"image_url\";\r\n}\r\n\r\n/**\r\n * Convert message content into plain text for providers that do not support\r\n * image/message blocks in their input shape.\r\n */\r\nexport function messageContentToText(content: MessageContent): string {\r\n  if (typeof content === \"string\") {\r\n    return content;\r\n  }\r\n\r\n  const parts: string[] = [];\r\n  for (const block of content) {\r\n    if (block.type === \"text\") {\r\n      parts.push(block.text);\r\n      continue;\r\n    }\r\n\r\n    if (isImageBlock(block)) {\r\n      parts.push(`[image_url:${block.image_url.url}]`);\r\n    }\r\n  }\r\n\r\n  return parts.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Extract only text blocks from a message for providers with text-only system\r\n * channels.\r\n */\r\nexport function getMessageText(message: Message): string {\r\n  return messageContentToText(message.content);\r\n}\r\n"],"mappings":"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","names":[]}