2023-11-12 05:41:59 +01:00
|
|
|
package ai
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2023-12-20 05:54:56 +01:00
|
|
|
"os/exec"
|
2023-12-20 01:49:31 +01:00
|
|
|
"runtime"
|
2023-11-12 05:41:59 +01:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ddworken/hishtory/client/data"
|
|
|
|
"github.com/ddworken/hishtory/client/hctx"
|
|
|
|
"github.com/ddworken/hishtory/client/lib"
|
|
|
|
"github.com/ddworken/hishtory/shared/ai"
|
|
|
|
)
|
|
|
|
|
|
|
|
var mostRecentQuery string
|
|
|
|
|
2024-02-19 21:12:04 +01:00
|
|
|
func DebouncedGetAiSuggestions(ctx context.Context, shellName, query string, numberCompletions int) ([]string, error) {
|
2023-11-12 05:41:59 +01:00
|
|
|
mostRecentQuery = query
|
|
|
|
time.Sleep(time.Millisecond * 300)
|
|
|
|
if mostRecentQuery == query {
|
2024-02-19 21:12:04 +01:00
|
|
|
return GetAiSuggestions(ctx, shellName, query, numberCompletions)
|
2023-11-12 05:41:59 +01:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2024-02-19 21:12:04 +01:00
|
|
|
func GetAiSuggestions(ctx context.Context, shellName, query string, numberCompletions int) ([]string, error) {
|
2024-03-27 06:13:57 +01:00
|
|
|
if os.Getenv("OPENAI_API_KEY") == "" && hctx.GetConf(ctx).AiCompletionEndpoint == ai.DefaultOpenAiEndpoint {
|
2024-02-19 21:12:04 +01:00
|
|
|
return GetAiSuggestionsViaHishtoryApi(ctx, shellName, query, numberCompletions)
|
2023-11-12 05:41:59 +01:00
|
|
|
} else {
|
2024-03-27 06:13:57 +01:00
|
|
|
suggestions, _, err := ai.GetAiSuggestionsViaOpenAiApi(hctx.GetConf(ctx).AiCompletionEndpoint, query, shellName, getOsName(), numberCompletions)
|
2023-11-12 05:41:59 +01:00
|
|
|
return suggestions, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-20 01:49:31 +01:00
|
|
|
func getOsName() string {
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "linux":
|
2023-12-20 05:54:56 +01:00
|
|
|
if _, err := exec.LookPath("apt-get"); err == nil {
|
|
|
|
return "Ubuntu Linux"
|
|
|
|
}
|
|
|
|
if _, err := exec.LookPath("dnf"); err == nil {
|
|
|
|
return "Fedora Linux"
|
|
|
|
}
|
|
|
|
if _, err := exec.LookPath("pacman"); err == nil {
|
|
|
|
return "Arch Linux"
|
|
|
|
}
|
2023-12-20 01:49:31 +01:00
|
|
|
return "Linux"
|
|
|
|
case "darwin":
|
|
|
|
return "MacOS"
|
|
|
|
default:
|
|
|
|
return runtime.GOOS
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-19 21:12:04 +01:00
|
|
|
func GetAiSuggestionsViaHishtoryApi(ctx context.Context, shellName, query string, numberCompletions int) ([]string, error) {
|
2023-11-12 06:44:21 +01:00
|
|
|
hctx.GetLogger().Infof("Running OpenAI query for %#v", query)
|
2023-11-12 05:41:59 +01:00
|
|
|
req := ai.AiSuggestionRequest{
|
|
|
|
DeviceId: hctx.GetConf(ctx).DeviceId,
|
|
|
|
UserId: data.UserId(hctx.GetConf(ctx).UserSecret),
|
|
|
|
Query: query,
|
|
|
|
NumberCompletions: numberCompletions,
|
2023-12-20 01:49:31 +01:00
|
|
|
OsName: getOsName(),
|
2024-02-19 21:12:04 +01:00
|
|
|
ShellName: shellName,
|
2023-11-12 05:41:59 +01:00
|
|
|
}
|
|
|
|
reqData, err := json.Marshal(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to marshal AiSuggestionRequest: %w", err)
|
|
|
|
}
|
|
|
|
respData, err := lib.ApiPost(ctx, "/api/v1/ai-suggest", "application/json", reqData)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to query /api/v1/ai-suggest: %w", err)
|
|
|
|
}
|
|
|
|
var resp ai.AiSuggestionResponse
|
|
|
|
err = json.Unmarshal(respData, &resp)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to parse /api/v1/ai-suggest response: %w", err)
|
|
|
|
}
|
2023-11-12 06:44:21 +01:00
|
|
|
hctx.GetLogger().Infof("For OpenAI query=%#v ==> %#v", query, resp.Suggestions)
|
2023-11-12 05:41:59 +01:00
|
|
|
return resp.Suggestions, nil
|
|
|
|
}
|