nano-bots 0.1.1 → 1.0.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.
@@ -6,9 +6,9 @@ require_relative '../logic/helpers/hash'
6
6
  require_relative '../components/provider'
7
7
  require_relative '../components/storage'
8
8
  require_relative '../components/stream'
9
- require_relative './interfaces/repl'
10
- require_relative './interfaces/eval'
11
- require_relative './session'
9
+ require_relative 'interfaces/repl'
10
+ require_relative 'interfaces/eval'
11
+ require_relative 'session'
12
12
 
13
13
  module NanoBot
14
14
  module Controllers
@@ -83,7 +83,7 @@ module NanoBot
83
83
  raise StandardError, "Cartridge file not found: \"#{path}\""
84
84
  end
85
85
 
86
- @cartridge = YAML.safe_load(File.read(elected_path), permitted_classes: [Symbol])
86
+ @cartridge = YAML.safe_load_file(elected_path, permitted_classes: [Symbol])
87
87
  end
88
88
 
89
89
  @safe_cartridge = Marshal.load(Marshal.dump(@cartridge))
@@ -81,7 +81,7 @@ module NanoBot
81
81
  when 'cartridge'
82
82
  puts YAML.dump(bot.cartridge)
83
83
  else
84
- raise "TODO: [#{params[:command]}]"
84
+ raise "Command not found: [#{params[:command]}]"
85
85
  end
86
86
  end
87
87
  end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+
5
+ require_relative '../../logic/cartridge/tools'
6
+ require_relative '../../logic/cartridge/safety'
7
+ require_relative '../../components/embedding'
8
+
9
+ module NanoBot
10
+ module Controllers
11
+ module Interfaces
12
+ module Tool
13
+ def self.confirming(session, cartridge, mode, feedback)
14
+ yeses = Logic::Cartridge::Safety.yeses(cartridge)
15
+ default_answer = Logic::Cartridge::Safety.default_answer(cartridge)
16
+ dispatch_feedback(session, cartridge, mode, feedback)
17
+ session.flush
18
+ answer = $stdin.gets.chomp.to_s.downcase.strip
19
+ answer = default_answer if answer == ''
20
+ session.print("\n")
21
+ yeses.include?(answer)
22
+ end
23
+
24
+ def self.adapt(feedback, adapter, cartridge)
25
+ call = {
26
+ parameters: %w[id name parameters parameters-as-json output],
27
+ values: [
28
+ feedback[:id], feedback[:name], feedback[:parameters],
29
+ feedback[:parameters].to_json,
30
+ feedback[:output]
31
+ ],
32
+ safety: { sandboxed: Logic::Cartridge::Safety.sandboxed?(cartridge) }
33
+ }
34
+
35
+ raise StandardError, 'conflicting adapters' if %i[fennel lua clojure].count { |key| !adapter[key].nil? } > 1
36
+
37
+ if adapter[:fennel]
38
+ call[:source] = adapter[:fennel]
39
+ Components::Embedding.fennel(**call)
40
+ elsif adapter[:clojure]
41
+ call[:source] = adapter[:clojure]
42
+ Components::Embedding.clojure(**call)
43
+ elsif adapter[:lua]
44
+ call[:parameters] = %w[id name parameters parameters_as_json output]
45
+ call[:source] = adapter[:lua]
46
+ Components::Embedding.lua(**call)
47
+ else
48
+ raise 'missing handler for adapter'
49
+ end
50
+ end
51
+
52
+ def self.dispatch_feedback(session, cartridge, mode, feedback)
53
+ enabled = Logic::Cartridge::Tools.feedback?(cartridge, mode.to_sym, feedback[:action].to_sym)
54
+
55
+ enabled = true if feedback[:action].to_sym == :confirming
56
+
57
+ return unless enabled
58
+
59
+ color = Logic::Cartridge::Tools.fetch_from_interface(
60
+ cartridge, mode.to_sym, feedback[:action].to_sym, [:color]
61
+ )
62
+
63
+ adapter = Tool.adapter(cartridge, mode, feedback)
64
+
65
+ if %i[fennel lua clojure].any? { |key| !adapter[key].nil? }
66
+ message = adapt(feedback, adapter, cartridge)
67
+ else
68
+ message = "#{feedback[:name]} #{feedback[:parameters].to_json}"
69
+
70
+ message += "\n#{feedback[:output]}" if feedback[:action].to_sym == :responding
71
+ end
72
+
73
+ message = "#{adapter[:prefix]}#{message}#{adapter[:suffix]}"
74
+
75
+ session.print(color.nil? ? message : Rainbow(message).send(color))
76
+ end
77
+
78
+ def self.adapter(cartridge, mode, feedback)
79
+ prefix = Logic::Cartridge::Tools.fetch_from_interface(
80
+ cartridge, mode.to_sym, feedback[:action].to_sym, [:prefix]
81
+ )
82
+
83
+ suffix = Logic::Cartridge::Tools.fetch_from_interface(
84
+ cartridge, mode.to_sym, feedback[:action].to_sym, [:suffix]
85
+ )
86
+
87
+ fennel = Logic::Cartridge::Tools.fetch_from_interface(
88
+ cartridge, mode.to_sym, feedback[:action].to_sym, %i[adapter fennel]
89
+ )
90
+
91
+ lua = Logic::Cartridge::Tools.fetch_from_interface(
92
+ cartridge, mode.to_sym, feedback[:action].to_sym, %i[adapter lua]
93
+ )
94
+
95
+ clojure = Logic::Cartridge::Tools.fetch_from_interface(
96
+ cartridge, mode.to_sym, feedback[:action].to_sym, %i[adapter clojure]
97
+ )
98
+
99
+ { prefix:, suffix:, fennel:, lua:, clojure: }
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -3,10 +3,14 @@
3
3
  require 'babosa'
