@karixi/payload-ai 0.1.3 → 0.2.0

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 CHANGED
@@ -271,10 +271,10 @@ These tools are registered inside the MCP plugin and callable by any MCP client:
271
271
 
272
272
  ### Dev Tools (`features.devTools: true`)
273
273
 
274
- Requires `@anthropic-ai/stagehand` (optional peer dependency):
274
+ Requires `@browserbasehq/stagehand` (optional peer dependency):
275
275
 
276
276
  ```bash
277
- bun add -d @anthropic-ai/stagehand
277
+ bun add -d @browserbasehq/stagehand
278
278
  ```
279
279
 
280
280
  Adds four additional MCP tools:
@@ -3,9 +3,13 @@ import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
3
3
  function isAnthropicResponse(value) {
4
4
  return typeof value === "object" && value !== null && "content" in value && Array.isArray(value.content);
5
5
  }
6
- function createAnthropicProvider(apiKey) {
6
+ function createAnthropicProvider(configOrKey) {
7
+ const config = typeof configOrKey === "string" ? { apiKey: configOrKey } : configOrKey;
8
+ const apiKey = config.apiKey;
9
+ const model = config.model ?? "claude-sonnet-4-20250514";
10
+ const baseUrl = (config.baseUrl ?? "https://api.anthropic.com").replace(/\/+$/, "");
7
11
  async function callAPI(messages) {
8
- const response = await fetch("https://api.anthropic.com/v1/messages", {
12
+ const response = await fetch(`${baseUrl}/v1/messages`, {
9
13
  method: "POST",
10
14
  headers: {
11
15
  "x-api-key": apiKey,
@@ -13,7 +17,7 @@ function createAnthropicProvider(apiKey) {
13
17
  "content-type": "application/json"
14
18
  },
15
19
  body: JSON.stringify({
16
- model: "claude-sonnet-4-20250514",
20
+ model,
17
21
  max_tokens: 8192,
18
22
  messages
19
23
  })
@@ -209,14 +213,18 @@ function createOllamaProvider(config) {
209
213
  function isOpenAIResponse(value) {
210
214
  return typeof value === "object" && value !== null && "choices" in value && Array.isArray(value.choices);
211
215
  }
212
- function createOpenAIProvider(apiKey) {
216
+ function createOpenAIProvider(configOrKey) {
217
+ const config = typeof configOrKey === "string" ? { apiKey: configOrKey } : configOrKey;
218
+ const apiKey = config.apiKey;
219
+ const model = config.model ?? "gpt-4o";
220
+ const baseUrl = (config.baseUrl ?? "https://api.openai.com").replace(/\/+$/, "");
213
221
  async function callAPI(messages, jsonMode) {
214
222
  const body = {
215
- model: "gpt-4o",
223
+ model,
216
224
  messages
217
225
  };
218
226
  if (jsonMode) body.response_format = { type: "json_object" };
219
- const response = await fetch("https://api.openai.com/v1/chat/completions", {
227
+ const response = await fetch(`${baseUrl}/v1/chat/completions`, {
220
228
  method: "POST",
221
229
  headers: {
222
230
  Authorization: `Bearer ${apiKey}`,
@@ -273,8 +281,16 @@ function createOpenAIProvider(apiKey) {
273
281
  var base_exports = /* @__PURE__ */ __exportAll({ createProvider: () => createProvider });
274
282
  function createProvider(config) {
275
283
  switch (config.provider) {
276
- case "anthropic": return createAnthropicProvider(config.apiKey);
277
- case "openai": return createOpenAIProvider(config.apiKey);
284
+ case "anthropic": return createAnthropicProvider({
285
+ apiKey: config.apiKey,
286
+ model: config.model,
287
+ baseUrl: config.baseUrl
288
+ });
289
+ case "openai": return createOpenAIProvider({
290
+ apiKey: config.apiKey,
291
+ model: config.model,
292
+ baseUrl: config.baseUrl
293
+ });
278
294
  case "gemini": return createGeminiProvider({
279
295
  apiKey: config.apiKey,
280
296
  model: config.model,
@@ -294,4 +310,4 @@ function createProvider(config) {
294
310
  //#endregion
295
311
  export { createProvider as n, base_exports as t };
296
312
 
297
- //# sourceMappingURL=base-B4GYFuC6.mjs.map
313
+ //# sourceMappingURL=base-CWybHD_y.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-CWybHD_y.mjs","names":["detectMediaType"],"sources":["../src/core/providers/anthropic.ts","../src/core/providers/gemini.ts","../src/core/providers/ollama.ts","../src/core/providers/openai.ts","../src/core/providers/base.ts"],"sourcesContent":["import type { AIProvider } from '../../types.js'\n\ntype AnthropicMessage = {\n role: 'user' | 'assistant'\n content: string | AnthropicContentBlock[]\n}\n\ntype AnthropicContentBlock =\n | { type: 'text'; text: string }\n | { type: 'image'; source: { type: 'base64'; media_type: string; data: string } }\n\ntype AnthropicResponse = {\n content: Array<{ type: string; text?: string }>\n usage?: { input_tokens: number; output_tokens: number }\n}\n\nfunction isAnthropicResponse(value: unknown): value is AnthropicResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'content' in value &&\n Array.isArray((value as AnthropicResponse).content)\n )\n}\n\nexport type AnthropicProviderConfig = {\n apiKey: string\n model?: string\n baseUrl?: string\n}\n\nexport function createAnthropicProvider(configOrKey: AnthropicProviderConfig | string): AIProvider {\n const config: AnthropicProviderConfig =\n typeof configOrKey === 'string' ? { apiKey: configOrKey } : configOrKey\n const apiKey = config.apiKey\n const model = config.model ?? 'claude-sonnet-4-20250514'\n const baseUrl = (config.baseUrl ?? 'https://api.anthropic.com').replace(/\\/+$/, '')\n\n async function callAPI(messages: AnthropicMessage[]): Promise<AnthropicResponse> {\n const response = await fetch(`${baseUrl}/v1/messages`, {\n method: 'POST',\n headers: {\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n model,\n max_tokens: 8192,\n messages,\n }),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Anthropic API error ${response.status}: ${errorText}`)\n }\n\n const data: unknown = await response.json()\n if (!isAnthropicResponse(data)) {\n throw new Error('Unexpected Anthropic API response shape')\n }\n return data\n }\n\n return {\n async generate(prompt: string, _outputSchema: Record<string, unknown>): Promise<unknown[]> {\n const messages: AnthropicMessage[] = [\n {\n role: 'user',\n content: `${prompt}\\n\\nRespond with ONLY a valid JSON array. No markdown, no explanation, just the JSON array.`,\n },\n ]\n\n const data = await callAPI(messages)\n const textBlock = data.content.find((block) => block.type === 'text')\n if (!textBlock || !('text' in textBlock) || typeof textBlock.text !== 'string') {\n throw new Error('No text content in Anthropic response')\n }\n\n const text = textBlock.text.trim()\n // Strip markdown code fences if present\n const jsonText = text\n .replace(/^```(?:json)?\\s*/i, '')\n .replace(/\\s*```\\s*$/, '')\n .trim()\n\n const parsed: unknown = JSON.parse(jsonText)\n if (!Array.isArray(parsed)) {\n throw new Error('Anthropic response is not a JSON array')\n }\n return parsed\n },\n\n async analyzeImage(imageBuffer: Buffer): Promise<string> {\n const base64 = imageBuffer.toString('base64')\n // Detect image type from buffer magic bytes\n let mediaType = 'image/jpeg'\n if (imageBuffer[0] === 0x89 && imageBuffer[1] === 0x50) mediaType = 'image/png'\n else if (imageBuffer[0] === 0x47 && imageBuffer[1] === 0x49) mediaType = 'image/gif'\n else if (imageBuffer[0] === 0x52 && imageBuffer[1] === 0x49) mediaType = 'image/webp'\n\n const messages: AnthropicMessage[] = [\n {\n role: 'user',\n content: [\n {\n type: 'image',\n source: { type: 'base64', media_type: mediaType, data: base64 },\n },\n {\n type: 'text',\n text: 'Describe this image concisely for use as alt text. Focus on the main subject and important visual details. Respond with only the alt text description, no extra explanation.',\n },\n ],\n },\n ]\n\n const data = await callAPI(messages)\n const textBlock = data.content.find((block) => block.type === 'text')\n if (!textBlock || !('text' in textBlock) || typeof textBlock.text !== 'string') {\n throw new Error('No text content in Anthropic image analysis response')\n }\n return textBlock.text.trim()\n },\n }\n}\n","import type { AIProvider } from '../../types.js'\n\ntype GeminiPart = { text: string } | { inline_data: { mime_type: string; data: string } }\n\ntype GeminiContent = {\n role: 'user' | 'model'\n parts: GeminiPart[]\n}\n\ntype GeminiResponse = {\n candidates?: Array<{\n content: { parts: Array<{ text?: string }>; role: string }\n finishReason: string\n }>\n usageMetadata?: {\n promptTokenCount: number\n candidatesTokenCount: number\n totalTokenCount: number\n }\n promptFeedback?: { blockReason?: string }\n}\n\nfunction isGeminiResponse(value: unknown): value is GeminiResponse {\n return typeof value === 'object' && value !== null && 'candidates' in value\n}\n\nfunction detectMediaType(buffer: Buffer): string {\n if (buffer[0] === 0x89 && buffer[1] === 0x50) return 'image/png'\n if (buffer[0] === 0x47 && buffer[1] === 0x49) return 'image/gif'\n if (buffer[0] === 0x52 && buffer[1] === 0x49) return 'image/webp'\n return 'image/jpeg'\n}\n\nfunction extractText(response: GeminiResponse): string {\n if (!response.candidates || response.candidates.length === 0) {\n const reason = response.promptFeedback?.blockReason ?? 'unknown'\n throw new Error(`Gemini request blocked: ${reason}`)\n }\n\n const candidate = response.candidates[0]\n const text = candidate.content.parts.find((p) => 'text' in p)?.text\n if (!text) {\n throw new Error('No text content in Gemini response')\n }\n\n if (candidate.finishReason === 'MAX_TOKENS') {\n throw new Error('Gemini response truncated (MAX_TOKENS) — output may be incomplete')\n }\n\n return text.trim()\n}\n\nexport type GeminiProviderConfig = {\n apiKey: string\n model?: string\n baseUrl?: string\n}\n\nexport function createGeminiProvider(config: GeminiProviderConfig): AIProvider {\n const model = config.model ?? 'gemini-2.5-flash'\n const baseUrl = config.baseUrl ?? 'https://generativelanguage.googleapis.com/v1beta'\n\n async function callAPI(\n contents: GeminiContent[],\n systemInstruction?: string,\n jsonMode?: boolean,\n ): Promise<GeminiResponse> {\n const body: Record<string, unknown> = { contents }\n\n if (systemInstruction) {\n body.system_instruction = { parts: [{ text: systemInstruction }] }\n }\n\n if (jsonMode) {\n body.generationConfig = {\n responseMimeType: 'application/json',\n }\n }\n\n const url = `${baseUrl}/models/${model}:generateContent`\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'x-goog-api-key': config.apiKey,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Gemini API error ${response.status}: ${errorText}`)\n }\n\n const data: unknown = await response.json()\n if (!isGeminiResponse(data)) {\n throw new Error('Unexpected Gemini API response shape')\n }\n return data\n }\n\n return {\n async generate(prompt: string, _outputSchema: Record<string, unknown>): Promise<unknown[]> {\n const contents: GeminiContent[] = [\n {\n role: 'user',\n parts: [\n {\n text: `${prompt}\\n\\nRespond with ONLY a valid JSON array. No markdown, no explanation, just the JSON array.`,\n },\n ],\n },\n ]\n\n const data = await callAPI(\n contents,\n 'You are a data generation assistant. Always respond with valid JSON arrays only.',\n true,\n )\n\n const text = extractText(data)\n const jsonText = text\n .replace(/^```(?:json)?\\s*/i, '')\n .replace(/\\s*```\\s*$/, '')\n .trim()\n\n const parsed: unknown = JSON.parse(jsonText)\n if (Array.isArray(parsed)) {\n return parsed\n }\n if (typeof parsed === 'object' && parsed !== null && 'items' in parsed) {\n const items = (parsed as { items: unknown }).items\n if (Array.isArray(items)) return items\n }\n throw new Error('Gemini response is not a JSON array')\n },\n\n async analyzeImage(imageBuffer: Buffer): Promise<string> {\n const base64 = imageBuffer.toString('base64')\n const mimeType = detectMediaType(imageBuffer)\n\n const contents: GeminiContent[] = [\n {\n role: 'user',\n parts: [\n { inline_data: { mime_type: mimeType, data: base64 } },\n {\n text: 'Describe this image concisely for use as alt text. Focus on the main subject and important visual details. Respond with only the alt text description, no extra explanation.',\n },\n ],\n },\n ]\n\n const data = await callAPI(contents)\n return extractText(data)\n },\n }\n}\n","import type { AIProvider } from '../../types.js'\n\n/**\n * OpenAI-compatible provider for local LLM servers.\n * Works with: Ollama, LocalAI, vLLM, LM Studio, and any\n * server exposing an OpenAI-compatible /v1/chat/completions endpoint.\n */\n\ntype ChatMessage = {\n role: 'user' | 'assistant' | 'system'\n content: string | ContentBlock[]\n}\n\ntype ContentBlock =\n | { type: 'text'; text: string }\n | { type: 'image_url'; image_url: { url: string } }\n\ntype ChatResponse = {\n choices: Array<{\n message: { role: string; content: string | null }\n }>\n}\n\nfunction isChatResponse(value: unknown): value is ChatResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'choices' in value &&\n Array.isArray((value as ChatResponse).choices)\n )\n}\n\nfunction detectMediaType(buffer: Buffer): string {\n if (buffer[0] === 0x89 && buffer[1] === 0x50) return 'image/png'\n if (buffer[0] === 0x47 && buffer[1] === 0x49) return 'image/gif'\n if (buffer[0] === 0x52 && buffer[1] === 0x49) return 'image/webp'\n return 'image/jpeg'\n}\n\nexport type OllamaProviderConfig = {\n baseUrl?: string\n model?: string\n apiKey?: string\n}\n\nexport function createOllamaProvider(config: OllamaProviderConfig): AIProvider {\n const baseUrl = (config.baseUrl ?? 'http://localhost:11434').replace(/\\/+$/, '')\n const model = config.model ?? 'llama3.3:8b'\n const apiKey = config.apiKey ?? 'ollama'\n\n async function callAPI(messages: ChatMessage[], jsonMode: boolean): Promise<ChatResponse> {\n const body: Record<string, unknown> = { model, messages }\n if (jsonMode) {\n body.response_format = { type: 'json_object' }\n }\n\n const response = await fetch(`${baseUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Ollama API error ${response.status}: ${errorText}`)\n }\n\n const data: unknown = await response.json()\n if (!isChatResponse(data)) {\n throw new Error('Unexpected API response shape from local LLM server')\n }\n return data\n }\n\n return {\n async generate(prompt: string, _outputSchema: Record<string, unknown>): Promise<unknown[]> {\n const messages: ChatMessage[] = [\n {\n role: 'system',\n content:\n 'You are a data generation assistant. Always respond with valid JSON only. When asked for an array, wrap it in {\"items\": [...]} so json_object mode is satisfied.',\n },\n {\n role: 'user',\n content: `${prompt}\\n\\nRespond with JSON object {\"items\": [...]} where items is the array of generated documents.`,\n },\n ]\n\n const data = await callAPI(messages, true)\n const choice = data.choices[0]\n if (!choice || choice.message.content === null) {\n throw new Error('No content in response from local LLM server')\n }\n\n const parsed: unknown = JSON.parse(choice.message.content)\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'items' in parsed &&\n Array.isArray((parsed as { items: unknown }).items)\n ) {\n return (parsed as { items: unknown[] }).items\n }\n if (Array.isArray(parsed)) {\n return parsed\n }\n throw new Error('Local LLM response is not a JSON array')\n },\n\n async analyzeImage(imageBuffer: Buffer): Promise<string> {\n const base64 = imageBuffer.toString('base64')\n const mediaType = detectMediaType(imageBuffer)\n const dataUrl = `data:${mediaType};base64,${base64}`\n\n const messages: ChatMessage[] = [\n {\n role: 'user',\n content: [\n { type: 'image_url', image_url: { url: dataUrl } },\n {\n type: 'text',\n text: 'Describe this image concisely for use as alt text. Focus on the main subject and important visual details. Respond with only the alt text description, no extra explanation.',\n },\n ],\n },\n ]\n\n const data = await callAPI(messages, false)\n const choice = data.choices[0]\n if (!choice || choice.message.content === null) {\n throw new Error('No content in image analysis response from local LLM server')\n }\n return (choice.message.content as string).trim()\n },\n }\n}\n","import type { AIProvider } from '../../types.js'\n\ntype OpenAIMessage = {\n role: 'user' | 'assistant' | 'system'\n content: string | OpenAIContentBlock[]\n}\n\ntype OpenAIContentBlock =\n | { type: 'text'; text: string }\n | { type: 'image_url'; image_url: { url: string } }\n\ntype OpenAIResponse = {\n choices: Array<{\n message: { role: string; content: string | null }\n }>\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number }\n}\n\nfunction isOpenAIResponse(value: unknown): value is OpenAIResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'choices' in value &&\n Array.isArray((value as OpenAIResponse).choices)\n )\n}\n\nexport type OpenAIProviderConfig = {\n apiKey: string\n model?: string\n baseUrl?: string\n}\n\nexport function createOpenAIProvider(configOrKey: OpenAIProviderConfig | string): AIProvider {\n const config: OpenAIProviderConfig =\n typeof configOrKey === 'string' ? { apiKey: configOrKey } : configOrKey\n const apiKey = config.apiKey\n const model = config.model ?? 'gpt-4o'\n const baseUrl = (config.baseUrl ?? 'https://api.openai.com').replace(/\\/+$/, '')\n\n async function callAPI(messages: OpenAIMessage[], jsonMode: boolean): Promise<OpenAIResponse> {\n const body: Record<string, unknown> = {\n model,\n messages,\n }\n if (jsonMode) {\n body.response_format = { type: 'json_object' }\n }\n\n const response = await fetch(`${baseUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`OpenAI API error ${response.status}: ${errorText}`)\n }\n\n const data: unknown = await response.json()\n if (!isOpenAIResponse(data)) {\n throw new Error('Unexpected OpenAI API response shape')\n }\n return data\n }\n\n return {\n async generate(prompt: string, _outputSchema: Record<string, unknown>): Promise<unknown[]> {\n const messages: OpenAIMessage[] = [\n {\n role: 'system',\n content:\n 'You are a data generation assistant. Always respond with valid JSON only. When asked for an array, wrap it in {\"items\": [...]} so json_object mode is satisfied.',\n },\n {\n role: 'user',\n content: `${prompt}\\n\\nRespond with JSON object {\"items\": [...]} where items is the array of generated documents.`,\n },\n ]\n\n const data = await callAPI(messages, true)\n const choice = data.choices[0]\n if (!choice || choice.message.content === null) {\n throw new Error('No content in OpenAI response')\n }\n\n const parsed: unknown = JSON.parse(choice.message.content)\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'items' in parsed &&\n Array.isArray((parsed as { items: unknown }).items)\n ) {\n return (parsed as { items: unknown[] }).items\n }\n if (Array.isArray(parsed)) {\n return parsed\n }\n throw new Error('OpenAI response is not a JSON array')\n },\n\n async analyzeImage(imageBuffer: Buffer): Promise<string> {\n const base64 = imageBuffer.toString('base64')\n // Detect image type from buffer magic bytes\n let mediaType = 'image/jpeg'\n if (imageBuffer[0] === 0x89 && imageBuffer[1] === 0x50) mediaType = 'image/png'\n else if (imageBuffer[0] === 0x47 && imageBuffer[1] === 0x49) mediaType = 'image/gif'\n else if (imageBuffer[0] === 0x52 && imageBuffer[1] === 0x49) mediaType = 'image/webp'\n\n const dataUrl = `data:${mediaType};base64,${base64}`\n\n const messages: OpenAIMessage[] = [\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: { url: dataUrl },\n },\n {\n type: 'text',\n text: 'Describe this image concisely for use as alt text. Focus on the main subject and important visual details. Respond with only the alt text description, no extra explanation.',\n },\n ],\n },\n ]\n\n const data = await callAPI(messages, false)\n const choice = data.choices[0]\n if (!choice || choice.message.content === null) {\n throw new Error('No content in OpenAI image analysis response')\n }\n return choice.message.content.trim()\n },\n }\n}\n","import type { AIProvider } from '../../types.js'\nimport { createAnthropicProvider } from './anthropic.js'\nimport { createGeminiProvider } from './gemini.js'\nimport { createOllamaProvider } from './ollama.js'\nimport { createOpenAIProvider } from './openai.js'\n\nexport type { AIProvider }\n\nexport type ProviderConfig = {\n provider: 'anthropic' | 'openai' | 'gemini' | 'ollama'\n apiKey: string\n baseUrl?: string\n model?: string\n}\n\nexport function createProvider(config: ProviderConfig): AIProvider {\n switch (config.provider) {\n case 'anthropic':\n return createAnthropicProvider({\n apiKey: config.apiKey,\n model: config.model,\n baseUrl: config.baseUrl,\n })\n case 'openai':\n return createOpenAIProvider({\n apiKey: config.apiKey,\n model: config.model,\n baseUrl: config.baseUrl,\n })\n case 'gemini':\n return createGeminiProvider({\n apiKey: config.apiKey,\n model: config.model,\n baseUrl: config.baseUrl,\n })\n case 'ollama':\n return createOllamaProvider({\n baseUrl: config.baseUrl,\n model: config.model,\n apiKey: config.apiKey,\n })\n default: {\n const _exhaustive: never = config.provider\n throw new Error(`Unknown provider: ${String(_exhaustive)}`)\n }\n }\n}\n"],"mappings":"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"}