nano-bots 0.0.4 → 0.0.5

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: 19a8bc3b2ea8dcd2703a22efb3ac334485536b602e385c3d5cd69cdb6e1bfa1b
4
- data.tar.gz: 76375f04692caacd92d832f843acaf3fb82cf68e0e467674749730a04e30794a
3
+ metadata.gz: 1ef7d964a5303c4cf07054210b720b5e57eede718ce549cb697331911577e884
4
+ data.tar.gz: bcfad5aec3b82903fc144d58d37640458bb97e957bddd5deabf46bc890d3a1e7
5
5
  SHA512:
6
- metadata.gz: 9ddbdc1421ce91117a2d16d94794f6111d2ea72503c24ed0f3597c7522a851e7fd7eef08703c5ba8f68826e51e9b34621591232e2d9a5220efda5d026027d413
7
- data.tar.gz: b2a729b278245a971a815c2333cd7676d795a64cdd86aef0d737ad9510c9a78bc8420eaaef9067f305201afbbccaf63e40508832d4cfad7cbf19b91fefc3aa07
6
+ metadata.gz: 816c65f1d09e912d76dfd5e651e9ae17fa9e0bb4fcbfd0932ef6498922c2c4d20422c329dfd239af90ccdd00dc8d1eb03a15ac723f0907e19fbecc79b4fcb2ad
7
+ data.tar.gz: b3254fb89ddfc4d69139130388150e986b2f750a3f56e6a068d211bff6db7413ed47b536dcbc84b04fde1c1679ea5968c7cf63e4ba62d72f07c436d64d21b611
data/Gemfile.lock CHANGED
@@ -1,13 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nano-bots (0.0.4)
4
+ nano-bots (0.0.5)
5
5
  babosa (~> 2.0)
6
6
  dotenv (~> 2.8, >= 2.8.1)
7
7
  faraday (~> 2.7, >= 2.7.4)
8
8
  pry (~> 0.14.2)
9
9
  rainbow (~> 3.1, >= 3.1.1)
10
10
  ruby-openai (~> 4.0)
11
+ sweet-moon (~> 0.0.7)
11
12
 
12
13
  GEM
13
14
  remote: https://rubygems.org/
@@ -23,6 +24,7 @@ GEM
23
24
  faraday-multipart (1.0.4)
24
25
  multipart-post (~> 2)
25
26
  faraday-net_http (3.0.2)
27
+ ffi (1.15.5)
26
28
  json (2.6.3)
27
29
  method_source (1.0.0)
28
30
  multipart-post (2.3.0)
@@ -73,6 +75,8 @@ GEM
73
75
  faraday-multipart (>= 1)
74
76
  ruby-progressbar (1.13.0)
75
77
  ruby2_keywords (0.0.5)
78
+ sweet-moon (0.0.7)
79
+ ffi (~> 1.15, >= 1.15.5)
76
80
  unicode-display_width (2.4.2)
77
81
 
78
82
  PLATFORMS
data/README.md CHANGED
@@ -23,13 +23,13 @@ https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b
23
23
  For a system usage:
24
24
 
25
25
  ```sh
26
- gem install nano-bots -v 0.0.4
26
+ gem install nano-bots -v 0.0.5
27
27
  ```
28
28
 
29
29
  To use it in a project, add it to your `Gemfile`:
30
30
 
31
31
  ```ruby
32
- gem 'nano-bots', '~> 0.0.4'
32
+ gem 'nano-bots', '~> 0.0.5'
33
33
  ```
34
34
 