4
4
 
5
5
  require 'fileutils'
6
+ require 'rainbow'
6
7
 
7
8
  require_relative '../logic/helpers/hash'
9
+ require_relative '../logic/cartridge/safety'
8
10
  require_relative '../logic/cartridge/streaming'
9
11
  require_relative '../logic/cartridge/interaction'
12
+ require_relative '../logic/cartridge/fetch'
13
+ require_relative 'interfaces/tools'
10
14
  require_relative '../components/storage'
11
15
  require_relative '../components/adapter'
12
16
  require_relative '../components/crypto'
@@ -14,6 +18,7 @@ require_relative '../components/crypto'
14
18
  module NanoBot
15
19
  module Controllers
16
20
  STREAM_TIMEOUT_IN_SECONDS = 5
21
+ INFINITE_LOOP_PREVENTION = 10
17
22
 
18
23
  class Session
19
24
  attr_accessor :stream
@@ -41,9 +46,9 @@ module NanoBot
41
46
  end
42
47
 
43
48
  def load_state
44
- @state = Logic::Helpers::Hash.symbolize_keys(JSON.parse(
45
- Components::Crypto.decrypt(File.read(@state_path))
46
- ))
49
+ @state = Logic::Helpers::Hash.symbolize_keys(
50
+ JSON.parse(Components::Crypto.decrypt(File.read(@state_path)))
51
+ )
47
52
  end
48
53
 
49
54
  def store_state!
@@ -68,7 +73,7 @@ module NanoBot
68
73
  mode: mode.to_s,
69
74
  input: message,
70
75
  message: Components::Adapter.apply(
71
- :input, Logic::Cartridge::Interaction.input(@cartridge, mode.to_sym, message)
76
+ Logic::Cartridge::Interaction.input(@cartridge, mode.to_sym, message), @cartridge
72
77
  )
73
78
  }
74
79
 
@@ -78,41 +83,88 @@ module NanoBot
78
83
  end
79
84
 
80
85
  def process(input, mode:)
86
+ interface = Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym]) || {}
87
+
88
+ input[:interface] = interface
89
+ input[:tools] = @cartridge[:tools]
90
+
91
+ needs_another_round = true
92
+
93
+ rounds = 0
94
+
95
+ while needs_another_round
96
+ needs_another_round = process_interaction(input, mode:)
97
+ rounds += 1
98
+ raise StandardError, 'infinite loop prevention' if rounds > INFINITE_LOOP_PREVENTION
99
+ end
100
+ end
101
+
102
+ def process_interaction(input, mode:)
81
103
  prefix = Logic::Cartridge::Affixes.get(@cartridge, mode.to_sym, :output, :prefix)
