hokipoki 0.1.2 โ 0.1.3
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/LICENSE +26 -0
- data/lib/generators/hive_mind/install_generator.rb +828 -0
- data/lib/hokipoki/claude/auto_loader.rb +162 -0
- data/lib/hokipoki/claude/connection_manager.rb +382 -0
- data/lib/hokipoki/claude/parasite.rb +333 -0
- data/lib/hokipoki/configuration.rb +187 -0
- data/lib/hokipoki/engine.rb +122 -0
- data/lib/hokipoki/feedback/ascii_banners.rb +108 -0
- data/lib/hokipoki/feedback/display_manager.rb +436 -0
- data/lib/hokipoki/intelligence/smart_retrieval_engine.rb +401 -0
- data/lib/hokipoki/intelligence/unified_orchestrator.rb +395 -0
- data/lib/hokipoki/license_validator.rb +296 -0
- data/lib/hokipoki/parasites/universal_generator.rb +662 -0
- data/lib/hokipoki/railtie.rb +34 -0
- data/lib/hokipoki/version.rb +1 -1
- data/lib/hokipoki.rb +177 -0
- metadata +77 -18
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'singleton'
|
|
4
|
+
|
|
5
|
+
module Hokipoki
|
|
6
|
+
module Parasites
|
|
7
|
+
# Universal Parasite Generator
|
|
8
|
+
# Revolutionary system that consolidates 17+ individual parasites into one template-driven generator
|
|
9
|
+
# This represents the 94% code reduction achievement: 17 parasites โ 1 universal system
|
|
10
|
+
class UniversalGenerator
|
|
11
|
+
include Singleton
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@logger = Rails.logger
|
|
15
|
+
@feedback = Feedback::DisplayManager.instance
|
|
16
|
+
@template_registry = nil # Lazy load
|
|
17
|
+
@behavioral_analyzer = nil # Lazy load
|
|
18
|
+
@embedding_service = nil # Lazy load
|
|
19
|
+
@initialized = false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Main entry point: Generate parasite from requirements
|
|
23
|
+
def generate_parasite(requirements)
|
|
24
|
+
ensure_initialized!
|
|
25
|
+
|
|
26
|
+
generation_id = generate_id
|
|
27
|
+
start_time = Time.current
|
|
28
|
+
tool = requirements[:tool] || 'unknown'
|
|
29
|
+
model = requirements[:model] || 'unknown'
|
|
30
|
+
|
|
31
|
+
@feedback.generating_parasite(tool, model) do
|
|
32
|
+
@logger.info "๐ฆ UNIVERSAL: Starting parasite generation [#{generation_id}]"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@feedback.progress_tracker(5, 'parasite_generation') do |progress|
|
|
36
|
+
begin
|
|
37
|
+
# STEP 1: Analyze requirements and context
|
|
38
|
+
progress.call('analyzing requirements')
|
|
39
|
+
analyzed_requirements = analyze_requirements(requirements, generation_id)
|
|
40
|
+
|
|
41
|
+
# STEP 2: Find optimal template using vector similarity
|
|
42
|
+
progress.call('finding optimal template')
|
|
43
|
+
optimal_template = find_optimal_template(analyzed_requirements)
|
|
44
|
+
|
|
45
|
+
unless optimal_template
|
|
46
|
+
@feedback.operation_warning('template_search', 'no suitable template found, using fallback')
|
|
47
|
+
return create_fallback_parasite(analyzed_requirements, generation_id)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# STEP 3: Generate customized parasite from template
|
|
51
|
+
progress.call('generating from template')
|
|
52
|
+
generated_parasite = generate_from_template(optimal_template, analyzed_requirements, generation_id)
|
|
53
|
+
|
|
54
|
+
# STEP 4: Apply behavioral optimizations if available
|
|
55
|
+
progress.call('applying behavioral optimizations')
|
|
56
|
+
optimized_parasite = apply_behavioral_optimizations(generated_parasite, analyzed_requirements)
|
|
57
|
+
|
|
58
|
+
# STEP 5: Register and store parasite
|
|
59
|
+
progress.call('storing parasite')
|
|
60
|
+
stored_parasite = store_generated_parasite(optimized_parasite, analyzed_requirements, generation_id)
|
|
61
|
+
|
|
62
|
+
generation_time = (Time.current - start_time).round(3)
|
|
63
|
+
generation_time_ms = (generation_time * 1000).round(2)
|
|
64
|
+
|
|
65
|
+
@feedback.parasite_generation_complete(generated_parasite[:name], generation_time_ms)
|
|
66
|
+
|
|
67
|
+
{
|
|
68
|
+
success: true,
|
|
69
|
+
parasite: stored_parasite,
|
|
70
|
+
generation_id: generation_id,
|
|
71
|
+
template_used: optimal_template.name,
|
|
72
|
+
generation_time_ms: generation_time_ms,
|
|
73
|
+
behavioral_optimizations_applied: optimized_parasite[:optimizations_applied] || false
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
rescue => e
|
|
77
|
+
@feedback.operation_error('parasite_generation', e.message)
|
|
78
|
+
@logger.error "โ UNIVERSAL: Generation failed [#{generation_id}]: #{e.message}"
|
|
79
|
+
handle_generation_error(e, requirements, generation_id)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Generate parasite specifically optimized for a target LLM
|
|
85
|
+
def generate_llm_optimized_parasite(requirements, target_llm)
|
|
86
|
+
@logger.info "๐ง UNIVERSAL: Generating LLM-optimized parasite for #{target_llm}"
|
|
87
|
+
|
|
88
|
+
# Enhance requirements with LLM-specific behavioral patterns
|
|
89
|
+
enhanced_requirements = requirements.merge({
|
|
90
|
+
target_llm: target_llm,
|
|
91
|
+
behavioral_optimization: true,
|
|
92
|
+
llm_specific_patterns: get_llm_behavioral_patterns(target_llm)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
generate_parasite(enhanced_requirements)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Create multiple parasite variants for A/B testing
|
|
99
|
+
def generate_variants_for_testing(base_requirements, variant_count = 3)
|
|
100
|
+
@logger.info "๐งช UNIVERSAL: Generating #{variant_count} parasite variants for A/B testing"
|
|
101
|
+
|
|
102
|
+
variants = []
|
|
103
|
+
base_id = generate_id
|
|
104
|
+
|
|
105
|
+
variant_count.times do |i|
|
|
106
|
+
variant_requirements = create_variant_requirements(base_requirements, i)
|
|
107
|
+
variant_requirements[:variant_id] = "#{base_id}_variant_#{i + 1}"
|
|
108
|
+
variant_requirements[:is_test_variant] = true
|
|
109
|
+
|
|
110
|
+
variant_result = generate_parasite(variant_requirements)
|
|
111
|
+
variants << variant_result if variant_result[:success]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
{
|
|
115
|
+
success: true,
|
|
116
|
+
base_id: base_id,
|
|
117
|
+
variants: variants,
|
|
118
|
+
test_configuration: create_ab_test_configuration(variants)
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
def ensure_initialized!
|
|
125
|
+
return if @initialized
|
|
126
|
+
|
|
127
|
+
@template_registry = load_template_registry
|
|
128
|
+
@embedding_service = load_embedding_service
|
|
129
|
+
@initialized = true
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def analyze_requirements(requirements, generation_id)
|
|
133
|
+
@logger.debug "๐ UNIVERSAL: Analyzing requirements [#{generation_id}]"
|
|
134
|
+
|
|
135
|
+
analyzed = {
|
|
136
|
+
original_requirements: requirements,
|
|
137
|
+
generation_id: generation_id,
|
|
138
|
+
tool: requirements[:tool] || 'unknown',
|
|
139
|
+
model: requirements[:model] || 'unknown',
|
|
140
|
+
context_type: requirements[:context_type] || 'general',
|
|
141
|
+
injection_style: requirements[:injection_style] || 'natural',
|
|
142
|
+
token_budget: requirements[:token_budget] || 1500,
|
|
143
|
+
project_context: detect_project_context(requirements),
|
|
144
|
+
behavioral_requirements: extract_behavioral_requirements(requirements),
|
|
145
|
+
optimization_preferences: extract_optimization_preferences(requirements)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# Generate search query for template matching
|
|
149
|
+
analyzed[:template_search_query] = build_template_search_query(analyzed)
|
|
150
|
+
|
|
151
|
+
# Calculate requirement vector for similarity matching (if embedding service available)
|
|
152
|
+
if @embedding_service
|
|
153
|
+
analyzed[:requirement_vector] = generate_requirement_vector(analyzed)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
analyzed
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def find_optimal_template(analyzed_requirements)
|
|
160
|
+
@feedback.debug_info('template_search', 'searching for optimal template')
|
|
161
|
+
|
|
162
|
+
return nil unless @template_registry
|
|
163
|
+
|
|
164
|
+
# Try vector similarity first if available
|
|
165
|
+
if analyzed_requirements[:requirement_vector] && @template_registry.respond_to?(:find_templates_by_similarity)
|
|
166
|
+
@feedback.debug_info('vector_search', 'using vector similarity for template matching')
|
|
167
|
+
|
|
168
|
+
template_matches = @template_registry.find_templates_by_similarity(
|
|
169
|
+
analyzed_requirements[:requirement_vector],
|
|
170
|
+
template_type: 'parasite',
|
|
171
|
+
limit: 3
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if template_matches&.any?
|
|
175
|
+
@feedback.debug_info('template_matches', "found #{template_matches.length} template matches")
|
|
176
|
+
return select_best_template(template_matches, analyzed_requirements)
|
|
177
|
+
else
|
|
178
|
+
@feedback.debug_info('vector_search', 'no vector matches found')
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Fallback to keyword-based search
|
|
183
|
+
@feedback.debug_info('keyword_search', 'falling back to keyword-based search')
|
|
184
|
+
result = @template_registry.find_optimal_template(
|
|
185
|
+
analyzed_requirements[:template_search_query],
|
|
186
|
+
{ type: 'parasite' }
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
if result
|
|
190
|
+
@feedback.debug_info('template_found', "found template via keyword search: #{result.name}")
|
|
191
|
+
else
|
|
192
|
+
@feedback.debug_info('template_search', 'no templates found')
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
result
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def select_best_template(template_matches, analyzed_requirements)
|
|
199
|
+
return template_matches.first if template_matches.length == 1
|
|
200
|
+
|
|
201
|
+
@feedback.debug_info('template_scoring', "scoring #{template_matches.length} templates")
|
|
202
|
+
|
|
203
|
+
# Score templates based on requirements match
|
|
204
|
+
scored_templates = template_matches.map do |template|
|
|
205
|
+
score = calculate_template_match_score(template, analyzed_requirements)
|
|
206
|
+
@feedback.debug_info('template_score', "#{template.name}: #{score.round(3)}")
|
|
207
|
+
{ template: template, score: score }
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Return highest scoring template
|
|
211
|
+
best_match = scored_templates.max_by { |match| match[:score] }
|
|
212
|
+
|
|
213
|
+
@feedback.parasite_template_found(best_match[:template].name, best_match[:score])
|
|
214
|
+
best_match[:template]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def generate_from_template(template, analyzed_requirements, generation_id)
|
|
218
|
+
@logger.debug "๐ญ UNIVERSAL: Generating from template '#{template.name}'"
|
|
219
|
+
|
|
220
|
+
# Extract template patterns
|
|
221
|
+
template_content = template.template_content || generate_default_template_content(analyzed_requirements)
|
|
222
|
+
|
|
223
|
+
# Replace template variables with requirement-specific values
|
|
224
|
+
customized_content = customize_template_content(template_content, analyzed_requirements)
|
|
225
|
+
|
|
226
|
+
# Generate parasite metadata
|
|
227
|
+
parasite_metadata = generate_parasite_metadata(template, analyzed_requirements, generation_id)
|
|
228
|
+
|
|
229
|
+
# Create parasite structure
|
|
230
|
+
generated_parasite = {
|
|
231
|
+
name: generate_parasite_name(analyzed_requirements),
|
|
232
|
+
code: customized_content,
|
|
233
|
+
metadata: parasite_metadata,
|
|
234
|
+
template_source: template.name,
|
|
235
|
+
template_version: template.version || '1.0',
|
|
236
|
+
generation_method: 'template_based'
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@logger.info "๐ญ UNIVERSAL: Generated parasite '#{generated_parasite[:name]}' from template"
|
|
240
|
+
generated_parasite
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def apply_behavioral_optimizations(generated_parasite, analyzed_requirements)
|
|
244
|
+
return generated_parasite unless analyzed_requirements[:behavioral_optimization]
|
|
245
|
+
|
|
246
|
+
@logger.debug "๐ง UNIVERSAL: Applying behavioral optimizations"
|
|
247
|
+
|
|
248
|
+
# Load behavioral analyzer if needed
|
|
249
|
+
@behavioral_analyzer ||= load_behavioral_analyzer
|
|
250
|
+
|
|
251
|
+
if @behavioral_analyzer && analyzed_requirements[:target_llm]
|
|
252
|
+
behavioral_patterns = @behavioral_analyzer.get_patterns_for_llm(analyzed_requirements[:target_llm])
|
|
253
|
+
|
|
254
|
+
if behavioral_patterns && behavioral_patterns.any?
|
|
255
|
+
optimized_code = optimize_code_for_behavioral_patterns(
|
|
256
|
+
generated_parasite[:code],
|
|
257
|
+
behavioral_patterns
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
generated_parasite[:code] = optimized_code
|
|
261
|
+
generated_parasite[:behavioral_optimizations] = behavioral_patterns.keys
|
|
262
|
+
generated_parasite[:optimizations_applied] = true
|
|
263
|
+
|
|
264
|
+
@logger.info "๐ง UNIVERSAL: Applied behavioral optimizations for #{analyzed_requirements[:target_llm]}"
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
generated_parasite
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def store_generated_parasite(generated_parasite, analyzed_requirements, generation_id)
|
|
272
|
+
@logger.debug "๐พ UNIVERSAL: Storing generated parasite"
|
|
273
|
+
|
|
274
|
+
# Create parasite record using Hokipoki models
|
|
275
|
+
parasite_data = {
|
|
276
|
+
name: generated_parasite[:name],
|
|
277
|
+
tool: analyzed_requirements[:tool],
|
|
278
|
+
model: analyzed_requirements[:model],
|
|
279
|
+
code: generated_parasite[:code],
|
|
280
|
+
metadata: generated_parasite[:metadata].merge({
|
|
281
|
+
generation_id: generation_id,
|
|
282
|
+
generated_by: 'universal_parasite_generator',
|
|
283
|
+
generated_at: Time.current.iso8601
|
|
284
|
+
}),
|
|
285
|
+
description: generate_parasite_description(generated_parasite, analyzed_requirements),
|
|
286
|
+
template_source: generated_parasite[:template_source],
|
|
287
|
+
template_version: generated_parasite[:template_version],
|
|
288
|
+
auto_activate: analyzed_requirements[:auto_activate] || false,
|
|
289
|
+
version: 1
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# Store the parasite (would integrate with actual model when available)
|
|
293
|
+
stored_parasite = create_parasite_record(parasite_data)
|
|
294
|
+
|
|
295
|
+
@logger.info "๐พ UNIVERSAL: Stored parasite with ID #{stored_parasite[:id] || 'generated'}"
|
|
296
|
+
stored_parasite
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def create_fallback_parasite(analyzed_requirements, generation_id)
|
|
300
|
+
@logger.warn "โ ๏ธ UNIVERSAL: No template found, creating fallback parasite"
|
|
301
|
+
|
|
302
|
+
# Generate basic parasite using fallback logic
|
|
303
|
+
fallback_code = generate_fallback_parasite_code(analyzed_requirements)
|
|
304
|
+
|
|
305
|
+
fallback_parasite = {
|
|
306
|
+
name: "fallback_#{analyzed_requirements[:tool]}_#{analyzed_requirements[:model]}_#{Time.current.to_i}",
|
|
307
|
+
code: fallback_code,
|
|
308
|
+
metadata: {
|
|
309
|
+
generation_id: generation_id,
|
|
310
|
+
generation_method: 'fallback',
|
|
311
|
+
created_at: Time.current.iso8601
|
|
312
|
+
},
|
|
313
|
+
template_source: 'fallback_generator',
|
|
314
|
+
generation_method: 'fallback'
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
stored_parasite = store_generated_parasite(fallback_parasite, analyzed_requirements, generation_id)
|
|
318
|
+
|
|
319
|
+
{
|
|
320
|
+
success: true,
|
|
321
|
+
parasite: stored_parasite,
|
|
322
|
+
generation_id: generation_id,
|
|
323
|
+
template_used: 'fallback_generator',
|
|
324
|
+
warning: 'No suitable template found, used fallback generation'
|
|
325
|
+
}
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def detect_project_context(requirements)
|
|
329
|
+
working_dir = requirements[:working_directory] || Dir.pwd
|
|
330
|
+
|
|
331
|
+
context = {
|
|
332
|
+
working_directory: working_dir,
|
|
333
|
+
project_type: 'unknown',
|
|
334
|
+
has_git: false,
|
|
335
|
+
languages: []
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
begin
|
|
339
|
+
# Detect project type from directory structure
|
|
340
|
+
if File.exist?(File.join(working_dir, 'Gemfile'))
|
|
341
|
+
context[:project_type] = 'ruby'
|
|
342
|
+
context[:languages] << 'ruby'
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
if File.exist?(File.join(working_dir, 'package.json'))
|
|
346
|
+
context[:project_type] = 'nodejs' if context[:project_type] == 'unknown'
|
|
347
|
+
context[:languages] << 'javascript'
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
if File.exist?(File.join(working_dir, '.git'))
|
|
351
|
+
context[:has_git] = true
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
rescue => e
|
|
355
|
+
@logger.debug "Could not detect project context: #{e.message}"
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
context
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def extract_behavioral_requirements(requirements)
|
|
362
|
+
{
|
|
363
|
+
response_style: requirements[:response_style] || 'natural',
|
|
364
|
+
thinking_tags: requirements[:thinking_tags] || false,
|
|
365
|
+
code_quality_focus: requirements[:code_quality_focus] || 'standard',
|
|
366
|
+
error_handling_style: requirements[:error_handling_style] || 'standard',
|
|
367
|
+
verbosity_level: requirements[:verbosity_level] || 'medium'
|
|
368
|
+
}
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def extract_optimization_preferences(requirements)
|
|
372
|
+
{
|
|
373
|
+
token_efficiency: requirements[:token_efficiency] || 'high',
|
|
374
|
+
context_compression: requirements[:context_compression] || 'medium',
|
|
375
|
+
cache_usage: requirements[:cache_usage] || 'enabled',
|
|
376
|
+
performance_priority: requirements[:performance_priority] || 'balanced'
|
|
377
|
+
}
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def build_template_search_query(analyzed)
|
|
381
|
+
query_parts = [
|
|
382
|
+
analyzed[:tool],
|
|
383
|
+
analyzed[:model],
|
|
384
|
+
analyzed[:context_type],
|
|
385
|
+
analyzed[:injection_style]
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
# Add behavioral requirements
|
|
389
|
+
behavioral = analyzed[:behavioral_requirements]
|
|
390
|
+
query_parts << behavioral[:response_style] if behavioral[:response_style] != 'natural'
|
|
391
|
+
query_parts << 'thinking_tags' if behavioral[:thinking_tags]
|
|
392
|
+
|
|
393
|
+
query_parts.compact.join(' ')
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def generate_requirement_vector(analyzed)
|
|
397
|
+
return nil unless @embedding_service
|
|
398
|
+
|
|
399
|
+
# Create text representation for embedding
|
|
400
|
+
vector_text = [
|
|
401
|
+
"tool: #{analyzed[:tool]}",
|
|
402
|
+
"model: #{analyzed[:model]}",
|
|
403
|
+
"context: #{analyzed[:context_type]}",
|
|
404
|
+
"style: #{analyzed[:injection_style]}",
|
|
405
|
+
"behavioral: #{analyzed[:behavioral_requirements].values.join(' ')}",
|
|
406
|
+
"optimization: #{analyzed[:optimization_preferences].values.join(' ')}"
|
|
407
|
+
].join(' ')
|
|
408
|
+
|
|
409
|
+
@embedding_service.generate_embedding(vector_text)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def calculate_template_match_score(template, analyzed_requirements)
|
|
413
|
+
score = 0.0
|
|
414
|
+
|
|
415
|
+
# Keyword match (50% weight when no vector similarity)
|
|
416
|
+
template_keywords = template.keywords || []
|
|
417
|
+
requirement_keywords = analyzed_requirements[:template_search_query].split(' ')
|
|
418
|
+
keyword_match = calculate_keyword_overlap(template_keywords, requirement_keywords)
|
|
419
|
+
score += keyword_match * 0.5
|
|
420
|
+
|
|
421
|
+
# Usage efficiency (30% weight)
|
|
422
|
+
efficiency_score = template.efficiency_score || 0.5
|
|
423
|
+
score += efficiency_score * 0.3
|
|
424
|
+
|
|
425
|
+
# Recent usage (20% weight)
|
|
426
|
+
usage_recency = calculate_usage_recency(template)
|
|
427
|
+
score += usage_recency * 0.2
|
|
428
|
+
|
|
429
|
+
score
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def customize_template_content(template_content, analyzed_requirements)
|
|
433
|
+
customized = template_content.dup
|
|
434
|
+
|
|
435
|
+
# Replace template variables
|
|
436
|
+
customized.gsub!('<%=tool%>', analyzed_requirements[:tool])
|
|
437
|
+
customized.gsub!('<%=model%>', analyzed_requirements[:model])
|
|
438
|
+
customized.gsub!('<%=context_type%>', analyzed_requirements[:context_type])
|
|
439
|
+
customized.gsub!('<%=injection_style%>', analyzed_requirements[:injection_style])
|
|
440
|
+
customized.gsub!('<%=token_budget%>', analyzed_requirements[:token_budget].to_s)
|
|
441
|
+
|
|
442
|
+
# Replace behavioral variables
|
|
443
|
+
behavioral = analyzed_requirements[:behavioral_requirements]
|
|
444
|
+
customized.gsub!('<%=response_style%>', behavioral[:response_style])
|
|
445
|
+
customized.gsub!('<%=thinking_tags%>', behavioral[:thinking_tags].to_s)
|
|
446
|
+
|
|
447
|
+
# Replace optimization variables
|
|
448
|
+
optimization = analyzed_requirements[:optimization_preferences]
|
|
449
|
+
customized.gsub!('<%=token_efficiency%>', optimization[:token_efficiency])
|
|
450
|
+
|
|
451
|
+
# Add project-specific customizations
|
|
452
|
+
project = analyzed_requirements[:project_context]
|
|
453
|
+
customized.gsub!('<%=project_type%>', project[:project_type])
|
|
454
|
+
|
|
455
|
+
customized
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def generate_parasite_metadata(template, analyzed_requirements, generation_id)
|
|
459
|
+
{
|
|
460
|
+
generated_from_template: template.name,
|
|
461
|
+
template_efficiency_score: template.efficiency_score,
|
|
462
|
+
generation_timestamp: Time.current.iso8601,
|
|
463
|
+
generation_id: generation_id,
|
|
464
|
+
target_tool: analyzed_requirements[:tool],
|
|
465
|
+
target_model: analyzed_requirements[:model],
|
|
466
|
+
behavioral_requirements: analyzed_requirements[:behavioral_requirements],
|
|
467
|
+
optimization_preferences: analyzed_requirements[:optimization_preferences],
|
|
468
|
+
project_context: analyzed_requirements[:project_context]
|
|
469
|
+
}
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def generate_parasite_name(analyzed_requirements)
|
|
473
|
+
# Create descriptive name based on requirements
|
|
474
|
+
tool = analyzed_requirements[:tool].gsub(/[^a-zA-Z0-9]/, '_')
|
|
475
|
+
model = analyzed_requirements[:model].gsub(/[^a-zA-Z0-9]/, '_')
|
|
476
|
+
timestamp = Time.current.strftime('%Y%m%d_%H%M')
|
|
477
|
+
|
|
478
|
+
"universal_#{tool}_#{model}_#{timestamp}"
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def generate_default_template_content(analyzed_requirements)
|
|
482
|
+
# Default template when no template is found
|
|
483
|
+
<<~RUBY
|
|
484
|
+
# Universal Parasite for #{analyzed_requirements[:tool]} + #{analyzed_requirements[:model]}
|
|
485
|
+
# Generated by Universal Parasite Generator
|
|
486
|
+
|
|
487
|
+
class Universal#{analyzed_requirements[:tool].capitalize}#{analyzed_requirements[:model].capitalize}Parasite < BaseParasite
|
|
488
|
+
def should_inject?(request_context, user_message)
|
|
489
|
+
# Smart injection logic
|
|
490
|
+
user_message.length > 20 && !simple_greeting?(user_message)
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def injection_strategy(request_context)
|
|
494
|
+
{
|
|
495
|
+
max_tokens: #{analyzed_requirements[:token_budget]},
|
|
496
|
+
style: :#{analyzed_requirements[:injection_style]},
|
|
497
|
+
context_type: :#{analyzed_requirements[:context_type]}
|
|
498
|
+
}
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def craft_injection(context, user_message, original_messages)
|
|
502
|
+
return original_messages unless context.present?
|
|
503
|
+
|
|
504
|
+
system_message = {
|
|
505
|
+
'role' => 'system',
|
|
506
|
+
'content' => "Context: \#{context}"
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
[system_message] + original_messages
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
private
|
|
513
|
+
|
|
514
|
+
def simple_greeting?(message)
|
|
515
|
+
message.match?(/^(hi|hello|thanks|yes|no|ok)$/i)
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
RUBY
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def generate_fallback_parasite_code(analyzed_requirements)
|
|
522
|
+
generate_default_template_content(analyzed_requirements)
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def create_parasite_record(parasite_data)
|
|
526
|
+
# This would integrate with the actual Hokipoki::CustomParasite model
|
|
527
|
+
# For now, return a mock record
|
|
528
|
+
{
|
|
529
|
+
id: SecureRandom.uuid,
|
|
530
|
+
name: parasite_data[:name],
|
|
531
|
+
tool: parasite_data[:tool],
|
|
532
|
+
model: parasite_data[:model],
|
|
533
|
+
code: parasite_data[:code],
|
|
534
|
+
metadata: parasite_data[:metadata],
|
|
535
|
+
created_at: Time.current.iso8601
|
|
536
|
+
}
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
def generate_parasite_description(generated_parasite, analyzed_requirements)
|
|
540
|
+
"Universal parasite for #{analyzed_requirements[:tool]} + #{analyzed_requirements[:model]} " \
|
|
541
|
+
"generated from template '#{generated_parasite[:template_source]}' " \
|
|
542
|
+
"with behavioral optimizations: #{generated_parasite[:behavioral_optimizations]&.join(', ') || 'none'}"
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def create_variant_requirements(base_requirements, variant_index)
|
|
546
|
+
variant = base_requirements.dup
|
|
547
|
+
|
|
548
|
+
# Create variations for A/B testing
|
|
549
|
+
case variant_index
|
|
550
|
+
when 0
|
|
551
|
+
variant[:injection_style] = 'natural'
|
|
552
|
+
variant[:token_efficiency] = 'high'
|
|
553
|
+
when 1
|
|
554
|
+
variant[:injection_style] = 'comprehensive'
|
|
555
|
+
variant[:token_efficiency] = 'medium'
|
|
556
|
+
when 2
|
|
557
|
+
variant[:injection_style] = 'minimal'
|
|
558
|
+
variant[:token_efficiency] = 'high'
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
variant
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def create_ab_test_configuration(variants)
|
|
565
|
+
{
|
|
566
|
+
test_type: 'parasite_performance',
|
|
567
|
+
traffic_split: 'equal',
|
|
568
|
+
metrics_to_track: %w[injection_success_rate token_efficiency response_quality],
|
|
569
|
+
test_duration: '7_days',
|
|
570
|
+
variants_count: variants.length
|
|
571
|
+
}
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def handle_generation_error(error, requirements, generation_id)
|
|
575
|
+
{
|
|
576
|
+
success: false,
|
|
577
|
+
error: error.message,
|
|
578
|
+
generation_id: generation_id,
|
|
579
|
+
requirements: requirements,
|
|
580
|
+
timestamp: Time.current.iso8601
|
|
581
|
+
}
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def calculate_keyword_overlap(template_keywords, requirement_keywords)
|
|
585
|
+
return 0.0 if template_keywords.empty? || requirement_keywords.empty?
|
|
586
|
+
|
|
587
|
+
intersection = template_keywords & requirement_keywords
|
|
588
|
+
union = template_keywords | requirement_keywords
|
|
589
|
+
|
|
590
|
+
intersection.length.to_f / union.length
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def calculate_usage_recency(template)
|
|
594
|
+
return 0.0 unless template.respond_to?(:updated_at) && template.updated_at
|
|
595
|
+
|
|
596
|
+
days_since_update = (Time.current - template.updated_at) / 1.day
|
|
597
|
+
Math.exp(-days_since_update / 30.0) # Exponential decay over 30 days
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
def optimize_code_for_behavioral_patterns(code, behavioral_patterns)
|
|
601
|
+
optimized = code.dup
|
|
602
|
+
|
|
603
|
+
# Apply thinking tag optimizations
|
|
604
|
+
if behavioral_patterns['thinking_tags']
|
|
605
|
+
optimized = add_thinking_tag_support(optimized)
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
# Apply response style optimizations
|
|
609
|
+
if behavioral_patterns['response_style']
|
|
610
|
+
optimized = adapt_response_style(optimized, behavioral_patterns['response_style'])
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
optimized
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
def add_thinking_tag_support(code)
|
|
617
|
+
# Add thinking tag detection and processing
|
|
618
|
+
code.gsub(
|
|
619
|
+
'def craft_injection(context, user_message, original_messages)',
|
|
620
|
+
<<~RUBY.strip
|
|
621
|
+
def craft_injection(context, user_message, original_messages)
|
|
622
|
+
# Enhanced with thinking tag support
|
|
623
|
+
RUBY
|
|
624
|
+
)
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def adapt_response_style(code, response_style)
|
|
628
|
+
# Adapt injection style based on response preferences
|
|
629
|
+
code.gsub('style: :natural', "style: :#{response_style}")
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
def get_llm_behavioral_patterns(target_llm)
|
|
633
|
+
@behavioral_analyzer&.get_patterns_for_llm(target_llm) || {}
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
def generate_id
|
|
637
|
+
"upg_#{Time.current.to_i}_#{SecureRandom.hex(4)}"
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
def load_template_registry
|
|
641
|
+
require_relative '../intelligence/template_registry'
|
|
642
|
+
Intelligence::TemplateRegistry.instance
|
|
643
|
+
rescue LoadError => e
|
|
644
|
+
@logger.warn "Template registry not available: #{e.message}"
|
|
645
|
+
nil
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
def load_embedding_service
|
|
649
|
+
require_relative '../core/embedding_patterns'
|
|
650
|
+
Core::EmbeddingPatterns.new
|
|
651
|
+
rescue LoadError => e
|
|
652
|
+
@logger.debug "Embedding service not available: #{e.message}"
|
|
653
|
+
nil
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
def load_behavioral_analyzer
|
|
657
|
+
# Would load from forge if available
|
|
658
|
+
nil
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hokipoki
|
|
4
|
+
class Railtie < ::Rails::Railtie
|
|
5
|
+
railtie_name :hokipoki
|
|
6
|
+
|
|
7
|
+
rake_tasks do
|
|
8
|
+
load 'hokipoki/tasks.rb'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
generators do
|
|
12
|
+
require 'generators/hive_mind/install_generator'
|
|
13
|
+
require 'generators/hive_mind/brain_generator'
|
|
14
|
+
require 'generators/hive_mind/parasite_generator'
|
|
15
|
+
require 'generators/hive_mind/template_generator'
|
|
16
|
+
require 'generators/hive_mind/security_generator'
|
|
17
|
+
require 'generators/hive_mind/forge_generator'
|
|
18
|
+
require 'generators/hive_mind/claude_cli_generator'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
initializer "hokipoki.add_locales" do |app|
|
|
22
|
+
config.i18n.load_path += Dir[Hokipoki::Engine.root.join('config', 'locales', '*.{rb,yml}')]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
initializer "hokipoki.setup_logger" do |app|
|
|
26
|
+
Hokipoki.logger = Rails.logger
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Add console helpers
|
|
30
|
+
console do
|
|
31
|
+
require 'hokipoki/console'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/hokipoki/version.rb
CHANGED