richat 0.2.3 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9d0ef493fcedb52399b88baee0ef20c11d90fdf258c5aa4f8df2caca0e2ec23
4
- data.tar.gz: caf49bffd8f470ba54bcfd27d639899a10068a4a7ba696eab2e3bcba8416a755
3
+ metadata.gz: a6a6598af5c6e17f582012237108fdb8476d3c8c2b015114a8f2e5b72fcd8e02
4
+ data.tar.gz: 2103424385ccbc8342beca1be859faeb2c42a5f15ae4188b8253651d18a438d1
5
5
  SHA512:
6
- metadata.gz: 207d40655ca0be10eb68a2409943206ba1ef42d946a70553d8f0db4260d415486e8922fa9da578eb9b9634622d77b7d68f9c2496a9f3cfaebfcf476759b13e29
7
- data.tar.gz: 9d4091ce31a3783ddd50cc5f1a00844ac1baa61937e8edcbf5b21f3e03ccfd909854212da22b4d284073104c6894b8472c4ac5ad1ff996117a7fe84f5cb9a697
6
+ metadata.gz: e6a3aad954fb88a24cf79e9f334d5912fd0fac875b74c4e585d4fa10626179ce22c0912686b8b7e2ac4642ed77fdab7962b2a63a5fbca8c0df4ebf821e4ecad4
7
+ data.tar.gz: c4012e6a086e7bddfdcc1e65a488f4248254e4ab3d814319806cd53725f12e8b4f5ac6eff78b1df5203398e34d82825f3082ccc0a96823b891e295a779e70510
data/exe/richat CHANGED
@@ -1,36 +1,76 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'bundler/setup'
3
+ require 'optparse'
4
4
  require 'richat'
5
5
 
6
- log_dir = File.expand_path(Richat::Config.get("log", "log_dir"))
7
- FileUtils.mkdir_p(log_dir) unless File.directory?(log_dir)
6
+ cli_opts = {}
8
7
 
9
- prompt_dir = File.expand_path(Richat::Config.get("prompt", "prompt_dir"))
10
- FileUtils.mkdir_p(prompt_dir) unless File.directory?(prompt_dir)
8
+ OptionParser.new do |opts|
9
+ opts.banner = %q{Usage: richat [options] [chat content]
10
+ richat will enter shell mode if chat content is empty}
11
+ opts.version = Richat::VERSION
12
+ opts.program_name = "richat"
11
13
 
12
- chat_config = {
13
- api_key: Richat::Config.get("chatgpt", "api_key"),
14
- model: Richat::Config.get("chatgpt", "model"),
15
- temperature: Richat::Config.get("chatgpt", "temperature"),
16
- stream: true
17
- }
14
+ opts.separator "\nOptions:"
15
+
16
+ opts.on("-l", "--logfile=LOG FILE", "Set log file path") do |l|
17
+ cli_opts["log"] = { "log_file" => l }
18
+ end
19
+
20
+ opts.on_tail("-h", "--help", "Print help") do
21
+ puts opts
22
+ puts "\nFurther help: https://github.com/fzdp/richat"
23
+ exit
24
+ end
18
25
 
19
- if chat_config[:api_key].nil? || chat_config[:api_key].empty?
26
+ opts.on_tail("-v", "--version", "Version") do
27
+ puts "richat " + Richat::VERSION
28
+ exit
29
+ end
30
+ end.parse!
31
+
32
+ Richat::Config.override_with(cli_opts) unless cli_opts.empty?
33
+
34
+ api_key = Richat::Config.get("chatgpt", "api_key")
35
+ if api_key.nil? || api_key.empty?
20
36
  puts "OpenAI API key not set, refer https://github.com/fzdp/richat#usage for more info."
21
37
  exit
22
38
  end
23
39
 
24
40
  if Richat::Config.get("log", "enable")
25
- logger = Richat::Logger.new(log_file: "#{log_dir}/#{Time.now.strftime('%Y%m%d')}.md")
41
+ log_dir = File.expand_path(Richat::Config.get("log", "log_dir"))
42
+ log_file = Richat::Config.get("log", "log_file")
43
+
44
+ if log_file.nil? || log_file.empty?
45
+ log_file = File.join(log_dir, "#{Time.now.strftime('%Y%m%d')}.md")
46
+ elsif log_file.start_with? "~/"
47
+ log_file = File.expand_path(log_file)
48
+ elsif !Richat::Utils.absolute_path?(log_file)
49
+ log_file = File.join(log_dir, log_file)
50
+ end
51
+
52
+ Richat::Utils.ensure_dir_exist(File.dirname(log_file))
53
+ logger = Richat::Logger.new(log_file: log_file)
26
54
  else
