mirror of
https://github.com/Direct-Dev-Ru/go-lcg.git
synced 2026-11-09 17:06:40 +00:00
Исправления в ветке main
This commit is contained in:
103
config/config.go
103
config/config.go
@@ -9,29 +9,34 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Cwd string
|
||||
Host string
|
||||
ProxyUrl string
|
||||
AppName string
|
||||
Completions string
|
||||
Model string
|
||||
Prompt string
|
||||
ApiKeyFile string
|
||||
ConfigFolder string
|
||||
ResultFolder string
|
||||
PromptFolder string
|
||||
ProviderType string
|
||||
JwtToken string
|
||||
PromptID string
|
||||
Timeout string
|
||||
ResultHistory string
|
||||
NoHistoryEnv string
|
||||
AllowExecution bool
|
||||
Think bool
|
||||
Query string
|
||||
MainFlags MainFlags
|
||||
Server ServerConfig
|
||||
Validation ValidationConfig
|
||||
Cwd string
|
||||
Host string
|
||||
ProxyUrl string
|
||||
AppName string
|
||||
Completions string
|
||||
Model string
|
||||
Prompt string
|
||||
ApiKeyFile string
|
||||
ConfigFolder string
|
||||
ResultFolder string
|
||||
PromptFolder string
|
||||
ProviderType string
|
||||
JwtToken string
|
||||
PromptID string
|
||||
Timeout string
|
||||
Retries int
|
||||
ResultHistory string
|
||||
NoHistoryEnv string
|
||||
AllowExecution bool
|
||||
Think bool
|
||||
Query string
|
||||
OutputMode string
|
||||
OutputFile string
|
||||
ContextMaxBytes int
|
||||
BackupCount int
|
||||
MainFlags MainFlags
|
||||
Server ServerConfig
|
||||
Validation ValidationConfig
|
||||
}
|
||||
|
||||
type MainFlags struct {
|
||||
@@ -41,6 +46,7 @@ type MainFlags struct {
|
||||
PromptID int
|
||||
Timeout int
|
||||
Debug bool
|
||||
DebugFile string
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
@@ -117,6 +123,16 @@ func isSecureHost(host string) bool {
|
||||
func Load() Config {
|
||||
cwd, _ := os.Getwd()
|
||||
|
||||
providerType := getEnv("LCG_PROVIDER", "ollama")
|
||||
hostDefault := "http://192.168.87.108:11434/"
|
||||
completionsDefault := "api/chat"
|
||||
apiKeyFileDefault := ".openai_api_key"
|
||||
if providerType == "apimira" {
|
||||
hostDefault = "https://apimira.com"
|
||||
completionsDefault = "/v1/chat/completions"
|
||||
apiKeyFileDefault = ".apimira_api_key"
|
||||
}
|
||||
|
||||
homedir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
homedir = cwd
|
||||
@@ -134,24 +150,29 @@ func Load() Config {
|
||||
configFolder := getEnv("LCG_CONFIG_FOLDER", privateConfigDir)
|
||||
|
||||
return Config{
|
||||
Cwd: cwd,
|
||||
AppName: getEnv("LCG_APP_NAME", "Linux Command GPT"),
|
||||
Host: getEnv("LCG_HOST", "http://192.168.87.108:11434/"),
|
||||
ProxyUrl: getEnv("LCG_PROXY_URL", "/api/v1/protected/sberchat/chat"),
|
||||
Completions: getEnv("LCG_COMPLETIONS_PATH", "api/chat"),
|
||||
Model: getEnv("LCG_MODEL", "hf.co/yandex/YandexGPT-5-Lite-8B-instruct-GGUF:Q4_K_M"),
|
||||
Prompt: getEnv("LCG_PROMPT", "Reply with linux command and nothing else. Output with plain response - no need formatting. No need explanation. No need code blocks. No need ` symbols."),
|
||||
ApiKeyFile: getEnv("LCG_API_KEY_FILE", ".openai_api_key"),
|
||||
ResultFolder: resultFolder,
|
||||
PromptFolder: promptFolder,
|
||||
ConfigFolder: configFolder,
|
||||
ProviderType: getEnv("LCG_PROVIDER", "ollama"),
|
||||
JwtToken: getEnv("LCG_JWT_TOKEN", ""),
|
||||
PromptID: getEnv("LCG_PROMPT_ID", "1"),
|
||||
Timeout: getEnv("LCG_TIMEOUT", "300"),
|
||||
ResultHistory: getEnv("LCG_RESULT_HISTORY", path.Join(resultFolder, "lcg_history.json")),
|
||||
NoHistoryEnv: getEnv("LCG_NO_HISTORY", ""),
|
||||
AllowExecution: isAllowExecutionEnabled(),
|
||||
Cwd: cwd,
|
||||
AppName: getEnv("LCG_APP_NAME", "Linux Command GPT"),
|
||||
Host: getEnv("LCG_HOST", hostDefault),
|
||||
ProxyUrl: getEnv("LCG_PROXY_URL", "/api/v1/protected/sberchat/chat"),
|
||||
Completions: getEnv("LCG_COMPLETIONS_PATH", completionsDefault),
|
||||
Model: getEnv("LCG_MODEL", "hf.co/yandex/YandexGPT-5-Lite-8B-instruct-GGUF:Q4_K_M"),
|
||||
Prompt: getEnv("LCG_PROMPT", "Reply with linux command and nothing else. Output with plain response - no need formatting. No need explanation. No need code blocks. No need ` symbols."),
|
||||
ApiKeyFile: getEnv("LCG_API_KEY_FILE", apiKeyFileDefault),
|
||||
ResultFolder: resultFolder,
|
||||
PromptFolder: promptFolder,
|
||||
ConfigFolder: configFolder,
|
||||
ProviderType: providerType,
|
||||
JwtToken: getEnv("LCG_JWT_TOKEN", ""),
|
||||
OutputMode: getEnv("LCG_MODE", "stdout"),
|
||||
OutputFile: getEnv("LCG_OUTPUT_FILE", "lcg-out-script.sh"),
|
||||
ContextMaxBytes: getEnvInt("LCG_CONTEXT_MAX_BYTES", 16000),
|
||||
BackupCount: getEnvInt("LCG_BACKUP_COUNT", 3),
|
||||
PromptID: getEnv("LCG_PROMPT_ID", "1"),
|
||||
Timeout: getEnv("LCG_TIMEOUT", "300"),
|
||||
Retries: getEnvInt("LCG_RETRIES", 3),
|
||||
ResultHistory: getEnv("LCG_RESULT_HISTORY", path.Join(resultFolder, "lcg_history.json")),
|
||||
NoHistoryEnv: getEnv("LCG_NO_HISTORY", ""),
|
||||
AllowExecution: isAllowExecutionEnabled(),
|
||||
Server: ServerConfig{
|
||||
Port: getEnv("LCG_SERVER_PORT", "8080"),
|
||||
Host: getEnv("LCG_SERVER_HOST", "localhost"),
|
||||
|
||||
43
config/debug.go
Normal file
43
config/debug.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
debugFileMu sync.Mutex
|
||||
debugFileWarned bool
|
||||
)
|
||||
|
||||
// DebugLogf пишет строку в debug-файл (флаг --debug-file или переменная LCG_DEBUG_FILE),
|
||||
// если он задан. Файл открывается в режиме дозаписи с правами 0600,
|
||||
// каждая запись получает отметку времени. Ошибка открытия выводится один раз в stderr.
|
||||
func DebugLogf(format string, args ...any) {
|
||||
path := AppConfig.MainFlags.DebugFile
|
||||
if path == "" {
|
||||
path = os.Getenv("LCG_DEBUG_FILE")
|
||||
}
|
||||
if path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
line := fmt.Sprintf(format, args...)
|
||||
|
||||
debugFileMu.Lock()
|
||||
defer debugFileMu.Unlock()
|
||||
|
||||
file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
if !debugFileWarned {
|
||||
debugFileWarned = true
|
||||
fmt.Fprintf(os.Stderr, "⚠️ Не удалось открыть debug-файл %s: %v\n", path, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fmt.Fprintf(file, "[%s] %s\n", time.Now().Format("2006-01-02 15:04:05.000"), line)
|
||||
}
|
||||
28
config/filename.go
Normal file
28
config/filename.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package config
|
||||
|
||||
import "strings"
|
||||
|
||||
// SafeFileName делает строку безопасной для использования в имени файла:
|
||||
// недопустимые символы (включая "/" из формата моделей поставщик/имя) заменяются на "-",
|
||||
// пустой результат заменяется на "unknown".
|
||||
func SafeFileName(s string) string {
|
||||
replacer := strings.NewReplacer(
|
||||
"/", "-",
|
||||
"\\", "-",
|
||||
":", "-",
|
||||
"*", "-",
|
||||
"?", "-",
|
||||
"\"", "-",
|
||||
"<", "-",
|
||||
">", "-",
|
||||
"|", "-",
|
||||
"\n", "-",
|
||||
"\r", "-",
|
||||
"\t", "-",
|
||||
)
|
||||
result := strings.TrimSpace(replacer.Replace(s))
|
||||
if result == "" {
|
||||
return "unknown"
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user