35
35
  ```sh
@@ -76,7 +76,7 @@ version: '3.7'
76
76
  services:
77
77
  nano-bots:
78
78
  image: ruby:3.2.2-slim-bullseye
79
- command: sh -c "gem install nano-bots -v 0.0.4 && bash"
79
+ command: sh -c "gem install nano-bots -v 0.0.5 && bash"
80
80
  environment:
81
81
  OPENAI_API_ADDRESS: https://api.openai.com
82
82
  OPENAI_API_ACCESS_TOKEN: your-token
@@ -254,5 +254,5 @@ gem build nano-bots.gemspec
254
254
 
255
255
  gem signin
256
256
 
257
- gem push nano-bots-0.0.4.gem
257
+ gem push nano-bots-0.0.5.gem
258
258
  ```
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sweet-moon'
4
+
5
+ module NanoBot
6
+ module Components
7
+ class Adapter
8
+ def self.apply(_direction, params)
9
+ content = params[:content]
10
+
11
+ if params[:fennel] && params[:lua]
12
+ raise StandardError, 'Adapter conflict: You can only use either Lua or Fennel, not both.'
13
+ end
14
+
15
+ if params[:fennel]
16
+ content = fennel(content, params[:fennel])
17
+ elsif params[:lua]
18
+ content = lua(content, params[:lua])
19
+ end
20
+
21
+ "#{params[:prefix]}#{content}#{params[:suffix]}"
22
+ end
23
+
24
+ def self.fennel(content, expression)
25
+ path = "#{File.expand_path('../static/fennel', __dir__)}/?.lua"
26
+ state = SweetMoon::State.new(package_path: path).fennel
27
+ state.fennel.eval("(set _G.adapter (fn [content] #{expression}))")
28
+ adapter = state.get(:adapter)
29
+ adapter.call([content])
30
+ end
31
+
32
+ def self.lua(content, expression)
33
+ state = SweetMoon::State.new
34
+ state.eval("adapter = function(content) return #{expression}; end")
35
+ adapter = state.get(:adapter)
36
+ adapter.call([content])
37
+ end
38
+ end
39
+ end
40
+ end
@@ -43,7 +43,7 @@ module NanoBot
43
43
 
44
44
  partial = File.join(File.dirname(partial), File.basename(partial, File.extname(partial)))
45
45
 
46
- partial = path.sub(%r{^\.?/}, '')
46
+ partial = partial.sub(%r{^\.?/}, '')
47
47
 
48
48
  candidates << "#{directory}/#{partial}"
49
49
  candidates << "#{directory}/#{partial}.yml"
@@ -54,7 +54,7 @@ module NanoBot
54
54
 
55
55
  partial = File.join(File.dirname(partial), File.basename(partial, File.extname(partial)))
56
56
 
57
- partial = path.sub(%r{^\.?/}, '')
57
+ partial = partial.sub(%r{^\.?/}, '')
58
58
 
59
59
  candidates << "#{directory}/#{partial}"
60
60
  candidates << "#{directory}/#{partial}.yml"
@@ -55,7 +55,7 @@ module NanoBot
55
55
 
56
56
  def load_cartridge!(path)
57
57
  elected_path = if path.strip == '-'
58
- File.expand_path('../static/cartridges/default.yml', __dir__)
58
+ File.expand_path('../static/cartridges/baseline.yml', __dir__)
59
59
  else
60
60
  Components::Storage.cartridge_path(path)
61
61
  end
@@ -4,34 +4,21 @@ require 'pry'
4
4
  require 'rainbow'
5
5
 
6
6
  require_relative '../../logic/helpers/hash'
7
+ require_relative '../../logic/cartridge/affixes'
7
8
 
8
9
  module NanoBot
9
10
  module Controllers
10
11
  module Interfaces
11
12
  module Eval
12
13
  def self.evaluate(input, cartridge, session)
13
- prefix = build_prefix(cartridge)
14
- postfix = build_postfix(cartridge)
14
+ prefix = Logic::Cartridge::Affixes.get(cartridge, :eval, :output, :prefix)
15
+ suffix = Logic::Cartridge::Affixes.get(cartridge, :eval, :output, :suffix)
15
16
 
16
17
  session.print(prefix) unless prefix.nil?
17
18
 
18
19
  session.evaluate_and_print(input, mode: 'eval')
19
20
 
20
- session.print(postfix) unless postfix.nil?
21
- end
22
-
23
- def self.build_prefix(cartridge)
24
- eval_interface = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces eval])
25
- return nil if eval_interface.nil?
26
-
27
- eval_interface[:prefix]
28
- end
29
-
30
- def self.build_postfix(cartridge)
31
- eval_interface = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces eval])
32
- return "\n" if eval_interface.nil? || !eval_interface.key?(:postfix) # default
33
-
34
- eval_interface[:postfix]
21
+ session.print(suffix) unless suffix.nil?
35
22
  end