27
55
  logger = Richat::Logger.empty_logger
28
56
  end
29
57
 
30
- if ARGV.size.zero?
58
+ prompt_dir = File.expand_path(Richat::Config.get("prompt", "prompt_dir"))
59
+ Richat::Utils.ensure_dir_exist(prompt_dir)
60
+
61
+ user_content = ARGV.join(" ")
62
+
63
+ chat_config = {
64
+ api_key: Richat::Config.get("chatgpt", "api_key"),
65
+ model: Richat::Config.get("chatgpt", "model"),
66
+ temperature: Richat::Config.get("chatgpt", "temperature"),
67
+ stream: true
68
+ }
69
+
70
+ if user_content.empty?
31
71
  client = Openai::Chat.new(chat_config)
32
72
  Richat::Shell.new(chat_client: client, logger: logger).call
33
73
  else
34
74
  client = Openai::Chat.new(chat_config.merge(stream: false))
35
- Richat::Cli.new(chat_client: client, logger: logger, user_content: ARGV.join(" ")).call
75
+ Richat::Cli.new(chat_client: client, logger: logger, user_content: user_content).call
36
76
  end
@@ -32,7 +32,7 @@ module Richat
32
32
 
33
33
  def handle_config
34
34
  puts "\e[32mConfiguration file path is #{File.expand_path("~/.richat/config.json")}\e[0m"
35
- puts JSON.pretty_generate(Config.config)
35
+ puts JSON.pretty_generate(Config.get_config)
36
36
  NEXT_CODE
37
37
  end
38
38
 
@@ -123,7 +123,13 @@ module Richat
123
123
  @prompt_id = nil
124
124
  return
125
125
  end
126
- File.read(File.join(File.expand_path(Config.get("prompt", "prompt_dir")), @prompt_id))
126
+
127
+ begin
128
+ File.read(File.join(File.expand_path(Config.get("prompt", "prompt_dir")), @prompt_id))
129
+ rescue => e
130
+ print_exception(e.message)
131
+ exit
132
+ end
127
133
  end
128
134
  end
129
135
  end
