hokipoki 0.8.4 → 0.8.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8431a8c43517c5acfa725df99108d9b0c1751cd930a1b8dbf58825738b2d93e4
4
- data.tar.gz: 1b9e86fe6b36e7157cdd7168b1b7808575340310c0c6650600e31a220fd78bbf
3
+ metadata.gz: b91046938bebd8651bae6ceae238830821314e7e76fc3a056b38f316f5f3afdf
4
+ data.tar.gz: 2cb95e0535b1dc51cf1e6eb9ccd294a11f7c56f71a36dbb598132c52b9adb811
5
5
  SHA512:
6
- metadata.gz: 240f6d073408ff5fea984d55dc37865a50eac078e63b0df33b615d47b8278a7c86751864e8e0352edad3c897507d417a4555b245584691a649e124c0e62026a5
7
- data.tar.gz: e9431bebc13de61241be6e56cb62ff063f93bbd8bd6ee290f6e5ee08239050aa78736c62c59ce9dfd20d0d35cf8c36e191685f61a269a9df838b656618592073
6
+ metadata.gz: fa66e7e8197c2242eeec56e125cb79e2cd9e1c94d05c083aaac04c4668697afac8c75e471b6d9eb29238e5b9d1567d31b7a5a91697f1948593b4b346603ae364
7
+ data.tar.gz: a163960c56d505b79ed3dc7393c17e2568cc104785d98bd294f172c561392a6dbd2c0390da4ce37ff74c21cd89867516c2526e9f0b85abfb37f148a916ef254a
@@ -129,11 +129,31 @@ module HiveMind
129
129
  # Create smart retrieval engine
130
130
  template 'smart_retrieval_engine.rb', 'app/services/smart_retrieval_engine.rb'
131
131
  say @pastel.green("✓ Created app/services/smart_retrieval_engine.rb")
132
+
133
+ # Create Gemini API controller for vector refinement
134
+ directory 'api', 'app/controllers/api'
135
+ say @pastel.green("✓ Created app/controllers/api/gemini_controller.rb")
132
136
  end
133
137
 
134
138
  def setup_routing
135
- say "\n#{@pastel.cyan('🛣️ Skipping routes for lightweight install')}"
136
- say @pastel.green("✓ No additional routes needed")
139
+ say "\n#{@pastel.cyan('🛣️ Adding Gemini API routes')}"
140
+
141
+ # Add Gemini API routes
142
+ routes_content = <<~RUBY
143
+
144
+ # Gemini vector refinement API
145
+ namespace :api do
146
+ namespace :gemini do
147
+ get :health_check
148
+ get :unrefined_vectors
149
+ post :submit_refined
150
+ get :stats
151
+ end
152
+ end
153
+ RUBY
154
+
155
+ append_to_file 'config/routes.rb', routes_content
156
+ say @pastel.green("✓ Added Gemini API routes")
137
157
  end
138
158
 
139
159
  def create_cli_tools