82
104
  suffix = Logic::Cartridge::Affixes.get(@cartridge, mode.to_sym, :output, :suffix)
83
105
 
84
- interface = Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym]) || {}
106
+ color = Logic::Cartridge::Fetch.cascate(
107
+ @cartridge, [[:interfaces, mode.to_sym, :output, :color], %i[interfaces output color]]
108
+ )
85
109
 
86
- streaming = Logic::Cartridge::Streaming.enabled?(@cartridge, mode.to_sym)
110
+ color = color.to_sym if color
87
111
 
88
- input[:interface] = interface
112
+ streaming = Logic::Cartridge::Streaming.enabled?(@cartridge, mode.to_sym)
89
113
 
90
114
  updated_at = Time.now
91
115
 
92
116
  ready = false
93
- @provider.evaluate(input) do |output, finished|
94
- updated_at = Time.now
95
-
96
- if finished
97
- event = Marshal.load(Marshal.dump(output))
98
117
 
99
- output = Logic::Cartridge::Interaction.output(
100
- @cartridge, mode.to_sym, output, streaming, finished
101
- )
118
+ needs_another_round = false
102
119
 
103
- output[:message] = Components::Adapter.apply(:output, output[:message])
120
+ @provider.evaluate(input, streaming, @cartridge) do |feedback|
121
+ needs_another_round = true if feedback[:needs_another_round]
104
122
 
105
- event[:mode] = mode.to_s
106
- event[:output] = "#{prefix}#{output[:message]}#{suffix}"
107
-
108
- @state[:history] << event
109
-
110
- self.print(output[:message]) unless streaming
123
+ updated_at = Time.now
111
124
 
112
- ready = true
113
- flush
114
- elsif streaming
115
- self.print(output[:message])
125
+ if feedback[:interaction] &&
126
+ feedback.dig(:interaction, :meta, :tool, :action) &&
127
+ feedback[:interaction][:meta][:tool][:action] == 'confirming'
128
+ Interfaces::Tool.confirming(self, @cartridge, mode, feedback[:interaction][:meta][:tool])
129
+ else
130
+
131
+ if feedback[:interaction] && feedback.dig(:interaction, :meta, :tool, :action)
132
+ Interfaces::Tool.dispatch_feedback(
133
+ self, @cartridge, mode, feedback[:interaction][:meta][:tool]
134
+ )
135
+ end
136
+
137
+ if feedback[:interaction]
138
+ event = Marshal.load(Marshal.dump(feedback[:interaction]))
139
+ event[:mode] = mode.to_s
140
+ event[:output] = nil
141
+
142
+ if feedback[:interaction][:who] == 'AI' && feedback[:interaction][:message]
143
+ event[:output] = feedback[:interaction][:message]
144
+ unless streaming
145
+ output = Logic::Cartridge::Interaction.output(
146
+ @cartridge, mode.to_sym, feedback[:interaction], streaming, feedback[:finished]
147
+ )
148
+ output[:message] = Components::Adapter.apply(output[:message], @cartridge)
149
+ event[:output] = (output[:message]).to_s
150
+ end
151
+ end
152
+
153
+ @state[:history] << event if feedback[:should_be_stored]
154
+
155
+ if event[:output] && ((!feedback[:finished] && streaming) || (!streaming && feedback[:finished]))
156
+ self.print(color ? Rainbow(event[:output]).send(color) : event[:output])
157
+ end
158
+
159
+ # The `print` function already outputs a prefix and a suffix, so
160
+ # we should add them afterwards to avoid printing them twice.
161
+ event[:output] = "#{prefix}#{event[:output]}#{suffix}"
162
+ end
163
+
164
+ if feedback[:finished]
165
+ flush
166
+ ready = true
167
+ end
116
168
  end
117
169
  end
118
170
 
@@ -122,6 +174,8 @@ module NanoBot
122
174
  end
123
175
 
124
176
  store_state! unless @stateless
177
+
178
+ needs_another_round
125
179
  end
126
180
 
127
181
  def flush
@@ -3,7 +3,7 @@ version: '3.7'
3
3
  services:
4
4
  nano-bots:
5
5
  image: ruby:3.2.2-slim-bullseye
6
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev && gem install nano-bots -v 0.1.1 && bash"
6
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev && gem install nano-bots -v 1.0.0 && bash"
7
7
  environment:
8
8
  OPENAI_API_ADDRESS: https://api.openai.com
9
9
  OPENAI_API_KEY: your-access-token
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../helpers/hash'
4
- require_relative './default'
4
+ require_relative 'default'
5
5
 
6
6
  module NanoBot
7
7
  module Logic
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../helpers/hash'
4
- require_relative './default'
4
+ require_relative 'default'
5
5
 
6
6
  module NanoBot
7
7
  module Logic
@@ -15,7 +15,7 @@ module NanoBot
15
15
  return @values if @values
16
16
 
17
17
  path = File.expand_path('../../static/cartridges/default.yml', __dir__)
18
- cartridge = YAML.safe_load(File.read(path), permitted_classes: [Symbol])
18
+ cartridge = YAML.safe_load_file(path, permitted_classes: [Symbol])
19
19
  @values = Logic::Helpers::Hash.symbolize_keys(cartridge)
20
20
  @values
21
21
  end
@@ -24,7 +24,7 @@ module NanoBot
24
24
  return @baseline if @baseline
25
25
 
26
26
  path = File.expand_path('../../static/cartridges/baseline.yml', __dir__)
27
- cartridge = YAML.safe_load(File.read(path), permitted_classes: [Symbol])
27
+ cartridge = YAML.safe_load_file(path, permitted_classes: [Symbol])
28
28
  @baseline = Logic::Helpers::Hash.symbolize_keys(cartridge)
29
29
  @baseline
30
30
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'default'
4
+ require_relative '../helpers/hash'
5
+
6
+ module NanoBot
7
+ module Logic
8
+ module Cartridge
9
+ module Fetch
10
+ def self.cascate(cartridge, paths)
11
+ results = paths.map { |path| Helpers::Hash.fetch(cartridge, path) }
12
+ result = results.find { |candidate| !candidate.nil? }
13
+ return result unless result.nil?
14
+
15
+ results = paths.map { |path| Helpers::Hash.fetch(Default.instance.values, path) }
16
+ result = results.find { |candidate| !candidate.nil? }
17
+ return result unless result.nil?
18
+
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sweet-moon'
4
-
5
- require_relative './affixes'
6
- require_relative './adapters'
3
+ require_relative 'affixes'
4
+ require_relative 'adapters'
7
5
 
8
6
  module NanoBot
9
7
  module Logic
@@ -12,23 +10,25 @@ module NanoBot
12
10
  def self.input(cartridge, interface, content)
13
11
  lua = Adapter.expression(cartridge, interface, :input, :lua)
14
12
  fennel = Adapter.expression(cartridge, interface, :input, :fennel)
13
+ clojure = Adapter.expression(cartridge, interface, :input, :clojure)
15
14
 
16
15
  prefix = Affixes.get(cartridge, interface, :input, :prefix)
17
16
  suffix = Affixes.get(cartridge, interface, :input, :suffix)
18
17
 
19
- { content:, prefix:, suffix:, lua:, fennel: }
18
+ { content:, prefix:, suffix:, lua:, fennel:, clojure: }
20
19
  end
21
20
 
22
21
  def self.output(cartridge, interface, result, streaming, _finished)
23
22
  if streaming
24
- result[:message] = { content: result[:message], lua: nil, fennel: nil }
23
+ result[:message] = { content: result[:message], lua: nil, fennel: nil, clojure: nil }
25
24
  return result
26
25
  end
27
26
 
28
27
  lua = Adapter.expression(cartridge, interface, :output, :lua)
29
28
  fennel = Adapter.expression(cartridge, interface, :output, :fennel)
29
+ clojure = Adapter.expression(cartridge, interface, :output, :clojure)
30
30
 
31
- result[:message] = { content: result[:message], lua:, fennel: }
31
+ result[:message] = { content: result[:message], lua:, fennel:, clojure: }
32
32
 
33
33
  result