36
23
  end
37
24
  end
@@ -4,19 +4,20 @@ require 'pry'
4
4
  require 'rainbow'
5
5
 
6
6
  require_relative '../../logic/helpers/hash'
7
+ require_relative '../../logic/cartridge/affixes'
7
8
 
8
9
  module NanoBot
9
10
  module Controllers
10
11
  module Interfaces
11
12
  module REPL
12
13
  def self.start(cartridge, session)
13
- prefix = build_prefix(cartridge)
14
- postfix = build_postfix(cartridge)
14
+ prefix = Logic::Cartridge::Affixes.get(cartridge, :repl, :output, :prefix)
15
+ suffix = Logic::Cartridge::Affixes.get(cartridge, :repl, :output, :suffix)
15
16
 
16
17
  if Logic::Helpers::Hash.fetch(cartridge, %i[behaviors boot instruction])
17
18
  session.print(prefix) unless prefix.nil?
18
19
  session.boot(mode: 'repl')
19
- session.print(postfix) unless postfix.nil?
20
+ session.print(suffix) unless suffix.nil?
20
21
  session.print("\n")
21
22
  end
22
23
 
@@ -29,9 +30,9 @@ module NanoBot
29
30
  )
30
31
 
31
32
  Pry.commands.block_command(/(.*)/, 'handler') do |line|
32
- session.print(postfix) unless postfix.nil?
33
+ session.print(prefix) unless prefix.nil?
33
34
  session.evaluate_and_print(line, mode: 'repl')
34
- session.print(postfix) unless postfix.nil?
35
+ session.print(suffix) unless suffix.nil?
35
36
  session.print("\n")
36
37
  session.flush
37
38
  end
@@ -39,20 +40,6 @@ module NanoBot
39
40
  Pry.start
40
41
  end
41
42
 
42
- def self.build_prefix(cartridge)
43
- repl = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl])
44
- return "\n" if repl.nil? || !repl.key?(:prefix) # default
45
-
46
- repl[:prefix]
47
- end
48
-
49
- def self.build_postfix(cartridge)
50
- repl = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl])
51
- return "\n" if repl.nil? || !repl.key?(:postfix) # default
52
-
53
- repl[:postfix]
54
- end
55
-
56
43
  def self.build_prompt(prompt)
57
44
  result = ''
58
45
 
@@ -5,7 +5,10 @@ require 'babosa'
5
5
  require 'fileutils'
6
6
 
7
7
  require_relative '../logic/helpers/hash'
8
+ require_relative '../logic/cartridge/streaming'
9
+ require_relative '../logic/cartridge/interaction'
8
10
  require_relative '../components/storage'
11
+ require_relative '../components/adapter'
9
12
 
10
13
  module NanoBot
11
14
  module Controllers
@@ -56,24 +59,22 @@ module NanoBot
56
59
  def evaluate_and_print(message, mode:)
57
60
  behavior = Logic::Helpers::Hash.fetch(@cartridge, %i[behaviors interaction]) || {}
58
61
 
59
- @state[:history] << ({ who: 'user', message: })
62
+ @state[:history] << {
63
+ who: 'user',
64
+ message: Components::Adapter.apply(
65
+ :input, Logic::Cartridge::Interaction.input(@cartridge, mode.to_sym, message)
66
+ )
67
+ }
60
68
 
61
69
  input = { behavior:, history: @state[:history] }
62
70
 
63
71
  process(input, mode:)
64
72
  end
65
73
 
66
- def streaming(interface)
67
- provider = @provider.settings.key?(:stream) ? @provider.settings[:stream] : true
68
- interface = interface.key?(:stream) ? interface[:stream] : true
69
-
70
- provider && interface
71
- end
72
-
73
74
  def process(input, mode:)
74
75
  interface = Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym]) || {}
75
76
 