data/lib/richat/config.rb CHANGED
@@ -9,6 +9,7 @@ module Richat
9
9
  "log" => {
10
10
  "enable" => true,
11
11
  "log_dir" => "~/.richat/logs",
12
+ "log_file" => nil,
12
13
  "user_role" => "USR",
13
14
  "ai_role" => "GPT",
14
15
  "system_role" => "SYS"
@@ -28,8 +29,16 @@ module Richat
28
29
  class << self
29
30
  attr_reader :config
30
31
 
32
+ def get_config
33
+ (@config ||= merge_config)
34
+ end
35
+
31
36
  def get(*keys)
32
- (@config ||= merge_config).dig(*keys)
37
+ get_config.dig(*keys)
38
+ end
39
+
40
+ def override_with(other_config)
41
+ @config = Utils.deep_merge_hash(get_config, other_config)
33
42
  end
34
43
  end
35
44
 
@@ -41,7 +50,7 @@ module Richat
41
50
  else
42
51
  {}
43
52
  end
44
- DEFAULT_CONFIG.deep_merge(user_config)
53
+ Utils.deep_merge_hash(DEFAULT_CONFIG, user_config)
45
54
  end
46
55
  end
47
56
  end
data/lib/richat/logger.rb CHANGED
@@ -6,12 +6,12 @@ module Richat
6
6
 
7
7
  def initialize(options = {})
8
8
  original_log_header = ::Logger::LogDevice.instance_method(:add_log_header)
9
- ::Logger::LogDevice.define_method(:add_log_header) {|file|}
9
+ ::Logger::LogDevice.send(:define_method, :add_log_header) { |_file| nil }
10
10
 
11
- @logger = ::Logger.new(options[:log_file])
12
- ::Logger::LogDevice.define_method(original_log_header.name, original_log_header)
11
+ @logger = ::Logger.new(options[:log_file])
12
+ ::Logger::LogDevice.send(:define_method, original_log_header.name, original_log_header)
13
13
 
14
- @logger.formatter = proc do |severity, datetime, role, msg|
14
+ @logger.formatter = proc do |_severity, datetime, role, msg|
15
15
  "[#{role}] #{datetime.strftime('%Y-%m-%d %H:%M:%S')}\n\n#{msg}\n\n"
16
16
  end
17
17
  end
data/lib/richat/shell.rb CHANGED
@@ -11,7 +11,7 @@ module Richat
11
11
  @ai_role = Config.get("log", "ai_role")
12
12
  @system_role = Config.get("log", "system_role")
13
13
  @history_path = File.expand_path(Config.get("shell", "shell_history_file"))
14
- File.open(@history_path, 'w') {} unless File.exists?(@history_path)
14
+ File.open(@history_path, 'w') {} unless File.exist?(@history_path)
15
15
  end
16
16
 
17
17
  def call
@@ -0,0 +1,33 @@
1
+ module Richat
2
+ class Utils
3
+ class << self
4
+ def deep_merge_hash(hs1, hs2)
5
+ result = hs1.dup
6
+
7
+ hs2.each do |key, value|
8
+ if value.is_a?(Hash) && hs1[key].is_a?(Hash)
9
+ result[key] = deep_merge_hash(result[key], value)
10
+ else
11
+ result[key] = value
12
+ end
13
+ end
14
+
15
+ result
16
+ end
17
+
18
+ def absolute_path?(fp)
19
+ File.expand_path(fp) == fp
20
+ end
21
+
22
+ def ensure_dir_exist(*dirs)
23
+ dirs.each do |dir_name|
24
+ if dir_name.nil? || dir_name.empty?
25
+ puts "invalid directory"
26
+ exit
27
+ end
28
+ FileUtils.mkdir_p(dir_name) unless File.directory?(dir_name)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module Richat
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.5"
3
3
  end
data/lib/richat.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require "richat/version"
2
2
 
3
- require_relative 'extension/hash'
3
+ require_relative 'richat/utils'
4
4
  require_relative 'richat/config'
5
5
  require_relative 'richat/command'
6
6
  require_relative 'openai/chat'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: richat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - fzdp
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-31 00:00:00.000000000 Z
11
+ date: 2023-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -30,42 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.17'
33
+ version: 2.4.10
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.17'
40
+ version: 2.4.10
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.0'
61
+ version: '3.12'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.0'
68
+ version: '3.12'
69
69
  description: Richat is a command-line ChatGPT tool implemented in Ruby that supports
70
70
  highly customizable configuration. It can save chat logs, performs fuzzy searches
71
71
  on historical inputs, allows for prompt customization and switching at any time
@@ -77,7 +77,6 @@ extensions: []
77
77
  extra_rdoc_files: []
78
78
  files:
79
79
  - exe/richat
80
- - lib/extension/hash.rb
81
80
  - lib/openai/chat.rb
82
81
  - lib/richat.rb
83
82
  - lib/richat/cli.rb
@@ -85,6 +84,7 @@ files:
85
84
  - lib/richat/config.rb
86
85
  - lib/richat/logger.rb
87
86
  - lib/richat/shell.rb
87
+ - lib/richat/utils.rb
88
88
  - lib/richat/version.rb
89
89
  homepage: https://github.com/fzdp/richat
90
90
  licenses:
@@ -100,14 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 2.3.0
103
+ version: 2.6.0
104
104
  required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
109
  requirements: []
110
- rubygems_version: 3.0.9
110
+ rubygems_version: 3.4.10
111
111
  signing_key:
112
112
  specification_version: 4
113
113
  summary: Richat is a command-line ChatGPT tool
@@ -1,15 +0,0 @@
1
- class Hash
2
- def deep_merge(other_hash)
3
- result = self.dup
4
-
5
- other_hash.each do |key, value|
6
- if value.is_a?(Hash) && self[key].is_a?(Hash)
7
- result[key] = result[key].deep_merge(value)
8
- else
9
- result[key] = value
10
- end
11
- end
12
-
13
- result
14
- end
15
- end