Public/ConvertTo-ProviderToolSchema.ps1
|
<#
.SYNOPSIS Converts agnostic tool definitions into provider-specific tool schemas. .DESCRIPTION ConvertTo-ProviderToolSchema accepts agnostic tool definitions (Name, Description, Parameters) or raw provider tool objects. It converts agnostic tools into provider-specific schemas based on -Provider and passes through already provider-formatted tools (type = 'function'). The function always returns an array of tools and uses ordered hashtables to preserve key order. .PARAMETER Tools One or more tool definitions to convert. Accepts pipeline input or an array. Tools can be: - Agnostic tools: PSCustomObject or hashtable with keys Name, Description, Parameters - Raw provider tools: objects that already have type = 'function' .PARAMETER Provider The target provider schema to generate. Currently supports only "openai". .PARAMETER PassThru Returns the input tools unchanged without conversion. .EXAMPLE $tool = @{ Name = "Invoke-WebSearch" Description = "Search the web" Parameters = @{ type = "object"; properties = @{ query = @{ type = "string"; description = "Query" } }; required = @("query") } } ConvertTo-ProviderToolSchema -Tools $tool -Provider openai Converts an agnostic tool definition into the OpenAI tool schema. #> function ConvertTo-ProviderToolSchema { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [object[]]$Tools, [Parameter(Mandatory)] [ValidateSet('openai', 'anthropic', 'google')] [string]$Provider, [switch]$PassThru ) Begin { $collectedTools = New-Object System.Collections.Generic.List[object] function Get-ToolValue { param( [Parameter(Mandatory)] [object]$Tool, [Parameter(Mandatory)] [string]$Key ) if ($Tool -is [System.Collections.IDictionary]) { foreach ($toolKey in $Tool.Keys) { if ($toolKey -ieq $Key) { return $Tool[$toolKey] } } return $null } $property = $Tool.PSObject.Properties | Where-Object { $_.Name -ieq $Key } | Select-Object -First 1 if ($property) { return $property.Value } return $null } } Process { if ($null -ne $Tools) { foreach ($tool in $Tools) { $collectedTools.Add($tool) } } } End { $results = @() if ($PassThru) { return @($collectedTools.ToArray()) } foreach ($tool in $collectedTools) { if ($null -eq $tool) { continue } $toolType = Get-ToolValue -Tool $tool -Key 'type' if ($toolType -eq 'function') { if ($Provider -eq 'openai') { $results += $tool continue } # For non-OpenAI providers, extract from the function block $functionDef = Get-ToolValue -Tool $tool -Key 'function' if ($functionDef) { $name = Get-ToolValue -Tool $functionDef -Key 'name' $description = Get-ToolValue -Tool $functionDef -Key 'description' $parameters = Get-ToolValue -Tool $functionDef -Key 'parameters' } else { Write-Warning "Skipping tool: type is 'function' but no function definition found." continue } } else { $name = Get-ToolValue -Tool $tool -Key 'Name' $description = Get-ToolValue -Tool $tool -Key 'Description' $parameters = Get-ToolValue -Tool $tool -Key 'Parameters' } if ([string]::IsNullOrWhiteSpace($name)) { Write-Warning "Skipping tool because Name is missing." continue } if ([string]::IsNullOrWhiteSpace($description)) { $description = $name } if ($null -eq $parameters) { $parameters = @{ type = 'object'; properties = @{}; required = @() } } switch ($Provider.ToLower()) { 'openai' { $results += [ordered]@{ type = 'function' function = [ordered]@{ name = $name description = $description parameters = $parameters } } } 'anthropic' { $results += [ordered]@{ name = $name description = $description input_schema = $parameters } } 'google' { $results += [ordered]@{ name = $name description = $description parameters = $parameters } } default { throw "Unsupported provider: $Provider." } } } return $results } } |