hokipoki 0.3.3 ā 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/lib/generators/hive_mind/install_generator.rb +18 -2
- data/lib/generators/hive_mind/templates/hokipoki_claude.rb +45 -0
- data/lib/generators/hokipoki/attach_parasite_generator.rb +355 -0
- data/lib/generators/hokipoki/install_generator.rb +515 -0
- data/lib/generators/hokipoki/scan_project_generator.rb +279 -0
- data/lib/generators/parasite/install_generator.rb +458 -0
- data/lib/hokipoki/atomic_fact_extractor.rb +524 -0
- data/lib/hokipoki/claude/parasite.rb +62 -10
- data/lib/hokipoki/claude/thought_interceptor.rb +385 -0
- data/lib/hokipoki/claude_auto_loader.rb +28 -11
- data/lib/hokipoki/feedback/ascii_banners.rb +1 -1
- data/lib/hokipoki/template_store.rb +425 -0
- data/lib/hokipoki/vector_engine.rb +525 -0
- data/lib/hokipoki/version.rb +1 -1
- data/lib/hokipoki.rb +260 -6
- metadata +80 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module Hokipoki
|
|
6
|
+
module Generators
|
|
7
|
+
# Project Scanner Generator - Scans and vectorizes project files
|
|
8
|
+
# Command: rails g hokipoki:scan_project
|
|
9
|
+
class ScanProjectGenerator < Rails::Generators::Base
|
|
10
|
+
source_root File.expand_path('templates', __dir__)
|
|
11
|
+
|
|
12
|
+
class_option :force_rescan, type: :boolean, default: false,
|
|
13
|
+
desc: 'Force rescan of all files even if already processed'
|
|
14
|
+
|
|
15
|
+
class_option :file_patterns, type: :array, default: ['**/*.rb', '**/*.js', '**/*.erb', '**/*.yml'],
|
|
16
|
+
desc: 'File patterns to scan'
|
|
17
|
+
|
|
18
|
+
class_option :exclude_paths, type: :array, default: ['node_modules', 'vendor', 'log', 'tmp', '.git'],
|
|
19
|
+
desc: 'Paths to exclude from scanning'
|
|
20
|
+
|
|
21
|
+
class_option :show_progress, type: :boolean, default: true,
|
|
22
|
+
desc: 'Show detailed progress during scanning'
|
|
23
|
+
|
|
24
|
+
def display_banner
|
|
25
|
+
say "\nš HOKIPOKI PROJECT SCANNER", :cyan
|
|
26
|
+
say "=" * 50, :cyan
|
|
27
|
+
say "Scanning project files for vector intelligence...", :white
|
|
28
|
+
say "This will create a vector database of your project's knowledge.", :yellow
|
|
29
|
+
say ""
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def validate_environment
|
|
33
|
+
unless defined?(Rails)
|
|
34
|
+
say "ā Rails environment required", :red
|
|
35
|
+
say "Please run this generator from a Rails application directory.", :yellow
|
|
36
|
+
exit(1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
say "ā
Rails environment detected: #{Rails.env}", :green
|
|
40
|
+
say "š Project root: #{Rails.root}", :white
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def scan_and_vectorize_project
|
|
44
|
+
require_hokipoki_components
|
|
45
|
+
|
|
46
|
+
# Initialize components
|
|
47
|
+
vector_engine = Hokipoki::VectorEngine.instance
|
|
48
|
+
fact_extractor = Hokipoki::AtomicFactExtractor.new
|
|
49
|
+
|
|
50
|
+
# Get project files
|
|
51
|
+
files_to_scan = find_project_files
|
|
52
|
+
|
|
53
|
+
if files_to_scan.empty?
|
|
54
|
+
say "ā ļø No files found to scan", :yellow
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
say "\nšÆ SCANNING STRATEGY:", :cyan
|
|
59
|
+
say " š Files to process: #{files_to_scan.length}", :white
|
|
60
|
+
say " š File patterns: #{options[:file_patterns].join(', ')}", :white
|
|
61
|
+
say " ā Excluded paths: #{options[:exclude_paths].join(', ')}", :white
|
|
62
|
+
say ""
|
|
63
|
+
|
|
64
|
+
# Process files with visible progress
|
|
65
|
+
processed_files = 0
|
|
66
|
+
total_facts = 0
|
|
67
|
+
start_time = Time.current
|
|
68
|
+
|
|
69
|
+
files_to_scan.each_with_index do |file_path, index|
|
|
70
|
+
begin
|
|
71
|
+
# Show progress
|
|
72
|
+
if options[:show_progress]
|
|
73
|
+
progress_percent = ((index + 1).to_f / files_to_scan.length * 100).round(1)
|
|
74
|
+
say "š§ [#{index + 1}/#{files_to_scan.length}] (#{progress_percent}%) #{relative_path(file_path)}", :cyan
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Check if file should be rescanned
|
|
78
|
+
if should_process_file?(file_path)
|
|
79
|
+
# Read and extract facts
|
|
80
|
+
content = File.read(file_path)
|
|
81
|
+
next if content.strip.empty?
|
|
82
|
+
|
|
83
|
+
# Extract atomic facts
|
|
84
|
+
facts = fact_extractor.extract_facts(
|
|
85
|
+
content,
|
|
86
|
+
source_file: file_path,
|
|
87
|
+
metadata: {
|
|
88
|
+
file_type: File.extname(file_path),
|
|
89
|
+
file_size: content.bytesize,
|
|
90
|
+
scan_session: Time.current.iso8601
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Store in vector engine
|
|
95
|
+
vector_id = vector_engine.store_template_vector(
|
|
96
|
+
content,
|
|
97
|
+
file_path,
|
|
98
|
+
{
|
|
99
|
+
facts_count: facts.length,
|
|
100
|
+
processing_time: Time.current.iso8601
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
processed_files += 1
|
|
105
|
+
total_facts += facts.length
|
|
106
|
+
|
|
107
|
+
if options[:show_progress]
|
|
108
|
+
say " ā
#{facts.length} facts extracted", :green
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
else
|
|
112
|
+
if options[:show_progress]
|
|
113
|
+
say " āļø Skipped (already processed)", :yellow
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
rescue => e
|
|
118
|
+
say " ā Error processing #{file_path}: #{e.message}", :red
|
|
119
|
+
next
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Display completion summary
|
|
124
|
+
display_completion_summary(processed_files, total_facts, start_time)
|
|
125
|
+
|
|
126
|
+
# Create or update configuration
|
|
127
|
+
create_hokipoki_config(processed_files, total_facts)
|
|
128
|
+
|
|
129
|
+
# Display vector engine statistics
|
|
130
|
+
display_vector_statistics(vector_engine)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def create_initializer
|
|
134
|
+
say "\nš CREATING INITIALIZER:", :cyan
|
|
135
|
+
|
|
136
|
+
create_file "config/initializers/hokipoki_scanner.rb", <<~RUBY
|
|
137
|
+
# Hokipoki Project Scanner Configuration
|
|
138
|
+
# Generated by rails g hokipoki:scan_project
|
|
139
|
+
|
|
140
|
+
if Rails.env.development?
|
|
141
|
+
Rails.application.config.after_initialize do
|
|
142
|
+
# Auto-scan new files when Rails starts
|
|
143
|
+
if defined?(Hokipoki::VectorEngine)
|
|
144
|
+
Thread.new do
|
|
145
|
+
sleep(2) # Let Rails fully initialize
|
|
146
|
+
|
|
147
|
+
vector_engine = Hokipoki::VectorEngine.instance
|
|
148
|
+
|
|
149
|
+
# Display scanner status
|
|
150
|
+
stats = vector_engine.statistics
|
|
151
|
+
puts "\\nš§ HOKIPOKI SCANNER STATUS:"
|
|
152
|
+
puts " š Total vectors: \#{stats[:total_vectors]}"
|
|
153
|
+
puts " šļø Avg compression: \#{stats[:average_compression]}%"
|
|
154
|
+
puts " ā
Success rate: \#{stats[:success_rate]}%"
|
|
155
|
+
puts ""
|
|
156
|
+
|
|
157
|
+
# Auto-scan if Claude is detected
|
|
158
|
+
if Hokipoki.claude_parasite_active?
|
|
159
|
+
puts "š¦ CLAUDE DETECTED: Vector intelligence ready"
|
|
160
|
+
puts "š” Parasite attached to project knowledge base"
|
|
161
|
+
puts ""
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
RUBY
|
|
168
|
+
|
|
169
|
+
say "ā
Created config/initializers/hokipoki_scanner.rb", :green
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def display_next_steps
|
|
173
|
+
say "\nš PROJECT SCAN COMPLETE!", :green
|
|
174
|
+
say "=" * 50, :green
|
|
175
|
+
say ""
|
|
176
|
+
say "š NEXT STEPS:", :cyan
|
|
177
|
+
say "1. š Restart Rails server to load vector intelligence", :white
|
|
178
|
+
say "2. š¦ Run: rails g hokipoki:attach_parasite", :white
|
|
179
|
+
say "3. š§ Start Claude Code CLI to activate parasite", :white
|
|
180
|
+
say "4. ⨠Enjoy 10x enhanced Claude responses!", :white
|
|
181
|
+
say ""
|
|
182
|
+
say "š Vector database location: ~/.hokipoki/vectors.db", :yellow
|
|
183
|
+
say "š§ Configuration: config/initializers/hokipoki_scanner.rb", :yellow
|
|
184
|
+
say ""
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
private
|
|
188
|
+
|
|
189
|
+
def require_hokipoki_components
|
|
190
|
+
begin
|
|
191
|
+
require 'hokipoki/vector_engine'
|
|
192
|
+
require 'hokipoki/atomic_fact_extractor'
|
|
193
|
+
rescue LoadError => e
|
|
194
|
+
say "ā Failed to load Hokipoki components: #{e.message}", :red
|
|
195
|
+
say "Make sure hokipoki gem is properly installed", :yellow
|
|
196
|
+
exit(1)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def find_project_files
|
|
201
|
+
files = []
|
|
202
|
+
|
|
203
|
+
options[:file_patterns].each do |pattern|
|
|
204
|
+
pattern_files = Dir.glob(File.join(Rails.root, pattern))
|
|
205
|
+
files.concat(pattern_files)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Filter out excluded paths
|
|
209
|
+
filtered_files = files.reject do |file|
|
|
210
|
+
options[:exclude_paths].any? { |excluded| file.include?(excluded) }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Remove duplicates and ensure files exist
|
|
214
|
+
filtered_files.uniq.select { |file| File.file?(file) }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def should_process_file?(file_path)
|
|
218
|
+
# Always process if force_rescan is true
|
|
219
|
+
return true if options[:force_rescan]
|
|
220
|
+
|
|
221
|
+
# Check if file has been modified since last scan
|
|
222
|
+
# For now, always process (could add timestamp checking later)
|
|
223
|
+
true
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def relative_path(file_path)
|
|
227
|
+
file_path.gsub(Rails.root.to_s + '/', '')
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def display_completion_summary(processed_files, total_facts, start_time)
|
|
231
|
+
duration = Time.current - start_time
|
|
232
|
+
|
|
233
|
+
say "\nš SCAN RESULTS:", :cyan
|
|
234
|
+
say "=" * 30, :cyan
|
|
235
|
+
say "ā±ļø Total time: #{duration.round(2)} seconds", :white
|
|
236
|
+
say "š Files processed: #{processed_files}", :white
|
|
237
|
+
say "š¬ Facts extracted: #{total_facts}", :white
|
|
238
|
+
say "š Avg facts per file: #{total_facts > 0 ? (total_facts.to_f / processed_files).round(1) : 0}", :white
|
|
239
|
+
say "ā” Processing rate: #{(processed_files.to_f / duration).round(1)} files/sec", :white
|
|
240
|
+
say ""
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def create_hokipoki_config(processed_files, total_facts)
|
|
244
|
+
config_dir = File.expand_path('~/.hokipoki')
|
|
245
|
+
FileUtils.mkdir_p(config_dir) unless Dir.exist?(config_dir)
|
|
246
|
+
|
|
247
|
+
config_file = File.join(config_dir, 'project_config.yml')
|
|
248
|
+
config_data = {
|
|
249
|
+
project_name: Rails.application.class.module_parent_name,
|
|
250
|
+
project_path: Rails.root.to_s,
|
|
251
|
+
last_scan: Time.current.iso8601,
|
|
252
|
+
files_processed: processed_files,
|
|
253
|
+
facts_extracted: total_facts,
|
|
254
|
+
scan_options: {
|
|
255
|
+
file_patterns: options[:file_patterns],
|
|
256
|
+
exclude_paths: options[:exclude_paths]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
File.write(config_file, config_data.to_yaml)
|
|
261
|
+
say "š Updated project config: #{config_file}", :green
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def display_vector_statistics(vector_engine)
|
|
265
|
+
stats = vector_engine.statistics
|
|
266
|
+
|
|
267
|
+
say "\nš§ VECTOR ENGINE STATISTICS:", :cyan
|
|
268
|
+
say "=" * 35, :cyan
|
|
269
|
+
say "š Total vectors: #{stats[:total_vectors]}", :white
|
|
270
|
+
say "ā
Success rate: #{stats[:success_rate]}%", :white
|
|
271
|
+
say "šļø Avg compression: #{stats[:average_compression]}%", :white
|
|
272
|
+
say "š¾ Cache size: #{stats[:cache_size]} entries", :white
|
|
273
|
+
say "š§ Learning patterns: #{stats[:learning_patterns]}", :white
|
|
274
|
+
say "šæ Database size: #{(stats[:database_size] / 1024.0).round(2)} KB", :white
|
|
275
|
+
say ""
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|