34
34
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'fetch'
4
+
5
+ module NanoBot
6
+ module Logic
7
+ module Cartridge
8
+ module Safety
9
+ def self.default_answer(cartridge)
10
+ default = Fetch.cascate(cartridge, [%i[interfaces tools confirming default]])
11
+ return [] if default.nil?
12
+
13
+ default
14
+ end
15
+
16
+ def self.yeses(cartridge)
17
+ yeses_values = Fetch.cascate(cartridge, [%i[interfaces tools confirming yeses]])
18
+ return [] if yeses_values.nil?
19
+
20
+ yeses_values
21
+ end
22
+
23
+ def self.confirmable?(cartridge)
24
+ confirmable = Fetch.cascate(cartridge, [%i[safety tools confirmable]])
25
+ return true if confirmable.nil?
26
+
27
+ confirmable
28
+ end
29
+
30
+ def self.sandboxed?(cartridge)
31
+ sandboxed = Fetch.cascate(cartridge, [%i[safety functions sandboxed]])
32
+ return true if sandboxed.nil?
33
+
34
+ sandboxed
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'fetch'
4
+ require_relative 'affixes'
5
+ require_relative 'adapters'
6
+
7
+ module NanoBot
8
+ module Logic
9
+ module Cartridge
10
+ module Tools
11
+ def self.fetch_from_interface(cartridge, interface, action, path)
12
+ Fetch.cascate(cartridge, [
13
+ [:interfaces, interface, :tools, action].concat(path),
14
+ [:interfaces, :tools, action].concat(path),
15
+ %i[interfaces tools].concat(path)
16
+ ])
17
+ end
18
+
19
+ def self.feedback?(cartridge, interface, action)
20
+ Fetch.cascate(cartridge, [
21
+ [:interfaces, interface, :tools, action, :feedback],
22
+ [:interfaces, :tools, action, :feedback],
23
+ %i[interfaces tools feedback]
24
+ ])
25
+ end
26
+
27
+ def self.input(cartridge, interface, content)
28
+ lua = Adapter.expression(cartridge, interface, :input, :lua)
29
+ fennel = Adapter.expression(cartridge, interface, :input, :fennel)
30
+
31
+ prefix = Affixes.get(cartridge, interface, :input, :prefix)
32
+ suffix = Affixes.get(cartridge, interface, :input, :suffix)
33
+
34
+ { content:, prefix:, suffix:, lua:, fennel: }
35
+ end
36
+
37
+ def self.output(cartridge, interface, result, streaming, _finished)
38
+ if streaming
39
+ result[:message] = { content: result[:message], lua: nil, fennel: nil }
40
+ return result
41
+ end
42
+
43
+ lua = Adapter.expression(cartridge, interface, :output, :lua)
44
+ fennel = Adapter.expression(cartridge, interface, :output, :fennel)
45
+
46
+ result[:message] = { content: result[:message], lua:, fennel: }
47
+
48
+ result
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative '../../helpers/hash'
6
+
7
+ module NanoBot
8
+ module Logic
9
+ module OpenAI
10
+ module Tools
11
+ def self.prepare(cartridge, tools)
12
+ applies = []
13
+
14
+ tools = Marshal.load(Marshal.dump(tools))
15
+
16
+ tools.each do |tool|
17
+ tool = Helpers::Hash.symbolize_keys(tool)
18
+
19
+ cartridge.each do |candidate|
20
+ next unless tool[:function][:name] == candidate[:name]
21
+
22
+ source = {}
23
+
24
+ source[:clojure] = candidate[:clojure] if candidate[:clojure]
25
+ source[:fennel] = candidate[:fennel] if candidate[:fennel]
26
+ source[:lua] = candidate[:lua] if candidate[:lua]
27
+
28
+ applies << {
29
+ id: tool[:id],
30
+ name: tool[:function][:name],
31
+ type: 'function',
32
+ parameters: JSON.parse(tool[:function][:arguments]),
33
+ source:
34
+ }
35
+ end
36
+ end
37
+
38
+ raise 'missing tool' if applies.size != tools.size
39
+
40
+ applies
41
+ end
42
+
43
+ def self.adapt(cartridge)
44
+ output = {
45
+ type: 'function',
46
+ function: {
47
+ name: cartridge[:name], description: cartridge[:description]
48
+ }
49
+ }
50
+
51
+ output[:function][:parameters] = (cartridge[:parameters] || { type: 'object', properties: {} })
52
+
53
+ output
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module NanoBot
6
+ module Logic
7
+ module OpenAI
8
+ def self.prepare_tools(cartridge, tools)
9
+ applies = []
10
+ tools.each do |tool|
11
+ cartridge.each do |candidate|
12
+ next unless candidate[:type] == 'function' &&
13
+ tool[:type] == candidate[:type] &&
14
+ tool[:function][:name] == candidate[:name]
15
+
16
+ source = {}
17
+
18
+ source[:fennel] = candidate[:fennel] if candidate[:fennel]
19
+ source[:lua] = candidate[:lua] if candidate[:lua]
20
+
21
+ applies << {
22
+ name: tool[:function][:name],
23
+ type: candidate[:type],
24
+ parameters: JSON.parse(tool[:function][:arguments]),
25
+ source:
26
+ }
27
+ end
28
+ end
29
+
30
+ applies
31
+ end
32
+
33
+ def self.adapt_tool(cartridge)
34
+ raise 'unsupported tool' if cartridge[:type] != 'function'
35
+
36
+ adapted = {
37
+ type: 'function',
38
+ function: {
39
+ name: cartridge[:name], description: cartridge[:description],
40
+ parameters: { type: 'object', properties: {} }
41
+ }
42
+ }
43
+
44
+ properties = adapted[:function][:parameters][:properties]
45
+
46
+ cartridge[:parameters].each do |parameter|
47
+ key = parameter[:name].to_sym
48
+ properties[key] = {}
49
+ properties[key][:type] = parameter[:type] || 'string'
50
+ properties[key][:description] = parameter[:description] if parameter[:description]
51
+ end
52
+
53
+ adapted
54
+ end
55
+ end
56
+ end
57
+ end
data/nano-bots.gemspec CHANGED
@@ -32,12 +32,13 @@ Gem::Specification.new do |spec|
32
32
  spec.executables = ['nb']