76
- streaming = streaming(interface)
77
+ streaming = Logic::Cartridge::Streaming.enabled?(@cartridge, mode.to_sym)
77
78
 
78
79
  input[:interface] = interface
79
80
 
@@ -82,9 +83,18 @@ module NanoBot
82
83
  ready = false
83
84
  @provider.evaluate(input) do |output, finished|
84
85
  updated_at = Time.now
86
+
85
87
  if finished
86
- @state[:history] << output
88
+ @state[:history] << Marshal.load(Marshal.dump(output))
89
+
90
+ output = Logic::Cartridge::Interaction.output(
91
+ @cartridge, mode.to_sym, output, streaming, finished
92
+ )
93
+
94
+ output[:message] = Components::Adapter.apply(:output, output[:message])
95
+
87
96
  self.print(output[:message]) unless streaming
97
+
88
98
  ready = true
89
99
  flush
90
100
  elsif streaming
@@ -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 "gem install nano-bots -v 0.0.4 && bash"
6
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev lua5.4-dev && gem install nano-bots -v 0.0.5 && bash"
7
7
  environment:
8
8
  OPENAI_API_ADDRESS: https://api.openai.com
9
9
  OPENAI_API_ACCESS_TOKEN: your-token
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helpers/hash'
4
+ require_relative './default'
5
+
6
+ module NanoBot
7
+ module Logic
8
+ module Cartridge
9
+ module Adapter
10
+ def self.expression(cartridge, interface, direction, language)
11
+ adapter = [
12
+ {
13
+ exists: (Helpers::Hash.fetch(cartridge, [:interfaces, direction, :adapter]) || {}).key?(language),
14
+ value: Helpers::Hash.fetch(cartridge, [:interfaces, direction, :adapter, language])
15
+ },
16
+ {
17
+ exists: (Helpers::Hash.fetch(cartridge,
18
+ [:interfaces, interface, direction, :adapter]) || {}).key?(language),
19
+ value: Helpers::Hash.fetch(cartridge, [:interfaces, interface, direction, :adapter, language])
20
+ }
21
+ ].filter { |candidate| candidate[:exists] }.last
22
+
23
+ return nil if adapter.nil?
24
+
25
+ adapter[:value]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helpers/hash'
4
+ require_relative './default'
5
+
6
+ module NanoBot
7
+ module Logic
8
+ module Cartridge
9
+ module Affixes
10
+ def self.get(cartridge, interface, direction, kind)
11
+ affix = [
12
+ {
13
+ exists: (Helpers::Hash.fetch(cartridge, [:interfaces, direction]) || {}).key?(kind),
14
+ value: Helpers::Hash.fetch(cartridge, [:interfaces, direction, kind])
15
+ },
16
+ {
17
+ exists: (Helpers::Hash.fetch(cartridge, [:interfaces, interface, direction]) || {}).key?(kind),
18
+ value: Helpers::Hash.fetch(cartridge, [:interfaces, interface, direction, kind])
19
+ }
20
+ ].filter { |candidate| candidate[:exists] }.last
21
+
22
+ if affix.nil?
23
+ return Helpers::Hash.fetch(
24
+ Default.instance.values, [:interfaces, interface, direction, kind]
25
+ )
26
+ end
27
+
28
+ affix[:value]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'singleton'
5
+
6
+ require_relative '../helpers/hash'
7
+
8
+ module NanoBot
9
+ module Logic
10
+ module Cartridge
11
+ class Default
12
+ include Singleton
13
+
14
+ def values
15
+ return @values if @values
16
+
17
+ path = File.expand_path('../../static/cartridges/default.yml', __dir__)
18
+ cartridge = YAML.safe_load(File.read(path), permitted_classes: [Symbol])
19
+ @values = Logic::Helpers::Hash.symbolize_keys(cartridge)
20
+ @values
21
+ end
22
+
23
+ def baseline
24
+ return @baseline if @baseline
25
+
26
+ path = File.expand_path('../../static/cartridges/baseline.yml', __dir__)
27
+ cartridge = YAML.safe_load(File.read(path), permitted_classes: [Symbol])
28
+ @baseline = Logic::Helpers::Hash.symbolize_keys(cartridge)
29
+ @baseline
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sweet-moon'
4
+
5
+ require_relative './affixes'
6
+ require_relative './adapters'
7
+
8
+ module NanoBot
9
+ module Logic
10
+ module Cartridge
11
+ module Interaction
12
+ def self.input(cartridge, interface, content)
13
+ lua = Adapter.expression(cartridge, interface, :input, :lua)
14
+ fennel = Adapter.expression(cartridge, interface, :input, :fennel)
15
+
16
+ prefix = Affixes.get(cartridge, interface, :input, :prefix)
17
+ suffix = Affixes.get(cartridge, interface, :input, :suffix)
18
+
19
+ { content:, prefix:, suffix:, lua:, fennel: }
20
+ end
21
+
22
+ def self.output(cartridge, interface, result, streaming, _finished)
23
+ if streaming
24
+ result[:message] = { content: result[:message], lua: nil, fennel: nil }
25
+ return result
26
+ end
27
+
28
+ lua = Adapter.expression(cartridge, interface, :output, :lua)
29
+ fennel = Adapter.expression(cartridge, interface, :output, :fennel)
30
+
31
+ result[:message] = { content: result[:message], lua:, fennel: }
32
+
33
+ result
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helpers/hash'
4
+
5
+ module NanoBot
6
+ module Logic
7
+ module Cartridge
8
+ module Streaming
9
+ def self.enabled?(cartridge, interface)
10
+ return false if Helpers::Hash.fetch(cartridge, %i[provider settings stream]) == false
11
+
12
+ specific_interface = Helpers::Hash.fetch(cartridge, [:interfaces, interface, :output, :stream])
13
+
14
+ return specific_interface unless specific_interface.nil?
15
+
16
+ interface = Helpers::Hash.fetch(cartridge, %i[interfaces output stream])
17
+
18
+ return interface unless interface.nil?
19
+
20
+ true
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -23,6 +23,10 @@ module NanoBot
23
23
  return nil unless node
