matheus 0.2.1 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72cfeba7ddd84ef4fd7c7c80144a1a8821eb4c3d03fd33f3d718109b08d39bae
4
- data.tar.gz: add8482702c9e6af603e6ea2ba5cb7cefa589c57bf133385f2682db7532b8324
3
+ metadata.gz: 8f0188994d160b9cfc3ce6ab06610e4f42102ddf828dc01e1c917cdf02ac77c6
4
+ data.tar.gz: 0cf90a3177f25047f2b15fcf5198eb0de8ea3439116107576b7fdd7daab5bddf
5
5
  SHA512:
6
- metadata.gz: 222e09a48119ad9aa15daa86b26f8159dd45dc9f7b1a8743e6bc8e1255399562e4a4ed2ee3a8ac2539b61c15d61b5d79532913cd2710b2a9f1657dae82de4a44
7
- data.tar.gz: c46798f32fc8a73cd99fb47372bdb61060718e1f0366f5d1623215e397bdb0ae5074666fc145a7957350f80bcdd4eeb459fe47809f4e656fa242423d07e28d9c
6
+ metadata.gz: 364f6273dfdbc464d491b3ce29d670351c5c4c007524c0aa6ad46e1d44e810bf4e7dfa083821a20ae2f0058d01e45a601f7b68c70b9d42ed156df3e6205af895
7
+ data.tar.gz: d8c641cbaeca884aff2d5782b0abbe720ddaf08af0057676d85ea9bdb9bb0adff33f81c8b158d8a18ba32879dd2f7e30f667c9e400ca4e9862befcae44409366
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 3.2.0
1
+ ruby 3.3.4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.0]
4
+
5
+ _Released 2024-10-02_
6
+
7
+ - Save past questions with `q` and retrieve them with the `qs` command.
8
+ - Reuse answers for the same questions.
9
+
10
+ ## [0.3.0]
11
+
12
+ _Released 2024-08-27_
13
+
14
+ - Add `alert-me` command.
15
+
3
16
  ## [0.2.0]
4
17
 
5
18
  _Released 2024-08-26_
data/README.md CHANGED
@@ -6,6 +6,48 @@ A bunch of CLI tools I made for my own use.
6
6
 
7
7
  $ gem install matheus
8
8
 
9
+ ## Usage
10
+
11
+ ### `alert-me`
12
+
13
+ ```sh
14
+ $ alert-me 'sleep 1 && echo "Done!"'
15
+ Done!
16
+ # plays a sound after the command finishes
17
+ ```
18
+
19
+ ### `date-of-last`
20
+
21
+ Prints the date of the last week day.
22
+
23
+ ```sh
24
+ $ date-of-last monday
25
+ 2024-02-12
26
+
27
+ $ date-of-last sun
28
+ 2024-02-11
29
+ ```
30
+
31
+ ### `q`
32
+
33
+ It expects a OPENAI_API_KEY environment variable to be set. It will try to load
34
+ it from a `.env` file at `~/.env`.
35
+
36
+ ```sh
37
+ $ q "What is the capital of France?"
38
+ The capital of France is **Paris**
39
+ ```
40
+
41
+ ### `puts`
42
+
43
+ It evaluates the given Ruby code and prints the result. Active Support is
44
+ available.
45
+
46
+ ```sh
47
+ $ puts 10.days.ago
48
+ 2024-08-17 15:50:11 -0300
49
+ ```
50
+
9
51
  ## Contributing
10
52
 
11
53
  Probably not accepting contributions at the moment, but feel free to open an issue if you have any ideas or suggestions.
data/Rakefile CHANGED
@@ -45,3 +45,5 @@ end
45
45
 
46
46
  # Ensure the generate_executables task runs before the build task
47
47
  task build: :generate_executables
48
+ # Ensure tests are run before releasing the gem
49
+ task release: :spec
data/exe/alert-me ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift("#{__dir__}/../lib")
4
+
5
+ require "matheus"
6
+
7
+ Matheus::AlertMe.call ARGV
data/exe/qs ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift("#{__dir__}/../lib")
4
+
5
+ require "matheus"
6
+
7
+ Matheus::Qs.call ARGV
@@ -0,0 +1,16 @@
1
+ module Matheus
2
+ class AlertMe < Command
3
+ # Usage:
4
+ # $ alert-me "sleep 1 && echo 'Done!'"
5
+ # Runs the command and plays a sound based on its success or failure after it finishes.
6
+ def call(*args)
7
+ if system(args.join(" "))
8
+ system("afplay /System/Library/Sounds/Glass.aiff")
9
+ else
10
+ system("afplay /System/Library/Sounds/Sosumi.aiff")
11
+ end
12
+ rescue => e
13
+ Failure(e.message)
14
+ end
15
+ end
16
+ end
data/lib/matheus/q.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require "openai"
2
2
  require "tty-markdown"
3
+ require "tty-prompt"
4
+ require "json"
3
5
 
4
6
  module Matheus
5
7
  # Usage:
@@ -9,7 +11,17 @@ module Matheus
9
11
  BASE_PROMPT = "Answer this question in a short and concise way. You can use markdown in the response: "
10
12
 
11
13
  def call(question)
12
- ask_llm(question).then { print_markdown _1 }
14
+ question = question.join(" ")
15
+ existing_entry = search_question_in_history(question)
16
+
17
+ if existing_entry && use_existing_answer?
18
+ answer = existing_entry['answer']
19
+ else
20
+ answer = ask_llm(question)
21
+ save_qa(question, answer)
22
+ end
23
+
24
+ print_markdown(answer)
13
25
  rescue => e
14
26
  Failure(e.message)
15
27
  end
@@ -21,7 +33,7 @@ module Matheus
21
33
 
22
34
  response = client.chat(
23
35
  parameters: {
24
- model: "gpt-4o-mini", # using gpt-4o model
36
+ model: "gpt-4o-mini",
25
37
  messages: [{role: "user", content: "#{BASE_PROMPT}#{question}"}]
26
38
  }
27
39
  )
@@ -29,6 +41,8 @@ module Matheus
29
41
  raise response["error"]["message"] if response.has_key?("error")
30
42
 
31
43
  response.dig("choices", 0, "message", "content")
44
+ rescue Faraday::ClientError => error
45
+ raise error.response_body.dig("error", "message") || error
32
46
  end
33
47
 
34
48
  def print_markdown(text)
@@ -38,5 +52,26 @@ module Matheus
38
52
  def client
39
53
  OpenAI::Client.new(access_token: ENV.fetch("OPENAI_API_KEY"))
40
54
  end
55
+
56
+ def save_qa(question, answer)
57
+ history = load_history
58
+ history << { question:, answer:, timestamp: Time.now.to_s }
59
+ File.write(QUESTION_HISTORY_FILE, JSON.pretty_generate(history))
60
+ end
61
+
62
+ def load_history
63
+ File.exist?(QUESTION_HISTORY_FILE) ? JSON.parse(File.read(QUESTION_HISTORY_FILE)) : []
64
+ end
65
+
66
+ def search_question_in_history(question)
67
+ load_history.reverse.find { |entry| entry['question'].downcase.strip == question.downcase.strip }
68
+ end
69
+
70
+ def use_existing_answer?
71
+ prompt = TTY::Prompt.new
72
+ prompt.yes?("An existing answer was found. Do you want to use it?") do |q|
73
+ q.default true
74
+ end
75
+ end
41
76
  end
42
77
  end
data/lib/matheus/qs.rb ADDED
@@ -0,0 +1,40 @@
1
+ require "json"
2
+ require "tty-prompt"
3
+ require "tty-markdown"
4
+
5
+ module Matheus
6
+ # Usage:
7
+ # $ qs
8
+ # Lists the questions asked and their answers.
9
+ class Qs < Command
10
+ def call(_)
11
+ return puts "No questions found in history." if history.empty?
12
+
13
+ answer = prompt.select("Question:", choices, per_page: 10)
14
+ print_markdown(answer)
15
+ rescue => e
16
+ Failure(e.message)
17
+ end
18
+
19
+ private
20
+ def choices
21
+ history.map do |entry|
22
+ {entry['question'] => entry['answer'] }
23
+ end
24
+ end
25
+
26
+
27
+ def history
28
+ @history ||= File.exist?(QUESTION_HISTORY_FILE) ? JSON.parse(File.read(QUESTION_HISTORY_FILE)) : []
29
+ end
30
+
31
+ def prompt
32
+ @prompt ||= TTY::Prompt.new(interrupt: :exit)
33
+ end
34
+
35
+ def print_markdown(answer)
36
+ puts
37
+ puts TTY::Markdown.parse(answer)
38
+ end
39
+ end
40
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Matheus
4
- VERSION = "0.2.1"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/matheus.rb CHANGED
@@ -9,4 +9,5 @@ Dotenv.load("~/.env")
9
9
  Zeitwerk::Loader.for_gem.setup
10
10
 
11
11
  module Matheus
12
+ QUESTION_HISTORY_FILE = File.expand_path("~/.qa_history.json")
12
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matheus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matheus Richard
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-26 00:00:00.000000000 Z
11
+ date: 2024-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.7.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: tty-table
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.12.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.12.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: tty-prompt
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.23.1
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.23.1
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: dotenv
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -84,9 +112,11 @@ description: A bunch of CLI tools I made for my own use.
84
112
  email:
85
113
  - matheusrichardt@gmail.com
86
114
  executables:
115
+ - alert-me
87
116
  - date-of-last
88
117
  - puts
89
118
  - q
119
+ - qs
90
120
  extensions: []
91
121
  extra_rdoc_files: []
92
122
  files:
@@ -96,14 +126,18 @@ files:
96
126
  - LICENSE.txt
97
127
  - README.md
98
128
  - Rakefile
129
+ - exe/alert-me
99
130
  - exe/date-of-last
100
131
  - exe/puts
101
132
  - exe/q
133
+ - exe/qs
102
134
  - lib/matheus.rb
135
+ - lib/matheus/alert_me.rb
103
136
  - lib/matheus/command.rb
104
137
  - lib/matheus/date_of_last.rb
105
138
  - lib/matheus/puts.rb
106
139
  - lib/matheus/q.rb
140
+ - lib/matheus/qs.rb
107
141
  - lib/matheus/result.rb
108
142
  - lib/matheus/string_format.rb
109
143
  - lib/matheus/version.rb
@@ -129,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
163
  - !ruby/object:Gem::Version
130
164
  version: '0'
131
165
  requirements: []
132
- rubygems_version: 3.5.17
166
+ rubygems_version: 3.5.11
133
167
  signing_key:
134
168
  specification_version: 4
135
169
  summary: A bunch of CLI tools I made for my own use.