improoved version

This commit is contained in:
2025-08-11 13:01:27 +06:00
parent 3e1c4594b1
commit cc242e1192
9 changed files with 503 additions and 36 deletions

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@ bin-linux-amd64/*
bin-linux-arm64/* bin-linux-arm64/*
binaries-for-upload/* binaries-for-upload/*
gpt_results gpt_results
shell-code/jwt.admin.token

View File

@@ -2,7 +2,8 @@ FROM --platform=${BUILDPLATFORM} golang:1.24.6-alpine3.22 AS builder
ARG TARGETARCH ARG TARGETARCH
RUN apk add git && go install mvdan.cc/garble@latest RUN apk add git
#&& go install mvdan.cc/garble@latest
WORKDIR /app WORKDIR /app
@@ -11,8 +12,8 @@ COPY . .
RUN echo $BUILDPLATFORM > buildplatform RUN echo $BUILDPLATFORM > buildplatform
RUN echo $TARGETARCH > targetarch RUN echo $TARGETARCH > targetarch
# RUN GOOS=linux GOARCH=$TARGETARCH go build -o /app/go-lcg . RUN GOOS=linux GOARCH=$TARGETARCH go build -ldflags="-w -s" -o /app/go-lcg .
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} garble -literals -tiny build -ldflags="-w -s" -o /app/go-lcg . #RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} garble -literals -tiny build -ldflags="-w -s" -o /app/go-lcg .
FROM alpine:latest FROM alpine:latest

View File

@@ -1,15 +1,16 @@
FROM --platform=${BUILDPLATFORM} golang:1.24.6-alpine3.22 AS build FROM --platform=${BUILDPLATFORM} golang:1.24.6-alpine3.22 AS build
ARG TARGETOS ARG TARGETOS
ARG TARGETARCH ARG TARGETARCH
RUN apk add git && go install mvdan.cc/garble@latest # RUN apk add git
#&& go install mvdan.cc/garble@latest
WORKDIR /src WORKDIR /src
ENV CGO_ENABLED=0 ENV CGO_ENABLED=0
COPY go.* . COPY go.* .
RUN go mod download RUN go mod download
COPY . . COPY . .
# RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /out/go-lcg . RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -ldflags="-w -s -buildid=" -trimpath -o /out/go-lcg .
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} garble -literals -tiny build -ldflags="-w -s" -o /out/go-lcg . # RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} garble -literals -tiny build -ldflags="-w -s" -o /out/go-lcg .
FROM scratch AS bin-unix FROM scratch AS bin-unix
COPY --from=build /out/go-lcg /lcg COPY --from=build /out/go-lcg /lcg

View File

@@ -1 +1 @@
v1.0.1 v1.1.0

View File

@@ -151,8 +151,8 @@ func (gpt3 *Gpt3) DeleteKey() {
} }
func (gpt3 *Gpt3) InitKey() { func (gpt3 *Gpt3) InitKey() {
// Для proxy провайдера не нужен API ключ, используется JWT токен // Для ollama и proxy провайдеров не нужен API ключ
if gpt3.ProviderType == "proxy" { if gpt3.ProviderType == "ollama" || gpt3.ProviderType == "proxy" {
return return
} }
@@ -167,16 +167,16 @@ func (gpt3 *Gpt3) InitKey() {
} }
// NewGpt3 создает новый экземпляр GPT с выбранным провайдером // NewGpt3 создает новый экземпляр GPT с выбранным провайдером
func NewGpt3(providerType, host, apiKey, model, prompt string, temperature float64) *Gpt3 { func NewGpt3(providerType, host, apiKey, model, prompt string, temperature float64, timeout int) *Gpt3 {
var provider Provider var provider Provider
switch providerType { switch providerType {
case "proxy": case "proxy":
provider = NewProxyAPIProvider(host, apiKey, model) // apiKey используется как JWT токен provider = NewProxyAPIProvider(host, apiKey, model, timeout) // apiKey используется как JWT токен
case "ollama": case "ollama":
provider = NewOllamaProvider(host, model, temperature) provider = NewOllamaProvider(host, model, temperature, timeout)
default: default:
provider = NewOllamaProvider(host, model, temperature) provider = NewOllamaProvider(host, model, temperature, timeout)
} }
return &Gpt3{ return &Gpt3{
@@ -209,3 +209,8 @@ func (gpt3 *Gpt3) Completions(ask string) string {
func (gpt3 *Gpt3) Health() error { func (gpt3 *Gpt3) Health() error {
return gpt3.Provider.Health() return gpt3.Provider.Health()
} }
// GetAvailableModels возвращает список доступных моделей
func (gpt3 *Gpt3) GetAvailableModels() ([]string, error) {
return gpt3.Provider.GetAvailableModels()
}

203
gpt/prompts.go Normal file
View File

@@ -0,0 +1,203 @@
package gpt
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
)
// SystemPrompt представляет системный промпт
type SystemPrompt struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Content string `json:"content"`
}
// PromptManager управляет системными промптами
type PromptManager struct {
Prompts []SystemPrompt
ConfigFile string
HomeDir string
}
// NewPromptManager создает новый менеджер промптов
func NewPromptManager(homeDir string) *PromptManager {
configFile := filepath.Join(homeDir, ".lcg_prompts.json")
pm := &PromptManager{
ConfigFile: configFile,
HomeDir: homeDir,
}
// Загружаем предустановленные промпты
pm.loadDefaultPrompts()
// Загружаем пользовательские промпты
pm.loadCustomPrompts()
return pm
}
// loadDefaultPrompts загружает предустановленные промпты
func (pm *PromptManager) loadDefaultPrompts() {
defaultPrompts := []SystemPrompt{
{
ID: 1,
Name: "linux-command",
Description: "Generate Linux commands (default)",
Content: "Reply with linux command and nothing else. Output with plain response - no need formatting. No need explanation. No need code blocks. No need ` symbols.",
},
{
ID: 2,
Name: "linux-command-with-explanation",
Description: "Generate Linux commands with explanation",
Content: "Generate a Linux command and provide a brief explanation of what it does. Format: COMMAND: explanation",
},
{
ID: 3,
Name: "linux-command-safe",
Description: "Generate safe Linux commands",
Content: "Generate a safe Linux command that won't cause data loss or system damage. Reply with linux command and nothing else. Output with plain response - no need formatting.",
},
{
ID: 4,
Name: "linux-command-verbose",
Description: "Generate Linux commands with detailed explanation",
Content: "Generate a Linux command and provide detailed explanation including what each flag does and potential alternatives.",
},
{
ID: 5,
Name: "linux-command-simple",
Description: "Generate simple Linux commands",
Content: "Generate a simple, easy-to-understand Linux command. Avoid complex flags and options when possible.",
},
}
pm.Prompts = defaultPrompts
}
// loadCustomPrompts загружает пользовательские промпты из файла
func (pm *PromptManager) loadCustomPrompts() {
if _, err := os.Stat(pm.ConfigFile); os.IsNotExist(err) {
return
}
data, err := os.ReadFile(pm.ConfigFile)
if err != nil {
return
}
var customPrompts []SystemPrompt
if err := json.Unmarshal(data, &customPrompts); err != nil {
return
}
// Добавляем пользовательские промпты с новыми ID
for i, prompt := range customPrompts {
prompt.ID = len(pm.Prompts) + i + 1
pm.Prompts = append(pm.Prompts, prompt)
}
}
// saveCustomPrompts сохраняет пользовательские промпты
func (pm *PromptManager) saveCustomPrompts() error {
// Находим пользовательские промпты (ID > 5)
var customPrompts []SystemPrompt
for _, prompt := range pm.Prompts {
if prompt.ID > 5 {
customPrompts = append(customPrompts, prompt)
}
}
data, err := json.MarshalIndent(customPrompts, "", " ")
if err != nil {
return err
}
return os.WriteFile(pm.ConfigFile, data, 0644)
}
// GetPromptByID возвращает промпт по ID
func (pm *PromptManager) GetPromptByID(id int) (*SystemPrompt, error) {
for _, prompt := range pm.Prompts {
if prompt.ID == id {
return &prompt, nil
}
}
return nil, fmt.Errorf("промпт с ID %d не найден", id)
}
// GetPromptByName возвращает промпт по имени
func (pm *PromptManager) GetPromptByName(name string) (*SystemPrompt, error) {
for _, prompt := range pm.Prompts {
if strings.EqualFold(prompt.Name, name) {
return &prompt, nil
}
}
return nil, fmt.Errorf("промпт с именем '%s' не найден", name)
}
// ListPrompts выводит список всех доступных промптов
func (pm *PromptManager) ListPrompts() {
fmt.Println("Available system prompts:")
fmt.Println("ID | Name | Description")
fmt.Println("---+---------------------------+--------------------------------")
for _, prompt := range pm.Prompts {
description := prompt.Description
if len(description) > 80 {
description = description[:77] + "..."
}
fmt.Printf("%-2d | %-25s | %s\n",
prompt.ID,
truncateString(prompt.Name, 25),
description)
}
}
// AddCustomPrompt добавляет новый пользовательский промпт
func (pm *PromptManager) AddCustomPrompt(name, description, content string) error {
// Проверяем, что имя уникально
for _, prompt := range pm.Prompts {
if strings.EqualFold(prompt.Name, name) {
return fmt.Errorf("промпт с именем '%s' уже существует", name)
}
}
newPrompt := SystemPrompt{
ID: len(pm.Prompts) + 1,
Name: name,
Description: description,
Content: content,
}
pm.Prompts = append(pm.Prompts, newPrompt)
return pm.saveCustomPrompts()
}
// DeleteCustomPrompt удаляет пользовательский промпт
func (pm *PromptManager) DeleteCustomPrompt(id int) error {
if id <= 5 {
return fmt.Errorf("нельзя удалить предустановленный промпт")
}
for i, prompt := range pm.Prompts {
if prompt.ID == id {
pm.Prompts = append(pm.Prompts[:i], pm.Prompts[i+1:]...)
return pm.saveCustomPrompts()
}
}
return fmt.Errorf("промпт с ID %d не найден", id)
}
// truncateString обрезает строку до указанной длины
func truncateString(s string, maxLen int) string {
if len(s) <= maxLen {
return s
}
return s[:maxLen-3] + "..."
}

View File

@@ -14,6 +14,7 @@ import (
type Provider interface { type Provider interface {
Chat(messages []Chat) (string, error) Chat(messages []Chat) (string, error)
Health() error Health() error
GetAvailableModels() ([]string, error)
} }
// ProxyAPIProvider реализация для прокси API (gin-restapi) // ProxyAPIProvider реализация для прокси API (gin-restapi)
@@ -66,21 +67,30 @@ type OllamaProvider struct {
HTTPClient *http.Client HTTPClient *http.Client
} }
func NewProxyAPIProvider(baseURL, jwtToken, model string) *ProxyAPIProvider { // OllamaTagsResponse структура ответа для получения списка моделей
type OllamaTagsResponse struct {
Models []struct {
Name string `json:"name"`
ModifiedAt string `json:"modified_at"`
Size int64 `json:"size"`
} `json:"models"`
}
func NewProxyAPIProvider(baseURL, jwtToken, model string, timeout int) *ProxyAPIProvider {
return &ProxyAPIProvider{ return &ProxyAPIProvider{
BaseURL: strings.TrimSuffix(baseURL, "/"), BaseURL: strings.TrimSuffix(baseURL, "/"),
JWTToken: jwtToken, JWTToken: jwtToken,
Model: model, Model: model,
HTTPClient: &http.Client{Timeout: 120 * time.Second}, HTTPClient: &http.Client{Timeout: time.Duration(timeout) * time.Second},
} }
} }
func NewOllamaProvider(baseURL, model string, temperature float64) *OllamaProvider { func NewOllamaProvider(baseURL, model string, temperature float64, timeout int) *OllamaProvider {
return &OllamaProvider{ return &OllamaProvider{
BaseURL: strings.TrimSuffix(baseURL, "/"), BaseURL: strings.TrimSuffix(baseURL, "/"),
Model: model, Model: model,
Temperature: temperature, Temperature: temperature,
HTTPClient: &http.Client{Timeout: 120 * time.Second}, HTTPClient: &http.Client{Timeout: time.Duration(timeout) * time.Second},
} }
} }
@@ -244,3 +254,43 @@ func (o *OllamaProvider) Health() error {
return nil return nil
} }
// GetAvailableModels для ProxyAPIProvider возвращает фиксированный список
func (p *ProxyAPIProvider) GetAvailableModels() ([]string, error) {
return []string{"GigaChat-2", "GigaChat-2-Pro", "GigaChat-2-Max"}, nil
}
// GetAvailableModels возвращает список доступных моделей для провайдера
func (o *OllamaProvider) GetAvailableModels() ([]string, error) {
req, err := http.NewRequest("GET", o.BaseURL+"/api/tags", nil)
if err != nil {
return nil, fmt.Errorf("ошибка создания запроса: %w", err)
}
resp, err := o.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("ошибка получения моделей: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("ошибка чтения ответа: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("ошибка API: %d - %s", resp.StatusCode, string(body))
}
var response OllamaTagsResponse
if err := json.Unmarshal(body, &response); err != nil {
return nil, fmt.Errorf("ошибка парсинга ответа: %w", err)
}
var models []string
for _, model := range response.Models {
models = append(models, model.Name)
}
return models, nil
}

224
main.go
View File

@@ -8,6 +8,7 @@ import (
"os/exec" "os/exec"
"os/user" "os/user"
"path" "path"
"strconv"
"strings" "strings"
"time" "time"
@@ -30,6 +31,8 @@ var (
RESULT_FOLDER = getEnv("LCG_RESULT_FOLDER", path.Join(cwd, "gpt_results")) RESULT_FOLDER = getEnv("LCG_RESULT_FOLDER", path.Join(cwd, "gpt_results"))
PROVIDER_TYPE = getEnv("LCG_PROVIDER", "ollama") // "ollama", "proxy" PROVIDER_TYPE = getEnv("LCG_PROVIDER", "ollama") // "ollama", "proxy"
JWT_TOKEN = getEnv("LCG_JWT_TOKEN", "") JWT_TOKEN = getEnv("LCG_JWT_TOKEN", "")
PROMPT_ID = getEnv("LCG_PROMPT_ID", "1") // ID промпта по умолчанию
TIMEOUT = getEnv("LCG_TIMEOUT", "120") // Таймаут в секундах по умолчанию
) )
const ( const (
@@ -76,21 +79,50 @@ Linux Command GPT - инструмент для генерации Linux ком
&cli.StringFlag{ &cli.StringFlag{
Name: "sys", Name: "sys",
Aliases: []string{"s"}, Aliases: []string{"s"},
Usage: "System prompt", Usage: "System prompt content or ID",
DefaultText: getEnv("LCG_PROMPT", "Reply with linux command and nothing else. Output with plain response - no need formatting. No need explanation. No need code blocks"), DefaultText: "Use prompt ID from LCG_PROMPT_ID or default prompt",
Value: getEnv("LCG_PROMPT", "Reply with linux command and nothing else. Output with plain response - no need formatting. No need explanation. No need code blocks"), Value: "",
},
&cli.IntFlag{
Name: "prompt-id",
Aliases: []string{"pid"},
Usage: "System prompt ID (1-5 for default prompts)",
DefaultText: "1",
Value: 1,
},
&cli.IntFlag{
Name: "timeout",
Aliases: []string{"t"},
Usage: "Request timeout in seconds",
DefaultText: "120",
Value: 120,
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
file := c.String("file") file := c.String("file")
system := c.String("sys") system := c.String("sys")
promptID := c.Int("prompt-id")
timeout := c.Int("timeout")
args := c.Args().Slice() args := c.Args().Slice()
if len(args) == 0 { if len(args) == 0 {
cli.ShowAppHelp(c) cli.ShowAppHelp(c)
showTips() showTips()
return nil return nil
} }
executeMain(file, system, strings.Join(args, " "))
// Если указан prompt-id, загружаем соответствующий промпт
if system == "" && promptID > 0 {
currentUser, _ := user.Current()
pm := gpt.NewPromptManager(currentUser.HomeDir)
if prompt, err := pm.GetPromptByID(promptID); err == nil {
system = prompt.Content
} else {
fmt.Printf("Warning: Prompt ID %d not found, using default prompt\n", promptID)
}
}
executeMain(file, system, strings.Join(args, " "), timeout)
return nil return nil
}, },
} }
@@ -117,7 +149,15 @@ func getCommands() []*cli.Command {
Aliases: []string{"u"}, Aliases: []string{"u"},
Usage: "Update the API key", Usage: "Update the API key",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
gpt3 := initGPT(PROMPT) if PROVIDER_TYPE == "ollama" || PROVIDER_TYPE == "proxy" {
fmt.Println("API key is not needed for ollama and proxy providers")
return nil
}
timeout := 120 // default timeout
if t, err := strconv.Atoi(TIMEOUT); err == nil {
timeout = t
}
gpt3 := initGPT(PROMPT, timeout)
gpt3.UpdateKey() gpt3.UpdateKey()
fmt.Println("API key updated.") fmt.Println("API key updated.")
return nil return nil
@@ -128,7 +168,15 @@ func getCommands() []*cli.Command {
Aliases: []string{"d"}, Aliases: []string{"d"},
Usage: "Delete the API key", Usage: "Delete the API key",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
gpt3 := initGPT(PROMPT) if PROVIDER_TYPE == "ollama" || PROVIDER_TYPE == "proxy" {
fmt.Println("API key is not needed for ollama and proxy providers")
return nil
}
timeout := 120 // default timeout
if t, err := strconv.Atoi(TIMEOUT); err == nil {
timeout = t
}
gpt3 := initGPT(PROMPT, timeout)
gpt3.DeleteKey() gpt3.DeleteKey()
fmt.Println("API key deleted.") fmt.Println("API key deleted.")
return nil return nil
@@ -180,12 +228,39 @@ func getCommands() []*cli.Command {
return nil return nil
}, },
}, },
{
Name: "models",
Aliases: []string{"m"},
Usage: "Show available models",
Action: func(c *cli.Context) error {
timeout := 120 // default timeout
if t, err := strconv.Atoi(TIMEOUT); err == nil {
timeout = t
}
gpt3 := initGPT(PROMPT, timeout)
models, err := gpt3.GetAvailableModels()
if err != nil {
fmt.Printf("Ошибка получения моделей: %v\n", err)
return err
}
fmt.Printf("Доступные модели для провайдера %s:\n", PROVIDER_TYPE)
for i, model := range models {
fmt.Printf(" %d. %s\n", i+1, model)
}
return nil
},
},
{ {
Name: "health", Name: "health",
Aliases: []string{"he"}, // Изменено с "h" на "he" Aliases: []string{"he"}, // Изменено с "h" на "he"
Usage: "Check API health", Usage: "Check API health",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
gpt3 := initGPT(PROMPT) timeout := 120 // default timeout
if t, err := strconv.Atoi(TIMEOUT); err == nil {
timeout = t
}
gpt3 := initGPT(PROMPT, timeout)
if err := gpt3.Health(); err != nil { if err := gpt3.Health(); err != nil {
fmt.Printf("Health check failed: %v\n", err) fmt.Printf("Health check failed: %v\n", err)
return err return err
@@ -203,6 +278,7 @@ func getCommands() []*cli.Command {
fmt.Printf("Host: %s\n", HOST) fmt.Printf("Host: %s\n", HOST)
fmt.Printf("Model: %s\n", MODEL) fmt.Printf("Model: %s\n", MODEL)
fmt.Printf("Prompt: %s\n", PROMPT) fmt.Printf("Prompt: %s\n", PROMPT)
fmt.Printf("Timeout: %s seconds\n", TIMEOUT)
if PROVIDER_TYPE == "proxy" { if PROVIDER_TYPE == "proxy" {
fmt.Printf("JWT Token: %s\n", func() string { fmt.Printf("JWT Token: %s\n", func() string {
if JWT_TOKEN != "" { if JWT_TOKEN != "" {
@@ -228,10 +304,126 @@ func getCommands() []*cli.Command {
return nil return nil
}, },
}, },
{
Name: "prompts",
Aliases: []string{"p"},
Usage: "Manage system prompts",
Subcommands: []*cli.Command{
{
Name: "list",
Aliases: []string{"l"},
Usage: "List all available prompts",
Action: func(c *cli.Context) error {
currentUser, _ := user.Current()
pm := gpt.NewPromptManager(currentUser.HomeDir)
pm.ListPrompts()
return nil
},
},
{
Name: "add",
Aliases: []string{"a"},
Usage: "Add a new custom prompt",
Action: func(c *cli.Context) error {
currentUser, _ := user.Current()
pm := gpt.NewPromptManager(currentUser.HomeDir)
var name, description, content string
fmt.Print("Название промпта: ")
fmt.Scanln(&name)
fmt.Print("Описание: ")
fmt.Scanln(&description)
fmt.Print("Содержание промпта: ")
fmt.Scanln(&content)
if err := pm.AddCustomPrompt(name, description, content); err != nil {
fmt.Printf("Ошибка добавления промпта: %v\n", err)
return err
}
fmt.Println("Промпт успешно добавлен!")
return nil
},
},
{
Name: "delete",
Aliases: []string{"d"},
Usage: "Delete a custom prompt",
Action: func(c *cli.Context) error {
if c.NArg() == 0 {
fmt.Println("Укажите ID промпта для удаления")
return nil
}
var id int
if _, err := fmt.Sscanf(c.Args().First(), "%d", &id); err != nil {
fmt.Println("Неверный ID промпта")
return err
}
currentUser, _ := user.Current()
pm := gpt.NewPromptManager(currentUser.HomeDir)
if err := pm.DeleteCustomPrompt(id); err != nil {
fmt.Printf("Ошибка удаления промпта: %v\n", err)
return err
}
fmt.Println("Промпт успешно удален!")
return nil
},
},
},
},
{
Name: "test-prompt",
Aliases: []string{"tp"},
Usage: "Test a specific prompt ID",
Action: func(c *cli.Context) error {
if c.NArg() == 0 {
fmt.Println("Usage: lcg test-prompt <prompt-id> <command>")
return nil
}
var promptID int
if _, err := fmt.Sscanf(c.Args().First(), "%d", &promptID); err != nil {
fmt.Println("Invalid prompt ID")
return err
}
currentUser, _ := user.Current()
pm := gpt.NewPromptManager(currentUser.HomeDir)
prompt, err := pm.GetPromptByID(promptID)
if err != nil {
fmt.Printf("Prompt ID %d not found\n", promptID)
return err
}
fmt.Printf("Testing prompt ID %d: %s\n", promptID, prompt.Name)
fmt.Printf("Description: %s\n", prompt.Description)
fmt.Printf("Content: %s\n", prompt.Content)
if len(c.Args().Slice()) > 1 {
command := strings.Join(c.Args().Slice()[1:], " ")
fmt.Printf("\nTesting with command: %s\n", command)
timeout := 120 // default timeout
if t, err := strconv.Atoi(TIMEOUT); err == nil {
timeout = t
}
executeMain("", prompt.Content, command, timeout)
}
return nil
},
},
} }
} }
func executeMain(file, system, commandInput string) { func executeMain(file, system, commandInput string, timeout int) {
if file != "" { if file != "" {
if err := reader.FileToPrompt(&commandInput, file); err != nil { if err := reader.FileToPrompt(&commandInput, file); err != nil {
printColored(fmt.Sprintf("❌ Ошибка чтения файла: %v\n", err), colorRed) printColored(fmt.Sprintf("❌ Ошибка чтения файла: %v\n", err), colorRed)
@@ -239,6 +431,11 @@ func executeMain(file, system, commandInput string) {
} }
} }
// Если system пустой, используем дефолтный промпт
if system == "" {
system = PROMPT
}
if _, err := os.Stat(RESULT_FOLDER); os.IsNotExist(err) { if _, err := os.Stat(RESULT_FOLDER); os.IsNotExist(err) {
if err := os.MkdirAll(RESULT_FOLDER, 0755); err != nil { if err := os.MkdirAll(RESULT_FOLDER, 0755); err != nil {
printColored(fmt.Sprintf("❌ Ошибка создания папки результатов: %v\n", err), colorRed) printColored(fmt.Sprintf("❌ Ошибка создания папки результатов: %v\n", err), colorRed)
@@ -246,7 +443,7 @@ func executeMain(file, system, commandInput string) {
} }
} }
gpt3 := initGPT(system) gpt3 := initGPT(system, timeout)
printColored("🤖 Запрос: ", colorCyan) printColored("🤖 Запрос: ", colorCyan)
fmt.Printf("%s\n", commandInput) fmt.Printf("%s\n", commandInput)
@@ -265,7 +462,7 @@ func executeMain(file, system, commandInput string) {
handlePostResponse(response, gpt3, system, commandInput) handlePostResponse(response, gpt3, system, commandInput)
} }
func initGPT(system string) gpt.Gpt3 { func initGPT(system string, timeout int) gpt.Gpt3 {
currentUser, _ := user.Current() currentUser, _ := user.Current()
// Загружаем JWT токен в зависимости от провайдера // Загружаем JWT токен в зависимости от провайдера
@@ -281,7 +478,7 @@ func initGPT(system string) gpt.Gpt3 {
} }
} }
return *gpt.NewGpt3(PROVIDER_TYPE, HOST, jwtToken, MODEL, system, 0.01) return *gpt.NewGpt3(PROVIDER_TYPE, HOST, jwtToken, MODEL, system, 0.01, timeout)
} }
func getCommand(gpt3 gpt.Gpt3, cmd string) (string, float64) { func getCommand(gpt3 gpt.Gpt3, cmd string) (string, float64) {
@@ -326,7 +523,7 @@ func handlePostResponse(response string, gpt3 gpt.Gpt3, system, cmd string) {
saveResponse(response, gpt3, cmd) saveResponse(response, gpt3, cmd)
case "r": case "r":
fmt.Println("🔄 Перегенерирую...") fmt.Println("🔄 Перегенерирую...")
executeMain("", system, cmd) executeMain("", system, cmd, 120) // Use default timeout for regeneration
case "e": case "e":
executeCommand(response) executeCommand(response)
default: default:
@@ -420,6 +617,9 @@ func showTips() {
printColored("💡 Подсказки:\n", colorCyan) printColored("💡 Подсказки:\n", colorCyan)
fmt.Println(" • Используйте --file для чтения из файла") fmt.Println(" • Используйте --file для чтения из файла")
fmt.Println(" • Используйте --sys для изменения системного промпта") fmt.Println(" • Используйте --sys для изменения системного промпта")
fmt.Println(" • Используйте --prompt-id для выбора предустановленного промпта")
fmt.Println(" • Используйте --timeout для установки таймаута запроса")
fmt.Println(" • Команда 'prompts list' покажет все доступные промпты")
fmt.Println(" • Команда 'history' покажет историю запросов") fmt.Println(" • Команда 'history' покажет историю запросов")
fmt.Println(" • Команда 'config' покажет текущие настройки") fmt.Println(" • Команда 'config' покажет текущие настройки")
fmt.Println(" • Команда 'health' проверит доступность API") fmt.Println(" • Команда 'health' проверит доступность API")

View File

@@ -0,0 +1,6 @@
#!/usr/bin/bash
# shellcheck disable=SC2034
LCG_PROVIDER=proxy LCG_HOST=http://localhost:8080 LCG_MODEL=GigaChat-2-Max LCG_JWT_TOKEN=$(go-ansible-vault -a -i shell-code/jwt.admin.token get -m 'JWT_TOKEN' -q) go run . $1 $2 $3 $4 $5 $6 $7 $8 $9
LCG_PROVIDER=proxy LCG_HOST=https://direct-dev.ru LCG_MODEL=GigaChat-2-Max LCG_JWT_TOKEN=$(go-ansible-vault --key $(cat ~/.config/gak) -i ~/.config/jwt.direct-dev.ru get -m 'JWT_TOKEN' -q) go run . [your question here]