24
24
 
25
25
  path.each do |key|
26
+ unless node.is_a?(::Hash)
27
+ node = nil
28
+ break
29
+ end
26
30
  node = node[key]
27
31
  break if node.nil?
28
32
  end
data/nano-bots.gemspec CHANGED
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.add_dependency 'pry', '~> 0.14.2'
38
38
  spec.add_dependency 'rainbow', '~> 3.1', '>= 3.1.1'
39
39
  spec.add_dependency 'ruby-openai', '~> 4.0'
40
+ spec.add_dependency 'sweet-moon', '~> 0.0.7'
40
41
 
41
42
  spec.metadata['rubygems_mfa_required'] = 'true'
42
43
  end
@@ -0,0 +1,14 @@
1
+ ---
2
+ meta:
3
+ name: Unknown
4
+ author: Nobody
5
+ version: 0.0.0
6
+
7
+ provider:
8
+ name: openai
9
+ settings:
10
+ model: gpt-3.5-turbo
11
+ credentials:
12
+ address: ENV/OPENAI_API_ADDRESS
13
+ access-token: ENV/OPENAI_API_ACCESS_TOKEN
14
+ user-identifier: ENV/OPENAI_API_USER_IDENTIFIER
@@ -1,14 +1,19 @@
1
1
  ---
2
- meta:
3
- name: Unknown
4
- author: Nobody
5
- version: 0.0.0
2
+ interfaces:
3
+ repl:
4
+ output:
5
+ stream: true
6
+ suffix: "\n"
7
+ prefix: "\n"
8
+ prompt:
9
+ - text: '🤖'
10
+ - text: '> '
11
+ color: blue
12
+ eval:
13
+ output:
14
+ stream: true
15
+ suffix: "\n"
6
16
 
7
17
  provider:
8
- name: openai
9
18
  settings:
10
- model: gpt-3.5-turbo
11
- credentials:
12
- address: ENV/OPENAI_API_ADDRESS
13
- access-token: ENV/OPENAI_API_ACCESS_TOKEN
14
- user-identifier: ENV/OPENAI_API_USER_IDENTIFIER
19
+ stream: true