nano-bots 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -3
- data/README.md +104 -4
- data/components/crypto.rb +43 -0
- data/components/provider.rb +2 -2
- data/components/providers/openai.rb +13 -6
- data/components/storage.rb +29 -4
- data/controllers/cartridges.rb +1 -1
- data/controllers/instance.rb +5 -3
- data/controllers/interfaces/cli.rb +23 -0
- data/controllers/interfaces/eval.rb +0 -4
- data/controllers/security.rb +27 -0
- data/controllers/session.rb +8 -4
- data/docker-compose.example.yml +2 -1
- data/nano-bots.gemspec +1 -0
- data/ports/dsl/nano-bots.rb +16 -4
- data/static/fennel/LICENSE +21 -0
- data/static/gem.rb +1 -1
- metadata +25 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b042b76220123246b7456f35a892292b4df837d7174870ec8f5b9afed97a17cf
|
4
|
+
data.tar.gz: 3088c0a1f4b1744ee8827d7eaa9aaefdc6a35568dd0eff5963b22034ae3955e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8abc4664db7e12421519eea694c8d42267cce0264d0501e3469a452854b6b1e9de27a0d5a939afb8b6903d32114d05d3f6392d0f45bbfe4f399de0d99b3a6f6
|
7
|
+
data.tar.gz: a12beec15362c517d5d0cbe3d114a74c9cd95b5bd44d6d66346e7180a399f96521e8508719a501c0a62817bf9783bf54687e9ac2eb5b18cc5e92cc1c5fe39948
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nano-bots (0.0.
|
4
|
+
nano-bots (0.0.10)
|
5
5
|
babosa (~> 2.0)
|
6
6
|
dotenv (~> 2.8, >= 2.8.1)
|
7
7
|
faraday (~> 2.7, >= 2.7.5)
|
8
8
|
pry (~> 0.14.2)
|
9
9
|
rainbow (~> 3.1, >= 3.1.1)
|
10
|
+
rbnacl (~> 7.1, >= 7.1.1)
|
10
11
|
ruby-openai (~> 4.0)
|
11
12
|
sweet-moon (~> 0.0.7)
|
12
13
|
|
@@ -35,6 +36,8 @@ GEM
|
|
35
36
|
coderay (~> 1.1)
|
36
37
|
method_source (~> 1.0)
|
37
38
|
rainbow (3.1.1)
|
39
|
+
rbnacl (7.1.1)
|
40
|
+
ffi
|
38
41
|
regexp_parser (2.8.0)
|
39
42
|
rexml (3.2.5)
|
40
43
|
rspec (3.12.0)
|
@@ -50,7 +53,7 @@ GEM
|
|
50
53
|
diff-lcs (>= 1.2.0, < 2.0)
|
51
54
|
rspec-support (~> 3.12.0)
|
52
55
|
rspec-support (3.12.0)
|
53
|
-
rubocop (1.
|
56
|
+
rubocop (1.52.0)
|
54
57
|
json (~> 2.3)
|
55
58
|
parallel (~> 1.10)
|
56
59
|
parser (>= 3.2.0.0)
|
@@ -60,7 +63,7 @@ GEM
|
|
60
63
|
rubocop-ast (>= 1.28.0, < 2.0)
|
61
64
|
ruby-progressbar (~> 1.7)
|
62
65
|
unicode-display_width (>= 2.4.0, < 3.0)
|
63
|
-
rubocop-ast (1.
|
66
|
+
rubocop-ast (1.29.0)
|
64
67
|
parser (>= 3.2.1.0)
|
65
68
|
rubocop-capybara (2.18.0)
|
66
69
|
rubocop (~> 1.41)
|
data/README.md
CHANGED
@@ -13,6 +13,11 @@ https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b
|
|
13
13
|
- [Command Line](#command-line)
|
14
14
|
- [Library](#library)
|
15
15
|
- [Cartridges](#cartridges)
|
16
|
+
- [Marketplace](#marketplace)
|
17
|
+
- [Security and Privacy](#security-and-privacy)
|
18
|
+
- [Cryptography](#cryptography)
|
19
|
+
- [End-user IDs](#end-user-ids)
|
20
|
+
- [Decrypting](#decrypting)
|
16
21
|
- [Providers](#providers)
|
17
22
|
- [Debugging](#debugging)
|
18
23
|
- [Development](#development)
|
@@ -23,13 +28,13 @@ https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b
|
|
23
28
|
For a system usage:
|
24
29
|
|
25
30
|
```sh
|
26
|
-
gem install nano-bots -v 0.0.
|
31
|
+
gem install nano-bots -v 0.0.10
|
27
32
|
```
|
28
33
|
|
29
34
|
To use it in a project, add it to your `Gemfile`:
|
30
35
|
|
31
36
|
```ruby
|
32
|
-
gem 'nano-bots', '~> 0.0.
|
37
|
+
gem 'nano-bots', '~> 0.0.10'
|
33
38
|
```
|
34
39
|
|
35
40
|
```sh
|
@@ -39,6 +44,7 @@ bundle install
|
|
39
44
|
For credentials and configurations, relevant environment variables can be set in your `.bashrc`, `.zshrc`, or equivalent files, as well as in your Docker Container or System Environment. Example:
|
40
45
|
|
41
46
|
```sh
|
47
|
+
export NANO_BOTS_ENCRYPTION_PASSWORD="UNSAFE"
|
42
48
|
export OPENAI_API_ADDRESS=https://api.openai.com
|
43
49
|
export OPENAI_API_ACCESS_TOKEN=your-token
|
44
50
|
export OPENAI_API_USER_IDENTIFIER=your-user
|
@@ -50,6 +56,7 @@ export OPENAI_API_USER_IDENTIFIER=your-user
|
|
50
56
|
Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded:
|
51
57
|
|
52
58
|
```sh
|
59
|
+
NANO_BOTS_ENCRYPTION_PASSWORD="UNSAFE"
|
53
60
|
OPENAI_API_ADDRESS=https://api.openai.com
|
54
61
|
OPENAI_API_ACCESS_TOKEN=your-token
|
55
62
|
OPENAI_API_USER_IDENTIFIER=your-user
|
@@ -76,8 +83,9 @@ version: '3.7'
|
|
76
83
|
services:
|
77
84
|
nano-bots:
|
78
85
|
image: ruby:3.2.2-slim-bullseye
|
79
|
-
command: sh -c "gem install nano-bots -v 0.0.
|
86
|
+
command: sh -c "gem install nano-bots -v 0.0.10 && bash"
|
80
87
|
environment:
|
88
|
+
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
81
89
|
OPENAI_API_ADDRESS: https://api.openai.com
|
82
90
|
OPENAI_API_ACCESS_TOKEN: your-token
|
83
91
|
OPENAI_API_USER_IDENTIFIER: your-user
|
@@ -261,6 +269,98 @@ Check the Nano Bots specification to learn more about [how to build cartridges](
|
|
261
269
|
|
262
270
|
Try the [Nano Bots Clinic (Live Editor)](https://clinic.nbots.io) to learn about creating Cartridges.
|
263
271
|
|
272
|
+
### Marketplace
|
273
|
+
|
274
|
+
You can explore the Nano Bots [Marketplace](https://nbots.io) to discover new Cartridges that can help you.
|
275
|
+
|
276
|
+
## Security and Privacy
|
277
|
+
|
278
|
+
Each provider will have its own security and privacy policies (e.g. [OpenAI Policy](https://openai.com/policies/api-data-usage-policies)), so you must consult them to understand their implications.
|
279
|
+
|
280
|
+
### Cryptography
|
281
|
+
|
282
|
+
By default, all states stored in your local disk are encrypted.
|
283
|
+
|
284
|
+
To ensure that the encryption is secure, you need to define a password through the `NANO_BOTS_ENCRYPTION_PASSWORD` environment variable. Otherwise, although the content will be encrypted, anyone would be able to decrypt it without a password.
|
285
|
+
|
286
|
+
It's important to note that the content shared with providers, despite being transmitted over secure connections (e.g., [HTTPS](https://en.wikipedia.org/wiki/HTTPS)), will be readable by the provider. This is because providers need to operate on the data, which would not be possible if the content was encrypted beyond HTTPS. So, the data stored locally on your system is encrypted, which does not mean that what you share with providers will not be readable by them.
|
287
|
+
|
288
|
+
To ensure that your encryption and password are configured properly, you can run the following command:
|
289
|
+
```sh
|
290
|
+
nb security
|
291
|
+
```
|
292
|
+
|
293
|
+
Which should return:
|
294
|
+
```text
|
295
|
+
✅ Encryption is enabled and properly working.
|
296
|
+
This means that your data is stored in an encrypted format on your disk.
|
297
|
+
|
298
|
+
✅ A password is being used for the encrypted content.
|
299
|
+
This means that only those who possess the password can decrypt your data.
|
300
|
+
```
|
301
|
+
|
302
|
+
Alternatively, you can check it at runtime with:
|
303
|
+
```ruby
|
304
|
+
require 'nano-bots'
|
305
|
+
|
306
|
+
NanoBot.security.check
|
307
|
+
# => { encryption: true, password: true }
|
308
|
+
```
|
309
|
+
|
310
|
+
#### End-user IDs
|
311
|
+
|
312
|
+
A common strategy for deploying Nano Bots to multiple users through APIs or automations is to assign a unique [end-user ID](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids) for each user. This can be useful if any of your users violate the provider's policy due to abusive behavior. By providing the end-user ID, you can unravel that even though the activity originated from your API Key, the actions taken were not your own.
|
313
|
+
|
314
|
+
You can define custom end-user identifiers in the following way:
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
NanoBot.new(environment: { NANO_BOTS_USER_IDENTIFIER: 'user-a' })
|
318
|
+
NanoBot.new(environment: { NANO_BOTS_USER_IDENTIFIER: 'user-b' })
|
319
|
+
```
|
320
|
+
|
321
|
+
Consider that you have have the following OpenAI user identifier:
|
322
|
+
```sh
|
323
|
+
OPENAI_API_USER_IDENTIFIER=your-name
|
324
|
+
```
|
325
|
+
|
326
|
+
The requests will be performed as follows:
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
NanoBot.new(environment: {NANO_BOTS_USER_IDENTIFIER: 'user-a'})
|
330
|
+
# { user: 'your-name/user-a' }
|
331
|
+
|
332
|
+
NanoBot.new(environment: {NANO_BOTS_USER_IDENTIFIER: 'user-b'})
|
333
|
+
# { user: 'your-name/user-b' }
|
334
|
+
```
|
335
|
+
|
336
|
+
Actually, to enhance privacy, neither your user nor your users' identifiers will be shared in this way. Instead, they will be encrypted before being shared with the provider:
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
'your-name/user-a'
|
340
|
+
# -onBK9GWafYz-JM8-cydhn4jd4Bkfkec5FtJ1ReCrtHCDPjkhCqUjRobG1zLnAz3BLo1kFhRW3w=
|
341
|
+
|
342
|
+
'your-name/user-a'
|
343
|
+
# RldW4_xxktCksEAR9G8aORuq3skPAc9ivWj3eye2ICCHQy8gG_R5qLMS3Fg-0lY6LwxKGQur5Ww=
|
344
|
+
```
|
345
|
+
|
346
|
+
In this manner, you possess identifiers if required, however, their actual content can only be decrypted by you via your secure password (`NANO_BOTS_ENCRYPTION_PASSWORD`).
|
347
|
+
|
348
|
+
## Decrypting
|
349
|
+
|
350
|
+
To decrypt your encrypted data, once you have properly configured your password, you can simply run:
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
require 'nano-bots'
|
354
|
+
|
355
|
+
NanoBot.security.decrypt('-onBK9GWafYz-JM8-cydhn4jd4Bkfkec5FtJ1ReCrtHCDPjkhCqUjRobG1zLnAz3BLo1kFhRW3w=')
|
356
|
+
# your-name/user-b
|
357
|
+
|
358
|
+
NanoBot.security.decrypt('RldW4_xxktCksEAR9G8aORuq3skPAc9ivWj3eye2ICCHQy8gG_R5qLMS3Fg-0lY6LwxKGQur5Ww=')
|
359
|
+
# your-name/user-b
|
360
|
+
```
|
361
|
+
|
362
|
+
If you lose your password, you lose your data. It is not possible to recover it at all. For real.
|
363
|
+
|
264
364
|
## Providers
|
265
365
|
|
266
366
|
Currently supported providers:
|
@@ -288,5 +388,5 @@ gem build nano-bots.gemspec
|
|
288
388
|
|
289
389
|
gem signin
|
290
390
|
|
291
|
-
gem push nano-bots-0.0.
|
391
|
+
gem push nano-bots-0.0.10.gem
|
292
392
|
```
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require 'rbnacl'
|
5
|
+
require 'base64'
|
6
|
+
|
7
|
+
module NanoBot
|
8
|
+
module Components
|
9
|
+
class Crypto
|
10
|
+
include Singleton
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
password = ENV.fetch('NANO_BOTS_ENCRYPTION_PASSWORD', nil)
|
14
|
+
|
15
|
+
password = 'UNSAFE' unless password && password != ''
|
16
|
+
|
17
|
+
@box = RbNaCl::SecretBox.new(RbNaCl::Hash.sha256(password))
|
18
|
+
@fixed_nonce = RbNaCl::Hash.sha256(password)[0...@box.nonce_bytes]
|
19
|
+
end
|
20
|
+
|
21
|
+
def encrypt(content, soft: false)
|
22
|
+
nonce = soft ? @fixed_nonce : RbNaCl::Random.random_bytes(@box.nonce_bytes)
|
23
|
+
Base64.urlsafe_encode64(nonce + @box.encrypt(nonce, content))
|
24
|
+
end
|
25
|
+
|
26
|
+
def decrypt(content)
|
27
|
+
decoded_content = Base64.urlsafe_decode64(content)
|
28
|
+
nonce = decoded_content[0...@box.nonce_bytes]
|
29
|
+
cipher_text = decoded_content[@box.nonce_bytes..]
|
30
|
+
|
31
|
+
@box.decrypt(nonce, cipher_text)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.encrypt(content, soft: false)
|
35
|
+
instance.encrypt(content, soft:)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.decrypt(content)
|
39
|
+
instance.decrypt(content)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/components/provider.rb
CHANGED
@@ -7,10 +7,10 @@ require_relative './providers/openai'
|
|
7
7
|
module NanoBot
|
8
8
|
module Components
|
9
9
|
class Provider
|
10
|
-
def self.new(provider)
|
10
|
+
def self.new(provider, environment: {})
|
11
11
|
case provider[:name]
|
12
12
|
when 'openai'
|
13
|
-
Providers::OpenAI.new(provider[:settings])
|
13
|
+
Providers::OpenAI.new(provider[:settings], environment:)
|
14
14
|
else
|
15
15
|
raise "Unsupported provider #{provider[:name]}"
|
16
16
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'openai'
|
4
4
|
|
5
5
|
require_relative './base'
|
6
|
+
require_relative '../crypto'
|
6
7
|
|
7
8
|
module NanoBot
|
8
9
|
module Components
|
@@ -15,8 +16,9 @@ module NanoBot
|
|
15
16
|
|
16
17
|
attr_reader :settings
|
17
18
|
|
18
|
-
def initialize(settings)
|
19
|
+
def initialize(settings, environment: {})
|
19
20
|
@settings = settings
|
21
|
+
@environment = environment
|
20
22
|
|
21
23
|
@client = ::OpenAI::Client.new(
|
22
24
|
uri_base: "#{@settings[:credentials][:address].sub(%r{/$}, '')}/",
|
@@ -46,11 +48,16 @@ module NanoBot
|
|
46
48
|
)
|
47
49
|
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
user = @settings[:credentials][:'user-identifier']
|
52
|
+
|
53
|
+
user_suffix = @environment && (
|
54
|
+
@environment['NANO_BOTS_USER_IDENTIFIER'] ||
|
55
|
+
@environment[:NANO_BOTS_USER_IDENTIFIER]
|
56
|
+
)
|
57
|
+
|
58
|
+
user = "#{user}/#{user_suffix}" if user_suffix && user_suffix != ''
|
59
|
+
|
60
|
+
payload = { model: @settings[:model], user: Crypto.encrypt(user, soft: true), messages: }
|
54
61
|
|
55
62
|
CHAT_SETTINGS.each do |key|
|
56
63
|
payload[key] = @settings[key] if @settings.key?(key)
|
data/components/storage.rb
CHANGED
@@ -3,11 +3,12 @@
|
|
3
3
|
require 'babosa'
|
4
4
|
|
5
5
|
require_relative '../logic/helpers/hash'
|
6
|
+
require_relative './crypto'
|
6
7
|
|
7
8
|
module NanoBot
|
8
9
|
module Components
|
9
10
|
class Storage
|
10
|
-
def self.build_path_and_ensure_state_file!(key, cartridge)
|
11
|
+
def self.build_path_and_ensure_state_file!(key, cartridge, environment: {})
|
11
12
|
path = [
|
12
13
|
Logic::Helpers::Hash.fetch(cartridge, %i[state directory]),
|
13
14
|
ENV.fetch('NANO_BOTS_STATE_DIRECTORY', nil)
|
@@ -17,14 +18,38 @@ module NanoBot
|
|
17
18
|
|
18
19
|
path = "#{user_home!.sub(%r{/$}, '')}/.local/state/nano-bots" if path.nil?
|
19
20
|
|
20
|
-
|
21
|
+
prefix = environment && (
|
22
|
+
environment['NANO_BOTS_USER_IDENTIFIER'] ||
|
23
|
+
environment[:NANO_BOTS_USER_IDENTIFIER]
|
24
|
+
)
|
25
|
+
|
26
|
+
path = "#{path.sub(%r{/$}, '')}/ruby-nano-bots/vault"
|
27
|
+
|
28
|
+
if prefix
|
29
|
+
normalized = prefix.split('/').map do |part|
|
30
|
+
Crypto.encrypt(
|
31
|
+
part.to_s.gsub('.', '-').force_encoding('UTF-8').to_slug.normalize,
|
32
|
+
soft: true
|
33
|
+
)
|
34
|
+
end.join('/')
|
35
|
+
|
36
|
+
path = "#{path}/#{normalized}"
|
37
|
+
end
|
38
|
+
|
39
|
+
path = "#{path}/#{cartridge[:meta][:author].to_slug.normalize}"
|
21
40
|
path = "#{path}/#{cartridge[:meta][:name].to_slug.normalize}"
|
22
|
-
path = "#{path}/#{cartridge[:meta][:version].to_s.gsub('.', '-').to_slug.normalize}
|
41
|
+
path = "#{path}/#{cartridge[:meta][:version].to_s.gsub('.', '-').to_slug.normalize}"
|
42
|
+
path = "#{path}/#{Crypto.encrypt(key, soft: true)}"
|
23
43
|
path = "#{path}/state.json"
|
24
44
|
|
25
45
|
FileUtils.mkdir_p(File.dirname(path))
|
26
46
|
|
27
|
-
|
47
|
+
unless File.exist?(path)
|
48
|
+
File.write(
|
49
|
+
path,
|
50
|
+
Crypto.encrypt(JSON.generate({ key:, history: [] }))
|
51
|
+
)
|
52
|
+
end
|
28
53
|
|
29
54
|
path
|
30
55
|
end
|
data/controllers/cartridges.rb
CHANGED
@@ -39,7 +39,7 @@ module NanoBot
|
|
39
39
|
rescue StandardError => _e
|
40
40
|
end
|
41
41
|
|
42
|
-
cartridges.sort_by { |cartridge| cartridge[:meta][:name] }
|
42
|
+
cartridges = cartridges.sort_by { |cartridge| cartridge[:meta][:name] }
|
43
43
|
|
44
44
|
cartridges.prepend(
|
45
45
|
{ system: { id: '-' }, meta: { name: 'Default', symbol: '🤖' } }
|
data/controllers/instance.rb
CHANGED
@@ -13,14 +13,16 @@ require_relative './session'
|
|
13
13
|
module NanoBot
|
14
14
|
module Controllers
|
15
15
|
class Instance
|
16
|
-
def initialize(cartridge_path:, stream:, state: nil)
|
16
|
+
def initialize(cartridge_path:, stream:, state: nil, environment: {})
|
17
17
|
@stream = stream
|
18
18
|
|
19
19
|
load_cartridge!(cartridge_path)
|
20
20
|
|
21
|
-
provider = Components::Provider.new(@cartridge[:provider])
|
21
|
+
provider = Components::Provider.new(@cartridge[:provider], environment:)
|
22
22
|
|
23
|
-
@session = Session.new(
|
23
|
+
@session = Session.new(
|
24
|
+
provider:, cartridge: @cartridge, state:, stream: @stream, environment:
|
25
|
+
)
|
24
26
|
end
|
25
27
|
|
26
28
|
def cartridge
|
@@ -11,6 +11,28 @@ module NanoBot
|
|
11
11
|
case ARGV[0]
|
12
12
|
when 'version'
|
13
13
|
puts NanoBot::GEM[:version]
|
14
|
+
exit
|
15
|
+
when 'security'
|
16
|
+
result = NanoBot.security.check
|
17
|
+
|
18
|
+
if result[:encryption]
|
19
|
+
puts "\n✅ Encryption is enabled and properly working."
|
20
|
+
puts ' This means that your data is stored in an encrypted format on your disk.'
|
21
|
+
else
|
22
|
+
puts "\n❌ Encryption is not being utilized to store your content."
|
23
|
+
puts ' This means that your data can be easily read because it is stored in plaintext.'
|
24
|
+
end
|
25
|
+
|
26
|
+
if result[:password]
|
27
|
+
puts "\n✅ A password is being used for the encrypted content."
|
28
|
+
puts ' This means that only those who possess the password can decrypt your data.'
|
29
|
+
else
|
30
|
+
puts "\n❌ No custom password is being used for the encrypted content."
|
31
|
+
puts ' This means that anyone can easily decrypt your data.'
|
32
|
+
end
|
33
|
+
|
34
|
+
puts ''
|
35
|
+
|
14
36
|
exit
|
15
37
|
when 'help', '', nil
|
16
38
|
puts ''
|
@@ -34,6 +56,7 @@ module NanoBot
|
|
34
56
|
puts ' nb - STATE-KEY state'
|
35
57
|
puts ' nb cartridge.yml STATE-KEY state'
|
36
58
|
puts ''
|
59
|
+
puts ' nb security'
|
37
60
|
puts ' nb version'
|
38
61
|
puts ' nb help'
|
39
62
|
puts ''
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../components/crypto'
|
4
|
+
|
5
|
+
module NanoBot
|
6
|
+
module Controllers
|
7
|
+
module Security
|
8
|
+
def self.decrypt(content)
|
9
|
+
Components::Crypto.decrypt(content)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.check
|
13
|
+
password = ENV.fetch('NANO_BOTS_ENCRYPTION_PASSWORD', nil)
|
14
|
+
password = 'UNSAFE' unless password && password != ''
|
15
|
+
|
16
|
+
{
|
17
|
+
encryption: (
|
18
|
+
Components::Crypto.encrypt('SAFE') != 'SAFE' &&
|
19
|
+
Components::Crypto.encrypt('SAFE') != Components::Crypto.encrypt('SAFE') &&
|
20
|
+
Components::Crypto.decrypt(Components::Crypto.encrypt('SAFE')) == 'SAFE'
|
21
|
+
),
|
22
|
+
password: password != 'UNSAFE'
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/controllers/session.rb
CHANGED
@@ -9,6 +9,7 @@ require_relative '../logic/cartridge/streaming'
|
|
9
9
|
require_relative '../logic/cartridge/interaction'
|
10
10
|
require_relative '../components/storage'
|
11
11
|
require_relative '../components/adapter'
|
12
|
+
require_relative '../components/crypto'
|
12
13
|
|
13
14
|
module NanoBot
|
14
15
|
module Controllers
|
@@ -17,7 +18,7 @@ module NanoBot
|
|
17
18
|
class Session
|
18
19
|
attr_accessor :stream
|
19
20
|
|
20
|
-
def initialize(provider:, cartridge:, state: nil, stream: $stdout)
|
21
|
+
def initialize(provider:, cartridge:, state: nil, stream: $stdout, environment: {})
|
21
22
|
@stream = stream
|
22
23
|
@provider = provider
|
23
24
|
@cartridge = cartridge
|
@@ -28,8 +29,9 @@ module NanoBot
|
|
28
29
|
@state = { history: [] }
|
29
30
|
else
|
30
31
|
@state_path = Components::Storage.build_path_and_ensure_state_file!(
|
31
|
-
state.strip, @cartridge
|
32
|
+
state.strip, @cartridge, environment:
|
32
33
|
)
|
34
|
+
|
33
35
|
@state = load_state
|
34
36
|
end
|
35
37
|
end
|
@@ -39,11 +41,13 @@ module NanoBot
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def load_state
|
42
|
-
@state = Logic::Helpers::Hash.symbolize_keys(JSON.parse(
|
44
|
+
@state = Logic::Helpers::Hash.symbolize_keys(JSON.parse(
|
45
|
+
Components::Crypto.decrypt(File.read(@state_path))
|
46
|
+
))
|
43
47
|
end
|
44
48
|
|
45
49
|
def store_state!
|
46
|
-
File.write(@state_path, JSON.generate(@state))
|
50
|
+
File.write(@state_path, Components::Crypto.encrypt(JSON.generate(@state)))
|
47
51
|
end
|
48
52
|
|
49
53
|
def boot(mode:)
|
data/docker-compose.example.yml
CHANGED
@@ -3,8 +3,9 @@ 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 lua5.4-dev && gem install nano-bots -v 0.0.
|
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.0.10 && bash"
|
7
7
|
environment:
|
8
|
+
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
8
9
|
OPENAI_API_ADDRESS: https://api.openai.com
|
9
10
|
OPENAI_API_ACCESS_TOKEN: your-token
|
10
11
|
OPENAI_API_USER_IDENTIFIER: your-user
|
data/nano-bots.gemspec
CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_dependency 'faraday', '~> 2.7', '>= 2.7.5'
|
37
37
|
spec.add_dependency 'pry', '~> 0.14.2'
|
38
38
|
spec.add_dependency 'rainbow', '~> 3.1', '>= 3.1.1'
|
39
|
+
spec.add_dependency 'rbnacl', '~> 7.1', '>= 7.1.1'
|
39
40
|
spec.add_dependency 'ruby-openai', '~> 4.0'
|
40
41
|
spec.add_dependency 'sweet-moon', '~> 0.0.7'
|
41
42
|
|
data/ports/dsl/nano-bots.rb
CHANGED
@@ -5,12 +5,22 @@ require 'dotenv/load'
|
|
5
5
|
require_relative '../../static/gem'
|
6
6
|
require_relative '../../controllers/cartridges'
|
7
7
|
require_relative '../../controllers/instance'
|
8
|
+
require_relative '../../controllers/security'
|
8
9
|
require_relative '../../controllers/interfaces/cli'
|
9
10
|
require_relative '../../components/stream'
|
10
11
|
|
11
12
|
module NanoBot
|
12
|
-
def self.new(cartridge: '-', state: '-')
|
13
|
-
Controllers::Instance.new(
|
13
|
+
def self.new(cartridge: '-', state: '-', environment: {})
|
14
|
+
Controllers::Instance.new(
|
15
|
+
cartridge_path: cartridge,
|
16
|
+
state:,
|
17
|
+
stream: Components::Stream.new,
|
18
|
+
environment:
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.security
|
23
|
+
Controllers::Security
|
14
24
|
end
|
15
25
|
|
16
26
|
def self.cartridges
|
@@ -21,8 +31,10 @@ module NanoBot
|
|
21
31
|
Controllers::Interfaces::CLI.handle!
|
22
32
|
end
|
23
33
|
|
24
|
-
def self.repl(cartridge: '-', state: '-')
|
25
|
-
Controllers::Instance.new(
|
34
|
+
def self.repl(cartridge: '-', state: '-', environment: {})
|
35
|
+
Controllers::Instance.new(
|
36
|
+
cartridge_path: cartridge, state:, stream: $stdout, environment:
|
37
|
+
).repl
|
26
38
|
end
|
27
39
|
|
28
40
|
def self.version
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright © 2016-2022 Calvin Rose and contributors
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/static/gem.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module NanoBot
|
4
4
|
GEM = {
|
5
5
|
name: 'nano-bots',
|
6
|
-
version: '0.0.
|
6
|
+
version: '0.0.10',
|
7
7
|
author: 'icebaker',
|
8
8
|
summary: 'Ruby Implementation of Nano Bots: small, AI-powered bots',
|
9
9
|
description: 'Ruby Implementation of Nano Bots: small, AI-powered bots easily shared as a single file, designed to support multiple providers such as Vicuna, OpenAI ChatGPT, Google PaLM, Alpaca, and LLaMA.',
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nano-bots
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- icebaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: babosa
|
@@ -98,6 +98,26 @@ dependencies:
|
|
98
98
|
- - ">="
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: 3.1.1
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: rbnacl
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '7.1'
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 7.1.1
|
111
|
+
type: :runtime
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '7.1'
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 7.1.1
|
101
121
|
- !ruby/object:Gem::Dependency
|
102
122
|
name: ruby-openai
|
103
123
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,6 +164,7 @@ files:
|
|
144
164
|
- README.md
|
145
165
|
- bin/nb
|
146
166
|
- components/adapter.rb
|
167
|
+
- components/crypto.rb
|
147
168
|
- components/provider.rb
|
148
169
|
- components/providers/base.rb
|
149
170
|
- components/providers/openai.rb
|
@@ -154,6 +175,7 @@ files:
|
|
154
175
|
- controllers/interfaces/cli.rb
|
155
176
|
- controllers/interfaces/eval.rb
|
156
177
|
- controllers/interfaces/repl.rb
|
178
|
+
- controllers/security.rb
|
157
179
|
- controllers/session.rb
|
158
180
|
- docker-compose.example.yml
|
159
181
|
- logic/cartridge/adapters.rb
|
@@ -167,6 +189,7 @@ files:
|
|
167
189
|
- ports/dsl/nano-bots/cli.rb
|
168
190
|
- static/cartridges/baseline.yml
|
169
191
|
- static/cartridges/default.yml
|
192
|
+
- static/fennel/LICENSE
|
170
193
|
- static/fennel/fennel.lua
|
171
194
|
- static/gem.rb
|
172
195
|
homepage: https://github.com/icebaker/ruby-nano-bots
|