Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,43 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"name": "Debug `bot`",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {"DEBUG": "1"},
"console": "integratedTerminal",
},
{
"name": "Debug `bot nc`",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {"DEBUG": "1"},
"console": "integratedTerminal",
"args": ["nc"]
},
{
"name": "Debug `bot -mode config chron`",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {"DEBUG": "1"},
"console": "integratedTerminal",
"args": ["-mode","config","cron"]
},
{
"name": "Debug `bot i`",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {"DEBUG": "1"},
"console": "integratedTerminal",
"args": ["-i"]
}
]
}
82 changes: 61 additions & 21 deletions bot.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"embed"
_ "embed"
"flag"
"fmt"
Expand All @@ -11,41 +12,51 @@ import (
"sync"
)

//go:embed prompt_prefix.txt
var promptPrefix string
/*
- The "go:embed" directive must immediately precede a line containing the declaration of a single variable
- Therefore, this program embeds all files in the current folder that match prompt_prefix*.txt into a file system variable "promptPrefixFS"
- Then, depending on the flags passed to the command, the actual "promptPrefix" is defined by reading from "promptPrefixFS"
- This method makes use of the embed directive while allowing the final "promptPrefix" to be conditionally defined
*/

//go:embed prompt_prefix*.txt
var promptPrefixFS embed.FS

const promptStartText = "\n[EXAMPLES]\n"

var err error

func main() {

args := parseArgs()
if len(args.Prompt) == 0 {
usage()
os.Exit(1)

var promptPrefix []byte
switch args.Config {
case false:
promptPrefix, err = promptPrefixFS.ReadFile("prompt_prefix_command.txt")
errHandler(err, "Error reading prompt_prefix_command")
case true:
promptPrefix, err = promptPrefixFS.ReadFile("prompt_prefix_config.txt")
errHandler(err, "Error reading prompt_prefix_config")
}

homeDir, err := os.UserHomeDir()
if err != nil {
fmt.Fprintf(os.Stderr, "Error retrieving home directory: %v", err)
os.Exit(1)
}
errHandler(err, "Error retrieving home directory")

configPath := filepath.Join(homeDir, configFilename)
config, err := loadConfig(configPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading config: %v", err)
os.Exit(1)
}
botConfigPath := filepath.Join(homeDir, configFilename)
botConfig, err := loadConfig(botConfigPath)
errHandler(err, "Error loading config")

respCh := make(chan string)

var wg sync.WaitGroup
wg.Add(2)

client := &OpenAIAdapter{APIKey: config.APIKey}
client := &OpenAIAdapter{APIKey: botConfig.APIKey}
go func() {
defer wg.Done()
err := client.FetchCompletionStream(CreateRequest(args.Prompt), respCh)
err := client.FetchCompletionStream(CreateRequest(string(promptPrefix), args.Prompt), respCh)
errHandler(err)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
Expand All @@ -61,19 +72,36 @@ func main() {
}

type Args struct {
Help bool
Interactive bool
Config bool
Prompt string
}

func parseArgs() *Args {
interactive := flag.Bool("i", false, "Enter interactive mode (optional)")

help := flag.Bool("help", false, "Display usage options")
interactive := flag.Bool("i", false, "Enter interactive mode (coming soon!)")
config := flag.Bool("config", false, "Optional flag to operate as config bot")
flag.Parse()
prompt := strings.Join(flag.Args(), " ")
return &Args{Interactive: *interactive, Prompt: prompt}

if *help || len(os.Args) < 2 || len(prompt) == 0 {
Usage()
}

return &Args{Help: *help, Interactive: *interactive, Config: *config, Prompt: prompt}
}

func usage() {
fmt.Fprintf(os.Stderr, "Usage: %s [prompt]", os.Args[0])
func Usage() {
fmt.Println("Simple command-line utility for looking up command usage or config file examples.")
fmt.Println("Flags:")
flag.PrintDefaults()
fmt.Println("Example usage:")
fmt.Println(" bot nc")
fmt.Println(" bot -config cron")
fmt.Println(" bot -help")
os.Exit(1)
}

func RenderCompletionStreamResponse(w io.Writer, respCh <-chan string) {
Expand All @@ -82,3 +110,15 @@ func RenderCompletionStreamResponse(w io.Writer, respCh <-chan string) {
}
fmt.Fprintln(w, "")
}

func errHandler(err error, args ...string) {
errString := "Error"
if len(args) > 0 {
errString = args[0]
}

if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v", errString, err)
os.Exit(1)
}
}
2 changes: 1 addition & 1 deletion openai_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type OpenAIAdapter struct {
APIKey string
}

func CreateRequest(prompt string) openai.CompletionRequest {
func CreateRequest(promptPrefix string, prompt string) openai.CompletionRequest {
return openai.CompletionRequest{
Model: openai.GPT3TextDavinci003,
MaxTokens: 1024,
Expand Down
2 changes: 1 addition & 1 deletion openai_adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestFetchCompletionStream(t *testing.T) {

go func() {
defer wg.Done()
err := client.FetchCompletionStream(CreateRequest("prompt"), respCh)
err := client.FetchCompletionStream(CreateRequest("promptPrefix", "prompt"), respCh)
if err != nil {
fmt.Println(err)
}
Expand Down
File renamed without changes.
23 changes: 23 additions & 0 deletions prompt_prefix_config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Provide example usage of configuraiton file information when the user provides the configuration file name or description. Use variable names in place of user-provided arguments. If the configuration file does not exist, respond with [NOT FOUND].

COMMAND>.ssh/config
[EXAMPLES]
# Basic use example
Host dev
HostName $HOSTNAME
User $USERNAME
Port $PORT

# Advanced use example
Host dev
HostName $HOSTNAME
User $USERNAME
Port $PORT
IdentityFile $IDENTITYFILE
LogLevel $LOGLEVEL
Compression $COMPRESSION

[REFERENCES]
- https://linuxize.com/post/using-the-ssh-config-file/

COMMAND>