@@ -0,0 +1,283 @@
1
+ class Api::GeminiController < ApplicationController
2
+ skip_before_action :verify_authenticity_token
3
+ before_action :log_gemini_activity, except: [:health_check]
4
+
5
+ # Health check endpoint
6
+ def health_check
7
+ render json: {
8
+ status: 'ok',
9
+ timestamp: Time.current,
10
+ system: 'hokipoki_gemini_api'
11
+ }
12
+ end
13
+
14
+ # Endpoint for Gemini to fetch unrefined vectors
15
+ def unrefined_vectors
16
+ begin
17
+ batch_size = params[:batch_size]&.to_i || 10
18
+ batch_size = [batch_size, 50].min # Cap at 50 for safety
19
+
20
+ vectors = HiveMindDocument.where(refined: false)
21
+ .limit(batch_size)
22
+ .order(:created_at)
23
+
24
+ response_data = {
25
+ vectors: vectors.map { |v| format_vector_for_gemini(v) },
26
+ refinement_template: refinement_template,
27
+ batch_info: {
28
+ requested: batch_size,
29
+ returned: vectors.count,
30
+ total_pending: HiveMindDocument.where(refined: false).count
31
+ },
32
+ timestamp: Time.current
33
+ }
34
+
35
+ log_gemini_status('info', "Served #{vectors.count} unrefined vectors to Gemini")
36
+
37
+ render json: response_data
38
+
39
+ rescue => e
40
+ log_gemini_status('error', "Failed to fetch unrefined vectors: #{e.message}")
41
+
42
+ render json: {
43
+ error: 'Failed to fetch vectors',
44
+ message: e.message,
45
+ timestamp: Time.current
46
+ }, status: 500
47
+ end
48
+ end
49
+
50
+ # Endpoint for Gemini to submit refined vectors
51
+ def submit_refined
52
+ begin
53
+ refined_data = JSON.parse(request.body.read)
54
+ processed_count = 0
55
+ errors = []
56
+
57
+ refined_data['vectors']&.each do |refined|
58
+ begin
59
+ vector = HiveMindDocument.find(refined['id'])
60
+
61
+ # Update with refined data
62
+ update_data = {
63
+ refined: true,
64
+ refined_at: Time.current,
65
+ refined_by: 'gemini'
66
+ }
67
+
68
+ # Add refined content if provided
69
+ if refined['chunks']
70
+ update_data[:chunks] = refined['chunks']
71
+ end
72
+
73
+ if refined['keywords']
74
+ update_data[:keywords] = refined['keywords']
75
+ end
76
+
77
+ if refined['generators']
78
+ update_data[:generators] = refined['generators']
79
+ end
80
+
81
+ # Store refined metadata
82
+ existing_metadata = vector.metadata || {}
83
+ update_data[:metadata] = existing_metadata.merge({
84
+ 'refined_by' => 'gemini',
85
+ 'refined_at' => Time.current.iso8601,
86
+ 'original_content_length' => vector.content&.length,
87
+ 'chunks_count' => refined['chunks']&.length,
88
+ 'keywords_count' => refined['keywords']&.length
89
+ })
90
+
91
+ vector.update!(update_data)
92
+ processed_count += 1
93
+
94
+ log_gemini_status('success', "Refined vector ##{vector.id} (#{refined['keywords']&.length || 0} keywords)")
95
+
96
+ rescue => e
97
+ error_msg = "Failed to update vector #{refined['id']}: #{e.message}"
98
+ errors << error_msg
99
+ log_gemini_status('error', error_msg)
100
+ end
101
+ end
102
+
103
+ response_data = {
104
+ status: 'success',
105
+ processed: processed_count,
106
+ errors: errors,
107
+ timestamp: Time.current
108
+ }
109
+
110
+ if errors.any?
111
+ response_data[:status] = 'partial_success'
112
+ render json: response_data, status: 207 # Multi-status
113
+ else
114
+ render json: response_data
115
+ end
116
+
117
+ rescue JSON::ParserError => e
118
+ log_gemini_status('error', "Invalid JSON in refined data: #{e.message}")
119
+
120
+ render json: {
121
+ error: 'Invalid JSON format',
122
+ message: e.message,
123
+ timestamp: Time.current
124
+ }, status: 400
125
+
126
+ rescue => e
127
+ log_gemini_status('error', "Failed to process refined vectors: #{e.message}")
128
+
129
+ render json: {
130
+ error: 'Failed to process refined vectors',
131
+ message: e.message,
132
+ timestamp: Time.current
133
+ }, status: 500
134
+ end
135
+ end
136
+
137
+ # Stats endpoint for monitoring
138
+ def stats
139
+ begin
140
+ stats = {
141
+ total_vectors: HiveMindDocument.count,
142
+ refined_vectors: HiveMindDocument.where(refined: true).count,
143
+ pending_vectors: HiveMindDocument.where(refined: false).count,
144
+ refinement_rate: calculate_refinement_rate,
145
+ last_activity: get_last_activity,
146
+ timestamp: Time.current
147
+ }
148
+
149
+ render json: stats
150
+
151
+ rescue => e
152
+ render json: {
153
+ error: 'Failed to generate stats',
154
+ message: e.message,
155
+ timestamp: Time.current
156
+ }, status: 500
157
+ end
158
+ end
159
+
160
+ private
161
+
162
+ def format_vector_for_gemini(vector)
163
+ {
164
+ id: vector.id,
165
+ content: vector.content,
166
+ source_type: vector.source_type,
167
+ source_id: vector.source_id,
168
+ metadata: vector.metadata || {},
169
+ created_at: vector.created_at,
170
+ content_length: vector.content&.length || 0,
171
+ preview: vector.content&.truncate(100)
172
+ }
173
+ end
174
+
175
+ def refinement_template
176
+ {
177
+ instruction: "Refine each vector into atomic facts with keywords and generators",
178
+ chunking_rules: {
179
+ max_words_per_chunk: 50,
180
+ min_words_per_chunk: 10,
181
+ overlap_words: 5,
182
+ preserve_context: true
183
+ },
184
+ keyword_extraction: {
185
+ keywords_per_chunk: "3-5",
186
+ types: ["technical", "contextual", "semantic"],
187
+ importance_threshold: 0.6
188
+ },
189
+ generator_creation: {
190
+ pattern: "trigger_keywords → response_template",
191
+ confidence_threshold: 0.7,
192
+ max_generators_per_chunk: 3
193
+ },
194
+ output_format: {
195
+ chunks: "Array of atomic fact strings",
196
+ keywords: "Array of keyword strings",
197
+ generators: "Array of {trigger: [...], template: '...', confidence: 0.0-1.0}"
198
+ },
199
+ example: {
200
+ input: "Rails authentication with Devise requires configuration",
201
+ expected_output: {
202
+ chunks: ["Rails authentication with Devise requires configuration"],
203
+ keywords: ["rails", "authentication", "devise", "configuration"],
204
+ generators: [
205
+ {
206
+ trigger: ["rails", "authentication", "devise"],
207
+ template: "For Rails authentication, use Devise gem with proper configuration",
208
+ confidence: 0.85
209
+ }
210
+ ]
211
+ }
212
+ }
213
+ }
214
+ end
215
+
216
+ def calculate_refinement_rate
217
+ # Calculate vectors refined in last hour
218
+ one_hour_ago = 1.hour.ago
219
+ recent_refined = HiveMindDocument.where(refined: true)
220
+ .where('refined_at > ?', one_hour_ago)
221
+ .count
222
+
223
+ # Return per minute rate
224
+ (recent_refined / 60.0).round(2)
225
+ end
226
+
227
+ def get_last_activity
228
+ begin
229
+ last_refined = HiveMindDocument.where(refined: true)
230
+ .order(:refined_at)
231
+ .last
232
+
233
+ if last_refined&.refined_at
234
+ {
235
+ type: 'refinement',
236
+ timestamp: last_refined.refined_at,
237
+ vector_id: last_refined.id
238
+ }
239
+ else
240
+ {
241
+ type: 'none',
242
+ timestamp: nil,
243
+ vector_id: nil
244
+ }
245
+ end
246
+ rescue
247
+ { type: 'error', timestamp: nil, vector_id: nil }
248
+ end
249
+ end
250
+
251
+ def log_gemini_activity
252
+ activity_log = "#{Time.current.strftime('%H:%M:%S')} - #{action_name} - #{request.remote_ip}"
253
+
254
+ # Log to Gemini status file
255
+ File.open('/tmp/gemini_status.log', 'a') do |f|
256
+ f.puts "#{Time.current.strftime('%H:%M:%S')} - api - #{activity_log}"
257
+ end
258
+ rescue
259
+ # Ignore logging errors
260
+ end
261
+
262
+ def log_gemini_status(level, message)
263
+ timestamp = Time.current.strftime('%H:%M:%S')
264
+ log_entry = "#{timestamp} - #{level} - #{message}"
265
+
266
+ # Log to Rails logger
267
+ case level
268
+ when 'error'
269
+ Rails.logger.error "[GEMINI] #{message}"
270
+ when 'success'
271
+ Rails.logger.info "[GEMINI] #{message}"
272
+ else
273
+ Rails.logger.debug "[GEMINI] #{message}"
274
+ end
275
+
276
+ # Log to Gemini status file for dashboard
277
+ File.open('/tmp/gemini_status.log', 'a') do |f|
278
+ f.puts log_entry
279
+ end
280
+ rescue
281
+ # Ignore logging errors
282
+ end
283
+ end
@@ -228,37 +228,38 @@ module Hokipoki
228
228
  end
