gchatsh 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/Makefile +7 -0
- data/bin/gchatsh +5 -0
- data/lib/credentials.rb +29 -0
- data/lib/gchatsh/version.rb +1 -1
- data/lib/gchatsh.rb +18 -215
- data/lib/groq_api.rb +55 -0
- data/lib/options.rb +9 -0
- data/lib/parser.rb +41 -0
- data/lib/request.rb +48 -0
- data/lib/syntax_highlighter.rb +15 -0
- data/lib/system_prompt.txt +184 -0
- data/lib/user_input.rb +26 -0
- metadata +19 -12
- data/LICENSE.txt +0 -21
- data/gchatsh.rb +0 -222
- data/install-locally.sh +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15e8554d23c59775496e8459936f7fba1caecb5bab66d7037ac65e84c8592068
|
4
|
+
data.tar.gz: dd6d7d0b047f450923fc984771aa610afdd6d4ef5d0379e656666957e4407525
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ed0cb1b67355dd020c42f3ef3360b346f814d1ef016918796dc5ab3f166df109e42a41fd0addb56572ffbfa5eb2d3c679714ba04878555769fa97d78eaf4ae6
|
7
|
+
data.tar.gz: d95fa6665e69e4eaf21fe9e044f7ae246d9c5da5a969fd4b8cf3fa831028f1ce7ec7bf00a24af9f6a9a5518b534f608057bd5db6f6199c3451f66fe8cdeba732
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.1.3
|
data/Makefile
ADDED
data/bin/gchatsh
ADDED
data/lib/credentials.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Credentials class
|
4
|
+
class Credentials
|
5
|
+
attr_accessor :url, :key, :model
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
credentials_file = File.expand_path('~/.gchatsh')
|
9
|
+
unless File.exist?(credentials_file)
|
10
|
+
raise "Credentials file not found at #{credentials_file} " \
|
11
|
+
"add a file here with the following credentials format:\n" \
|
12
|
+
"GROQ_API_URL=<API_URL>\nAPI_KEY=<API_KEY>"
|
13
|
+
end
|
14
|
+
|
15
|
+
File.readlines(credentials_file).each do |line|
|
16
|
+
key, value = line.strip.split('=')
|
17
|
+
case key
|
18
|
+
when 'KEY'
|
19
|
+
@key = value
|
20
|
+
when 'URL'
|
21
|
+
@url = value
|
22
|
+
when 'MODEL'
|
23
|
+
@model = value
|
24
|
+
else
|
25
|
+
raise 'Invalid credentials file format'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/gchatsh/version.rb
CHANGED
data/lib/gchatsh.rb
CHANGED
@@ -1,222 +1,25 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
credentials
|
4
|
+
require_relative 'credentials'
|
5
|
+
require_relative 'options'
|
6
|
+
require_relative 'groq_api'
|
7
|
+
require_relative 'user_input'
|
8
|
+
|
9
|
+
module GChatSH
|
10
|
+
class Application
|
11
|
+
attr_accessor :options
|
12
|
+
def initialize
|
13
|
+
@options = Options.new
|
14
|
+
@options.credentials = Credentials.new
|
15
15
|
end
|
16
|
-
else
|
17
|
-
raise "Credentials file not found at #{credentials_file} add a file here with the following credentials format:\nGROQ_API_URL=<API_URL>\nAPI_KEY=<API_KEY>"
|
18
|
-
end
|
19
|
-
|
20
|
-
credentials
|
21
|
-
end
|
22
|
-
|
23
|
-
credentials = read_credentials
|
24
|
-
GROQ_API_URL = credentials['GROQ_API_URL']
|
25
|
-
API_KEY = credentials['API_KEY']
|
26
|
-
|
27
|
-
SYSTEM_PROMPT = <<~SYSTEM_PROMPT
|
28
|
-
You are ChatSH, an AI language model that specializes in assisting users with tasks on their system using shell commands, AND chatting or answering open-ended questions via the terminal.
|
29
|
-
|
30
|
-
# CHATSH GUIDE:
|
31
|
-
|
32
|
-
- If the USER asks you to perform a SYSTEM TASK, ChatSH must answer with a SHELL SCRIPT to perform the task.
|
33
|
-
|
34
|
-
- If the USER asks an open-ended question, ChatSH must answer with a friendly, concise, factual response.
|
35
|
-
|
36
|
-
# EXAMPLE 1: CHATTING AND PERFORMING SYSTEM COMMANDS
|
37
|
-
|
38
|
-
<USER>
|
39
|
-
Show me local files.
|
40
|
-
</USER>
|
41
|
-
|
42
|
-
<ChatSH>
|
43
|
-
\`\`\`sh
|
44
|
-
ls
|
45
|
-
\`\`\`
|
46
|
-
</ChatSH>
|
47
|
-
|
48
|
-
<SYSTEM>
|
49
|
-
example.gif example.tst example_dir/
|
50
|
-
</SYSTEM>
|
51
|
-
|
52
|
-
<USER>
|
53
|
-
Is there any text file?
|
54
|
-
</USER>
|
55
|
-
|
56
|
-
<ChatSH>
|
57
|
-
Yes, there is a file named example.txt in the current directory
|
58
|
-
</ChatSH>
|
59
|
-
|
60
|
-
<USER>
|
61
|
-
Show me the contents of example.txt.
|
62
|
-
</USER>
|
63
|
-
|
64
|
-
<ChatSH>
|
65
|
-
\`\`\`sh
|
66
|
-
cat example.txt
|
67
|
-
\`\`\`
|
68
|
-
</ChatSH>
|
69
|
-
|
70
|
-
# EXAMPLE 2: ASSISTING WITH CODING TASKS
|
71
|
-
|
72
|
-
<USER>
|
73
|
-
Fix main.ts
|
74
|
-
</USER>
|
75
|
-
|
76
|
-
<ChatSH>
|
77
|
-
\`\`\`sh
|
78
|
-
cat main.ts
|
79
|
-
tsc --noEmit main.ts
|
80
|
-
\`\`\`
|
81
|
-
</ChatSH>
|
82
|
-
|
83
|
-
<SYSTEM>
|
84
|
-
import List from './list';
|
85
|
-
import map from './map';
|
86
|
-
|
87
|
-
const n_1_2: List<number> = { $: "cons", head: 1, tail: { $: "cons", head: 2, tail: { $: "nil" }}};
|
88
|
-
const n_2_4: List<number> = map(n_1_2, x => x * 2);
|
89
|
-
|
90
|
-
console.log(JSON.stringify(n_2_4));
|
91
|
-
|
92
|
-
map.ts:7:22 - error TS2345: Argument of type '(val: T) => U' is not assignable to parameter of type 'List<unknown>'.
|
93
|
-
|
94
|
-
7 let tail = map(fun, list.tail);
|
95
|
-
~~~
|
96
|
-
</SYSTEM>
|
97
16
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
list.ts main.ts map.ts
|
106
|
-
</SYSTEM>
|
107
|
-
|
108
|
-
<ChatSH>
|
109
|
-
\`\`\`sh
|
110
|
-
cat map.ts
|
111
|
-
\`\`\`
|
112
|
-
</ChatSH>
|
113
|
-
|
114
|
-
<SYSTEM>
|
115
|
-
import List from './list';
|
116
|
-
|
117
|
-
function map<T, U>(list: List<T>, fun: (val: T) => U): List<U> {
|
118
|
-
switch (list.$) {
|
119
|
-
case "cons":
|
120
|
-
let head = fun(list.head);
|
121
|
-
let tail = map(fun, list.tail);
|
122
|
-
return { $: "cons", head, tail };
|
123
|
-
case "nil":
|
124
|
-
return { $: "nil" };
|
125
|
-
}
|
126
|
-
}
|
127
|
-
|
128
|
-
export default map;
|
129
|
-
</SYSTEM>
|
130
|
-
|
131
|
-
<ChatSH>
|
132
|
-
\`\`\`sh
|
133
|
-
cat > map.ts << EOL
|
134
|
-
import List from './list';
|
135
|
-
|
136
|
-
function map<T, U>(list: List<T>, fun: (val: T) => U): List<U> {
|
137
|
-
switch (list.$) {
|
138
|
-
case "cons":
|
139
|
-
let head = fun(list.head);
|
140
|
-
let tail = map(list.tail, fun);
|
141
|
-
return { $: "cons", head, tail };
|
142
|
-
case "nil":
|
143
|
-
return { $: "nil" };
|
144
|
-
}
|
145
|
-
}
|
146
|
-
|
147
|
-
export default map;
|
148
|
-
EOL
|
149
|
-
tsc --noEmit map.ts
|
150
|
-
\`\`\`
|
151
|
-
</ChatSH>
|
152
|
-
|
153
|
-
<SYSTEM>
|
154
|
-
|
155
|
-
</SYSTEM>
|
156
|
-
|
157
|
-
<ChatSH>
|
158
|
-
Done.
|
159
|
-
</ChatSH>
|
160
|
-
|
161
|
-
## NOTES:
|
162
|
-
|
163
|
-
- In COMMAND MODE, answer with SH BLOCKS.
|
164
|
-
|
165
|
-
- In TEXT MODE, answer with normal text.
|
166
|
-
|
167
|
-
- Be concise, objective, correct and factual.
|
168
|
-
|
169
|
-
- Do not attempt to install new tools; assume they're available.
|
170
|
-
|
171
|
-
- Do not include the <ChatSH> tags in your answer.
|
172
|
-
|
173
|
-
- REMEMBER: you are NOT limited to system tasks or shell commands. You must answer ANY question or request by the user.
|
174
|
-
|
175
|
-
- The system shell in use is: bash.;
|
176
|
-
SYSTEM_PROMPT
|
177
|
-
|
178
|
-
# Function to send a code generation request to Groq API
|
179
|
-
def generate_code(prompt)
|
180
|
-
uri = URI(GROQ_API_URL)
|
181
|
-
request = Net::HTTP::Post.new(uri)
|
182
|
-
request['Content-Type'] = 'application/json'
|
183
|
-
request['Authorization'] = "Bearer #{API_KEY}"
|
184
|
-
|
185
|
-
request.body = {
|
186
|
-
"model": 'llama3-8b-8192',
|
187
|
-
"messages": [
|
188
|
-
{
|
189
|
-
"role": 'system',
|
190
|
-
"content": SYSTEM_PROMPT
|
191
|
-
},
|
192
|
-
{
|
193
|
-
"role": 'user',
|
194
|
-
"content": prompt
|
195
|
-
}
|
196
|
-
]
|
197
|
-
}.to_json
|
198
|
-
|
199
|
-
# Perform the request
|
200
|
-
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
201
|
-
http.request(request)
|
202
|
-
end
|
203
|
-
|
204
|
-
# Process and display the result
|
205
|
-
if response.code.to_i == 200
|
206
|
-
result = JSON.parse(response.body)
|
207
|
-
message_content = result.dig('choices', 0, 'message', 'content')
|
208
|
-
puts message_content
|
209
|
-
command = message_content.match(/sh\n(.+?)\n/m)[1]
|
210
|
-
puts "\033[32m Execute the following command? (y/n) \033[0m"
|
211
|
-
prompt = gets.chomp
|
212
|
-
system(command) if prompt == 'y'
|
213
|
-
else
|
214
|
-
puts "Error: #{response.code} - #{response.message}"
|
215
|
-
puts response.body
|
17
|
+
def call
|
18
|
+
system_prompt = File.read(File.join(__dir__, 'system_prompt.txt'))
|
19
|
+
user_prompt = UserInput.new.call
|
20
|
+
options.user_prompt = user_prompt
|
21
|
+
options.system_prompt = system_prompt
|
22
|
+
GroqApi.new(options).call
|
23
|
+
end
|
216
24
|
end
|
217
25
|
end
|
218
|
-
|
219
|
-
# Example usage
|
220
|
-
puts 'Enter your prompt for code generation:'
|
221
|
-
prompt = gets.chomp
|
222
|
-
generate_code(prompt)
|
data/lib/groq_api.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'request'
|
4
|
+
require_relative 'parser'
|
5
|
+
require_relative 'syntax_highlighter'
|
6
|
+
require 'net/http'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
# GroqApi
|
10
|
+
class GroqApi
|
11
|
+
attr_accessor :request, :syntax_highlighter
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@request = Request.new(options)
|
15
|
+
@syntax_highlighter = SyntaxHighlighter.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def xclip_installed?
|
19
|
+
system('which xclip > /dev/null 2>&1')
|
20
|
+
end
|
21
|
+
|
22
|
+
def call
|
23
|
+
message_content = request.call
|
24
|
+
File.open(File.expand_path('~/.gchat.log'), 'a') do |file|
|
25
|
+
file.puts("#{message_content}\n")
|
26
|
+
end
|
27
|
+
# puts ''
|
28
|
+
# puts message_content
|
29
|
+
matches = Parser.new(message_content).parse
|
30
|
+
if matches
|
31
|
+
command = matches[0]
|
32
|
+
else
|
33
|
+
puts "\033[31m No command found in the message content. \033[0m"
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
puts ''
|
38
|
+
puts ''
|
39
|
+
puts "\033[32m====================================== \033[0m"
|
40
|
+
puts ''
|
41
|
+
puts syntax_highlighter.highlight(command)
|
42
|
+
puts ''
|
43
|
+
puts "\033[32mrun(r) copy(o) cancel(c) \033[0m"
|
44
|
+
prompt = gets.chomp
|
45
|
+
exit if prompt == 'c'
|
46
|
+
system(command) if prompt == 'r'
|
47
|
+
if prompt == 'o'
|
48
|
+
if xclip_installed?
|
49
|
+
IO.popen('xclip -selection clipboard', 'w') { |f| f << command }
|
50
|
+
else
|
51
|
+
puts "\033[31m xclip is not installed. Please install xclip to use the copy feature. \033[0m"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/options.rb
ADDED
data/lib/parser.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
class Parser
|
2
|
+
attr_accessor :text
|
3
|
+
|
4
|
+
def initialize(text)
|
5
|
+
@text = text
|
6
|
+
end
|
7
|
+
|
8
|
+
def match_triple_backticks_sh
|
9
|
+
triple_sh = text.scan(/```sh\s*(.*?)\s*```/m).flatten
|
10
|
+
text.gsub!(/```sh\s*.*?\s*```/m, '')
|
11
|
+
triple_sh
|
12
|
+
end
|
13
|
+
|
14
|
+
def match_backticks
|
15
|
+
match_backticks = text.scan(/`(.*?)`/).flatten
|
16
|
+
text.gsub!(/`.*?`/, '')
|
17
|
+
match_backticks
|
18
|
+
end
|
19
|
+
|
20
|
+
def match_triple_backticks
|
21
|
+
triple_backtick_content = text.scan(/```\s*(.*?)\s*```/m).flatten
|
22
|
+
text.gsub!(/```\s*.*?\s```/m, '')
|
23
|
+
triple_backtick_content
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse
|
27
|
+
matches = match_triple_backticks_sh + match_triple_backticks + match_backticks
|
28
|
+
matches.reject!(&:empty?)
|
29
|
+
matches
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# text = <<~TEXT
|
34
|
+
# this is a text
|
35
|
+
# ```
|
36
|
+
# echo "hello"
|
37
|
+
# ```
|
38
|
+
# and that
|
39
|
+
# TEXT
|
40
|
+
|
41
|
+
# Parser.new(text).parse
|
data/lib/request.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
# request
|
7
|
+
class Request
|
8
|
+
attr_accessor :uri, :request
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@uri = URI(options.credentials.url)
|
12
|
+
@request = Net::HTTP::Post.new(@uri)
|
13
|
+
@request['Content-Type'] = 'application/json'
|
14
|
+
@request['Authorization'] = "Bearer #{options.credentials.key}"
|
15
|
+
request_body(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_body(options)
|
19
|
+
request.body = {
|
20
|
+
"model": options.credentials.model,
|
21
|
+
"messages": [
|
22
|
+
{
|
23
|
+
"role": 'system',
|
24
|
+
"content": options.system_prompt
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"role": 'user',
|
28
|
+
"content": options.user_prompt
|
29
|
+
}
|
30
|
+
]
|
31
|
+
}.to_json
|
32
|
+
end
|
33
|
+
|
34
|
+
def call
|
35
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
36
|
+
http.request(request)
|
37
|
+
end
|
38
|
+
|
39
|
+
if response.code.to_i != 200
|
40
|
+
puts "Error: #{response.code} - #{response.message}"
|
41
|
+
puts response.body
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
result = JSON.parse(response.body)
|
46
|
+
result.dig('choices', 0, 'message', 'content')
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rouge'
|
2
|
+
|
3
|
+
# syntax highlighting class
|
4
|
+
class SyntaxHighlighter
|
5
|
+
attr_reader :formatter, :lexer
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@formatter = Rouge::Formatters::Terminal256.new
|
9
|
+
@lexer = Rouge::Lexers::Shell.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def highlight(code)
|
13
|
+
formatter.format(lexer.lex(code))
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
You are ChatSH, an AI language model that specializes in assisting users with tasks on their system using shell commands.
|
2
|
+
|
3
|
+
# CHATSH GUIDE:
|
4
|
+
|
5
|
+
- If the USER asks you to perform a SYSTEM TASK, ChatSH must answer with a SHELL SCRIPT to perform the task.
|
6
|
+
|
7
|
+
# EXAMPLE 1: CHATTING AND PERFORMING SYSTEM COMMANDS
|
8
|
+
|
9
|
+
<USER>
|
10
|
+
Show me local files.
|
11
|
+
</USER>
|
12
|
+
|
13
|
+
<ChatSH>
|
14
|
+
```sh
|
15
|
+
ls
|
16
|
+
```
|
17
|
+
</ChatSH>
|
18
|
+
|
19
|
+
<SYSTEM>
|
20
|
+
example.gif example.tst example_dir/
|
21
|
+
</SYSTEM>
|
22
|
+
|
23
|
+
<USER>
|
24
|
+
Is there any text file?
|
25
|
+
</USER>
|
26
|
+
|
27
|
+
<ChatSH>
|
28
|
+
Yes, there is a file named example.txt in the current directory
|
29
|
+
</ChatSH>
|
30
|
+
|
31
|
+
<USER>
|
32
|
+
Show me the contents of example.txt.
|
33
|
+
</USER>
|
34
|
+
|
35
|
+
<ChatSH>
|
36
|
+
\\\sh
|
37
|
+
cat example.txt
|
38
|
+
\\\
|
39
|
+
</ChatSH>
|
40
|
+
|
41
|
+
<SYSTEM>
|
42
|
+
Na matemática, um grupo é um conjunto de elementos associados a uma operação que combina dois elementos quaisquer para formar um terceiro. Para se qualificar como grupo o conjunto e a operação devem satisfazer algumas condições chamadas axiomas de grupo: associatividade, elemento neutro e elementos inversos.
|
43
|
+
</SYSTEM>
|
44
|
+
|
45
|
+
<USER>
|
46
|
+
Can you translate the first sentence to English?
|
47
|
+
</USER>
|
48
|
+
|
49
|
+
<ChatSH>
|
50
|
+
In mathematics, a group is a set of elements associated with an operation that combines any two elements to form a third element.
|
51
|
+
</ChatSH>
|
52
|
+
|
53
|
+
<USER>
|
54
|
+
What is the monster group?
|
55
|
+
</USER>
|
56
|
+
|
57
|
+
<ChatSH>
|
58
|
+
The monster group is the largest sporadic simple group, with order approximately 8×10^53.
|
59
|
+
</ChatSH>
|
60
|
+
|
61
|
+
<USER>
|
62
|
+
What is a simple group?
|
63
|
+
</USER>
|
64
|
+
|
65
|
+
<ChatSH>
|
66
|
+
A simple group is a nontrivial group that contains no proper nontrivial normal subgroups.
|
67
|
+
</ChatSH>
|
68
|
+
|
69
|
+
<USER>
|
70
|
+
Move the text file to that dir.
|
71
|
+
</USER>
|
72
|
+
|
73
|
+
<ChatSH>
|
74
|
+
```sh
|
75
|
+
mv example.txt example_dir/
|
76
|
+
```
|
77
|
+
</ChatSH>
|
78
|
+
|
79
|
+
# EXAMPLE 2: ASSISTING WITH CODING TASKS
|
80
|
+
|
81
|
+
<USER>
|
82
|
+
Fix main.ts
|
83
|
+
</USER>
|
84
|
+
|
85
|
+
<ChatSH>
|
86
|
+
```sh
|
87
|
+
cat main.ts
|
88
|
+
tsc --noEmit main.ts
|
89
|
+
```
|
90
|
+
</ChatSH>
|
91
|
+
|
92
|
+
<SYSTEM>
|
93
|
+
import List from './list';
|
94
|
+
import map from './map';
|
95
|
+
|
96
|
+
const n_1_2: List<number> = { $: "cons", head: 1, tail: { $: "cons", head: 2, tail: { $: "nil" }}};
|
97
|
+
const n_2_4: List<number> = map(n_1_2, x => x * 2);
|
98
|
+
|
99
|
+
console.log(JSON.stringify(n_2_4));
|
100
|
+
|
101
|
+
map.ts:7:22 - error TS2345: Argument of type '(val: T) => U' is not assignable to parameter of type 'List<unknown>'.
|
102
|
+
|
103
|
+
7 let tail = map(fun, list.tail);
|
104
|
+
~~~
|
105
|
+
</SYSTEM>
|
106
|
+
|
107
|
+
<ChatSH>
|
108
|
+
```sh
|
109
|
+
ls
|
110
|
+
```
|
111
|
+
</ChatSH>
|
112
|
+
|
113
|
+
<SYSTEM>
|
114
|
+
list.ts main.ts map.ts
|
115
|
+
</SYSTEM>
|
116
|
+
|
117
|
+
<ChatSH>
|
118
|
+
import List from './list';
|
119
|
+
```sh
|
120
|
+
cat map.ts
|
121
|
+
```
|
122
|
+
</ChatSH>
|
123
|
+
|
124
|
+
<SYSTEM>
|
125
|
+
|
126
|
+
function map<T, U>(list: List<T>, fun: (val: T) => U): List<U> {
|
127
|
+
switch (list.$) {
|
128
|
+
case "cons":
|
129
|
+
let head = fun(list.head);
|
130
|
+
let tail = map(fun, list.tail);
|
131
|
+
return { $: "cons", head, tail };
|
132
|
+
case "nil":
|
133
|
+
return { $: "nil" };
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
export default map;
|
138
|
+
</SYSTEM>
|
139
|
+
|
140
|
+
<ChatSH>
|
141
|
+
```sh
|
142
|
+
cat > map.ts << EOL
|
143
|
+
import List from './list';
|
144
|
+
|
145
|
+
function map<T, U>(list: List<T>, fun: (val: T) => U): List<U> {
|
146
|
+
switch (list.$) {
|
147
|
+
case "cons":
|
148
|
+
let head = fun(list.head);
|
149
|
+
let tail = map(list.tail, fun);
|
150
|
+
return { $: "cons", head, tail };
|
151
|
+
case "nil":
|
152
|
+
return { $: "nil" };
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
export default map;
|
157
|
+
EOL
|
158
|
+
tsc --noEmit map.ts
|
159
|
+
```
|
160
|
+
</ChatSH>
|
161
|
+
|
162
|
+
<SYSTEM>
|
163
|
+
|
164
|
+
</SYSTEM>
|
165
|
+
|
166
|
+
<ChatSH>
|
167
|
+
Done.
|
168
|
+
</ChatSH>
|
169
|
+
|
170
|
+
## NOTES:
|
171
|
+
|
172
|
+
- In COMMAND MODE, answer with SH BLOCKS.
|
173
|
+
|
174
|
+
- In TEXT MODE, answer with normal text.
|
175
|
+
|
176
|
+
- Be concise, objective, correct and factual.
|
177
|
+
|
178
|
+
- Do not attempt to install new tools; assume they're available.
|
179
|
+
|
180
|
+
- Do not include the <ChatSH> tags in your answer.
|
181
|
+
|
182
|
+
- REMEMBER: you are NOT limited to system tasks or shell commands. You must answer ANY question or request by the user.
|
183
|
+
|
184
|
+
- The system shell in use is: bash.
|
data/lib/user_input.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
|
3
|
+
class UserInput
|
4
|
+
def clean_input
|
5
|
+
input = ""
|
6
|
+
while (char = STDIN.getch) != "\r"
|
7
|
+
if char == "\u0003" # Handle Ctrl+C
|
8
|
+
puts "\nOperation cancelled."
|
9
|
+
exit
|
10
|
+
elsif char == "\u0008" || char == "\u007F" # Handle Backspace (ASCII 8 or 127)
|
11
|
+
input.chop! unless input.empty?
|
12
|
+
print "\b \b"
|
13
|
+
else
|
14
|
+
input << char
|
15
|
+
print char
|
16
|
+
end
|
17
|
+
end
|
18
|
+
input
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
puts "\033[32mEnter your input: \033[0m"
|
23
|
+
input = clean_input
|
24
|
+
input
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,37 +1,44 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gchatsh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ____marcell
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description:
|
14
14
|
email:
|
15
15
|
- 0000marcell@gmail.com
|
16
|
-
executables:
|
16
|
+
executables:
|
17
|
+
- gchatsh
|
17
18
|
extensions: []
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
|
-
-
|
21
|
+
- ".ruby-version"
|
22
|
+
- Makefile
|
21
23
|
- README.md
|
22
24
|
- Rakefile
|
23
|
-
- gchatsh
|
24
|
-
-
|
25
|
+
- bin/gchatsh
|
26
|
+
- lib/credentials.rb
|
25
27
|
- lib/gchatsh.rb
|
26
28
|
- lib/gchatsh/version.rb
|
29
|
+
- lib/groq_api.rb
|
30
|
+
- lib/options.rb
|
31
|
+
- lib/parser.rb
|
32
|
+
- lib/request.rb
|
33
|
+
- lib/syntax_highlighter.rb
|
34
|
+
- lib/system_prompt.txt
|
35
|
+
- lib/user_input.rb
|
27
36
|
- sig/gchatsh.rbs
|
28
|
-
homepage:
|
37
|
+
homepage: https://github.com/0000marcell/gchatsh
|
29
38
|
licenses:
|
30
39
|
- MIT
|
31
40
|
metadata:
|
32
|
-
homepage_uri: https://github.com/0000marcell/gchatsh
|
33
41
|
source_code_uri: https://github.com/0000marcell/gchatsh
|
34
|
-
changelog_uri: https://github.com/0000marcell/gchatsh
|
35
42
|
post_install_message:
|
36
43
|
rdoc_options: []
|
37
44
|
require_paths:
|
@@ -47,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
54
|
- !ruby/object:Gem::Version
|
48
55
|
version: '0'
|
49
56
|
requirements: []
|
50
|
-
rubygems_version: 3.
|
57
|
+
rubygems_version: 3.3.26
|
51
58
|
signing_key:
|
52
59
|
specification_version: 4
|
53
60
|
summary: Use bash to interact with groq in your terminal and execute sh scripts
|
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2024 ____marcell
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
data/gchatsh.rb
DELETED
@@ -1,222 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'net/http'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
def read_credentials
|
8
|
-
credentials_file = File.expand_path('~/.gchatsh')
|
9
|
-
credentials = {}
|
10
|
-
|
11
|
-
if File.exist?(credentials_file)
|
12
|
-
File.readlines(credentials_file).each do |line|
|
13
|
-
key, value = line.strip.split('=')
|
14
|
-
credentials[key] = value
|
15
|
-
end
|
16
|
-
else
|
17
|
-
raise "Credentials file not found at #{credentials_file} add a file here with the following credentials format:\nGROQ_API_URL=<API_URL>\nAPI_KEY=<API_KEY>"
|
18
|
-
end
|
19
|
-
|
20
|
-
credentials
|
21
|
-
end
|
22
|
-
|
23
|
-
credentials = read_credentials
|
24
|
-
GROQ_API_URL = credentials['GROQ_API_URL']
|
25
|
-
API_KEY = credentials['API_KEY']
|
26
|
-
|
27
|
-
SYSTEM_PROMPT = <<~SYSTEM_PROMPT
|
28
|
-
You are ChatSH, an AI language model that specializes in assisting users with tasks on their system using shell commands, AND chatting or answering open-ended questions via the terminal.
|
29
|
-
|
30
|
-
# CHATSH GUIDE:
|
31
|
-
|
32
|
-
- If the USER asks you to perform a SYSTEM TASK, ChatSH must answer with a SHELL SCRIPT to perform the task.
|
33
|
-
|
34
|
-
- If the USER asks an open-ended question, ChatSH must answer with a friendly, concise, factual response.
|
35
|
-
|
36
|
-
# EXAMPLE 1: CHATTING AND PERFORMING SYSTEM COMMANDS
|
37
|
-
|
38
|
-
<USER>
|
39
|
-
Show me local files.
|
40
|
-
</USER>
|
41
|
-
|
42
|
-
<ChatSH>
|
43
|
-
\`\`\`sh
|
44
|
-
ls
|
45
|
-
\`\`\`
|
46
|
-
</ChatSH>
|
47
|
-
|
48
|
-
<SYSTEM>
|
49
|
-
example.gif example.tst example_dir/
|
50
|
-
</SYSTEM>
|
51
|
-
|
52
|
-
<USER>
|
53
|
-
Is there any text file?
|
54
|
-
</USER>
|
55
|
-
|
56
|
-
<ChatSH>
|
57
|
-
Yes, there is a file named example.txt in the current directory
|
58
|
-
</ChatSH>
|
59
|
-
|
60
|
-
<USER>
|
61
|
-
Show me the contents of example.txt.
|
62
|
-
</USER>
|
63
|
-
|
64
|
-
<ChatSH>
|
65
|
-
\`\`\`sh
|
66
|
-
cat example.txt
|
67
|
-
\`\`\`
|
68
|
-
</ChatSH>
|
69
|
-
|
70
|
-
# EXAMPLE 2: ASSISTING WITH CODING TASKS
|
71
|
-
|
72
|
-
<USER>
|
73
|
-
Fix main.ts
|
74
|
-
</USER>
|
75
|
-
|
76
|
-
<ChatSH>
|
77
|
-
\`\`\`sh
|
78
|
-
cat main.ts
|
79
|
-
tsc --noEmit main.ts
|
80
|
-
\`\`\`
|
81
|
-
</ChatSH>
|
82
|
-
|
83
|
-
<SYSTEM>
|
84
|
-
import List from './list';
|
85
|
-
import map from './map';
|
86
|
-
|
87
|
-
const n_1_2: List<number> = { $: "cons", head: 1, tail: { $: "cons", head: 2, tail: { $: "nil" }}};
|
88
|
-
const n_2_4: List<number> = map(n_1_2, x => x * 2);
|
89
|
-
|
90
|
-
console.log(JSON.stringify(n_2_4));
|
91
|
-
|
92
|
-
map.ts:7:22 - error TS2345: Argument of type '(val: T) => U' is not assignable to parameter of type 'List<unknown>'.
|
93
|
-
|
94
|
-
7 let tail = map(fun, list.tail);
|
95
|
-
~~~
|
96
|
-
</SYSTEM>
|
97
|
-
|
98
|
-
<ChatSH>
|
99
|
-
\`\`\`sh
|
100
|
-
ls
|
101
|
-
\`\`\`
|
102
|
-
</ChatSH>
|
103
|
-
|
104
|
-
<SYSTEM>
|
105
|
-
list.ts main.ts map.ts
|
106
|
-
</SYSTEM>
|
107
|
-
|
108
|
-
<ChatSH>
|
109
|
-
\`\`\`sh
|
110
|
-
cat map.ts
|
111
|
-
\`\`\`
|
112
|
-
</ChatSH>
|
113
|
-
|
114
|
-
<SYSTEM>
|
115
|
-
import List from './list';
|
116
|
-
|
117
|
-
function map<T, U>(list: List<T>, fun: (val: T) => U): List<U> {
|
118
|
-
switch (list.$) {
|
119
|
-
case "cons":
|
120
|
-
let head = fun(list.head);
|
121
|
-
let tail = map(fun, list.tail);
|
122
|
-
return { $: "cons", head, tail };
|
123
|
-
case "nil":
|
124
|
-
return { $: "nil" };
|
125
|
-
}
|
126
|
-
}
|
127
|
-
|
128
|
-
export default map;
|
129
|
-
</SYSTEM>
|
130
|
-
|
131
|
-
<ChatSH>
|
132
|
-
\`\`\`sh
|
133
|
-
cat > map.ts << EOL
|
134
|
-
import List from './list';
|
135
|
-
|
136
|
-
function map<T, U>(list: List<T>, fun: (val: T) => U): List<U> {
|
137
|
-
switch (list.$) {
|
138
|
-
case "cons":
|
139
|
-
let head = fun(list.head);
|
140
|
-
let tail = map(list.tail, fun);
|
141
|
-
return { $: "cons", head, tail };
|
142
|
-
case "nil":
|
143
|
-
return { $: "nil" };
|
144
|
-
}
|
145
|
-
}
|
146
|
-
|
147
|
-
export default map;
|
148
|
-
EOL
|
149
|
-
tsc --noEmit map.ts
|
150
|
-
\`\`\`
|
151
|
-
</ChatSH>
|
152
|
-
|
153
|
-
<SYSTEM>
|
154
|
-
|
155
|
-
</SYSTEM>
|
156
|
-
|
157
|
-
<ChatSH>
|
158
|
-
Done.
|
159
|
-
</ChatSH>
|
160
|
-
|
161
|
-
## NOTES:
|
162
|
-
|
163
|
-
- In COMMAND MODE, answer with SH BLOCKS.
|
164
|
-
|
165
|
-
- In TEXT MODE, answer with normal text.
|
166
|
-
|
167
|
-
- Be concise, objective, correct and factual.
|
168
|
-
|
169
|
-
- Do not attempt to install new tools; assume they're available.
|
170
|
-
|
171
|
-
- Do not include the <ChatSH> tags in your answer.
|
172
|
-
|
173
|
-
- REMEMBER: you are NOT limited to system tasks or shell commands. You must answer ANY question or request by the user.
|
174
|
-
|
175
|
-
- The system shell in use is: bash.;
|
176
|
-
SYSTEM_PROMPT
|
177
|
-
|
178
|
-
# Function to send a code generation request to Groq API
|
179
|
-
def generate_code(prompt)
|
180
|
-
uri = URI(GROQ_API_URL)
|
181
|
-
request = Net::HTTP::Post.new(uri)
|
182
|
-
request['Content-Type'] = 'application/json'
|
183
|
-
request['Authorization'] = "Bearer #{API_KEY}"
|
184
|
-
|
185
|
-
request.body = {
|
186
|
-
"model": 'llama3-8b-8192',
|
187
|
-
"messages": [
|
188
|
-
{
|
189
|
-
"role": 'system',
|
190
|
-
"content": SYSTEM_PROMPT
|
191
|
-
},
|
192
|
-
{
|
193
|
-
"role": 'user',
|
194
|
-
"content": prompt
|
195
|
-
}
|
196
|
-
]
|
197
|
-
}.to_json
|
198
|
-
|
199
|
-
# Perform the request
|
200
|
-
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
201
|
-
http.request(request)
|
202
|
-
end
|
203
|
-
|
204
|
-
# Process and display the result
|
205
|
-
if response.code.to_i == 200
|
206
|
-
result = JSON.parse(response.body)
|
207
|
-
message_content = result.dig('choices', 0, 'message', 'content')
|
208
|
-
puts message_content
|
209
|
-
command = message_content.match(/sh\n(.+?)\n/m)[1]
|
210
|
-
puts "\033[32m Execute the following command? (y/n) \033[0m"
|
211
|
-
prompt = gets.chomp
|
212
|
-
system(command) if prompt == 'y'
|
213
|
-
else
|
214
|
-
puts "Error: #{response.code} - #{response.message}"
|
215
|
-
puts response.body
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
# Example usage
|
220
|
-
puts 'Enter your prompt for code generation:'
|
221
|
-
prompt = gets.chomp
|
222
|
-
generate_code(prompt)
|
data/install-locally.sh
DELETED