33
33
 
34
34
  spec.add_dependency 'babosa', '~> 2.0'
35
+ spec.add_dependency 'concurrent-ruby', '~> 1.2', '>= 1.2.2'
35
36
  spec.add_dependency 'dotenv', '~> 2.8', '>= 2.8.1'
36
- spec.add_dependency 'faraday', '~> 2.7', '>= 2.7.5'
37
+ spec.add_dependency 'faraday', '~> 2.7', '>= 2.7.12'
37
38
  spec.add_dependency 'pry', '~> 0.14.2'
38
39
  spec.add_dependency 'rainbow', '~> 3.1', '>= 3.1.1'
39
40
  spec.add_dependency 'rbnacl', '~> 7.1', '>= 7.1.1'
40
- spec.add_dependency 'ruby-openai', '~> 4.0'
41
+ spec.add_dependency 'ruby-openai', '~> 6.3'
41
42
  spec.add_dependency 'sweet-moon', '~> 0.0.7'
42
43
 
43
44
  spec.metadata['rubygems_mfa_required'] = 'true'
@@ -14,4 +14,4 @@ provider:
14
14
  access-token: ENV/OPENAI_API_KEY
15
15
  settings:
16
16
  user: ENV/NANO_BOTS_END_USER
17
- model: gpt-3.5-turbo
17
+ model: gpt-3.5-turbo-1106
@@ -1,4 +1,10 @@
1
1
  ---
2
+ safety:
3
+ functions:
4
+ sandboxed: true
5
+ tools:
6
+ confirmable: true
7
+
2
8
  interfaces:
3
9
  repl:
4
10
  output:
@@ -12,6 +18,16 @@ interfaces:
12
18
  output:
13
19
  stream: true
14
20
  suffix: "\n"
21
+ tools:
22
+ confirming:
23
+ suffix: ' [yN] '
24
+ default: 'n'
25
+ yeses: ['y', 'yes']
26
+ executing:
27
+ feedback: false
28
+ responding:
29
+ suffix: "\n\n"
30
+ feedback: true
15
31
 
16
32
  provider:
17
33
  settings: