@quilltap/plugin-utils 1.2.2 → 1.2.3
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/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -6
- package/dist/index.mjs.map +1 -1
- package/dist/tools/index.d.mts +20 -10
- package/dist/tools/index.d.ts +20 -10
- package/dist/tools/index.js +12 -6
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/index.mjs +10 -6
- package/dist/tools/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/tools/index.ts","../../src/tools/parsers.ts","../../src/tools/converters.ts"],"sourcesContent":["/**\n * Tool Utilities\n *\n * Exports all tool-related utilities for parsing and converting\n * tool calls between different LLM provider formats.\n *\n * @module @quilltap/plugin-utils/tools\n */\n\n// Re-export types\nexport type {\n OpenAIToolDefinition,\n UniversalTool,\n AnthropicToolDefinition,\n GoogleToolDefinition,\n ToolCall,\n ToolCallRequest,\n ToolResult,\n ToolFormatOptions,\n} from './types';\n\n// Export parsers\nexport {\n parseToolCalls,\n parseOpenAIToolCalls,\n parseAnthropicToolCalls,\n parseGoogleToolCalls,\n detectToolCallFormat,\n hasToolCalls,\n} from './parsers';\n\nexport type { ToolCallFormat } from './parsers';\n\n// Export converters\nexport {\n convertToAnthropicFormat,\n convertToGoogleFormat,\n convertFromAnthropicFormat,\n convertFromGoogleFormat,\n convertToolTo,\n convertToolsTo,\n applyDescriptionLimit,\n} from './converters';\n\nexport type { ToolConvertTarget } from './converters';\n","/**\n * Tool Call Parsers\n *\n * Provider-specific parsers for extracting tool calls from LLM responses.\n * Each parser converts from a provider's native format to the standardized\n * ToolCallRequest format.\n *\n * @module @quilltap/plugin-utils/tools/parsers\n */\n\nimport type { ToolCallRequest } from '@quilltap/plugin-types';\n\n/**\n * Supported tool call response formats\n */\nexport type ToolCallFormat = 'openai' | 'anthropic' | 'google' | 'auto';\n\n/**\n * Parse OpenAI format tool calls from LLM response\n *\n * Extracts tool calls from OpenAI/Grok API responses which return\n * tool_calls in the message object.\n *\n * Expected response structures:\n * - `response.tool_calls` (direct)\n * - `response.choices[0].message.tool_calls` (nested)\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await openai.chat.completions.create({...});\n * const toolCalls = parseOpenAIToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseOpenAIToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n // Handle direct tool_calls array (snake_case)\n let toolCallsArray = resp?.tool_calls as unknown[] | undefined;\n\n // Handle direct toolCalls array (camelCase - some SDKs use this)\n if (!toolCallsArray) {\n toolCallsArray = (resp as Record<string, unknown>)?.toolCalls as unknown[] | undefined;\n }\n\n // Check nested structure from non-streaming responses: choices[0].message.tool_calls\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ message?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls;\n }\n\n // Check nested structure from streaming responses: choices[0].delta.toolCalls\n // OpenRouter SDK uses camelCase and puts tool calls in delta for streaming\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls;\n }\n\n if (toolCallsArray && Array.isArray(toolCallsArray) && toolCallsArray.length > 0) {\n for (const toolCall of toolCallsArray) {\n const tc = toolCall as {\n type?: string;\n function?: { name: string; arguments: string };\n };\n\n if (tc.type === 'function' && tc.function) {\n toolCalls.push({\n name: tc.function.name,\n arguments: JSON.parse(tc.function.arguments || '{}'),\n });\n }\n }\n }\n } catch (error) {\n // Log error but don't throw - return empty array\n console.error('[plugin-utils] Error parsing OpenAI tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Anthropic format tool calls from LLM response\n *\n * Extracts tool calls from Anthropic API responses which return\n * tool_use blocks in the content array.\n *\n * Expected response structure:\n * - `response.content` array with `{ type: 'tool_use', name, input }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await anthropic.messages.create({...});\n * const toolCalls = parseAnthropicToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseAnthropicToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n if (!resp?.content || !Array.isArray(resp.content)) {\n return toolCalls;\n }\n\n for (const block of resp.content) {\n const b = block as { type?: string; name?: string; input?: Record<string, unknown> };\n\n if (b.type === 'tool_use' && b.name) {\n toolCalls.push({\n name: b.name,\n arguments: b.input || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Anthropic tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Google Gemini format tool calls from LLM response\n *\n * Extracts tool calls from Google Gemini API responses which return\n * functionCall objects in the parts array.\n *\n * Expected response structure:\n * - `response.candidates[0].content.parts` array with `{ functionCall: { name, args } }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await gemini.generateContent({...});\n * const toolCalls = parseGoogleToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseGoogleToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n const candidates = resp?.candidates as\n | Array<{ content?: { parts?: unknown[] } }>\n | undefined;\n const parts = candidates?.[0]?.content?.parts;\n\n if (!parts || !Array.isArray(parts)) {\n return toolCalls;\n }\n\n for (const part of parts) {\n const p = part as {\n functionCall?: { name: string; args?: Record<string, unknown> };\n };\n\n if (p.functionCall) {\n toolCalls.push({\n name: p.functionCall.name,\n arguments: p.functionCall.args || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Google tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Detect the format of a tool call response\n *\n * Analyzes the response structure to determine which provider format it uses.\n *\n * @param response - The raw response from a provider API\n * @returns The detected format, or null if unrecognized\n */\nexport function detectToolCallFormat(response: unknown): ToolCallFormat | null {\n if (!response || typeof response !== 'object') {\n return null;\n }\n\n const resp = response as Record<string, unknown>;\n\n // OpenAI format: has tool_calls/toolCalls directly or in choices[0].message or choices[0].delta\n if (resp.tool_calls && Array.isArray(resp.tool_calls)) {\n return 'openai';\n }\n if (resp.toolCalls && Array.isArray(resp.toolCalls)) {\n return 'openai';\n }\n\n const choices = resp.choices as Array<{\n message?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n }> | undefined;\n if (choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls) {\n return 'openai';\n }\n // Check delta for streaming responses (OpenRouter SDK uses this)\n if (choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls) {\n return 'openai';\n }\n\n // Anthropic format: has content array with tool_use type\n if (resp.content && Array.isArray(resp.content)) {\n const hasToolUse = (resp.content as Array<{ type?: string }>).some(\n (block) => block.type === 'tool_use'\n );\n if (hasToolUse) {\n return 'anthropic';\n }\n }\n\n // Google format: has candidates[0].content.parts with functionCall\n const candidates = resp.candidates as\n | Array<{ content?: { parts?: Array<{ functionCall?: unknown }> } }>\n | undefined;\n if (candidates?.[0]?.content?.parts) {\n const hasFunctionCall = candidates[0].content.parts.some((part) => part.functionCall);\n if (hasFunctionCall) {\n return 'google';\n }\n }\n\n return null;\n}\n\n/**\n * Parse tool calls with auto-detection or explicit format\n *\n * A unified parser that can either auto-detect the response format\n * or use a specified format. This is useful when you're not sure\n * which provider's response you're handling.\n *\n * @param response - The raw response from a provider API\n * @param format - The format to use: 'openai', 'anthropic', 'google', or 'auto'\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * // Auto-detect format\n * const toolCalls = parseToolCalls(response, 'auto');\n *\n * // Or specify format explicitly\n * const toolCalls = parseToolCalls(response, 'openai');\n * ```\n */\nexport function parseToolCalls(\n response: unknown,\n format: ToolCallFormat = 'auto'\n): ToolCallRequest[] {\n let actualFormat: ToolCallFormat | null = format;\n\n if (format === 'auto') {\n actualFormat = detectToolCallFormat(response);\n if (!actualFormat) {\n return [];\n }\n }\n\n switch (actualFormat) {\n case 'openai':\n return parseOpenAIToolCalls(response);\n case 'anthropic':\n return parseAnthropicToolCalls(response);\n case 'google':\n return parseGoogleToolCalls(response);\n default:\n return [];\n }\n}\n\n/**\n * Check if a response contains tool calls\n *\n * Quick check to determine if a response has any tool calls\n * without fully parsing them.\n *\n * @param response - The raw response from a provider API\n * @returns True if the response contains tool calls\n */\nexport function hasToolCalls(response: unknown): boolean {\n const format = detectToolCallFormat(response);\n return format !== null;\n}\n","/**\n * Tool Format Converters\n *\n * Utilities for converting between different provider tool formats.\n * The universal format (OpenAI-style) serves as the baseline for all conversions.\n *\n * @module @quilltap/plugin-utils/tools/converters\n */\n\nimport type {\n UniversalTool,\n AnthropicToolDefinition,\n GoogleToolDefinition,\n} from '@quilltap/plugin-types';\n\n/**\n * Convert OpenAI/Universal format tool to Anthropic format\n *\n * Anthropic uses a tool_use format with:\n * - name: string\n * - description: string\n * - input_schema: JSON schema object\n *\n * @param tool - Universal tool in OpenAI format\n * @returns Tool formatted for Anthropic's tool_use\n *\n * @example\n * ```typescript\n * const anthropicTool = convertToAnthropicFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // input_schema: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToAnthropicFormat(tool: UniversalTool): AnthropicToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description,\n input_schema: {\n type: 'object',\n properties: tool.function.parameters.properties,\n required: tool.function.parameters.required,\n },\n };\n}\n\n/**\n * Convert OpenAI/Universal format tool to Google Gemini format\n *\n * Google uses a function calling format with:\n * - name: string\n * - description: string\n * - parameters: JSON schema object\n *\n * @param tool - Universal tool in OpenAI format\n * @returns Tool formatted for Google's functionCall\n *\n * @example\n * ```typescript\n * const googleTool = convertToGoogleFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // parameters: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToGoogleFormat(tool: UniversalTool): GoogleToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description,\n parameters: {\n type: 'object',\n properties: tool.function.parameters.properties,\n required: tool.function.parameters.required,\n },\n };\n}\n\n/**\n * Convert Anthropic format tool to Universal/OpenAI format\n *\n * @param tool - Anthropic format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromAnthropicFormat(tool: AnthropicToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description ?? '',\n parameters: {\n type: 'object',\n properties: tool.input_schema.properties,\n required: tool.input_schema.required ?? [],\n },\n },\n };\n}\n\n/**\n * Convert Google format tool to Universal/OpenAI format\n *\n * @param tool - Google format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromGoogleFormat(tool: GoogleToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n },\n };\n}\n\n/**\n * Apply prompt/description length limit to a tool\n *\n * Modifies a tool's description if it exceeds maxBytes, appending a warning\n * that the description was truncated. This is useful for providers with\n * strict token limits.\n *\n * @param tool - Tool object (any format) with a description property\n * @param maxBytes - Maximum bytes allowed for description (including warning)\n * @returns Modified tool with truncated description if needed\n *\n * @example\n * ```typescript\n * const limitedTool = applyDescriptionLimit(tool, 500);\n * // If description > 500 bytes, truncates and adds warning\n * ```\n */\nexport function applyDescriptionLimit<T extends { description: string }>(\n tool: T,\n maxBytes: number\n): T {\n if (!tool || !tool.description) {\n return tool;\n }\n\n const warningText = ' [Note: description truncated due to length limit]';\n const maxDescBytes = maxBytes - Buffer.byteLength(warningText);\n\n if (maxDescBytes <= 0) {\n console.warn('[plugin-utils] Length limit too small for warning text:', maxBytes);\n return tool;\n }\n\n const descBytes = Buffer.byteLength(tool.description);\n\n if (descBytes > maxBytes) {\n // Truncate description to fit within the byte limit\n let truncated = tool.description;\n while (Buffer.byteLength(truncated) > maxDescBytes && truncated.length > 0) {\n truncated = truncated.slice(0, -1);\n }\n\n return {\n ...tool,\n description: truncated + warningText,\n };\n }\n\n return tool;\n}\n\n/**\n * Target format for tool conversion\n */\nexport type ToolConvertTarget = 'openai' | 'anthropic' | 'google';\n\n/**\n * Convert a universal tool to a specific provider format\n *\n * @param tool - Universal tool in OpenAI format\n * @param target - Target provider format\n * @returns Tool in the target format\n */\nexport function convertToolTo(\n tool: UniversalTool,\n target: ToolConvertTarget\n): UniversalTool | AnthropicToolDefinition | GoogleToolDefinition {\n switch (target) {\n case 'anthropic':\n return convertToAnthropicFormat(tool);\n case 'google':\n return convertToGoogleFormat(tool);\n case 'openai':\n default:\n return tool;\n }\n}\n\n/**\n * Convert multiple tools to a specific provider format\n *\n * @param tools - Array of universal tools\n * @param target - Target provider format\n * @returns Array of tools in the target format\n */\nexport function convertToolsTo(\n tools: UniversalTool[],\n target: ToolConvertTarget\n): Array<UniversalTool | AnthropicToolDefinition | GoogleToolDefinition> {\n return tools.map((tool) => convertToolTo(tool, target));\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/tools/index.ts","../../src/tools/parsers.ts","../../src/tools/converters.ts"],"sourcesContent":["/**\n * Tool Utilities\n *\n * Exports all tool-related utilities for parsing and converting\n * tool calls between different LLM provider formats.\n *\n * @module @quilltap/plugin-utils/tools\n */\n\n// Re-export types\nexport type {\n OpenAIToolDefinition,\n UniversalTool,\n AnthropicToolDefinition,\n GoogleToolDefinition,\n ToolCall,\n ToolCallRequest,\n ToolResult,\n ToolFormatOptions,\n} from './types';\n\n// Export parsers\nexport {\n parseToolCalls,\n parseOpenAIToolCalls,\n parseAnthropicToolCalls,\n parseGoogleToolCalls,\n detectToolCallFormat,\n hasToolCalls,\n} from './parsers';\n\nexport type { ToolCallFormat } from './parsers';\n\n// Export converters\nexport {\n convertToAnthropicFormat,\n convertToGoogleFormat,\n convertFromAnthropicFormat,\n convertFromGoogleFormat,\n convertToolTo,\n convertToolsTo,\n applyDescriptionLimit,\n // Backward-compatible aliases\n convertOpenAIToAnthropicFormat,\n convertOpenAIToGoogleFormat,\n} from './converters';\n\nexport type { ToolConvertTarget } from './converters';\n","/**\n * Tool Call Parsers\n *\n * Provider-specific parsers for extracting tool calls from LLM responses.\n * Each parser converts from a provider's native format to the standardized\n * ToolCallRequest format.\n *\n * @module @quilltap/plugin-utils/tools/parsers\n */\n\nimport type { ToolCallRequest } from '@quilltap/plugin-types';\n\n/**\n * Supported tool call response formats\n */\nexport type ToolCallFormat = 'openai' | 'anthropic' | 'google' | 'auto';\n\n/**\n * Parse OpenAI format tool calls from LLM response\n *\n * Extracts tool calls from OpenAI/Grok API responses which return\n * tool_calls in the message object.\n *\n * Expected response structures:\n * - `response.tool_calls` (direct)\n * - `response.choices[0].message.tool_calls` (nested)\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await openai.chat.completions.create({...});\n * const toolCalls = parseOpenAIToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseOpenAIToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n // Handle direct tool_calls array (snake_case)\n let toolCallsArray = resp?.tool_calls as unknown[] | undefined;\n\n // Handle direct toolCalls array (camelCase - some SDKs use this)\n if (!toolCallsArray) {\n toolCallsArray = (resp as Record<string, unknown>)?.toolCalls as unknown[] | undefined;\n }\n\n // Check nested structure from non-streaming responses: choices[0].message.tool_calls\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ message?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls;\n }\n\n // Check nested structure from streaming responses: choices[0].delta.toolCalls\n // OpenRouter SDK uses camelCase and puts tool calls in delta for streaming\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls;\n }\n\n if (toolCallsArray && Array.isArray(toolCallsArray) && toolCallsArray.length > 0) {\n for (const toolCall of toolCallsArray) {\n const tc = toolCall as {\n type?: string;\n function?: { name: string; arguments: string };\n };\n\n if (tc.type === 'function' && tc.function) {\n toolCalls.push({\n name: tc.function.name,\n arguments: JSON.parse(tc.function.arguments || '{}'),\n });\n }\n }\n }\n } catch (error) {\n // Log error but don't throw - return empty array\n console.error('[plugin-utils] Error parsing OpenAI tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Anthropic format tool calls from LLM response\n *\n * Extracts tool calls from Anthropic API responses which return\n * tool_use blocks in the content array.\n *\n * Expected response structure:\n * - `response.content` array with `{ type: 'tool_use', name, input }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await anthropic.messages.create({...});\n * const toolCalls = parseAnthropicToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseAnthropicToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n if (!resp?.content || !Array.isArray(resp.content)) {\n return toolCalls;\n }\n\n for (const block of resp.content) {\n const b = block as { type?: string; name?: string; input?: Record<string, unknown> };\n\n if (b.type === 'tool_use' && b.name) {\n toolCalls.push({\n name: b.name,\n arguments: b.input || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Anthropic tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Google Gemini format tool calls from LLM response\n *\n * Extracts tool calls from Google Gemini API responses which return\n * functionCall objects in the parts array.\n *\n * Expected response structure:\n * - `response.candidates[0].content.parts` array with `{ functionCall: { name, args } }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await gemini.generateContent({...});\n * const toolCalls = parseGoogleToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseGoogleToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n const candidates = resp?.candidates as\n | Array<{ content?: { parts?: unknown[] } }>\n | undefined;\n const parts = candidates?.[0]?.content?.parts;\n\n if (!parts || !Array.isArray(parts)) {\n return toolCalls;\n }\n\n for (const part of parts) {\n const p = part as {\n functionCall?: { name: string; args?: Record<string, unknown> };\n };\n\n if (p.functionCall) {\n toolCalls.push({\n name: p.functionCall.name,\n arguments: p.functionCall.args || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Google tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Detect the format of a tool call response\n *\n * Analyzes the response structure to determine which provider format it uses.\n *\n * @param response - The raw response from a provider API\n * @returns The detected format, or null if unrecognized\n */\nexport function detectToolCallFormat(response: unknown): ToolCallFormat | null {\n if (!response || typeof response !== 'object') {\n return null;\n }\n\n const resp = response as Record<string, unknown>;\n\n // OpenAI format: has tool_calls/toolCalls directly or in choices[0].message or choices[0].delta\n if (resp.tool_calls && Array.isArray(resp.tool_calls)) {\n return 'openai';\n }\n if (resp.toolCalls && Array.isArray(resp.toolCalls)) {\n return 'openai';\n }\n\n const choices = resp.choices as Array<{\n message?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n }> | undefined;\n if (choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls) {\n return 'openai';\n }\n // Check delta for streaming responses (OpenRouter SDK uses this)\n if (choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls) {\n return 'openai';\n }\n\n // Anthropic format: has content array with tool_use type\n if (resp.content && Array.isArray(resp.content)) {\n const hasToolUse = (resp.content as Array<{ type?: string }>).some(\n (block) => block.type === 'tool_use'\n );\n if (hasToolUse) {\n return 'anthropic';\n }\n }\n\n // Google format: has candidates[0].content.parts with functionCall\n const candidates = resp.candidates as\n | Array<{ content?: { parts?: Array<{ functionCall?: unknown }> } }>\n | undefined;\n if (candidates?.[0]?.content?.parts) {\n const hasFunctionCall = candidates[0].content.parts.some((part) => part.functionCall);\n if (hasFunctionCall) {\n return 'google';\n }\n }\n\n return null;\n}\n\n/**\n * Parse tool calls with auto-detection or explicit format\n *\n * A unified parser that can either auto-detect the response format\n * or use a specified format. This is useful when you're not sure\n * which provider's response you're handling.\n *\n * @param response - The raw response from a provider API\n * @param format - The format to use: 'openai', 'anthropic', 'google', or 'auto'\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * // Auto-detect format\n * const toolCalls = parseToolCalls(response, 'auto');\n *\n * // Or specify format explicitly\n * const toolCalls = parseToolCalls(response, 'openai');\n * ```\n */\nexport function parseToolCalls(\n response: unknown,\n format: ToolCallFormat = 'auto'\n): ToolCallRequest[] {\n let actualFormat: ToolCallFormat | null = format;\n\n if (format === 'auto') {\n actualFormat = detectToolCallFormat(response);\n if (!actualFormat) {\n return [];\n }\n }\n\n switch (actualFormat) {\n case 'openai':\n return parseOpenAIToolCalls(response);\n case 'anthropic':\n return parseAnthropicToolCalls(response);\n case 'google':\n return parseGoogleToolCalls(response);\n default:\n return [];\n }\n}\n\n/**\n * Check if a response contains tool calls\n *\n * Quick check to determine if a response has any tool calls\n * without fully parsing them.\n *\n * @param response - The raw response from a provider API\n * @returns True if the response contains tool calls\n */\nexport function hasToolCalls(response: unknown): boolean {\n const format = detectToolCallFormat(response);\n return format !== null;\n}\n","/**\n * Tool Format Converters\n *\n * Utilities for converting between different provider tool formats.\n * The universal format (OpenAI-style) serves as the baseline for all conversions.\n *\n * @module @quilltap/plugin-utils/tools/converters\n */\n\nimport type {\n UniversalTool,\n AnthropicToolDefinition,\n GoogleToolDefinition,\n OpenAIToolDefinition,\n} from '@quilltap/plugin-types';\n\n/**\n * Convert OpenAI/Universal format tool to Anthropic format\n *\n * Anthropic uses a tool_use format with:\n * - name: string\n * - description: string\n * - input_schema: JSON schema object\n *\n * @param tool - Universal tool or OpenAI tool definition\n * @returns Tool formatted for Anthropic's tool_use\n *\n * @example\n * ```typescript\n * const anthropicTool = convertToAnthropicFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // input_schema: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToAnthropicFormat(tool: UniversalTool | OpenAIToolDefinition): AnthropicToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description ?? '',\n input_schema: {\n type: 'object',\n properties: tool.function.parameters?.properties ?? {},\n required: tool.function.parameters?.required ?? [],\n },\n };\n}\n\n/**\n * Convert OpenAI/Universal format tool to Google Gemini format\n *\n * Google uses a function calling format with:\n * - name: string\n * - description: string\n * - parameters: JSON schema object\n *\n * @param tool - Universal tool or OpenAI tool definition\n * @returns Tool formatted for Google's functionCall\n *\n * @example\n * ```typescript\n * const googleTool = convertToGoogleFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // parameters: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToGoogleFormat(tool: UniversalTool | OpenAIToolDefinition): GoogleToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description ?? '',\n parameters: {\n type: 'object',\n properties: tool.function.parameters?.properties ?? {},\n required: tool.function.parameters?.required ?? [],\n },\n };\n}\n\n/**\n * Convert Anthropic format tool to Universal/OpenAI format\n *\n * @param tool - Anthropic format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromAnthropicFormat(tool: AnthropicToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description ?? '',\n parameters: {\n type: 'object',\n properties: tool.input_schema.properties,\n required: tool.input_schema.required ?? [],\n },\n },\n };\n}\n\n/**\n * Convert Google format tool to Universal/OpenAI format\n *\n * @param tool - Google format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromGoogleFormat(tool: GoogleToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n },\n };\n}\n\n/**\n * Apply prompt/description length limit to a tool\n *\n * Modifies a tool's description if it exceeds maxBytes, appending a warning\n * that the description was truncated. This is useful for providers with\n * strict token limits.\n *\n * @param tool - Tool object (any format) with a description property\n * @param maxBytes - Maximum bytes allowed for description (including warning)\n * @returns Modified tool with truncated description if needed\n *\n * @example\n * ```typescript\n * const limitedTool = applyDescriptionLimit(tool, 500);\n * // If description > 500 bytes, truncates and adds warning\n * ```\n */\nexport function applyDescriptionLimit<T extends { description: string }>(\n tool: T,\n maxBytes: number\n): T {\n if (!tool || !tool.description) {\n return tool;\n }\n\n const warningText = ' [Note: description truncated due to length limit]';\n const maxDescBytes = maxBytes - Buffer.byteLength(warningText);\n\n if (maxDescBytes <= 0) {\n console.warn('[plugin-utils] Length limit too small for warning text:', maxBytes);\n return tool;\n }\n\n const descBytes = Buffer.byteLength(tool.description);\n\n if (descBytes > maxBytes) {\n // Truncate description to fit within the byte limit\n let truncated = tool.description;\n while (Buffer.byteLength(truncated) > maxDescBytes && truncated.length > 0) {\n truncated = truncated.slice(0, -1);\n }\n\n return {\n ...tool,\n description: truncated + warningText,\n };\n }\n\n return tool;\n}\n\n/**\n * Target format for tool conversion\n */\nexport type ToolConvertTarget = 'openai' | 'anthropic' | 'google';\n\n/**\n * Convert a universal tool to a specific provider format\n *\n * @param tool - Universal tool or OpenAI tool definition\n * @param target - Target provider format\n * @returns Tool in the target format\n */\nexport function convertToolTo(\n tool: UniversalTool | OpenAIToolDefinition,\n target: ToolConvertTarget\n): UniversalTool | OpenAIToolDefinition | AnthropicToolDefinition | GoogleToolDefinition {\n switch (target) {\n case 'anthropic':\n return convertToAnthropicFormat(tool);\n case 'google':\n return convertToGoogleFormat(tool);\n case 'openai':\n default:\n return tool;\n }\n}\n\n/**\n * Convert multiple tools to a specific provider format\n *\n * @param tools - Array of universal tools or OpenAI tool definitions\n * @param target - Target provider format\n * @returns Array of tools in the target format\n */\nexport function convertToolsTo(\n tools: Array<UniversalTool | OpenAIToolDefinition>,\n target: ToolConvertTarget\n): Array<UniversalTool | OpenAIToolDefinition | AnthropicToolDefinition | GoogleToolDefinition> {\n return tools.map((tool) => convertToolTo(tool, target));\n}\n\n// ============================================================================\n// Backward-compatible aliases\n// ============================================================================\n\n/**\n * Alias for convertToAnthropicFormat\n * @deprecated Use convertToAnthropicFormat instead\n */\nexport const convertOpenAIToAnthropicFormat = convertToAnthropicFormat;\n\n/**\n * Alias for convertToGoogleFormat\n * @deprecated Use convertToGoogleFormat instead\n */\nexport const convertOpenAIToGoogleFormat = convertToGoogleFormat;\n"],"mappings":"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","names":[]}
|
package/dist/tools/index.mjs
CHANGED
|
@@ -138,22 +138,22 @@ function hasToolCalls(response) {
|
|
|
138
138
|
function convertToAnthropicFormat(tool) {
|
|
139
139
|
return {
|
|
140
140
|
name: tool.function.name,
|
|
141
|
-
description: tool.function.description,
|
|
141
|
+
description: tool.function.description ?? "",
|
|
142
142
|
input_schema: {
|
|
143
143
|
type: "object",
|
|
144
|
-
properties: tool.function.parameters
|
|
145
|
-
required: tool.function.parameters
|
|
144
|
+
properties: tool.function.parameters?.properties ?? {},
|
|
145
|
+
required: tool.function.parameters?.required ?? []
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
149
|
function convertToGoogleFormat(tool) {
|
|
150
150
|
return {
|
|
151
151
|
name: tool.function.name,
|
|
152
|
-
description: tool.function.description,
|
|
152
|
+
description: tool.function.description ?? "",
|
|
153
153
|
parameters: {
|
|
154
154
|
type: "object",
|
|
155
|
-
properties: tool.function.parameters
|
|
156
|
-
required: tool.function.parameters
|
|
155
|
+
properties: tool.function.parameters?.properties ?? {},
|
|
156
|
+
required: tool.function.parameters?.required ?? []
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
159
|
}
|
|
@@ -222,10 +222,14 @@ function convertToolTo(tool, target) {
|
|
|
222
222
|
function convertToolsTo(tools, target) {
|
|
223
223
|
return tools.map((tool) => convertToolTo(tool, target));
|
|
224
224
|
}
|
|
225
|
+
var convertOpenAIToAnthropicFormat = convertToAnthropicFormat;
|
|
226
|
+
var convertOpenAIToGoogleFormat = convertToGoogleFormat;
|
|
225
227
|
export {
|
|
226
228
|
applyDescriptionLimit,
|
|
227
229
|
convertFromAnthropicFormat,
|
|
228
230
|
convertFromGoogleFormat,
|
|
231
|
+
convertOpenAIToAnthropicFormat,
|
|
232
|
+
convertOpenAIToGoogleFormat,
|
|
229
233
|
convertToAnthropicFormat,
|
|
230
234
|
convertToGoogleFormat,
|
|
231
235
|
convertToolTo,
|
package/dist/tools/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/tools/parsers.ts","../../src/tools/converters.ts"],"sourcesContent":["/**\n * Tool Call Parsers\n *\n * Provider-specific parsers for extracting tool calls from LLM responses.\n * Each parser converts from a provider's native format to the standardized\n * ToolCallRequest format.\n *\n * @module @quilltap/plugin-utils/tools/parsers\n */\n\nimport type { ToolCallRequest } from '@quilltap/plugin-types';\n\n/**\n * Supported tool call response formats\n */\nexport type ToolCallFormat = 'openai' | 'anthropic' | 'google' | 'auto';\n\n/**\n * Parse OpenAI format tool calls from LLM response\n *\n * Extracts tool calls from OpenAI/Grok API responses which return\n * tool_calls in the message object.\n *\n * Expected response structures:\n * - `response.tool_calls` (direct)\n * - `response.choices[0].message.tool_calls` (nested)\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await openai.chat.completions.create({...});\n * const toolCalls = parseOpenAIToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseOpenAIToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n // Handle direct tool_calls array (snake_case)\n let toolCallsArray = resp?.tool_calls as unknown[] | undefined;\n\n // Handle direct toolCalls array (camelCase - some SDKs use this)\n if (!toolCallsArray) {\n toolCallsArray = (resp as Record<string, unknown>)?.toolCalls as unknown[] | undefined;\n }\n\n // Check nested structure from non-streaming responses: choices[0].message.tool_calls\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ message?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls;\n }\n\n // Check nested structure from streaming responses: choices[0].delta.toolCalls\n // OpenRouter SDK uses camelCase and puts tool calls in delta for streaming\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls;\n }\n\n if (toolCallsArray && Array.isArray(toolCallsArray) && toolCallsArray.length > 0) {\n for (const toolCall of toolCallsArray) {\n const tc = toolCall as {\n type?: string;\n function?: { name: string; arguments: string };\n };\n\n if (tc.type === 'function' && tc.function) {\n toolCalls.push({\n name: tc.function.name,\n arguments: JSON.parse(tc.function.arguments || '{}'),\n });\n }\n }\n }\n } catch (error) {\n // Log error but don't throw - return empty array\n console.error('[plugin-utils] Error parsing OpenAI tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Anthropic format tool calls from LLM response\n *\n * Extracts tool calls from Anthropic API responses which return\n * tool_use blocks in the content array.\n *\n * Expected response structure:\n * - `response.content` array with `{ type: 'tool_use', name, input }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await anthropic.messages.create({...});\n * const toolCalls = parseAnthropicToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseAnthropicToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n if (!resp?.content || !Array.isArray(resp.content)) {\n return toolCalls;\n }\n\n for (const block of resp.content) {\n const b = block as { type?: string; name?: string; input?: Record<string, unknown> };\n\n if (b.type === 'tool_use' && b.name) {\n toolCalls.push({\n name: b.name,\n arguments: b.input || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Anthropic tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Google Gemini format tool calls from LLM response\n *\n * Extracts tool calls from Google Gemini API responses which return\n * functionCall objects in the parts array.\n *\n * Expected response structure:\n * - `response.candidates[0].content.parts` array with `{ functionCall: { name, args } }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await gemini.generateContent({...});\n * const toolCalls = parseGoogleToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseGoogleToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n const candidates = resp?.candidates as\n | Array<{ content?: { parts?: unknown[] } }>\n | undefined;\n const parts = candidates?.[0]?.content?.parts;\n\n if (!parts || !Array.isArray(parts)) {\n return toolCalls;\n }\n\n for (const part of parts) {\n const p = part as {\n functionCall?: { name: string; args?: Record<string, unknown> };\n };\n\n if (p.functionCall) {\n toolCalls.push({\n name: p.functionCall.name,\n arguments: p.functionCall.args || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Google tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Detect the format of a tool call response\n *\n * Analyzes the response structure to determine which provider format it uses.\n *\n * @param response - The raw response from a provider API\n * @returns The detected format, or null if unrecognized\n */\nexport function detectToolCallFormat(response: unknown): ToolCallFormat | null {\n if (!response || typeof response !== 'object') {\n return null;\n }\n\n const resp = response as Record<string, unknown>;\n\n // OpenAI format: has tool_calls/toolCalls directly or in choices[0].message or choices[0].delta\n if (resp.tool_calls && Array.isArray(resp.tool_calls)) {\n return 'openai';\n }\n if (resp.toolCalls && Array.isArray(resp.toolCalls)) {\n return 'openai';\n }\n\n const choices = resp.choices as Array<{\n message?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n }> | undefined;\n if (choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls) {\n return 'openai';\n }\n // Check delta for streaming responses (OpenRouter SDK uses this)\n if (choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls) {\n return 'openai';\n }\n\n // Anthropic format: has content array with tool_use type\n if (resp.content && Array.isArray(resp.content)) {\n const hasToolUse = (resp.content as Array<{ type?: string }>).some(\n (block) => block.type === 'tool_use'\n );\n if (hasToolUse) {\n return 'anthropic';\n }\n }\n\n // Google format: has candidates[0].content.parts with functionCall\n const candidates = resp.candidates as\n | Array<{ content?: { parts?: Array<{ functionCall?: unknown }> } }>\n | undefined;\n if (candidates?.[0]?.content?.parts) {\n const hasFunctionCall = candidates[0].content.parts.some((part) => part.functionCall);\n if (hasFunctionCall) {\n return 'google';\n }\n }\n\n return null;\n}\n\n/**\n * Parse tool calls with auto-detection or explicit format\n *\n * A unified parser that can either auto-detect the response format\n * or use a specified format. This is useful when you're not sure\n * which provider's response you're handling.\n *\n * @param response - The raw response from a provider API\n * @param format - The format to use: 'openai', 'anthropic', 'google', or 'auto'\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * // Auto-detect format\n * const toolCalls = parseToolCalls(response, 'auto');\n *\n * // Or specify format explicitly\n * const toolCalls = parseToolCalls(response, 'openai');\n * ```\n */\nexport function parseToolCalls(\n response: unknown,\n format: ToolCallFormat = 'auto'\n): ToolCallRequest[] {\n let actualFormat: ToolCallFormat | null = format;\n\n if (format === 'auto') {\n actualFormat = detectToolCallFormat(response);\n if (!actualFormat) {\n return [];\n }\n }\n\n switch (actualFormat) {\n case 'openai':\n return parseOpenAIToolCalls(response);\n case 'anthropic':\n return parseAnthropicToolCalls(response);\n case 'google':\n return parseGoogleToolCalls(response);\n default:\n return [];\n }\n}\n\n/**\n * Check if a response contains tool calls\n *\n * Quick check to determine if a response has any tool calls\n * without fully parsing them.\n *\n * @param response - The raw response from a provider API\n * @returns True if the response contains tool calls\n */\nexport function hasToolCalls(response: unknown): boolean {\n const format = detectToolCallFormat(response);\n return format !== null;\n}\n","/**\n * Tool Format Converters\n *\n * Utilities for converting between different provider tool formats.\n * The universal format (OpenAI-style) serves as the baseline for all conversions.\n *\n * @module @quilltap/plugin-utils/tools/converters\n */\n\nimport type {\n UniversalTool,\n AnthropicToolDefinition,\n GoogleToolDefinition,\n} from '@quilltap/plugin-types';\n\n/**\n * Convert OpenAI/Universal format tool to Anthropic format\n *\n * Anthropic uses a tool_use format with:\n * - name: string\n * - description: string\n * - input_schema: JSON schema object\n *\n * @param tool - Universal tool in OpenAI format\n * @returns Tool formatted for Anthropic's tool_use\n *\n * @example\n * ```typescript\n * const anthropicTool = convertToAnthropicFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // input_schema: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToAnthropicFormat(tool: UniversalTool): AnthropicToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description,\n input_schema: {\n type: 'object',\n properties: tool.function.parameters.properties,\n required: tool.function.parameters.required,\n },\n };\n}\n\n/**\n * Convert OpenAI/Universal format tool to Google Gemini format\n *\n * Google uses a function calling format with:\n * - name: string\n * - description: string\n * - parameters: JSON schema object\n *\n * @param tool - Universal tool in OpenAI format\n * @returns Tool formatted for Google's functionCall\n *\n * @example\n * ```typescript\n * const googleTool = convertToGoogleFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // parameters: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToGoogleFormat(tool: UniversalTool): GoogleToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description,\n parameters: {\n type: 'object',\n properties: tool.function.parameters.properties,\n required: tool.function.parameters.required,\n },\n };\n}\n\n/**\n * Convert Anthropic format tool to Universal/OpenAI format\n *\n * @param tool - Anthropic format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromAnthropicFormat(tool: AnthropicToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description ?? '',\n parameters: {\n type: 'object',\n properties: tool.input_schema.properties,\n required: tool.input_schema.required ?? [],\n },\n },\n };\n}\n\n/**\n * Convert Google format tool to Universal/OpenAI format\n *\n * @param tool - Google format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromGoogleFormat(tool: GoogleToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n },\n };\n}\n\n/**\n * Apply prompt/description length limit to a tool\n *\n * Modifies a tool's description if it exceeds maxBytes, appending a warning\n * that the description was truncated. This is useful for providers with\n * strict token limits.\n *\n * @param tool - Tool object (any format) with a description property\n * @param maxBytes - Maximum bytes allowed for description (including warning)\n * @returns Modified tool with truncated description if needed\n *\n * @example\n * ```typescript\n * const limitedTool = applyDescriptionLimit(tool, 500);\n * // If description > 500 bytes, truncates and adds warning\n * ```\n */\nexport function applyDescriptionLimit<T extends { description: string }>(\n tool: T,\n maxBytes: number\n): T {\n if (!tool || !tool.description) {\n return tool;\n }\n\n const warningText = ' [Note: description truncated due to length limit]';\n const maxDescBytes = maxBytes - Buffer.byteLength(warningText);\n\n if (maxDescBytes <= 0) {\n console.warn('[plugin-utils] Length limit too small for warning text:', maxBytes);\n return tool;\n }\n\n const descBytes = Buffer.byteLength(tool.description);\n\n if (descBytes > maxBytes) {\n // Truncate description to fit within the byte limit\n let truncated = tool.description;\n while (Buffer.byteLength(truncated) > maxDescBytes && truncated.length > 0) {\n truncated = truncated.slice(0, -1);\n }\n\n return {\n ...tool,\n description: truncated + warningText,\n };\n }\n\n return tool;\n}\n\n/**\n * Target format for tool conversion\n */\nexport type ToolConvertTarget = 'openai' | 'anthropic' | 'google';\n\n/**\n * Convert a universal tool to a specific provider format\n *\n * @param tool - Universal tool in OpenAI format\n * @param target - Target provider format\n * @returns Tool in the target format\n */\nexport function convertToolTo(\n tool: UniversalTool,\n target: ToolConvertTarget\n): UniversalTool | AnthropicToolDefinition | GoogleToolDefinition {\n switch (target) {\n case 'anthropic':\n return convertToAnthropicFormat(tool);\n case 'google':\n return convertToGoogleFormat(tool);\n case 'openai':\n default:\n return tool;\n }\n}\n\n/**\n * Convert multiple tools to a specific provider format\n *\n * @param tools - Array of universal tools\n * @param target - Target provider format\n * @returns Array of tools in the target format\n */\nexport function convertToolsTo(\n tools: UniversalTool[],\n target: ToolConvertTarget\n): Array<UniversalTool | AnthropicToolDefinition | GoogleToolDefinition> {\n return tools.map((tool) => convertToolTo(tool, target));\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/tools/parsers.ts","../../src/tools/converters.ts"],"sourcesContent":["/**\n * Tool Call Parsers\n *\n * Provider-specific parsers for extracting tool calls from LLM responses.\n * Each parser converts from a provider's native format to the standardized\n * ToolCallRequest format.\n *\n * @module @quilltap/plugin-utils/tools/parsers\n */\n\nimport type { ToolCallRequest } from '@quilltap/plugin-types';\n\n/**\n * Supported tool call response formats\n */\nexport type ToolCallFormat = 'openai' | 'anthropic' | 'google' | 'auto';\n\n/**\n * Parse OpenAI format tool calls from LLM response\n *\n * Extracts tool calls from OpenAI/Grok API responses which return\n * tool_calls in the message object.\n *\n * Expected response structures:\n * - `response.tool_calls` (direct)\n * - `response.choices[0].message.tool_calls` (nested)\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await openai.chat.completions.create({...});\n * const toolCalls = parseOpenAIToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseOpenAIToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n // Handle direct tool_calls array (snake_case)\n let toolCallsArray = resp?.tool_calls as unknown[] | undefined;\n\n // Handle direct toolCalls array (camelCase - some SDKs use this)\n if (!toolCallsArray) {\n toolCallsArray = (resp as Record<string, unknown>)?.toolCalls as unknown[] | undefined;\n }\n\n // Check nested structure from non-streaming responses: choices[0].message.tool_calls\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ message?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls;\n }\n\n // Check nested structure from streaming responses: choices[0].delta.toolCalls\n // OpenRouter SDK uses camelCase and puts tool calls in delta for streaming\n if (!toolCallsArray) {\n const choices = resp?.choices as\n | Array<{ delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] } }>\n | undefined;\n toolCallsArray = choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls;\n }\n\n if (toolCallsArray && Array.isArray(toolCallsArray) && toolCallsArray.length > 0) {\n for (const toolCall of toolCallsArray) {\n const tc = toolCall as {\n type?: string;\n function?: { name: string; arguments: string };\n };\n\n if (tc.type === 'function' && tc.function) {\n toolCalls.push({\n name: tc.function.name,\n arguments: JSON.parse(tc.function.arguments || '{}'),\n });\n }\n }\n }\n } catch (error) {\n // Log error but don't throw - return empty array\n console.error('[plugin-utils] Error parsing OpenAI tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Anthropic format tool calls from LLM response\n *\n * Extracts tool calls from Anthropic API responses which return\n * tool_use blocks in the content array.\n *\n * Expected response structure:\n * - `response.content` array with `{ type: 'tool_use', name, input }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await anthropic.messages.create({...});\n * const toolCalls = parseAnthropicToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseAnthropicToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n\n if (!resp?.content || !Array.isArray(resp.content)) {\n return toolCalls;\n }\n\n for (const block of resp.content) {\n const b = block as { type?: string; name?: string; input?: Record<string, unknown> };\n\n if (b.type === 'tool_use' && b.name) {\n toolCalls.push({\n name: b.name,\n arguments: b.input || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Anthropic tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Parse Google Gemini format tool calls from LLM response\n *\n * Extracts tool calls from Google Gemini API responses which return\n * functionCall objects in the parts array.\n *\n * Expected response structure:\n * - `response.candidates[0].content.parts` array with `{ functionCall: { name, args } }`\n *\n * @param response - The raw response from provider API\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * const response = await gemini.generateContent({...});\n * const toolCalls = parseGoogleToolCalls(response);\n * // Returns: [{ name: 'search_web', arguments: { query: 'hello' } }]\n * ```\n */\nexport function parseGoogleToolCalls(response: unknown): ToolCallRequest[] {\n const toolCalls: ToolCallRequest[] = [];\n\n try {\n const resp = response as Record<string, unknown>;\n const candidates = resp?.candidates as\n | Array<{ content?: { parts?: unknown[] } }>\n | undefined;\n const parts = candidates?.[0]?.content?.parts;\n\n if (!parts || !Array.isArray(parts)) {\n return toolCalls;\n }\n\n for (const part of parts) {\n const p = part as {\n functionCall?: { name: string; args?: Record<string, unknown> };\n };\n\n if (p.functionCall) {\n toolCalls.push({\n name: p.functionCall.name,\n arguments: p.functionCall.args || {},\n });\n }\n }\n } catch (error) {\n console.error('[plugin-utils] Error parsing Google tool calls:', error);\n }\n\n return toolCalls;\n}\n\n/**\n * Detect the format of a tool call response\n *\n * Analyzes the response structure to determine which provider format it uses.\n *\n * @param response - The raw response from a provider API\n * @returns The detected format, or null if unrecognized\n */\nexport function detectToolCallFormat(response: unknown): ToolCallFormat | null {\n if (!response || typeof response !== 'object') {\n return null;\n }\n\n const resp = response as Record<string, unknown>;\n\n // OpenAI format: has tool_calls/toolCalls directly or in choices[0].message or choices[0].delta\n if (resp.tool_calls && Array.isArray(resp.tool_calls)) {\n return 'openai';\n }\n if (resp.toolCalls && Array.isArray(resp.toolCalls)) {\n return 'openai';\n }\n\n const choices = resp.choices as Array<{\n message?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n delta?: { tool_calls?: unknown[]; toolCalls?: unknown[] };\n }> | undefined;\n if (choices?.[0]?.message?.tool_calls || choices?.[0]?.message?.toolCalls) {\n return 'openai';\n }\n // Check delta for streaming responses (OpenRouter SDK uses this)\n if (choices?.[0]?.delta?.tool_calls || choices?.[0]?.delta?.toolCalls) {\n return 'openai';\n }\n\n // Anthropic format: has content array with tool_use type\n if (resp.content && Array.isArray(resp.content)) {\n const hasToolUse = (resp.content as Array<{ type?: string }>).some(\n (block) => block.type === 'tool_use'\n );\n if (hasToolUse) {\n return 'anthropic';\n }\n }\n\n // Google format: has candidates[0].content.parts with functionCall\n const candidates = resp.candidates as\n | Array<{ content?: { parts?: Array<{ functionCall?: unknown }> } }>\n | undefined;\n if (candidates?.[0]?.content?.parts) {\n const hasFunctionCall = candidates[0].content.parts.some((part) => part.functionCall);\n if (hasFunctionCall) {\n return 'google';\n }\n }\n\n return null;\n}\n\n/**\n * Parse tool calls with auto-detection or explicit format\n *\n * A unified parser that can either auto-detect the response format\n * or use a specified format. This is useful when you're not sure\n * which provider's response you're handling.\n *\n * @param response - The raw response from a provider API\n * @param format - The format to use: 'openai', 'anthropic', 'google', or 'auto'\n * @returns Array of parsed tool call requests\n *\n * @example\n * ```typescript\n * // Auto-detect format\n * const toolCalls = parseToolCalls(response, 'auto');\n *\n * // Or specify format explicitly\n * const toolCalls = parseToolCalls(response, 'openai');\n * ```\n */\nexport function parseToolCalls(\n response: unknown,\n format: ToolCallFormat = 'auto'\n): ToolCallRequest[] {\n let actualFormat: ToolCallFormat | null = format;\n\n if (format === 'auto') {\n actualFormat = detectToolCallFormat(response);\n if (!actualFormat) {\n return [];\n }\n }\n\n switch (actualFormat) {\n case 'openai':\n return parseOpenAIToolCalls(response);\n case 'anthropic':\n return parseAnthropicToolCalls(response);\n case 'google':\n return parseGoogleToolCalls(response);\n default:\n return [];\n }\n}\n\n/**\n * Check if a response contains tool calls\n *\n * Quick check to determine if a response has any tool calls\n * without fully parsing them.\n *\n * @param response - The raw response from a provider API\n * @returns True if the response contains tool calls\n */\nexport function hasToolCalls(response: unknown): boolean {\n const format = detectToolCallFormat(response);\n return format !== null;\n}\n","/**\n * Tool Format Converters\n *\n * Utilities for converting between different provider tool formats.\n * The universal format (OpenAI-style) serves as the baseline for all conversions.\n *\n * @module @quilltap/plugin-utils/tools/converters\n */\n\nimport type {\n UniversalTool,\n AnthropicToolDefinition,\n GoogleToolDefinition,\n OpenAIToolDefinition,\n} from '@quilltap/plugin-types';\n\n/**\n * Convert OpenAI/Universal format tool to Anthropic format\n *\n * Anthropic uses a tool_use format with:\n * - name: string\n * - description: string\n * - input_schema: JSON schema object\n *\n * @param tool - Universal tool or OpenAI tool definition\n * @returns Tool formatted for Anthropic's tool_use\n *\n * @example\n * ```typescript\n * const anthropicTool = convertToAnthropicFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // input_schema: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToAnthropicFormat(tool: UniversalTool | OpenAIToolDefinition): AnthropicToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description ?? '',\n input_schema: {\n type: 'object',\n properties: tool.function.parameters?.properties ?? {},\n required: tool.function.parameters?.required ?? [],\n },\n };\n}\n\n/**\n * Convert OpenAI/Universal format tool to Google Gemini format\n *\n * Google uses a function calling format with:\n * - name: string\n * - description: string\n * - parameters: JSON schema object\n *\n * @param tool - Universal tool or OpenAI tool definition\n * @returns Tool formatted for Google's functionCall\n *\n * @example\n * ```typescript\n * const googleTool = convertToGoogleFormat(universalTool);\n * // Returns: {\n * // name: 'search_web',\n * // description: 'Search the web',\n * // parameters: {\n * // type: 'object',\n * // properties: { query: { type: 'string' } },\n * // required: ['query']\n * // }\n * // }\n * ```\n */\nexport function convertToGoogleFormat(tool: UniversalTool | OpenAIToolDefinition): GoogleToolDefinition {\n return {\n name: tool.function.name,\n description: tool.function.description ?? '',\n parameters: {\n type: 'object',\n properties: tool.function.parameters?.properties ?? {},\n required: tool.function.parameters?.required ?? [],\n },\n };\n}\n\n/**\n * Convert Anthropic format tool to Universal/OpenAI format\n *\n * @param tool - Anthropic format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromAnthropicFormat(tool: AnthropicToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description ?? '',\n parameters: {\n type: 'object',\n properties: tool.input_schema.properties,\n required: tool.input_schema.required ?? [],\n },\n },\n };\n}\n\n/**\n * Convert Google format tool to Universal/OpenAI format\n *\n * @param tool - Google format tool\n * @returns Tool in universal OpenAI format\n */\nexport function convertFromGoogleFormat(tool: GoogleToolDefinition): UniversalTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n },\n };\n}\n\n/**\n * Apply prompt/description length limit to a tool\n *\n * Modifies a tool's description if it exceeds maxBytes, appending a warning\n * that the description was truncated. This is useful for providers with\n * strict token limits.\n *\n * @param tool - Tool object (any format) with a description property\n * @param maxBytes - Maximum bytes allowed for description (including warning)\n * @returns Modified tool with truncated description if needed\n *\n * @example\n * ```typescript\n * const limitedTool = applyDescriptionLimit(tool, 500);\n * // If description > 500 bytes, truncates and adds warning\n * ```\n */\nexport function applyDescriptionLimit<T extends { description: string }>(\n tool: T,\n maxBytes: number\n): T {\n if (!tool || !tool.description) {\n return tool;\n }\n\n const warningText = ' [Note: description truncated due to length limit]';\n const maxDescBytes = maxBytes - Buffer.byteLength(warningText);\n\n if (maxDescBytes <= 0) {\n console.warn('[plugin-utils] Length limit too small for warning text:', maxBytes);\n return tool;\n }\n\n const descBytes = Buffer.byteLength(tool.description);\n\n if (descBytes > maxBytes) {\n // Truncate description to fit within the byte limit\n let truncated = tool.description;\n while (Buffer.byteLength(truncated) > maxDescBytes && truncated.length > 0) {\n truncated = truncated.slice(0, -1);\n }\n\n return {\n ...tool,\n description: truncated + warningText,\n };\n }\n\n return tool;\n}\n\n/**\n * Target format for tool conversion\n */\nexport type ToolConvertTarget = 'openai' | 'anthropic' | 'google';\n\n/**\n * Convert a universal tool to a specific provider format\n *\n * @param tool - Universal tool or OpenAI tool definition\n * @param target - Target provider format\n * @returns Tool in the target format\n */\nexport function convertToolTo(\n tool: UniversalTool | OpenAIToolDefinition,\n target: ToolConvertTarget\n): UniversalTool | OpenAIToolDefinition | AnthropicToolDefinition | GoogleToolDefinition {\n switch (target) {\n case 'anthropic':\n return convertToAnthropicFormat(tool);\n case 'google':\n return convertToGoogleFormat(tool);\n case 'openai':\n default:\n return tool;\n }\n}\n\n/**\n * Convert multiple tools to a specific provider format\n *\n * @param tools - Array of universal tools or OpenAI tool definitions\n * @param target - Target provider format\n * @returns Array of tools in the target format\n */\nexport function convertToolsTo(\n tools: Array<UniversalTool | OpenAIToolDefinition>,\n target: ToolConvertTarget\n): Array<UniversalTool | OpenAIToolDefinition | AnthropicToolDefinition | GoogleToolDefinition> {\n return tools.map((tool) => convertToolTo(tool, target));\n}\n\n// ============================================================================\n// Backward-compatible aliases\n// ============================================================================\n\n/**\n * Alias for convertToAnthropicFormat\n * @deprecated Use convertToAnthropicFormat instead\n */\nexport const convertOpenAIToAnthropicFormat = convertToAnthropicFormat;\n\n/**\n * Alias for convertToGoogleFormat\n * @deprecated Use convertToGoogleFormat instead\n */\nexport const convertOpenAIToGoogleFormat = convertToGoogleFormat;\n"],"mappings":"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","names":[]}
|