229
229
 
230
230
  def display_next_steps
231
+ # Cool ASCII art for HOKIPOKI
232
+ ascii_art = <<~ASCII
233
+ ██╗ ██╗ ██████╗ ██╗ ██╗██╗██████╗ ██████╗ ██╗ ██╗██╗
234
+ ██║ ██║██╔═══██╗██║ ██╔╝██║██╔══██╗██╔═══██╗██║ ██╔╝██║
235
+ ███████║██║ ██║█████╔╝ ██║██████╔╝██║ ██║█████╔╝ ██║
236
+ ██╔══██║██║ ██║██╔═██╗ ██║██╔═══╝ ██║ ██║██╔═██╗ ██║
237
+ ██║ ██║╚██████╔╝██║ ██╗██║██║ ╚██████╔╝██║ ██╗██║
238
+ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
239
+ ASCII
240
+
241
+ say ascii_art, :cyan
242
+ say ""
231
243
  say "🎉 HOKIPOKI CORE INSTALLATION COMPLETE!", :green
232
244
  say "=" * 60, :green
233
245
  say ""
234
- say "📋 NEXT STEPS:", :cyan
246
+ say "🚀 SUPER SIMPLE NEXT STEPS:", :cyan
235
247
  say ""
236
248
  say "1. 📦 Install dependencies:", :white
