diff --git a/.gitignore b/.gitignore index 4d77469..815e9d3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ shell-code/build.env bin-linux-amd64/* bin-linux-arm64/* binaries-for-upload/* -gpt_results \ No newline at end of file +gpt_results +shell-code/jwt.admin.token diff --git a/Dockerfiles/ImageBuild/Dockerfile b/Dockerfiles/ImageBuild/Dockerfile index 847bd6d..3d9cae7 100644 --- a/Dockerfiles/ImageBuild/Dockerfile +++ b/Dockerfiles/ImageBuild/Dockerfile @@ -2,7 +2,8 @@ FROM --platform=${BUILDPLATFORM} golang:1.24.6-alpine3.22 AS builder ARG TARGETARCH -RUN apk add git && go install mvdan.cc/garble@latest +RUN apk add git +#&& go install mvdan.cc/garble@latest WORKDIR /app @@ -11,8 +12,8 @@ COPY . . RUN echo $BUILDPLATFORM > buildplatform RUN echo $TARGETARCH > targetarch -# RUN GOOS=linux GOARCH=$TARGETARCH go build -o /app/go-lcg . -RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} garble -literals -tiny build -ldflags="-w -s" -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 . FROM alpine:latest diff --git a/Dockerfiles/LocalCompile/Dockerfile b/Dockerfiles/LocalCompile/Dockerfile index f5e4c74..d058150 100644 --- a/Dockerfiles/LocalCompile/Dockerfile +++ b/Dockerfiles/LocalCompile/Dockerfile @@ -1,15 +1,16 @@ FROM --platform=${BUILDPLATFORM} golang:1.24.6-alpine3.22 AS build ARG TARGETOS ARG TARGETARCH -RUN apk add git && go install mvdan.cc/garble@latest +# RUN apk add git +#&& go install mvdan.cc/garble@latest WORKDIR /src ENV CGO_ENABLED=0 COPY go.* . RUN go mod download COPY . . -# RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -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} 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 . FROM scratch AS bin-unix COPY --from=build /out/go-lcg /lcg diff --git a/VERSION.txt b/VERSION.txt index b18d465..795460f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -v1.0.1 +v1.1.0 diff --git a/gpt/gpt.go b/gpt/gpt.go index 7cf978a..a5c9eff 100644 --- a/gpt/gpt.go +++ b/gpt/gpt.go @@ -151,8 +151,8 @@ func (gpt3 *Gpt3) DeleteKey() { } func (gpt3 *Gpt3) InitKey() { - // Для proxy провайдера не нужен API ключ, используется JWT токен - if gpt3.ProviderType == "proxy" { + // Для ollama и proxy провайдеров не нужен API ключ + if gpt3.ProviderType == "ollama" || gpt3.ProviderType == "proxy" { return } @@ -167,16 +167,16 @@ func (gpt3 *Gpt3) InitKey() { } // 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 switch providerType { case "proxy": - provider = NewProxyAPIProvider(host, apiKey, model) // apiKey используется как JWT токен + provider = NewProxyAPIProvider(host, apiKey, model, timeout) // apiKey используется как JWT токен case "ollama": - provider = NewOllamaProvider(host, model, temperature) + provider = NewOllamaProvider(host, model, temperature, timeout) default: - provider = NewOllamaProvider(host, model, temperature) + provider = NewOllamaProvider(host, model, temperature, timeout) } return &Gpt3{ @@ -209,3 +209,8 @@ func (gpt3 *Gpt3) Completions(ask string) string { func (gpt3 *Gpt3) Health() error { return gpt3.Provider.Health() } + +// GetAvailableModels возвращает список доступных моделей +func (gpt3 *Gpt3) GetAvailableModels() ([]string, error) { + return gpt3.Provider.GetAvailableModels() +} diff --git a/gpt/prompts.go b/gpt/prompts.go new file mode 100644 index 0000000..fad3efa --- /dev/null +++ b/gpt/prompts.go @@ -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] + "..." +} diff --git a/gpt/providers.go b/gpt/providers.go index da66ce6..f84e6ec 100644 --- a/gpt/providers.go +++ b/gpt/providers.go @@ -14,6 +14,7 @@ import ( type Provider interface { Chat(messages []Chat) (string, error) Health() error + GetAvailableModels() ([]string, error) } // ProxyAPIProvider реализация для прокси API (gin-restapi) @@ -66,21 +67,30 @@ type OllamaProvider struct { 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{ BaseURL: strings.TrimSuffix(baseURL, "/"), JWTToken: jwtToken, 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{ BaseURL: strings.TrimSuffix(baseURL, "/"), Model: model, Temperature: temperature, - HTTPClient: &http.Client{Timeout: 120 * time.Second}, + HTTPClient: &http.Client{Timeout: time.Duration(timeout) * time.Second}, } } @@ -88,12 +98,12 @@ func NewOllamaProvider(baseURL, model string, temperature float64) *OllamaProvid func (p *ProxyAPIProvider) Chat(messages []Chat) (string, error) { // Используем основной endpoint /api/v1/protected/sberchat/chat payload := ProxyChatRequest{ - Messages: messages, - Model: p.Model, - Temperature: 0.5, - TopP: 0.5, - Stream: false, - RandomWords: []string{"linux", "command", "gpt"}, + Messages: messages, + Model: p.Model, + Temperature: 0.5, + TopP: 0.5, + Stream: false, + RandomWords: []string{"linux", "command", "gpt"}, FallbackString: "I'm sorry, I can't help with that. Please try again.", } @@ -244,3 +254,43 @@ func (o *OllamaProvider) Health() error { 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 +} diff --git a/main.go b/main.go index 36c47ee..3e984f8 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "os/exec" "os/user" "path" + "strconv" "strings" "time" @@ -30,6 +31,8 @@ var ( RESULT_FOLDER = getEnv("LCG_RESULT_FOLDER", path.Join(cwd, "gpt_results")) PROVIDER_TYPE = getEnv("LCG_PROVIDER", "ollama") // "ollama", "proxy" JWT_TOKEN = getEnv("LCG_JWT_TOKEN", "") + PROMPT_ID = getEnv("LCG_PROMPT_ID", "1") // ID промпта по умолчанию + TIMEOUT = getEnv("LCG_TIMEOUT", "120") // Таймаут в секундах по умолчанию ) const ( @@ -76,21 +79,50 @@ Linux Command GPT - инструмент для генерации Linux ком &cli.StringFlag{ Name: "sys", Aliases: []string{"s"}, - Usage: "System prompt", - 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"), - 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"), + Usage: "System prompt content or ID", + DefaultText: "Use prompt ID from LCG_PROMPT_ID or default prompt", + 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 { file := c.String("file") system := c.String("sys") + promptID := c.Int("prompt-id") + timeout := c.Int("timeout") args := c.Args().Slice() + if len(args) == 0 { cli.ShowAppHelp(c) showTips() 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 }, } @@ -117,7 +149,15 @@ func getCommands() []*cli.Command { Aliases: []string{"u"}, Usage: "Update the API key", 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() fmt.Println("API key updated.") return nil @@ -128,7 +168,15 @@ func getCommands() []*cli.Command { Aliases: []string{"d"}, Usage: "Delete the API key", 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() fmt.Println("API key deleted.") return nil @@ -180,12 +228,39 @@ func getCommands() []*cli.Command { 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", Aliases: []string{"he"}, // Изменено с "h" на "he" Usage: "Check API health", 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 { fmt.Printf("Health check failed: %v\n", err) return err @@ -203,6 +278,7 @@ func getCommands() []*cli.Command { fmt.Printf("Host: %s\n", HOST) fmt.Printf("Model: %s\n", MODEL) fmt.Printf("Prompt: %s\n", PROMPT) + fmt.Printf("Timeout: %s seconds\n", TIMEOUT) if PROVIDER_TYPE == "proxy" { fmt.Printf("JWT Token: %s\n", func() string { if JWT_TOKEN != "" { @@ -228,10 +304,126 @@ func getCommands() []*cli.Command { 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 ") + 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 err := reader.FileToPrompt(&commandInput, file); err != nil { 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.MkdirAll(RESULT_FOLDER, 0755); err != nil { 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) fmt.Printf("%s\n", commandInput) @@ -265,7 +462,7 @@ func executeMain(file, system, commandInput string) { handlePostResponse(response, gpt3, system, commandInput) } -func initGPT(system string) gpt.Gpt3 { +func initGPT(system string, timeout int) gpt.Gpt3 { currentUser, _ := user.Current() // Загружаем 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) { @@ -326,7 +523,7 @@ func handlePostResponse(response string, gpt3 gpt.Gpt3, system, cmd string) { saveResponse(response, gpt3, cmd) case "r": fmt.Println("🔄 Перегенерирую...") - executeMain("", system, cmd) + executeMain("", system, cmd, 120) // Use default timeout for regeneration case "e": executeCommand(response) default: @@ -420,6 +617,9 @@ func showTips() { printColored("💡 Подсказки:\n", colorCyan) fmt.Println(" • Используйте --file для чтения из файла") fmt.Println(" • Используйте --sys для изменения системного промпта") + fmt.Println(" • Используйте --prompt-id для выбора предустановленного промпта") + fmt.Println(" • Используйте --timeout для установки таймаута запроса") + fmt.Println(" • Команда 'prompts list' покажет все доступные промпты") fmt.Println(" • Команда 'history' покажет историю запросов") fmt.Println(" • Команда 'config' покажет текущие настройки") fmt.Println(" • Команда 'health' проверит доступность API") diff --git a/shell-code/run-with-proxy.sh b/shell-code/run-with-proxy.sh new file mode 100644 index 0000000..ecd7485 --- /dev/null +++ b/shell-code/run-with-proxy.sh @@ -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] \ No newline at end of file