nano-bots 2.5.1 → 3.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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +15 -13
- data/README.md +35 -20
- data/components/embedding.rb +1 -1
- data/components/providers/openai.rb +2 -2
- data/components/storage.rb +52 -17
- data/controllers/cartridges.rb +25 -17
- data/controllers/instance.rb +2 -5
- data/docker-compose.example.yml +1 -1
- data/logic/cartridge/parser.rb +134 -0
- data/logic/helpers/hash.rb +23 -0
- data/nano-bots.gemspec +1 -0
- data/ports/dsl/nano-bots/cartridges.rb +15 -0
- data/ports/dsl/nano-bots.rb +2 -1
- data/static/gem.rb +2 -2
- metadata +18 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e8c2efff966a76151fb23a83f4c77bc5af780f31898194747c53d8ddd2ff2877
|
|
4
|
+
data.tar.gz: 94642cd59c39f0f9d308e97fe3736bb3d89f529928d3e3896f4c1351a2f10fed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff0d2f67a1126a43443cd231184ad3dd02dea9c34178d6aa5da4c49cfdcceb137ab24af7bbaaad83d3e9c61d7019b2ba2950c15b7c1c7d072abc24de8eb8a5a7
|
|
7
|
+
data.tar.gz: 6850151d3af95c232c800e891e4c6ef8ee610030e6f9e45d24c623d497b1d61804f4b709e35b682ad89781fbb5b304d2e9b1048ae0150abaffdec9a0b2084f03
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nano-bots (
|
|
4
|
+
nano-bots (3.0.0)
|
|
5
5
|
babosa (~> 2.0)
|
|
6
6
|
cohere-ai (~> 1.0, >= 1.0.1)
|
|
7
7
|
concurrent-ruby (~> 1.2, >= 1.2.2)
|
|
@@ -13,6 +13,7 @@ PATH
|
|
|
13
13
|
pry (~> 0.14.2)
|
|
14
14
|
rainbow (~> 3.1, >= 3.1.1)
|
|
15
15
|
rbnacl (~> 7.1, >= 7.1.1)
|
|
16
|
+
redcarpet (~> 3.6)
|
|
16
17
|
ruby-openai (~> 6.3, >= 6.3.1)
|
|
17
18
|
sweet-moon (~> 0.0.7)
|
|
18
19
|
|
|
@@ -23,7 +24,6 @@ GEM
|
|
|
23
24
|
public_suffix (>= 2.0.2, < 6.0)
|
|
24
25
|
ast (2.4.2)
|
|
25
26
|
babosa (2.0.0)
|
|
26
|
-
base64 (0.2.0)
|
|
27
27
|
byebug (11.1.3)
|
|
28
28
|
coderay (1.1.3)
|
|
29
29
|
cohere-ai (1.0.1)
|
|
@@ -32,13 +32,12 @@ GEM
|
|
|
32
32
|
diff-lcs (1.5.0)
|
|
33
33
|
dotenv (2.8.1)
|
|
34
34
|
event_stream_parser (1.0.0)
|
|
35
|
-
faraday (2.
|
|
36
|
-
|
|
37
|
-
faraday-net_http (>= 2.0, < 3.1)
|
|
38
|
-
ruby2_keywords (>= 0.0.4)
|
|
35
|
+
faraday (2.9.0)
|
|
36
|
+
faraday-net_http (>= 2.0, < 3.2)
|
|
39
37
|
faraday-multipart (1.0.4)
|
|
40
38
|
multipart-post (~> 2)
|
|
41
|
-
faraday-net_http (3.0
|
|
39
|
+
faraday-net_http (3.1.0)
|
|
40
|
+
net-http
|
|
42
41
|
ffi (1.16.3)
|
|
43
42
|
gemini-ai (3.1.2)
|
|
44
43
|
event_stream_parser (~> 1.0)
|
|
@@ -64,11 +63,13 @@ GEM
|
|
|
64
63
|
faraday (~> 2.8, >= 2.8.1)
|
|
65
64
|
multi_json (1.15.0)
|
|
66
65
|
multipart-post (2.3.0)
|
|
66
|
+
net-http (0.4.1)
|
|
67
|
+
uri
|
|
67
68
|
ollama-ai (1.0.0)
|
|
68
69
|
faraday (~> 2.8)
|
|
69
70
|
os (1.1.4)
|
|
70
71
|
parallel (1.24.0)
|
|
71
|
-
parser (3.3.0.
|
|
72
|
+
parser (3.3.0.2)
|
|
72
73
|
ast (~> 2.4.1)
|
|
73
74
|
racc
|
|
74
75
|
pry (0.14.2)
|
|
@@ -82,7 +83,8 @@ GEM
|
|
|
82
83
|
rainbow (3.1.1)
|
|
83
84
|
rbnacl (7.1.1)
|
|
84
85
|
ffi
|
|
85
|
-
|
|
86
|
+
redcarpet (3.6.0)
|
|
87
|
+
regexp_parser (2.9.0)
|
|
86
88
|
rexml (3.2.6)
|
|
87
89
|
rspec (3.12.0)
|
|
88
90
|
rspec-core (~> 3.12.0)
|
|
@@ -112,8 +114,8 @@ GEM
|
|
|
112
114
|
parser (>= 3.2.1.0)
|
|
113
115
|
rubocop-capybara (2.20.0)
|
|
114
116
|
rubocop (~> 1.41)
|
|
115
|
-
rubocop-factory_bot (2.25.
|
|
116
|
-
rubocop (~> 1.
|
|
117
|
+
rubocop-factory_bot (2.25.1)
|
|
118
|
+
rubocop (~> 1.41)
|
|
117
119
|
rubocop-rspec (2.26.1)
|
|
118
120
|
rubocop (~> 1.40)
|
|
119
121
|
rubocop-capybara (~> 2.17)
|
|
@@ -123,7 +125,6 @@ GEM
|
|
|
123
125
|
faraday (>= 1)
|
|
124
126
|
faraday-multipart (>= 1)
|
|
125
127
|
ruby-progressbar (1.13.0)
|
|
126
|
-
ruby2_keywords (0.0.5)
|
|
127
128
|
signet (0.18.0)
|
|
128
129
|
addressable (~> 2.8)
|
|
129
130
|
faraday (>= 0.17.5, < 3.a)
|
|
@@ -132,6 +133,7 @@ GEM
|
|
|
132
133
|
sweet-moon (0.0.7)
|
|
133
134
|
ffi (~> 1.15, >= 1.15.5)
|
|
134
135
|
unicode-display_width (2.5.0)
|
|
136
|
+
uri (0.13.0)
|
|
135
137
|
|
|
136
138
|
PLATFORMS
|
|
137
139
|
x86_64-linux
|
|
@@ -141,7 +143,7 @@ DEPENDENCIES
|
|
|
141
143
|
pry-byebug (~> 3.10, >= 3.10.1)
|
|
142
144
|
rspec (~> 3.12)
|
|
143
145
|
rubocop (~> 1.59)
|
|
144
|
-
rubocop-rspec (~> 2.
|
|
146
|
+
rubocop-rspec (~> 2.26, >= 2.26.1)
|
|
145
147
|
|
|
146
148
|
BUNDLED WITH
|
|
147
149
|
2.4.22
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Nano Bots 💎 🤖
|
|
2
2
|
|
|
3
|
-
An implementation of the [Nano Bots](https://spec.nbots.io) specification with support for [Cohere Command](https://cohere.com), [Google Gemini](https://deepmind.google/technologies/gemini), [Maritaca AI MariTalk](https://www.maritaca.ai), [Mistral AI](https://mistral.ai), [Ollama](https://ollama.ai), [OpenAI ChatGPT](https://openai.com/chatgpt), and others.
|
|
3
|
+
An implementation of the [Nano Bots](https://spec.nbots.io) specification with support for [Cohere Command](https://cohere.com), [Google Gemini](https://deepmind.google/technologies/gemini), [Maritaca AI MariTalk](https://www.maritaca.ai), [Mistral AI](https://mistral.ai), [Ollama](https://ollama.ai), [OpenAI ChatGPT](https://openai.com/chatgpt), and others, with support for calling tools (functions).
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b
|
|
|
9
9
|
## TL;DR and Quick Start
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
gem install nano-bots -v
|
|
12
|
+
gem install nano-bots -v 3.0.0
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
```bash
|
|
@@ -34,13 +34,22 @@ well. How can I assist you?
|
|
|
34
34
|
---
|
|
35
35
|
meta:
|
|
36
36
|
symbol: 🤖
|
|
37
|
-
name:
|
|
37
|
+
name: Nano Bot Name
|
|
38
|
+
author: Your Name
|
|
39
|
+
version: 1.0.0
|
|
40
|
+
license: CC0-1.0
|
|
41
|
+
description: A helpful assistant.
|
|
42
|
+
|
|
43
|
+
behaviors:
|
|
44
|
+
interaction:
|
|
45
|
+
directive: You are a helpful assistant.
|
|
38
46
|
|
|
39
47
|
provider:
|
|
40
48
|
id: openai
|
|
41
49
|
credentials:
|
|
42
50
|
access-token: ENV/OPENAI_API_KEY
|
|
43
51
|
settings:
|
|
52
|
+
user: ENV/NANO_BOTS_END_USER
|
|
44
53
|
model: gpt-4-1106-preview
|
|
45
54
|
```
|
|
46
55
|
|
|
@@ -50,7 +59,7 @@ nb gpt.yml - eval "hi"
|
|
|
50
59
|
```
|
|
51
60
|
|
|
52
61
|
```ruby
|
|
53
|
-
gem 'nano-bots', '~>
|
|
62
|
+
gem 'nano-bots', '~> 3.0.0'
|
|
54
63
|
```
|
|
55
64
|
|
|
56
65
|
```ruby
|
|
@@ -241,13 +250,13 @@ end
|
|
|
241
250
|
To install the CLI on your system:
|
|
242
251
|
|
|
243
252
|
```sh
|
|
244
|
-
gem install nano-bots -v
|
|
253
|
+
gem install nano-bots -v 3.0.0
|
|
245
254
|
```
|
|
246
255
|
|
|
247
256
|
To use it in a Ruby project as a library, add to your `Gemfile`:
|
|
248
257
|
|
|
249
258
|
```ruby
|
|
250
|
-
gem 'nano-bots', '~>
|
|
259
|
+
gem 'nano-bots', '~> 3.0.0'
|
|
251
260
|
```
|
|
252
261
|
|
|
253
262
|
```sh
|
|
@@ -260,8 +269,8 @@ For credentials and configurations, relevant environment variables can be set in
|
|
|
260
269
|
export NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE
|
|
261
270
|
export NANO_BOTS_END_USER=your-user
|
|
262
271
|
|
|
263
|
-
# export
|
|
264
|
-
# export
|
|
272
|
+
# export NANO_BOTS_STATE_PATH=/home/user/.local/state/nano-bots
|
|
273
|
+
# export NANO_BOTS_CARTRIDGES_PATH=/home/user/.local/share/nano-bots/cartridges
|
|
265
274
|
```
|
|
266
275
|
|
|
267
276
|
Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded:
|
|
@@ -270,8 +279,8 @@ Alternatively, if your current directory has a `.env` file with the environment
|
|
|
270
279
|
NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE
|
|
271
280
|
NANO_BOTS_END_USER=your-user
|
|
272
281
|
|
|
273
|
-
#
|
|
274
|
-
#
|
|
282
|
+
# NANO_BOTS_STATE_PATH=/home/user/.local/state/nano-bots
|
|
283
|
+
# NANO_BOTS_CARTRIDGES_PATH=/home/user/.local/share/nano-bots/cartridges
|
|
275
284
|
```
|
|
276
285
|
|
|
277
286
|
### Cohere Command
|
|
@@ -954,7 +963,7 @@ cd ruby-nano-bots
|
|
|
954
963
|
cp docker-compose.example.yml docker-compose.yml
|
|
955
964
|
```
|
|
956
965
|
|
|
957
|
-
Set your provider credentials and choose your desired
|
|
966
|
+
Set your provider credentials and choose your desired path for the cartridges files:
|
|
958
967
|
|
|
959
968
|
### Cohere Command Container
|
|
960
969
|
|
|
@@ -963,7 +972,7 @@ Set your provider credentials and choose your desired directory for the cartridg
|
|
|
963
972
|
services:
|
|
964
973
|
nano-bots:
|
|
965
974
|
image: ruby:3.2.2-slim-bookworm
|
|
966
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
975
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
967
976
|
environment:
|
|
968
977
|
COHERE_API_KEY: your-api-key
|
|
969
978
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -980,7 +989,7 @@ services:
|
|
|
980
989
|
services:
|
|
981
990
|
nano-bots:
|
|
982
991
|
image: ruby:3.2.2-slim-bookworm
|
|
983
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
992
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
984
993
|
environment:
|
|
985
994
|
MARITACA_API_KEY: your-api-key
|
|
986
995
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -997,7 +1006,7 @@ services:
|
|
|
997
1006
|
services:
|
|
998
1007
|
nano-bots:
|
|
999
1008
|
image: ruby:3.2.2-slim-bookworm
|
|
1000
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
1009
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
1001
1010
|
environment:
|
|
1002
1011
|
MISTRAL_API_KEY: your-api-key
|
|
1003
1012
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -1016,7 +1025,7 @@ Remember that your `localhost` is by default inaccessible from inside Docker. Yo
|
|
|
1016
1025
|
services:
|
|
1017
1026
|
nano-bots:
|
|
1018
1027
|
image: ruby:3.2.2-slim-bookworm
|
|
1019
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
1028
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
1020
1029
|
environment:
|
|
1021
1030
|
OLLAMA_API_ADDRESS: http://localhost:11434
|
|
1022
1031
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -1035,7 +1044,7 @@ services:
|
|
|
1035
1044
|
services:
|
|
1036
1045
|
nano-bots:
|
|
1037
1046
|
image: ruby:3.2.2-slim-bookworm
|
|
1038
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
1047
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
1039
1048
|
environment:
|
|
1040
1049
|
OPENAI_API_KEY: your-access-token
|
|
1041
1050
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -1054,7 +1063,7 @@ services:
|
|
|
1054
1063
|
services:
|
|
1055
1064
|
nano-bots:
|
|
1056
1065
|
image: ruby:3.2.2-slim-bookworm
|
|
1057
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
1066
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
1058
1067
|
environment:
|
|
1059
1068
|
GOOGLE_API_KEY: your-api-key
|
|
1060
1069
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -1071,7 +1080,7 @@ services:
|
|
|
1071
1080
|
services:
|
|
1072
1081
|
nano-bots:
|
|
1073
1082
|
image: ruby:3.2.2-slim-bookworm
|
|
1074
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
1083
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
1075
1084
|
environment:
|
|
1076
1085
|
GOOGLE_CREDENTIALS_FILE_PATH: /root/.config/google-credentials.json
|
|
1077
1086
|
GOOGLE_REGION: us-east4
|
|
@@ -1090,7 +1099,7 @@ services:
|
|
|
1090
1099
|
services:
|
|
1091
1100
|
nano-bots:
|
|
1092
1101
|
image: ruby:3.2.2-slim-bookworm
|
|
1093
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
1102
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
1094
1103
|
environment:
|
|
1095
1104
|
GOOGLE_REGION: us-east4
|
|
1096
1105
|
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
|
@@ -1139,6 +1148,12 @@ bundle exec ruby spec/tasks/run-model.rb spec/data/cartridges/models/openai/gpt-
|
|
|
1139
1148
|
bundle exec ruby spec/tasks/run-model.rb spec/data/cartridges/models/openai/gpt-4-turbo.yml stream
|
|
1140
1149
|
```
|
|
1141
1150
|
|
|
1151
|
+
If you face issues upgrading gem versions:
|
|
1152
|
+
|
|
1153
|
+
```sh
|
|
1154
|
+
bundle install --full-index
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1142
1157
|
### Publish to RubyGems
|
|
1143
1158
|
|
|
1144
1159
|
```bash
|
|
@@ -1146,5 +1161,5 @@ gem build nano-bots.gemspec
|
|
|
1146
1161
|
|
|
1147
1162
|
gem signin
|
|
1148
1163
|
|
|
1149
|
-
gem push nano-bots-
|
|
1164
|
+
gem push nano-bots-3.0.0.gem
|
|
1150
1165
|
```
|
data/components/embedding.rb
CHANGED
|
@@ -45,7 +45,7 @@ module NanoBot
|
|
|
45
45
|
def self.clojure(source:, parameters:, values:, safety:)
|
|
46
46
|
ensure_safety!(safety)
|
|
47
47
|
|
|
48
|
-
raise '
|
|
48
|
+
raise 'Sandboxed Clojure not supported.' if safety[:sandboxed]
|
|
49
49
|
|
|
50
50
|
raise 'invalid Clojure parameter name' if parameters.include?('injected-parameters')
|
|
51
51
|
|
|
@@ -140,7 +140,7 @@ module NanoBot
|
|
|
140
140
|
begin
|
|
141
141
|
@client.chat(parameters: Logic::OpenAI::Tokens.apply_policies!(cartridge, payload))
|
|
142
142
|
rescue StandardError => e
|
|
143
|
-
raise e.class, e.response[:body] if e.response && e.response[:body]
|
|
143
|
+
raise e.class, e.response[:body] if e.respond_to?(:response) && e.response && e.response[:body]
|
|
144
144
|
|
|
145
145
|
raise e
|
|
146
146
|
end
|
|
@@ -148,7 +148,7 @@ module NanoBot
|
|
|
148
148
|
begin
|
|
149
149
|
result = @client.chat(parameters: Logic::OpenAI::Tokens.apply_policies!(cartridge, payload))
|
|
150
150
|
rescue StandardError => e
|
|
151
|
-
raise e.class, e.response[:body] if e.response && e.response[:body]
|
|
151
|
+
raise e.class, e.response[:body] if e.respond_to?(:response) && e.response && e.response[:body]
|
|
152
152
|
|
|
153
153
|
raise e
|
|
154
154
|
end
|
data/components/storage.rb
CHANGED
|
@@ -8,6 +8,8 @@ require_relative 'crypto'
|
|
|
8
8
|
module NanoBot
|
|
9
9
|
module Components
|
|
10
10
|
class Storage
|
|
11
|
+
EXTENSIONS = %w[yml yaml markdown mdown mkdn md].freeze
|
|
12
|
+
|
|
11
13
|
def self.end_user(cartridge, environment)
|
|
12
14
|
user = ENV.fetch('NANO_BOTS_END_USER', nil)
|
|
13
15
|
|
|
@@ -35,7 +37,9 @@ module NanoBot
|
|
|
35
37
|
|
|
36
38
|
def self.build_path_and_ensure_state_file!(key, cartridge, environment: {})
|
|
37
39
|
path = [
|
|
40
|
+
Logic::Helpers::Hash.fetch(cartridge, %i[state path]),
|
|
38
41
|
Logic::Helpers::Hash.fetch(cartridge, %i[state directory]),
|
|
42
|
+
ENV.fetch('NANO_BOTS_STATE_PATH', nil),
|
|
39
43
|
ENV.fetch('NANO_BOTS_STATE_DIRECTORY', nil)
|
|
40
44
|
].find do |candidate|
|
|
41
45
|
!candidate.nil? && !candidate.empty?
|
|
@@ -64,32 +68,59 @@ module NanoBot
|
|
|
64
68
|
path
|
|
65
69
|
end
|
|
66
70
|
|
|
67
|
-
def self.cartridges_path
|
|
68
|
-
[
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
def self.cartridges_path(components: {})
|
|
72
|
+
components[:directory?] = ->(path) { File.directory?(path) } unless components.key?(:directory?)
|
|
73
|
+
components[:ENV] = ENV unless components.key?(:ENV)
|
|
74
|
+
|
|
75
|
+
default = "#{user_home!(components:).sub(%r{/$}, '')}/.local/share/nano-bots/cartridges"
|
|
76
|
+
|
|
77
|
+
from_environment = [
|
|
78
|
+
components[:ENV].fetch('NANO_BOTS_CARTRIDGES_PATH', nil),
|
|
79
|
+
components[:ENV].fetch('NANO_BOTS_CARTRIDGES_DIRECTORY', nil)
|
|
80
|
+
].compact
|
|
81
|
+
|
|
82
|
+
elected = [
|
|
83
|
+
from_environment.empty? ? nil : from_environment.join(':'),
|
|
84
|
+
default
|
|
85
|
+
].compact.uniq.filter do |path|
|
|
86
|
+
path.split(':').any? { |candidate| components[:directory?].call(candidate) }
|
|
87
|
+
end.compact.first
|
|
88
|
+
|
|
89
|
+
return default unless elected
|
|
90
|
+
|
|
91
|
+
elected = elected.split(':').filter do |path|
|
|
92
|
+
components[:directory?].call(path)
|
|
93
|
+
end.compact
|
|
94
|
+
|
|
95
|
+
elected.size.positive? ? elected.join(':') : default
|
|
72
96
|
end
|
|
73
97
|
|
|
74
98
|
def self.cartridge_path(path)
|
|
75
99
|
partial = File.join(File.dirname(path), File.basename(path, File.extname(path)))
|
|
76
100
|
|
|
77
|
-
candidates = [
|
|
78
|
-
path,
|
|
79
|
-
"#{partial}.yml",
|
|
80
|
-
"#{partial}.yaml"
|
|
81
|
-
]
|
|
101
|
+
candidates = [path]
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
|
|
103
|
+
EXTENSIONS.each do |extension|
|
|
104
|
+
candidates << "#{partial}.#{extension}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
directories = [
|
|
108
|
+
ENV.fetch('NANO_BOTS_CARTRIDGES_PATH', nil),
|
|
109
|
+
ENV.fetch('NANO_BOTS_CARTRIDGES_DIRECTORY', nil)
|
|
110
|
+
].compact.map do |directory|
|
|
111
|
+
directory.split(':')
|
|
112
|
+
end.flatten.map { |directory| directory.sub(%r{/$}, '') }
|
|
85
113
|
|
|
114
|
+
directories.each do |directory|
|
|
86
115
|
partial = File.join(File.dirname(partial), File.basename(partial, File.extname(partial)))
|
|
87
116
|
|
|
88
117
|
partial = partial.sub(%r{^\.?/}, '')
|
|
89
118
|
|
|
90
119
|
candidates << "#{directory}/#{partial}"
|
|
91
|
-
|
|
92
|
-
|
|
120
|
+
|
|
121
|
+
EXTENSIONS.each do |extension|
|
|
122
|
+
candidates << "#{directory}/#{partial}.#{extension}"
|
|
123
|
+
end
|
|
93
124
|
end
|
|
94
125
|
|
|
95
126
|
directory = "#{user_home!.sub(%r{/$}, '')}/.local/share/nano-bots/cartridges"
|
|
@@ -99,8 +130,10 @@ module NanoBot
|
|
|
99
130
|
partial = partial.sub(%r{^\.?/}, '')
|
|
100
131
|
|
|
101
132
|
candidates << "#{directory}/#{partial}"
|
|
102
|
-
|
|
103
|
-
|
|
133
|
+
|
|
134
|
+
EXTENSIONS.each do |extension|
|
|
135
|
+
candidates << "#{directory}/#{partial}.#{extension}"
|
|
136
|
+
end
|
|
104
137
|
|
|
105
138
|
candidates = candidates.uniq
|
|
106
139
|
|
|
@@ -109,7 +142,9 @@ module NanoBot
|
|
|
109
142
|
end
|
|
110
143
|
end
|
|
111
144
|
|
|
112
|
-
def self.user_home!
|
|
145
|
+
def self.user_home!(components: {})
|
|
146
|
+
return components[:home] if components[:home]
|
|
147
|
+
|
|
113
148
|
[Dir.home, `echo ~`.strip, '~'].find do |candidate|
|
|
114
149
|
!candidate.nil? && !candidate.empty?
|
|
115
150
|
end
|
data/controllers/cartridges.rb
CHANGED
|
@@ -3,35 +3,43 @@
|
|
|
3
3
|
require_relative '../components/storage'
|
|
4
4
|
require_relative '../logic/helpers/hash'
|
|
5
5
|
require_relative '../logic/cartridge/default'
|
|
6
|
+
require_relative '../logic/cartridge/parser'
|
|
6
7
|
|
|
7
8
|
module NanoBot
|
|
8
9
|
module Controllers
|
|
9
10
|
class Cartridges
|
|
10
|
-
def self.
|
|
11
|
+
def self.load(path)
|
|
12
|
+
Logic::Cartridge::Parser.parse(File.read(path), format: File.extname(path))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.all(components: {})
|
|
11
16
|
files = {}
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
paths = Components::Storage.cartridges_path(components:)
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
paths.split(':').each do |path|
|
|
21
|
+
Dir.glob("#{path}/**/*.{yml,yaml,markdown,mdown,mkdn,md}").each do |file|
|
|
22
|
+
files[Pathname.new(file).realpath] = {
|
|
23
|
+
base: path,
|
|
24
|
+
path: Pathname.new(file).realpath
|
|
25
|
+
}
|
|
26
|
+
end
|
|
20
27
|
end
|
|
21
28
|
|
|
22
29
|
cartridges = []
|
|
23
30
|
|
|
24
31
|
files.values.uniq.map do |file|
|
|
25
|
-
cartridge =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
cartridge = load(file[:path]).merge(
|
|
33
|
+
{
|
|
34
|
+
system: {
|
|
35
|
+
id: file[:path].to_s.sub(
|
|
36
|
+
/^#{Regexp.escape(file[:base])}/, ''
|
|
37
|
+
).sub(%r{^/}, '').sub(/\.[^.]+\z/, ''),
|
|
38
|
+
path: file[:path],
|
|
39
|
+
base: file[:base]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
)
|
|
35
43
|
|
|
36
44
|
next if cartridge[:meta][:name].nil?
|
|
37
45
|
|
data/controllers/instance.rb
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'yaml'
|
|
4
|
-
|
|
5
3
|
require_relative '../logic/helpers/hash'
|
|
6
4
|
require_relative '../components/provider'
|
|
7
5
|
require_relative '../components/storage'
|
|
8
6
|
require_relative '../components/stream'
|
|
7
|
+
require_relative 'cartridges'
|
|
9
8
|
require_relative 'interfaces/repl'
|
|
10
9
|
require_relative 'interfaces/eval'
|
|
11
10
|
require_relative 'session'
|
|
@@ -83,13 +82,11 @@ module NanoBot
|
|
|
83
82
|
raise StandardError, "Cartridge file not found: \"#{path}\""
|
|
84
83
|
end
|
|
85
84
|
|
|
86
|
-
@cartridge =
|
|
85
|
+
@cartridge = Cartridges.load(elected_path)
|
|
87
86
|
end
|
|
88
87
|
|
|
89
88
|
@safe_cartridge = Marshal.load(Marshal.dump(@cartridge))
|
|
90
89
|
|
|
91
|
-
@cartridge = Logic::Helpers::Hash.symbolize_keys(@cartridge)
|
|
92
|
-
|
|
93
90
|
inject_environment_variables!(@cartridge)
|
|
94
91
|
end
|
|
95
92
|
|
data/docker-compose.example.yml
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
services:
|
|
3
3
|
nano-bots:
|
|
4
4
|
image: ruby:3.2.2-slim-bookworm
|
|
5
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v
|
|
5
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.0.0 && bash"
|
|
6
6
|
environment:
|
|
7
7
|
COHERE_API_KEY: your-api-key
|
|
8
8
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'singleton'
|
|
4
|
+
|
|
5
|
+
require 'redcarpet'
|
|
6
|
+
require 'redcarpet/render_strip'
|
|
7
|
+
|
|
8
|
+
module NanoBot
|
|
9
|
+
module Logic
|
|
10
|
+
module Cartridge
|
|
11
|
+
module Parser
|
|
12
|
+
def self.parse(raw, format:)
|
|
13
|
+
normalized = format.to_s.downcase.gsub('.', '').strip
|
|
14
|
+
|
|
15
|
+
if %w[yml yaml].include?(normalized)
|
|
16
|
+
yaml(raw)
|
|
17
|
+
elsif %w[markdown mdown mkdn md].include?(normalized)
|
|
18
|
+
markdown(raw)
|
|
19
|
+
else
|
|
20
|
+
raise "Unknown cartridge format: '#{format}'"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.markdown(raw)
|
|
25
|
+
yaml_source = []
|
|
26
|
+
|
|
27
|
+
tools = []
|
|
28
|
+
|
|
29
|
+
blocks = Markdown.new.render(raw).blocks
|
|
30
|
+
|
|
31
|
+
previous_block_is_tool = false
|
|
32
|
+
|
|
33
|
+
blocks.each do |block|
|
|
34
|
+
if block[:language] == 'yaml'
|
|
35
|
+
parsed = Logic::Helpers::Hash.symbolize_keys(
|
|
36
|
+
YAML.safe_load(block[:source], permitted_classes: [Symbol])
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
if parsed.key?(:tools) && parsed[:tools].is_a?(Array) && !parsed[:tools].empty?
|
|
40
|
+
previous_block_is_tool = true
|
|
41
|
+
|
|
42
|
+
tools.concat(parsed[:tools])
|
|
43
|
+
|
|
44
|
+
parsed.delete(:tools)
|
|
45
|
+
|
|
46
|
+
unless parsed.empty?
|
|
47
|
+
yaml_source << YAML.dump(
|
|
48
|
+
Logic::Helpers::Hash.stringify_keys(parsed)
|
|
49
|
+
).gsub(/^---/, '') # TODO: Is this safe enough?
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
yaml_source << block[:source]
|
|
53
|
+
previous_block_is_tool = false
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
elsif previous_block_is_tool
|
|
57
|
+
tools.last[block[:language].to_sym] = block[:source]
|
|
58
|
+
previous_block_is_tool = false
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
unless tools.empty?
|
|
63
|
+
yaml_source << YAML.dump(
|
|
64
|
+
Logic::Helpers::Hash.stringify_keys({ tools: })
|
|
65
|
+
).gsub(/^---/, '') # TODO: Is this safe enough?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
cartridge = {}
|
|
69
|
+
|
|
70
|
+
yaml_source.each do |source|
|
|
71
|
+
cartridge = Logic::Helpers::Hash.deep_merge(cartridge, yaml(source))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
cartridge
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.yaml(raw)
|
|
78
|
+
Logic::Helpers::Hash.symbolize_keys(
|
|
79
|
+
YAML.safe_load(raw, permitted_classes: [Symbol])
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class Renderer < Redcarpet::Render::Base
|
|
84
|
+
LANGUAGES_MAP = {
|
|
85
|
+
'yml' => 'yaml',
|
|
86
|
+
'yaml' => 'yaml',
|
|
87
|
+
'lua' => 'lua',
|
|
88
|
+
'fnl' => 'fennel',
|
|
89
|
+
'fennel' => 'fennel',
|
|
90
|
+
'clj' => 'clojure',
|
|
91
|
+
'clojure' => 'clojure'
|
|
92
|
+
}.freeze
|
|
93
|
+
|
|
94
|
+
LANGUAGES = LANGUAGES_MAP.keys.freeze
|
|
95
|
+
|
|
96
|
+
def initialize(...)
|
|
97
|
+
super(...)
|
|
98
|
+
@_nano_bots_blocks = []
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
attr_reader :_nano_bots_blocks
|
|
102
|
+
|
|
103
|
+
def block_code(code, language)
|
|
104
|
+
key = language.to_s.downcase.strip
|
|
105
|
+
|
|
106
|
+
return nil unless LANGUAGES.include?(key)
|
|
107
|
+
|
|
108
|
+
@_nano_bots_blocks << { language: LANGUAGES_MAP[key], source: code }
|
|
109
|
+
|
|
110
|
+
nil
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
class Markdown
|
|
115
|
+
attr_reader :markdown
|
|
116
|
+
|
|
117
|
+
def initialize
|
|
118
|
+
@renderer = Renderer.new
|
|
119
|
+
@markdown = Redcarpet::Markdown.new(@renderer, fenced_code_blocks: true)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def blocks
|
|
123
|
+
@renderer._nano_bots_blocks
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def render(raw)
|
|
127
|
+
@markdown.render(raw.gsub(/```\w/, "\n\n\\0"))
|
|
128
|
+
self
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
data/logic/helpers/hash.rb
CHANGED
|
@@ -4,6 +4,16 @@ module NanoBot
|
|
|
4
4
|
module Logic
|
|
5
5
|
module Helpers
|
|
6
6
|
module Hash
|
|
7
|
+
def self.deep_merge(hash1, hash2)
|
|
8
|
+
hash1.merge(hash2) do |_key, old_val, new_val|
|
|
9
|
+
if old_val.is_a?(::Hash) && new_val.is_a?(::Hash)
|
|
10
|
+
deep_merge(old_val, new_val)
|
|
11
|
+
else
|
|
12
|
+
new_val
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
7
17
|
def self.symbolize_keys(object)
|
|
8
18
|
case object
|
|
9
19
|
when ::Hash
|
|
@@ -17,6 +27,19 @@ module NanoBot
|
|
|
17
27
|
end
|
|
18
28
|
end
|
|
19
29
|
|
|
30
|
+
def self.stringify_keys(object)
|
|
31
|
+
case object
|
|
32
|
+
when ::Hash
|
|
33
|
+
object.each_with_object({}) do |(key, value), result|
|
|
34
|
+
result[key.to_s] = stringify_keys(value)
|
|
35
|
+
end
|
|
36
|
+
when Array
|
|
37
|
+
object.map { |e| stringify_keys(e) }
|
|
38
|
+
else
|
|
39
|
+
object
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
20
43
|
def self.fetch(object, path)
|
|
21
44
|
node = object
|
|
22
45
|
|
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 'rbnacl', '~> 7.1', '>= 7.1.1'
|
|
40
|
+
spec.add_dependency 'redcarpet', '~> 3.6'
|
|
40
41
|
spec.add_dependency 'sweet-moon', '~> 0.0.7'
|
|
41
42
|
|
|
42
43
|
spec.add_dependency 'cohere-ai', '~> 1.0', '>= 1.0.1'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../controllers/cartridges'
|
|
4
|
+
|
|
5
|
+
module NanoBot
|
|
6
|
+
module Cartridges
|
|
7
|
+
def self.all(components: {})
|
|
8
|
+
Controllers::Cartridges.all(components:)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.load(path)
|
|
12
|
+
Controllers::Cartridges.load(path)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/ports/dsl/nano-bots.rb
CHANGED
|
@@ -8,6 +8,7 @@ require_relative '../../controllers/instance'
|
|
|
8
8
|
require_relative '../../controllers/security'
|
|
9
9
|
require_relative '../../controllers/interfaces/cli'
|
|
10
10
|
require_relative '../../components/stream'
|
|
11
|
+
require_relative 'nano-bots/cartridges'
|
|
11
12
|
|
|
12
13
|
module NanoBot
|
|
13
14
|
def self.new(cartridge: '-', state: '-', environment: {})
|
|
@@ -24,7 +25,7 @@ module NanoBot
|
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
def self.cartridges
|
|
27
|
-
|
|
28
|
+
Cartridges
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def self.cli
|
data/static/gem.rb
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module NanoBot
|
|
4
4
|
GEM = {
|
|
5
5
|
name: 'nano-bots',
|
|
6
|
-
version: '
|
|
7
|
-
specification: '
|
|
6
|
+
version: '3.0.0',
|
|
7
|
+
specification: '3.0.0',
|
|
8
8
|
author: 'icebaker',
|
|
9
9
|
summary: 'Ruby Implementation of Nano Bots: small, AI-powered bots for OpenAI ChatGPT, Ollama, Mistral AI, Cohere Command, Maritaca AI MariTalk, and Google Gemini.',
|
|
10
10
|
description: 'Ruby Implementation of Nano Bots: small, AI-powered bots that can be easily shared as a single file, designed to support multiple providers such as OpenAI ChatGPT, Ollama, Mistral AI, Cohere Command, Maritaca AI MariTalk, and Google Gemini, with support for calling Tools (Functions).',
|
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:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- icebaker
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-01-
|
|
11
|
+
date: 2024-01-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: babosa
|
|
@@ -118,6 +118,20 @@ dependencies:
|
|
|
118
118
|
- - ">="
|
|
119
119
|
- !ruby/object:Gem::Version
|
|
120
120
|
version: 7.1.1
|
|
121
|
+
- !ruby/object:Gem::Dependency
|
|
122
|
+
name: redcarpet
|
|
123
|
+
requirement: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - "~>"
|
|
126
|
+
- !ruby/object:Gem::Version
|
|
127
|
+
version: '3.6'
|
|
128
|
+
type: :runtime
|
|
129
|
+
prerelease: false
|
|
130
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - "~>"
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: '3.6'
|
|
121
135
|
- !ruby/object:Gem::Dependency
|
|
122
136
|
name: sweet-moon
|
|
123
137
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -287,6 +301,7 @@ files:
|
|
|
287
301
|
- logic/cartridge/default.rb
|
|
288
302
|
- logic/cartridge/fetch.rb
|
|
289
303
|
- logic/cartridge/interaction.rb
|
|
304
|
+
- logic/cartridge/parser.rb
|
|
290
305
|
- logic/cartridge/safety.rb
|
|
291
306
|
- logic/cartridge/streaming.rb
|
|
292
307
|
- logic/cartridge/tools.rb
|
|
@@ -302,6 +317,7 @@ files:
|
|
|
302
317
|
- logic/providers/openai/tools.rb
|
|
303
318
|
- nano-bots.gemspec
|
|
304
319
|
- ports/dsl/nano-bots.rb
|
|
320
|
+
- ports/dsl/nano-bots/cartridges.rb
|
|
305
321
|
- ports/dsl/nano-bots/cli.rb
|
|
306
322
|
- static/cartridges/baseline.yml
|
|
307
323
|
- static/cartridges/default.yml
|