237
249
  say " bundle install", :yellow
238
250
  say ""
239
- say "2. 🔐 Configure credentials (REQUIRED):", :white
240
- say " EDITOR=nano rails credentials:edit", :yellow
241
- say ""
242
- say " Add this structure:", :white
243
- say credentials_template, :yellow
244
- say ""
245
- say "3. 🗄️ Run database migrations:", :white
246
- say " rails db:migrate", :yellow
247
- say ""
248
- say "4. 🧠 Install HiveMind intelligence:", :white
251
+ say "2. 🧠 One-command setup (installs everything):", :white
249
252
  say " rails g hive_mind:install", :yellow
250
253
  say ""
251
- say "5. 🦠 Attach parasite (after HiveMind):", :white
252
- say " rails g hokipoki:attach_parasite", :yellow
254
+ say " This automatically installs:", :green
255
+ say " - HiveMind vector database", :dim
256
+ say " - Parasite attachment for Claude", :dim
257
+ say " - Gemini refinement system", :dim
258
+ say " - Database migrations", :dim
253
259
  say ""
254
- say "🔧 TROUBLESHOOTING:", :cyan
255
- say " - If bundle fails: Check Ruby version compatibility", :white
256
- say " - If credentials fail: Ensure master.key exists", :white
257
- say " - If GitHub OAuth needed: Set up GitHub app first", :white
260
+ say "🎭 THAT'S IT! Everything else is automatic!", :magenta
258
261
  say ""
259
- say "📚 DOCUMENTATION:", :cyan
260
- say " - GitHub OAuth setup: https://docs.github.com/en/apps/oauth-apps", :white
261
- say " - Rails credentials: https://guides.rubyonrails.org/security.html#custom-credentials", :white
262
+ say "Next: Start Rails server and restart Claude to see the magic! ✨", :yellow
262
263
  say ""
263
264
  end
264
265
 
@@ -1,3 +1,3 @@
1
1
  module Hokipoki
2
- VERSION = "0.8.4"
2
+ VERSION = "0.8.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hokipoki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rails Utilities
@@ -232,6 +232,7 @@ files:
232
232
  - bin/gemini_refiner
233
233
  - lib/generators/hive_mind/install_generator.rb
234
234
  - lib/generators/hive_mind/start_generator.rb
235
+ - lib/generators/hive_mind/templates/api/gemini_controller.rb
235
236
  - lib/generators/hive_mind/templates/create_hive_mind_documents.rb
236
237
  - lib/generators/hive_mind/templates/embedding_service.rb
237
238
  - lib/generators/hive_mind/templates/hive_mind_document.rb