ruby-mana 0.4.0 → 0.5.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/CHANGELOG.md +41 -1
- data/README.md +68 -0
- data/data/lang-rules.yml +196 -0
- data/lib/mana/compiler.rb +1 -1
- data/lib/mana/engine.rb +38 -432
- data/lib/mana/engines/base.rb +51 -0
- data/lib/mana/engines/detect.rb +93 -0
- data/lib/mana/engines/javascript.rb +90 -0
- data/lib/mana/engines/llm.rb +459 -0
- data/lib/mana/engines/python.rb +230 -0
- data/lib/mana/engines/ruby_eval.rb +11 -0
- data/lib/mana/version.rb +1 -1
- data/lib/mana.rb +8 -0
- metadata +23 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 04d7095024d30500930422b72e86fcdb1a27b1fa9a9f62ca70c9c124c2ceab77
|
|
4
|
+
data.tar.gz: 6e264f8292e908d45776481aa6af33bed5eb7d9113874d13e72f3a3cde513107
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 470e54537747878bbe07c6825a12bf515a2909af872ee4908e0eb07a0e58b31187dacadb6b20d988782a8f9a2bfaf12c4523ae09c149dc764ad90c2b8a420871
|
|
7
|
+
data.tar.gz: 1c322b45e74e8fa67aab109c10a5a7cac2d6546d1de61912157192e9f15330b8c2520bd5e90b4c70b942d36b7de4ecabfc165c2774be4b8489936e68e14614a0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.
|
|
3
|
+
## [0.5.0] - 2026-02-22
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Polyglot engine architecture** — run Ruby, JavaScript, and Python code side by side
|
|
7
|
+
- JavaScript engine via `mini_racer` with automatic variable bridging
|
|
8
|
+
- Python engine via `pycall` with automatic variable bridging
|
|
9
|
+
- Bidirectional Python ↔ Ruby calling through pycall bridge
|
|
10
|
+
- Engine interface abstraction (`Mana::Engines::Base`)
|
|
11
|
+
- Language auto-detection for polyglot dispatch
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Refactored LLM logic into `Engines::LLM`, extracted from monolithic core
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Polyglot engine bug fixes (CodeRabbit review feedback)
|
|
18
|
+
|
|
19
|
+
## [0.4.0] - 2026-02-22
|
|
20
|
+
|
|
21
|
+
- Multi-LLM backend — Anthropic + OpenAI-compatible APIs
|
|
22
|
+
- Test mode — `Mana.mock` + `mock_prompt` for stubbing LLM responses
|
|
23
|
+
|
|
24
|
+
## [0.3.1] - 2026-02-21
|
|
25
|
+
|
|
26
|
+
- Nested prompts — LLM calling LLM
|
|
27
|
+
- Lambda `call_func` support
|
|
28
|
+
- Expanded test coverage
|
|
29
|
+
|
|
30
|
+
## [0.3.0] - 2026-02-21
|
|
31
|
+
|
|
32
|
+
- Automatic memory — context sharing across LLM calls
|
|
33
|
+
- Incognito mode
|
|
34
|
+
- Persistent long-term memory
|
|
35
|
+
- `Mana.session` — shared conversation context across prompts
|
|
36
|
+
|
|
37
|
+
## [0.2.0] - 2026-02-20
|
|
38
|
+
|
|
39
|
+
- Custom effect handlers — user-defined LLM tools
|
|
40
|
+
- `mana def` — LLM-compiled methods with file caching
|
|
41
|
+
- Auto-discover functions via Prism introspection
|
|
42
|
+
|
|
43
|
+
## [0.1.0] - 2026-02-19
|
|
4
44
|
|
|
5
45
|
- Initial release
|
|
6
46
|
- `~"..."` syntax for embedding LLM prompts in Ruby
|
data/README.md
CHANGED
|
@@ -254,6 +254,74 @@ Mana.incognito do
|
|
|
254
254
|
end
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
+
### Polyglot — Cross-Language Interop
|
|
258
|
+
|
|
259
|
+
`~"..."` is a universal operator. It detects whether the code is JavaScript, Python, Ruby, or natural language, and routes to the appropriate engine. Variables bridge automatically.
|
|
260
|
+
|
|
261
|
+
#### JavaScript
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
require "mana"
|
|
265
|
+
|
|
266
|
+
data = [1, 2, 3, 4, 5]
|
|
267
|
+
|
|
268
|
+
# JavaScript — auto-detected from syntax
|
|
269
|
+
~"const evens = data.filter(n => n % 2 === 0)"
|
|
270
|
+
puts evens # => [2, 4]
|
|
271
|
+
|
|
272
|
+
# Multi-line with heredoc
|
|
273
|
+
~<<~JS
|
|
274
|
+
const sum = evens.reduce((a, b) => a + b, 0)
|
|
275
|
+
const avg = sum / evens.length
|
|
276
|
+
JS
|
|
277
|
+
puts avg # => 3.0
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Python
|
|
281
|
+
|
|
282
|
+
```ruby
|
|
283
|
+
# Python — auto-detected
|
|
284
|
+
~"evens = [n for n in data if n % 2 == 0]"
|
|
285
|
+
puts evens # => [2, 4]
|
|
286
|
+
|
|
287
|
+
# Multi-line
|
|
288
|
+
~<<~PY
|
|
289
|
+
import statistics
|
|
290
|
+
mean = statistics.mean(data)
|
|
291
|
+
stdev = statistics.stdev(data)
|
|
292
|
+
PY
|
|
293
|
+
puts mean # => 3.0
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### Natural language (LLM) — existing behavior
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
~"analyze <data> and find outliers, store in <result>"
|
|
300
|
+
puts result
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### How detection works
|
|
304
|
+
|
|
305
|
+
- Auto-detects from code syntax (token patterns)
|
|
306
|
+
- Context-aware: consecutive `~"..."` calls tend to stay in the same language
|
|
307
|
+
- Override with `Mana.engine = :javascript` or `Mana.with(:python) { ... }`
|
|
308
|
+
- Detection rules are defined in `data/lang-rules.yml` — transparent, no black box
|
|
309
|
+
|
|
310
|
+
#### Variable bridging
|
|
311
|
+
|
|
312
|
+
- Simple types (numbers, strings, booleans, nil, arrays, hashes) are copied
|
|
313
|
+
- Each engine maintains a persistent context (V8 for JS, Python interpreter for Python)
|
|
314
|
+
- Variables created in one `~"..."` call persist for the next call in the same engine
|
|
315
|
+
|
|
316
|
+
#### Setup
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
# Gemfile
|
|
320
|
+
gem "mana"
|
|
321
|
+
gem "mini_racer" # for JavaScript support (optional)
|
|
322
|
+
gem "pycall" # for Python support (optional)
|
|
323
|
+
```
|
|
324
|
+
|
|
257
325
|
### Testing
|
|
258
326
|
|
|
259
327
|
Use `Mana.mock` to test code that uses `~"..."` without calling any API:
|
data/data/lang-rules.yml
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
languages:
|
|
3
|
+
javascript:
|
|
4
|
+
strong:
|
|
5
|
+
- "const "
|
|
6
|
+
- "let "
|
|
7
|
+
- "=> "
|
|
8
|
+
- "=== "
|
|
9
|
+
- "!== "
|
|
10
|
+
- "console.log"
|
|
11
|
+
- "console.error"
|
|
12
|
+
- ".filter("
|
|
13
|
+
- ".map("
|
|
14
|
+
- ".reduce("
|
|
15
|
+
- ".forEach("
|
|
16
|
+
- ".indexOf("
|
|
17
|
+
- ".push("
|
|
18
|
+
- "function "
|
|
19
|
+
- "async "
|
|
20
|
+
- "await "
|
|
21
|
+
- "require("
|
|
22
|
+
- "module.exports"
|
|
23
|
+
- "export "
|
|
24
|
+
- "import "
|
|
25
|
+
- "new Promise"
|
|
26
|
+
- "document."
|
|
27
|
+
- "window."
|
|
28
|
+
- "JSON.parse"
|
|
29
|
+
- "JSON.stringify"
|
|
30
|
+
- "typeof "
|
|
31
|
+
- "undefined"
|
|
32
|
+
- "null;"
|
|
33
|
+
weak:
|
|
34
|
+
- "var "
|
|
35
|
+
- "return "
|
|
36
|
+
- "true"
|
|
37
|
+
- "false"
|
|
38
|
+
- "null"
|
|
39
|
+
- "this."
|
|
40
|
+
anti:
|
|
41
|
+
- "let me"
|
|
42
|
+
- "let us"
|
|
43
|
+
- "let's"
|
|
44
|
+
- "const ant"
|
|
45
|
+
- "import ant"
|
|
46
|
+
- "import this"
|
|
47
|
+
patterns:
|
|
48
|
+
- "\\bfunction\\s+\\w+\\s*\\("
|
|
49
|
+
- "\\(\\s*\\w+\\s*\\)\\s*=>"
|
|
50
|
+
- "\\bclass\\s+\\w+\\s*\\{"
|
|
51
|
+
|
|
52
|
+
python:
|
|
53
|
+
strong:
|
|
54
|
+
- "elif "
|
|
55
|
+
- "print("
|
|
56
|
+
- "__init__"
|
|
57
|
+
- "__name__"
|
|
58
|
+
- "self."
|
|
59
|
+
- "import numpy"
|
|
60
|
+
- "import pandas"
|
|
61
|
+
- "lambda "
|
|
62
|
+
- "except "
|
|
63
|
+
- "finally:"
|
|
64
|
+
- "nonlocal "
|
|
65
|
+
weak:
|
|
66
|
+
- "def "
|
|
67
|
+
- "from "
|
|
68
|
+
- "yield "
|
|
69
|
+
- "raise "
|
|
70
|
+
- "assert "
|
|
71
|
+
- "global "
|
|
72
|
+
- "import "
|
|
73
|
+
- "return "
|
|
74
|
+
- "class "
|
|
75
|
+
- "for "
|
|
76
|
+
- "while "
|
|
77
|
+
- "if "
|
|
78
|
+
- "is not"
|
|
79
|
+
- "not in"
|
|
80
|
+
- "pass"
|
|
81
|
+
anti:
|
|
82
|
+
- "import this"
|
|
83
|
+
- "import that"
|
|
84
|
+
- "from here"
|
|
85
|
+
- "from there"
|
|
86
|
+
- "for example"
|
|
87
|
+
- "for instance"
|
|
88
|
+
- "while I"
|
|
89
|
+
- "while we"
|
|
90
|
+
- "if you"
|
|
91
|
+
- "if we"
|
|
92
|
+
- "with you"
|
|
93
|
+
- "with the"
|
|
94
|
+
- "with a "
|
|
95
|
+
- "with my"
|
|
96
|
+
- "and the"
|
|
97
|
+
- "and I"
|
|
98
|
+
- "and we"
|
|
99
|
+
- "or the"
|
|
100
|
+
- "or a "
|
|
101
|
+
- "or I"
|
|
102
|
+
- "or False"
|
|
103
|
+
- "True or"
|
|
104
|
+
- "as a "
|
|
105
|
+
- "as the"
|
|
106
|
+
- "as I"
|
|
107
|
+
- "pass the"
|
|
108
|
+
- "pass it"
|
|
109
|
+
- "pass on"
|
|
110
|
+
patterns:
|
|
111
|
+
- "\\[.+\\bfor\\b.+\\bin\\b.+\\]"
|
|
112
|
+
- "\\bdef\\s+\\w+\\s*\\("
|
|
113
|
+
- "\\bclass\\s+\\w+\\s*[:(]"
|
|
114
|
+
- "^\\s{4}"
|
|
115
|
+
|
|
116
|
+
ruby:
|
|
117
|
+
strong:
|
|
118
|
+
- "puts "
|
|
119
|
+
- "require "
|
|
120
|
+
- "require_relative"
|
|
121
|
+
- "attr_accessor"
|
|
122
|
+
- "attr_reader"
|
|
123
|
+
- "attr_writer"
|
|
124
|
+
- ".each "
|
|
125
|
+
- ".map "
|
|
126
|
+
- ".select "
|
|
127
|
+
- ".reject "
|
|
128
|
+
- "do |"
|
|
129
|
+
- "def "
|
|
130
|
+
- "module "
|
|
131
|
+
- "rescue "
|
|
132
|
+
- "ensure "
|
|
133
|
+
- "unless "
|
|
134
|
+
- "until "
|
|
135
|
+
- "elsif "
|
|
136
|
+
- "nil"
|
|
137
|
+
- "p "
|
|
138
|
+
- "pp "
|
|
139
|
+
- "Proc.new"
|
|
140
|
+
- "lambda {"
|
|
141
|
+
- "-> {"
|
|
142
|
+
weak:
|
|
143
|
+
- "end"
|
|
144
|
+
- "begin"
|
|
145
|
+
- "class "
|
|
146
|
+
- "return "
|
|
147
|
+
- "if "
|
|
148
|
+
- "for "
|
|
149
|
+
- "while "
|
|
150
|
+
anti:
|
|
151
|
+
- "the end"
|
|
152
|
+
- "in the end"
|
|
153
|
+
- "at the end"
|
|
154
|
+
- "begin with"
|
|
155
|
+
- "begin to"
|
|
156
|
+
patterns:
|
|
157
|
+
- "\\bdo\\s*\\|\\w+\\|"
|
|
158
|
+
- "\\bdef\\s+\\w+[?!]?"
|
|
159
|
+
- "\\bend\\b"
|
|
160
|
+
|
|
161
|
+
natural_language:
|
|
162
|
+
strong:
|
|
163
|
+
- "please "
|
|
164
|
+
- "analyze "
|
|
165
|
+
- "summarize "
|
|
166
|
+
- "translate "
|
|
167
|
+
- "explain "
|
|
168
|
+
- "find "
|
|
169
|
+
- "calculate "
|
|
170
|
+
- "generate "
|
|
171
|
+
- "create "
|
|
172
|
+
- "write "
|
|
173
|
+
- "describe "
|
|
174
|
+
- "compare "
|
|
175
|
+
- "store in <"
|
|
176
|
+
- "save in <"
|
|
177
|
+
- "put in <"
|
|
178
|
+
- ", store "
|
|
179
|
+
- ", save "
|
|
180
|
+
weak:
|
|
181
|
+
- "the "
|
|
182
|
+
- "a "
|
|
183
|
+
- "an "
|
|
184
|
+
- "is "
|
|
185
|
+
- "are "
|
|
186
|
+
- "was "
|
|
187
|
+
- "were "
|
|
188
|
+
- "what "
|
|
189
|
+
- "how "
|
|
190
|
+
- "why "
|
|
191
|
+
- "when "
|
|
192
|
+
- "where "
|
|
193
|
+
- "which "
|
|
194
|
+
anti: []
|
|
195
|
+
patterns:
|
|
196
|
+
- "<\\w+>"
|
data/lib/mana/compiler.rb
CHANGED