memoflow 0.1.2 → 0.1.4
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/README.md +46 -0
- data/lib/memoflow/client.rb +4 -3
- data/lib/memoflow/embedding_provider.rb +1 -1
- data/lib/memoflow/encryptor.rb +1 -1
- data/lib/memoflow/provider_context.rb +6 -2
- data/lib/memoflow/server.rb +3 -3
- data/lib/memoflow/store.rb +14 -4
- data/lib/memoflow/vectorizer.rb +4 -2
- data/lib/memoflow/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '00489d24e9c215b49e98995ef01c58aa55d429af2ec5ed0dd9d5ac44a6b0e289'
|
|
4
|
+
data.tar.gz: 56b4fd3707959259d19224cac4a6cc61e70f2848b80ec4203ce8ddf6c141ac5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53c8e0ebff351f2f33d4470dd1c0a223dc8655beda9bcc69079d25f9a6da2db47e9757e85c2a3f4103dcdc3ac70afe30bd0d55f8baa53177f1aff41d7a59d408
|
|
7
|
+
data.tar.gz: 46d14a0e697308e858c0812ed81ed9565cf3663a0143ee301ba33517503392e0628140171088e763c66e94efbee8b145bba57f0d6e4374989e6ee54e01b54068
|
data/README.md
CHANGED
|
@@ -29,6 +29,46 @@ end
|
|
|
29
29
|
|
|
30
30
|
If you do not want a Rails initializer, the CLI can operate with `MEMOFLOW_KEY` alone.
|
|
31
31
|
|
|
32
|
+
## Encryption key setup
|
|
33
|
+
|
|
34
|
+
Memoflow encrypts stored context locally. `MEMOFLOW_KEY` is the secret used to encrypt and decrypt that repository's stored memory.
|
|
35
|
+
|
|
36
|
+
Generate a strong key with either:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
or:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
openssl rand -hex 32
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then export it in your shell:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
export MEMOFLOW_KEY="paste-generated-key-here"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Why it should be project-specific:
|
|
55
|
+
|
|
56
|
+
- it limits the blast radius if one key is exposed
|
|
57
|
+
- it keeps one repository's history isolated from another
|
|
58
|
+
- it lets teams share access only to the repos they should decrypt
|
|
59
|
+
|
|
60
|
+
Recommended handling:
|
|
61
|
+
|
|
62
|
+
- use one key per repository
|
|
63
|
+
- store it in a password manager or team secret store
|
|
64
|
+
- do not commit it to git
|
|
65
|
+
- do not reuse production application secrets for Memoflow
|
|
66
|
+
|
|
67
|
+
Important:
|
|
68
|
+
|
|
69
|
+
- if you lose the key, existing Memoflow data for that repository cannot be decrypted
|
|
70
|
+
- if your team needs shared access to the same stored context, everyone must use the same repo key
|
|
71
|
+
|
|
32
72
|
Optional embedding provider:
|
|
33
73
|
|
|
34
74
|
```ruby
|
|
@@ -81,6 +121,12 @@ bundle exec memoflow annotate "Problem statement: fix webhook retries"
|
|
|
81
121
|
bundle exec memoflow query "webhook retries"
|
|
82
122
|
```
|
|
83
123
|
|
|
124
|
+
## Ruby compatibility
|
|
125
|
+
|
|
126
|
+
Memoflow is currently targeted at Ruby `>= 2.3.0`.
|
|
127
|
+
|
|
128
|
+
This support floor is chosen to work more cleanly with older Rails applications while avoiding newer Ruby-only core methods in the runtime code.
|
|
129
|
+
|
|
84
130
|
Rails initializer example:
|
|
85
131
|
|
|
86
132
|
```ruby
|
data/lib/memoflow/client.rb
CHANGED
|
@@ -114,7 +114,8 @@ module Memoflow
|
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
def current_task_id
|
|
117
|
-
@store.read_state("current_task")
|
|
117
|
+
state = @store.read_state("current_task")
|
|
118
|
+
state ? state[:task_id] : nil
|
|
118
119
|
end
|
|
119
120
|
|
|
120
121
|
def query(term = nil, limit: 5)
|
|
@@ -173,8 +174,8 @@ module Memoflow
|
|
|
173
174
|
|
|
174
175
|
tokens = term.downcase.split(/\s+/)
|
|
175
176
|
fields = normalized_fields(entry)
|
|
176
|
-
score = tokens.
|
|
177
|
-
field_score(fields, token)
|
|
177
|
+
score = tokens.inject(0) do |total, token|
|
|
178
|
+
total + field_score(fields, token)
|
|
178
179
|
end
|
|
179
180
|
|
|
180
181
|
score + recency_boost(entry) + task_boost(entry) + semantic_boost(entry, term)
|
|
@@ -41,7 +41,7 @@ module Memoflow
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def normalize(vector)
|
|
44
|
-
magnitude = Math.sqrt(vector.
|
|
44
|
+
magnitude = Math.sqrt(vector.inject(0.0) { |total, value| total + value * value })
|
|
45
45
|
return vector if magnitude.zero?
|
|
46
46
|
|
|
47
47
|
vector.map { |value| (value / magnitude).round(6) }
|
data/lib/memoflow/encryptor.rb
CHANGED
|
@@ -10,11 +10,11 @@ module Memoflow
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def capture
|
|
13
|
-
|
|
13
|
+
compact_hash(
|
|
14
14
|
provider: provider,
|
|
15
15
|
repository: repository,
|
|
16
16
|
pull_request: pull_request
|
|
17
|
-
|
|
17
|
+
)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
private
|
|
@@ -68,6 +68,10 @@ module Memoflow
|
|
|
68
68
|
"#{parts[-2]}/#{parts[-1].sub(/\.git\z/, "")}"
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
def compact_hash(hash)
|
|
72
|
+
hash.reject { |_, value| value.nil? }
|
|
73
|
+
end
|
|
74
|
+
|
|
71
75
|
def source_text
|
|
72
76
|
[@remote_url, @env["GITHUB_SERVER_URL"], @env["CI_SERVER_URL"]].compact.join(" ").downcase
|
|
73
77
|
end
|
data/lib/memoflow/server.rb
CHANGED
|
@@ -21,11 +21,11 @@ module Memoflow
|
|
|
21
21
|
rescue IOError, SystemCallError
|
|
22
22
|
break unless @running
|
|
23
23
|
ensure
|
|
24
|
-
socket
|
|
24
|
+
socket.close if socket
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
ensure
|
|
28
|
-
@server
|
|
28
|
+
@server.close if @server
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
private
|
|
@@ -91,7 +91,7 @@ module Memoflow
|
|
|
91
91
|
%w[INT TERM].each do |signal|
|
|
92
92
|
trap(signal) do
|
|
93
93
|
@running = false
|
|
94
|
-
@server
|
|
94
|
+
@server.close if @server
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
end
|
data/lib/memoflow/store.rb
CHANGED
|
@@ -120,7 +120,7 @@ module Memoflow
|
|
|
120
120
|
with_lock do
|
|
121
121
|
setup!
|
|
122
122
|
path = @root.join(scope, filename)
|
|
123
|
-
payload = JSON.generate(envelope(record)
|
|
123
|
+
payload = JSON.generate(stringify_keys(envelope(record)))
|
|
124
124
|
atomic_write(path, @encryptor.encrypt(payload))
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -170,9 +170,11 @@ module Memoflow
|
|
|
170
170
|
setup!
|
|
171
171
|
File.open(@root.join(".lock"), File::RDWR | File::CREAT, 0o644) do |file|
|
|
172
172
|
file.flock(File::LOCK_EX)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
begin
|
|
174
|
+
yield
|
|
175
|
+
ensure
|
|
176
|
+
file.flock(File::LOCK_UN)
|
|
177
|
+
end
|
|
176
178
|
end
|
|
177
179
|
end
|
|
178
180
|
|
|
@@ -184,5 +186,13 @@ module Memoflow
|
|
|
184
186
|
ensure
|
|
185
187
|
File.delete(temp_path) if temp_path && File.exist?(temp_path)
|
|
186
188
|
end
|
|
189
|
+
|
|
190
|
+
def stringify_keys(hash)
|
|
191
|
+
result = {}
|
|
192
|
+
hash.each do |key, value|
|
|
193
|
+
result[key.to_s] = value
|
|
194
|
+
end
|
|
195
|
+
result
|
|
196
|
+
end
|
|
187
197
|
end
|
|
188
198
|
end
|
data/lib/memoflow/vectorizer.rb
CHANGED
|
@@ -19,7 +19,9 @@ module Memoflow
|
|
|
19
19
|
return 0.0 if left.nil? || right.nil?
|
|
20
20
|
return 0.0 if left.empty? || right.empty?
|
|
21
21
|
|
|
22
|
-
left.zip(right).
|
|
22
|
+
left.zip(right).inject(0.0) do |total, pair|
|
|
23
|
+
total + pair[0].to_f * pair[1].to_f
|
|
24
|
+
end
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def indexable_text(entry)
|
|
@@ -47,7 +49,7 @@ module Memoflow
|
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
def normalize(vector)
|
|
50
|
-
magnitude = Math.sqrt(vector.
|
|
52
|
+
magnitude = Math.sqrt(vector.inject(0.0) { |total, value| total + value * value })
|
|
51
53
|
return vector if magnitude.zero?
|
|
52
54
|
|
|
53
55
|
vector.map { |value| (value / magnitude).round(6) }
|
data/lib/memoflow/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: memoflow
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jayesh Pawar
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -51,12 +51,12 @@ files:
|
|
|
51
51
|
- lib/memoflow/store.rb
|
|
52
52
|
- lib/memoflow/vectorizer.rb
|
|
53
53
|
- lib/memoflow/version.rb
|
|
54
|
-
homepage: https://github.
|
|
54
|
+
homepage: https://jayesh-ikshalabs.github.io/memoflow-docs/
|
|
55
55
|
licenses:
|
|
56
56
|
- MIT
|
|
57
57
|
metadata:
|
|
58
|
-
source_code_uri: https://github.com/jayesh-ikshalabs/memoflow
|
|
59
|
-
changelog_uri: https://
|
|
58
|
+
source_code_uri: https://github.com/jayesh-ikshalabs/memoflow-docs
|
|
59
|
+
changelog_uri: https://jayesh-ikshalabs.github.io/memoflow-docs/#compatibility
|
|
60
60
|
post_install_message:
|
|
61
61
|
rdoc_options: []
|
|
62
62
|
require_paths:
|
|
@@ -65,7 +65,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
65
65
|
requirements:
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
68
|
+
version: 2.3.0
|
|
69
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
70
|
requirements:
|
|
71
71
|
- - ">="
|