Исправления в ветке main

This commit is contained in:
2026-10-22 12:42:32 +06:00
parent 933e5ccb58
commit 9b05edc263
31 changed files with 2433 additions and 114 deletions

View File

@@ -5,6 +5,9 @@ import (
"os"
"path/filepath"
"strings"
"time"
"github.com/direct-dev-ru/linux-command-gpt/config"
)
// ProxySimpleChatRequest структура для простого запроса
@@ -34,7 +37,8 @@ type Gpt3 struct {
ApiKeyFile string
ApiKey string
Temperature float64
ProviderType string // "ollama", "proxy"
Context string // дополнительные данные к запросу, отправляются отдельным сообщением
ProviderType string // "ollama", "proxy", "apimira"
}
type Chat struct {
@@ -94,7 +98,7 @@ func (gpt3 *Gpt3) deleteApiKey() {
func (gpt3 *Gpt3) updateApiKey(apiKey string) {
filePath := gpt3.HomeDir + string(filepath.Separator) + gpt3.ApiKeyFile
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0644)
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
panic(err)
}
@@ -105,6 +109,9 @@ func (gpt3 *Gpt3) updateApiKey(apiKey string) {
if err != nil {
panic(err)
}
if err := os.Chmod(filePath, 0600); err != nil {
panic(err)
}
gpt3.ApiKey = apiKey
}
@@ -113,7 +120,7 @@ func (gpt3 *Gpt3) storeApiKey(apiKey string) {
return
}
filePath := gpt3.HomeDir + string(filepath.Separator) + gpt3.ApiKeyFile
file, err := os.Create(filePath)
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
panic(err)
}
@@ -124,6 +131,9 @@ func (gpt3 *Gpt3) storeApiKey(apiKey string) {
if err != nil {
panic(err)
}
if err := os.Chmod(filePath, 0600); err != nil {
panic(err)
}
gpt3.ApiKey = apiKey
}
@@ -144,7 +154,11 @@ func (gpt3 *Gpt3) loadApiKey() bool {
func (gpt3 *Gpt3) UpdateKey() {
var apiKey string
fmt.Print("OpenAI API Key: ")
if gpt3.ProviderType == "apimira" {
fmt.Print("apimira API Key: ")
} else {
fmt.Print("OpenAI API Key: ")
}
fmt.Scanln(&apiKey)
gpt3.updateApiKey(apiKey)
}
@@ -159,8 +173,10 @@ func (gpt3 *Gpt3) DeleteKey() {
}
func (gpt3 *Gpt3) InitKey() {
// Для ollama и proxy провайдеров не нужен API ключ
if gpt3.ProviderType == "ollama" || gpt3.ProviderType == "proxy" {
// Для ollama, proxy и apimira провайдеров ключ не запрашивается интерактивно:
// ollama и proxy не требуют ключа, apimira читает его из LCG_JWT_TOKEN или
// ключевого файла (задать через команду update-key)
if gpt3.ProviderType == "ollama" || gpt3.ProviderType == "proxy" || gpt3.ProviderType == "apimira" {
return
}
@@ -181,16 +197,22 @@ func NewGpt3(providerType, host, apiKey, model, prompt string, temperature float
switch providerType {
case "proxy":
provider = NewProxyAPIProvider(host, apiKey, model, timeout) // apiKey используется как JWT токен
case "apimira":
provider = NewApimiraProvider(host, apiKey, model, config.AppConfig.Completions, temperature, timeout)
case "ollama":
provider = NewOllamaProvider(host, model, temperature, timeout)
default:
provider = NewOllamaProvider(host, model, temperature, timeout)
}
homeDir, _ := os.UserHomeDir()
return &Gpt3{
Provider: provider,
Prompt: prompt,
Model: model,
HomeDir: homeDir,
ApiKeyFile: config.AppConfig.ApiKeyFile,
ApiKey: apiKey,
Temperature: temperature,
ProviderType: providerType,
@@ -201,15 +223,41 @@ func NewGpt3(providerType, host, apiKey, model, prompt string, temperature float
func (gpt3 *Gpt3) Completions(ask string) string {
messages := []Chat{
{"system", gpt3.Prompt},
{"user", ask + ". " + gpt3.Prompt},
}
if gpt3.Context != "" {
messages = append(messages, Chat{"user", gpt3.Context})
}
messages = append(messages, Chat{"user", ask + ". " + gpt3.Prompt})
retries := config.AppConfig.Retries
if retries < 0 {
retries = 0
}
var response string
var err error
for attempt := 0; ; attempt++ {
response, err = gpt3.Provider.Chat(messages)
if err == nil {
break
}
if attempt >= retries || !IsRetryable(err) {
break
}
delay := time.Duration(5<<attempt) * time.Second // 5с, 10с, 20с, 40с, ...
msg := fmt.Sprintf("⚠️ Попытка %d из %d не удалась: %v — повтор через %s...", attempt+1, retries+1, err, delay)
fmt.Printf("\r%-60s\n", msg)
config.DebugLogf("[RETRY] %s", msg)
time.Sleep(delay)
}
response, err := gpt3.Provider.Chat(messages)
if err != nil {
config.DebugLogf("[ERROR] completions: %v", err)
fmt.Printf("Ошибка при выполнении запроса: %v\n", err)
return ""
}
config.DebugLogf("[RESULT] %s", response)
return response
}