summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock4
-rw-r--r--components/storage.rb4
-rw-r--r--controllers/instance.rb2
-rw-r--r--controllers/interfaces/eval.rb21
-rw-r--r--controllers/session.rb26
-rw-r--r--logic/helpers/hash.rb4
-rw-r--r--nano-bots.gemspec1
-rw-r--r--spec/spec_helper.rb93
-rw-r--r--static/cartridges/default.yml25
9 files changed, 57 insertions, 123 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 547a5b0..0acf361 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -8,6 +8,7 @@ PATH
pry (~> 0.14.2)
rainbow (~> 3.1, >= 3.1.1)
ruby-openai (~> 4.0)
+ sweet-moon (~> 0.0.7)
GEM
remote: https://rubygems.org/
@@ -23,6 +24,7 @@ GEM
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (3.0.2)
+ ffi (1.15.5)
json (2.6.3)
method_source (1.0.0)
multipart-post (2.3.0)
@@ -73,6 +75,8 @@ GEM
faraday-multipart (>= 1)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
+ sweet-moon (0.0.7)
+ ffi (~> 1.15, >= 1.15.5)
unicode-display_width (2.4.2)
PLATFORMS
diff --git a/components/storage.rb b/components/storage.rb
index d46455f..bdf0efe 100644
--- a/components/storage.rb
+++ b/components/storage.rb
@@ -43,7 +43,7 @@ module NanoBot
partial = File.join(File.dirname(partial), File.basename(partial, File.extname(partial)))
- partial = path.sub(%r{^\.?/}, '')
+ partial = partial.sub(%r{^\.?/}, '')
candidates << "#{directory}/#{partial}"
candidates << "#{directory}/#{partial}.yml"
@@ -54,7 +54,7 @@ module NanoBot
partial = File.join(File.dirname(partial), File.basename(partial, File.extname(partial)))
- partial = path.sub(%r{^\.?/}, '')
+ partial = partial.sub(%r{^\.?/}, '')
candidates << "#{directory}/#{partial}"
candidates << "#{directory}/#{partial}.yml"
diff --git a/controllers/instance.rb b/controllers/instance.rb
index 503b388..80ac9be 100644
--- a/controllers/instance.rb
+++ b/controllers/instance.rb
@@ -55,7 +55,7 @@ module NanoBot
def load_cartridge!(path)
elected_path = if path.strip == '-'
- File.expand_path('../static/cartridges/default.yml', __dir__)
+ File.expand_path('../static/cartridges/baseline.yml', __dir__)
else
Components::Storage.cartridge_path(path)
end
diff --git a/controllers/interfaces/eval.rb b/controllers/interfaces/eval.rb
index af519ab..851770b 100644
--- a/controllers/interfaces/eval.rb
+++ b/controllers/interfaces/eval.rb
@@ -4,34 +4,21 @@ require 'pry'
require 'rainbow'
require_relative '../../logic/helpers/hash'
+require_relative '../../logic/cartridge/affixes'
module NanoBot
module Controllers
module Interfaces
module Eval
def self.evaluate(input, cartridge, session)
- prefix = build_prefix(cartridge)
- postfix = build_postfix(cartridge)
+ prefix = Logic::Cartridge::Affixes.get(cartridge, :eval, :output, :prefix)
+ suffix = Logic::Cartridge::Affixes.get(cartridge, :eval, :output, :suffix)
session.print(prefix) unless prefix.nil?
session.evaluate_and_print(input, mode: 'eval')
- session.print(postfix) unless postfix.nil?
- end
-
- def self.build_prefix(cartridge)
- eval_interface = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces eval])
- return nil if eval_interface.nil?
-
- eval_interface[:prefix]
- end
-
- def self.build_postfix(cartridge)
- eval_interface = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces eval])
- return "\n" if eval_interface.nil? || !eval_interface.key?(:postfix) # default
-
- eval_interface[:postfix]
+ session.print(suffix) unless suffix.nil?
end
end
end
diff --git a/controllers/session.rb b/controllers/session.rb
index 1eb600d..d61fdd5 100644
--- a/controllers/session.rb
+++ b/controllers/session.rb
@@ -5,7 +5,10 @@ require 'babosa'
require 'fileutils'
require_relative '../logic/helpers/hash'
+require_relative '../logic/cartridge/streaming'
+require_relative '../logic/cartridge/interaction'
require_relative '../components/storage'
+require_relative '../components/adapter'
module NanoBot
module Controllers
@@ -56,24 +59,22 @@ module NanoBot
def evaluate_and_print(message, mode:)
behavior = Logic::Helpers::Hash.fetch(@cartridge, %i[behaviors interaction]) || {}
- @state[:history] << ({ who: 'user', message: })
+ @state[:history] << {
+ who: 'user',
+ message: Components::Adapter.apply(
+ :input, Logic::Cartridge::Interaction.input(@cartridge, mode.to_sym, message)
+ )
+ }
input = { behavior:, history: @state[:history] }
process(input, mode:)
end
- def streaming(interface)
- provider = @provider.settings.key?(:stream) ? @provider.settings[:stream] : true
- interface = interface.key?(:stream) ? interface[:stream] : true
-
- provider && interface
- end
-
def process(input, mode:)
interface = Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym]) || {}
- streaming = streaming(interface)
+ streaming = Logic::Cartridge::Streaming.enabled?(@cartridge, mode.to_sym)
input[:interface] = interface
@@ -81,7 +82,14 @@ module NanoBot
ready = false
@provider.evaluate(input) do |output, finished|
+ output = Logic::Cartridge::Interaction.output(
+ @cartridge, mode.to_sym, output, streaming, finished
+ )
+
+ output[:message] = Components::Adapter.apply(:output, output[:message])
+
updated_at = Time.now
+
if finished
@state[:history] << output
self.print(output[:message]) unless streaming
diff --git a/logic/helpers/hash.rb b/logic/helpers/hash.rb
index 52bd8d4..90432b5 100644
--- a/logic/helpers/hash.rb
+++ b/logic/helpers/hash.rb
@@ -23,6 +23,10 @@ module NanoBot
return nil unless node
path.each do |key|
+ unless node.is_a?(::Hash)
+ node = nil
+ break
+ end
node = node[key]
break if node.nil?
end
diff --git a/nano-bots.gemspec b/nano-bots.gemspec
index 0a3d9a6..b717371 100644
--- a/nano-bots.gemspec
+++ b/nano-bots.gemspec
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'pry', '~> 0.14.2'
spec.add_dependency 'rainbow', '~> 3.1', '>= 3.1.1'
spec.add_dependency 'ruby-openai', '~> 4.0'
+ spec.add_dependency 'sweet-moon', '~> 0.0.7'
spec.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 4f8c8d9..ad9038d 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,98 +1,23 @@
# frozen_string_literal: true
-# This file was generated by the `rspec --init` command. Conventionally, all
-# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
-# The generated `.rspec` file contains `--require spec_helper` which will cause
-# this file to always be loaded, without a need to explicitly require it in any
-# files.
-#
-# Given that it is always loaded, you are encouraged to keep this file as
-# light-weight as possible. Requiring heavyweight dependencies from this file
-# will add to the boot time of your test suite on EVERY test run, even for an
-# individual file that may not need all of that loaded. Instead, consider making
-# a separate helper file that requires the additional dependencies and performs
-# the additional setup, and require it from the spec files that actually need
-# it.
-#
-# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+require 'yaml'
+
+require_relative '../logic/helpers/hash'
+
RSpec.configure do |config|
- # rspec-expectations config goes here. You can use an alternate
- # assertion/expectation library such as wrong or the stdlib/minitest
- # assertions if you prefer.
config.expect_with :rspec do |expectations|
- # This option will default to `true` in RSpec 4. It makes the `description`
- # and `failure_message` of custom matchers include text for helper methods
- # defined using `chain`, e.g.:
- # be_bigger_than(2).and_smaller_than(4).description
- # # => "be bigger than 2 and smaller than 4"
- # ...rather than:
- # # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
- # rspec-mocks config goes here. You can use an alternate test double
- # library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
- # Prevents you from mocking or stubbing a method that does not exist on
- # a real object. This is generally recommended, and will default to
- # `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
- # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
- # have no way to turn it off -- the option exists only for backwards
- # compatibility in RSpec 3). It causes shared context metadata to be
- # inherited by the metadata hash of host groups and examples, rather than
- # triggering implicit auto-inclusion in groups with matching metadata.
config.shared_context_metadata_behavior = :apply_to_host_groups
+end
+
+def load_cartridge(path)
+ cartridge = YAML.safe_load(File.read("spec/data/cartridges/#{path}"), permitted_classes: [Symbol])
- # The settings below are suggested to provide a good initial experience
- # with RSpec, but feel free to customize to your heart's content.
- # # This allows you to limit a spec run to individual examples or groups
- # # you care about by tagging them with `:focus` metadata. When nothing
- # # is tagged with `:focus`, all examples get run. RSpec also provides
- # # aliases for `it`, `describe`, and `context` that include `:focus`
- # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
- # config.filter_run_when_matching :focus
- #
- # # Allows RSpec to persist some state between runs in order to support
- # # the `--only-failures` and `--next-failure` CLI options. We recommend
- # # you configure your source control system to ignore this file.
- # config.example_status_persistence_file_path = "spec/examples.txt"
- #
- # # Limits the available syntax to the non-monkey patched syntax that is
- # # recommended. For more details, see:
- # # https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/
- # config.disable_monkey_patching!
- #
- # # This setting enables warnings. It's recommended, but in some cases may
- # # be too noisy due to issues in dependencies.
- # config.warnings = true
- #
- # # Many RSpec users commonly either run the entire suite or an individual
- # # file, and it's useful to allow more verbose output when running an
- # # individual spec file.
- # if config.files_to_run.one?
- # # Use the documentation formatter for detailed output,
- # # unless a formatter has already been configured
- # # (e.g. via a command-line flag).
- # config.default_formatter = "doc"
- # end
- #
- # # Print the 10 slowest examples and example groups at the
- # # end of the spec run, to help surface which specs are running
- # # particularly slow.
- # config.profile_examples = 10
- #
- # # Run specs in random order to surface order dependencies. If you find an
- # # order dependency and want to debug it, you can fix the order by providing
- # # the seed, which is printed after each run.
- # # --seed 1234
- # config.order = :random
- #
- # # Seed global randomization in this process using the `--seed` CLI option.
- # # Setting this allows you to use `--seed` to deterministically reproduce
- # # test failures related to randomization by passing the same `--seed` value
- # # as the one that triggered the failure.
- # Kernel.srand config.seed
+ NanoBot::Logic::Helpers::Hash.symbolize_keys(cartridge)
end
diff --git a/static/cartridges/default.yml b/static/cartridges/default.yml
index b5eed62..df609ed 100644
--- a/static/cartridges/default.yml
+++ b/static/cartridges/default.yml
@@ -1,14 +1,19 @@
---
-meta:
- name: Unknown
- author: Nobody
- version: 0.0.0
+interfaces:
+ repl:
+ output:
+ suffix: "\n"
+ prefix: "\n"
+ stream: true
+ prompt:
+ - text: '🤖'
+ - text: '> '
+ color: blue
+ eval:
+ output:
+ stream: true
+ suffix: "\n"
provider:
- name: openai
settings:
- model: gpt-3.5-turbo
- credentials:
- address: ENV/OPENAI_API_ADDRESS
- access-token: ENV/OPENAI_API_ACCESS_TOKEN
- user-identifier: ENV/OPENAI_API_USER_IDENTIFIER
+ stream: true