|
59 | 59 | - For GitHub Models: gh extension install github/gh-models |
60 | 60 | - For GitHub Copilot: Install GitHub Copilot CLI from https://docs.github.com/en/copilot/how-tos/set-up/install-copilot-cli |
61 | 61 | - For OpenAI: `$env:OPENAI_API_KEY = "your-key" |
| 62 | + - For Azure OpenAI: `$env:AZURE_OPENAI_API_KEY = "your-key" and set LlmBaseUrl in config.ps1 |
62 | 63 | - For others: Set appropriate API key |
63 | 64 | 3. Edit config.ps1 to customize settings |
64 | 65 | "@ |
@@ -233,15 +234,7 @@ function Limit-Text { |
233 | 234 | function Get-UrlEncodedText { |
234 | 235 | param([string]$text) |
235 | 236 |
|
236 | | - # Basic URL encoding for GitHub issue URLs |
237 | | - $encoded = $text -replace '\r\n', '%0A' -replace '\n', '%0A' -replace '\r', '%0A' |
238 | | - $encoded = $encoded -replace ' ', '%20' -replace '#', '%23' -replace '&', '%26' |
239 | | - $encoded = $encoded -replace '\[', '%5B' -replace '\]', '%5D' -replace '\(', '%28' -replace '\)', '%29' |
240 | | - $encoded = $encoded -replace ':', '%3A' -replace ';', '%3B' -replace '\?', '%3F' -replace '=', '%3D' |
241 | | - $encoded = $encoded -replace '@', '%40' -replace '\+', '%2B' -replace '\$', '%24' |
242 | | - $encoded = $encoded -replace '"', '%22' -replace "'", '%27' -replace '<', '%3C' -replace '>', '%3E' |
243 | | - |
244 | | - return $encoded |
| 237 | + return [System.Web.HttpUtility]::UrlEncode($text) |
245 | 238 | } |
246 | 239 |
|
247 | 240 | # Function to fetch issue template from GitHub |
@@ -469,7 +462,7 @@ function Invoke-LlmApi { |
469 | 462 | $ghArgs += @("--system-prompt", $SystemPrompt) |
470 | 463 | } |
471 | 464 |
|
472 | | - $response = & gh @ghArgs |
| 465 | + $response = gh @ghArgs |
473 | 466 | return $response -join "`n" |
474 | 467 | } |
475 | 468 | catch { |
@@ -515,57 +508,102 @@ function Invoke-LlmApi { |
515 | 508 | return $null |
516 | 509 | } |
517 | 510 | } |
518 | | - default { |
519 | | - # Existing API-based providers |
520 | | - $headers = @{ 'Content-Type' = 'application/json' } |
521 | | - $body = @{} |
522 | | - $endpoint = "" |
523 | | - |
524 | | - switch ($Config.LlmProvider) { |
525 | | - "openai" { |
526 | | - $endpoint = if ($Config.LlmBaseUrl) { "$($Config.LlmBaseUrl)/chat/completions" } else { "https://api.openai.com/v1/chat/completions" } |
527 | | - $headers['Authorization'] = "Bearer $apiKey" |
528 | | - |
529 | | - $messages = @() |
530 | | - if ($SystemPrompt) { $messages += @{ role = "system"; content = $SystemPrompt } } |
531 | | - $messages += @{ role = "user"; content = $Prompt } |
532 | | - |
533 | | - $body = @{ |
534 | | - model = $Config.LlmModel |
535 | | - messages = $messages |
536 | | - max_tokens = $MaxTokens |
537 | | - temperature = 0.1 |
538 | | - } |
539 | | - } |
540 | | - "anthropic" { |
541 | | - $endpoint = if ($Config.LlmBaseUrl) { "$($Config.LlmBaseUrl)/messages" } else { "https://api.anthropic.com/v1/messages" } |
542 | | - $headers['x-api-key'] = $apiKey |
543 | | - $headers['anthropic-version'] = "2023-06-01" |
544 | | - |
545 | | - $fullPrompt = if ($SystemPrompt) { "$SystemPrompt`n`nHuman: $Prompt`n`nAssistant:" } else { "Human: $Prompt`n`nAssistant:" } |
546 | | - |
547 | | - $body = @{ |
548 | | - model = $Config.LlmModel |
549 | | - max_tokens = $MaxTokens |
550 | | - messages = @(@{ role = "user"; content = $fullPrompt }) |
551 | | - temperature = 0.1 |
552 | | - } |
553 | | - } |
| 511 | + "openai" { |
| 512 | + # OpenAI API |
| 513 | + $endpoint = if ($Config.LlmBaseUrl) { "$($Config.LlmBaseUrl)/chat/completions" } else { "https://api.openai.com/v1/chat/completions" } |
| 514 | + $headers = @{ |
| 515 | + 'Content-Type' = 'application/json' |
| 516 | + 'Authorization' = "Bearer $apiKey" |
| 517 | + } |
| 518 | + |
| 519 | + $messages = @() |
| 520 | + if ($SystemPrompt) { $messages += @{ role = "system"; content = $SystemPrompt } } |
| 521 | + $messages += @{ role = "user"; content = $Prompt } |
| 522 | + |
| 523 | + $body = @{ |
| 524 | + model = $Config.LlmModel |
| 525 | + messages = $messages |
| 526 | + max_tokens = $MaxTokens |
| 527 | + temperature = 0.1 |
554 | 528 | } |
555 | 529 |
|
556 | 530 | try { |
557 | 531 | $requestJson = $body | ConvertTo-Json -Depth 10 |
558 | 532 | $response = Invoke-RestMethod -Uri $endpoint -Method POST -Headers $headers -Body $requestJson |
| 533 | + return $response.choices[0].message.content |
| 534 | + } |
| 535 | + catch { |
| 536 | + Write-Error "OpenAI API call failed: $($_.Exception.Message)" |
| 537 | + return $null |
| 538 | + } |
| 539 | + } |
| 540 | + "anthropic" { |
| 541 | + # Anthropic API |
| 542 | + $endpoint = if ($Config.LlmBaseUrl) { "$($Config.LlmBaseUrl)/messages" } else { "https://api.anthropic.com/v1/messages" } |
| 543 | + $headers = @{ |
| 544 | + 'Content-Type' = 'application/json' |
| 545 | + 'x-api-key' = $apiKey |
| 546 | + 'anthropic-version' = "2023-06-01" |
| 547 | + } |
559 | 548 |
|
560 | | - switch ($Config.LlmProvider) { |
561 | | - "openai" { return $response.choices[0].message.content } |
562 | | - "anthropic" { return $response.content[0].text } |
563 | | - } |
| 549 | + $fullPrompt = if ($SystemPrompt) { "$SystemPrompt`n`nHuman: $Prompt`n`nAssistant:" } else { "Human: $Prompt`n`nAssistant:" } |
| 550 | + |
| 551 | + $body = @{ |
| 552 | + model = $Config.LlmModel |
| 553 | + max_tokens = $MaxTokens |
| 554 | + messages = @(@{ role = "user"; content = $fullPrompt }) |
| 555 | + temperature = 0.1 |
| 556 | + } |
| 557 | + |
| 558 | + try { |
| 559 | + $requestJson = $body | ConvertTo-Json -Depth 10 |
| 560 | + $response = Invoke-RestMethod -Uri $endpoint -Method POST -Headers $headers -Body $requestJson |
| 561 | + return $response.content[0].text |
564 | 562 | } |
565 | 563 | catch { |
566 | | - Write-Error "LLM API call failed: $($_.Exception.Message)" |
| 564 | + Write-Error "Anthropic API call failed: $($_.Exception.Message)" |
| 565 | + return $null |
| 566 | + } |
| 567 | + } |
| 568 | + "azure-openai" { |
| 569 | + # Azure OpenAI API |
| 570 | + # Endpoint format: https://{resource}.openai.azure.com/openai/deployments/{deployment}/chat/completions?api-version={api-version} |
| 571 | + if (-not $Config.LlmBaseUrl) { |
| 572 | + Write-Error "Azure OpenAI requires LlmBaseUrl to be set in config (e.g., 'https://your-resource.openai.azure.com')" |
567 | 573 | return $null |
568 | 574 | } |
| 575 | + |
| 576 | + $apiVersion = if ($Config.AzureApiVersion) { $Config.AzureApiVersion } else { "2024-02-15-preview" } |
| 577 | + $endpoint = "$($Config.LlmBaseUrl)/openai/deployments/$($Config.LlmModel)/chat/completions?api-version=$apiVersion" |
| 578 | + |
| 579 | + $headers = @{ |
| 580 | + 'Content-Type' = 'application/json' |
| 581 | + 'api-key' = $apiKey |
| 582 | + } |
| 583 | + |
| 584 | + $messages = @() |
| 585 | + if ($SystemPrompt) { $messages += @{ role = "system"; content = $SystemPrompt } } |
| 586 | + $messages += @{ role = "user"; content = $Prompt } |
| 587 | + |
| 588 | + $body = @{ |
| 589 | + messages = $messages |
| 590 | + max_tokens = $MaxTokens |
| 591 | + temperature = 0.1 |
| 592 | + } |
| 593 | + |
| 594 | + try { |
| 595 | + $requestJson = $body | ConvertTo-Json -Depth 10 |
| 596 | + $response = Invoke-RestMethod -Uri $endpoint -Method POST -Headers $headers -Body $requestJson |
| 597 | + return $response.choices[0].message.content |
| 598 | + } |
| 599 | + catch { |
| 600 | + Write-Error "Azure OpenAI API call failed: $($_.Exception.Message)" |
| 601 | + return $null |
| 602 | + } |
| 603 | + } |
| 604 | + default { |
| 605 | + Write-Error "Unknown LLM provider: $($Config.LlmProvider)" |
| 606 | + return $null |
569 | 607 | } |
570 | 608 | } |
571 | 609 | } |
|
0 commit comments