htm 0.0.30 → 0.0.32
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/.irbrc +2 -3
- data/.rubocop.yml +184 -0
- data/CHANGELOG.md +46 -0
- data/README.md +2 -0
- data/Rakefile +93 -12
- data/db/migrate/00008_create_node_relationships.rb +54 -0
- data/db/migrate/00009_fix_node_relationships_column_types.rb +17 -0
- data/db/schema.sql +124 -1
- data/docs/api/database.md +35 -57
- data/docs/api/embedding-service.md +1 -1
- data/docs/api/index.md +26 -15
- data/docs/api/working-memory.md +8 -8
- data/docs/architecture/index.md +5 -7
- data/docs/architecture/overview.md +5 -8
- data/docs/assets/images/htm-architecture-overview.svg +1 -1
- data/docs/assets/images/htm-context-assembly-flow.svg +2 -2
- data/docs/assets/images/htm-layered-architecture.svg +3 -3
- data/docs/assets/images/two-tier-memory-architecture.svg +1 -1
- data/docs/database/README.md +1 -0
- data/docs/database_rake_tasks.md +20 -28
- data/docs/development/contributing.md +5 -5
- data/docs/development/index.md +4 -7
- data/docs/development/schema.md +71 -1
- data/docs/development/setup.md +40 -82
- data/docs/development/testing.md +1 -1
- data/docs/examples/file-loading.md +4 -4
- data/docs/examples/mcp-client.md +1 -1
- data/docs/getting-started/quick-start.md +4 -4
- data/docs/guides/adding-memories.md +14 -1
- data/docs/guides/configuration.md +5 -5
- data/docs/guides/context-assembly.md +4 -4
- data/docs/guides/file-loading.md +12 -12
- data/docs/guides/getting-started.md +2 -2
- data/docs/guides/long-term-memory.md +7 -27
- data/docs/guides/propositions.md +20 -19
- data/docs/guides/recalling-memories.md +5 -5
- data/docs/guides/tags.md +18 -13
- data/docs/multi_framework_support.md +1 -1
- data/docs/robots/hive-mind.md +1 -1
- data/docs/robots/multi-robot.md +2 -2
- data/docs/robots/robot-groups.md +1 -1
- data/docs/robots/two-tier-memory.md +72 -94
- data/docs/setup_local_database.md +8 -54
- data/docs/using_rake_tasks_in_your_app.md +6 -6
- data/examples/01_basic_usage.rb +1 -0
- data/examples/03_custom_llm_configuration.rb +1 -0
- data/examples/04_file_loader_usage.rb +1 -0
- data/examples/05_timeframe_demo.rb +1 -0
- data/examples/06_example_app/app.rb +1 -0
- data/examples/07_cli_app/htm_cli.rb +1 -0
- data/examples/09_mcp_client.rb +1 -0
- data/examples/10_telemetry/demo.rb +1 -0
- data/examples/11_robot_groups/multi_process.rb +1 -0
- data/examples/11_robot_groups/same_process.rb +1 -0
- data/examples/12_rails_app/.envrc +12 -0
- data/examples/12_rails_app/Gemfile +8 -3
- data/examples/12_rails_app/Gemfile.lock +94 -89
- data/examples/12_rails_app/README.md +70 -19
- data/examples/12_rails_app/app/controllers/application_controller.rb +6 -0
- data/examples/12_rails_app/app/controllers/chats_controller.rb +305 -0
- data/examples/12_rails_app/app/controllers/dashboard_controller.rb +3 -0
- data/examples/12_rails_app/app/controllers/files_controller.rb +17 -2
- data/examples/12_rails_app/app/controllers/home_controller.rb +8 -0
- data/examples/12_rails_app/app/controllers/memories_controller.rb +9 -4
- data/examples/12_rails_app/app/controllers/messages_controller.rb +214 -0
- data/examples/12_rails_app/app/controllers/robots_controller.rb +11 -1
- data/examples/12_rails_app/app/controllers/tags_controller.rb +14 -1
- data/examples/12_rails_app/app/javascript/application.js +1 -1
- data/examples/12_rails_app/app/models/application_record.rb +5 -0
- data/examples/12_rails_app/app/models/chat.rb +36 -0
- data/examples/12_rails_app/app/models/message.rb +5 -0
- data/examples/12_rails_app/app/models/model.rb +5 -0
- data/examples/12_rails_app/app/models/tool_call.rb +5 -0
- data/examples/12_rails_app/app/views/chats/index.html.erb +61 -0
- data/examples/12_rails_app/app/views/chats/show.html.erb +213 -0
- data/examples/12_rails_app/app/views/dashboard/index.html.erb +3 -0
- data/examples/12_rails_app/app/views/files/index.html.erb +10 -5
- data/examples/12_rails_app/app/views/files/new.html.erb +4 -2
- data/examples/12_rails_app/app/views/files/show.html.erb +19 -3
- data/examples/12_rails_app/app/views/home/index.html.erb +45 -0
- data/examples/12_rails_app/app/views/layouts/application.html.erb +20 -18
- data/examples/12_rails_app/app/views/memories/_memory_card.html.erb +1 -1
- data/examples/12_rails_app/app/views/memories/deleted.html.erb +3 -1
- data/examples/12_rails_app/app/views/memories/edit.html.erb +2 -0
- data/examples/12_rails_app/app/views/memories/index.html.erb +2 -0
- data/examples/12_rails_app/app/views/memories/new.html.erb +2 -0
- data/examples/12_rails_app/app/views/memories/show.html.erb +4 -2
- data/examples/12_rails_app/app/views/messages/_message.html.erb +20 -0
- data/examples/12_rails_app/app/views/robots/index.html.erb +2 -0
- data/examples/12_rails_app/app/views/robots/new.html.erb +2 -0
- data/examples/12_rails_app/app/views/robots/show.html.erb +2 -0
- data/examples/12_rails_app/app/views/search/index.html.erb +59 -8
- data/examples/12_rails_app/app/views/shared/_navbar.html.erb +75 -29
- data/examples/12_rails_app/app/views/tags/index.html.erb +2 -0
- data/examples/12_rails_app/app/views/tags/show.html.erb +3 -1
- data/examples/12_rails_app/config/application.rb +1 -1
- data/examples/12_rails_app/config/database.yml +9 -5
- data/examples/12_rails_app/config/importmap.rb +1 -1
- data/examples/12_rails_app/config/initializers/htm.rb +9 -2
- data/examples/12_rails_app/config/initializers/ruby_llm.rb +33 -0
- data/examples/12_rails_app/config/routes.rb +39 -23
- data/examples/12_rails_app/db/migrate/20250124000001_create_ruby_llm_tables.rb +34 -0
- data/examples/12_rails_app/db/migrate/20250124000002_create_models_table.rb +28 -0
- data/examples/12_rails_app/db/schema.rb +67 -0
- data/examples/examples_helper.rb +25 -0
- data/lib/htm/circuit_breaker.rb +5 -6
- data/lib/htm/config/builder.rb +12 -12
- data/lib/htm/config/database.rb +21 -27
- data/lib/htm/config/defaults.yml +25 -13
- data/lib/htm/config/validator.rb +12 -18
- data/lib/htm/config.rb +93 -173
- data/lib/htm/database.rb +193 -199
- data/lib/htm/embedding_service.rb +4 -9
- data/lib/htm/integrations/sinatra.rb +7 -7
- data/lib/htm/job_adapter.rb +14 -21
- data/lib/htm/jobs/generate_embedding_job.rb +28 -44
- data/lib/htm/jobs/generate_propositions_job.rb +29 -55
- data/lib/htm/jobs/generate_relationships_job.rb +137 -0
- data/lib/htm/jobs/generate_tags_job.rb +45 -67
- data/lib/htm/loaders/markdown_loader.rb +65 -112
- data/lib/htm/long_term_memory/fulltext_search.rb +1 -1
- data/lib/htm/long_term_memory/hybrid_search.rb +300 -128
- data/lib/htm/long_term_memory/node_operations.rb +2 -2
- data/lib/htm/long_term_memory/relevance_scorer.rb +100 -68
- data/lib/htm/long_term_memory/tag_operations.rb +87 -120
- data/lib/htm/long_term_memory/vector_search.rb +1 -1
- data/lib/htm/long_term_memory.rb +2 -1
- data/lib/htm/mcp/cli.rb +59 -58
- data/lib/htm/mcp/server.rb +5 -6
- data/lib/htm/mcp/tools.rb +30 -36
- data/lib/htm/migration.rb +10 -10
- data/lib/htm/models/node.rb +2 -3
- data/lib/htm/models/node_relationship.rb +72 -0
- data/lib/htm/models/node_tag.rb +2 -2
- data/lib/htm/models/robot_node.rb +2 -2
- data/lib/htm/models/tag.rb +41 -28
- data/lib/htm/observability.rb +45 -51
- data/lib/htm/proposition_service.rb +3 -7
- data/lib/htm/query_cache.rb +13 -15
- data/lib/htm/railtie.rb +1 -2
- data/lib/htm/robot_group.rb +9 -9
- data/lib/htm/sequel_config.rb +1 -0
- data/lib/htm/sql_builder.rb +1 -1
- data/lib/htm/tag_service.rb +2 -6
- data/lib/htm/timeframe.rb +4 -5
- data/lib/htm/timeframe_extractor.rb +42 -83
- data/lib/htm/version.rb +1 -1
- data/lib/htm/workflows/remember_workflow.rb +112 -115
- data/lib/htm/working_memory.rb +21 -26
- data/lib/htm.rb +103 -116
- data/lib/tasks/db.rake +0 -2
- data/lib/tasks/doc.rake +14 -13
- data/lib/tasks/files.rake +5 -12
- data/lib/tasks/htm.rake +70 -71
- data/lib/tasks/jobs.rake +41 -47
- data/lib/tasks/tags.rake +3 -8
- metadata +28 -106
- data/lib/htm/config/section.rb +0 -74
- data/lib/htm/loaders/defaults_loader.rb +0 -166
- data/lib/htm/loaders/xdg_config_loader.rb +0 -116
data/lib/htm/config.rb
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
3
|
+
require 'myway_config'
|
|
4
4
|
require 'logger'
|
|
5
|
-
require 'yaml'
|
|
6
5
|
|
|
7
6
|
# Define Config class first to establish superclass
|
|
8
7
|
class HTM
|
|
9
|
-
class Config <
|
|
8
|
+
class Config < MywayConfig::Base
|
|
10
9
|
end
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
require_relative 'config/section'
|
|
14
12
|
require_relative 'config/validator'
|
|
15
13
|
require_relative 'config/database'
|
|
16
14
|
require_relative 'config/builder'
|
|
@@ -61,35 +59,11 @@ class HTM
|
|
|
61
59
|
|
|
62
60
|
config_name :htm
|
|
63
61
|
env_prefix :htm
|
|
62
|
+
defaults_path File.expand_path('config/defaults.yml', __dir__)
|
|
64
63
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# Path to bundled defaults file (defines both schema and default values)
|
|
70
|
-
DEFAULTS_PATH = File.expand_path('config/defaults.yml', __dir__).freeze
|
|
71
|
-
|
|
72
|
-
# Load schema from defaults.yml at class definition time
|
|
73
|
-
begin
|
|
74
|
-
defaults_content = File.read(DEFAULTS_PATH)
|
|
75
|
-
raw_yaml = YAML.safe_load(
|
|
76
|
-
defaults_content,
|
|
77
|
-
permitted_classes: [Symbol],
|
|
78
|
-
symbolize_names: true,
|
|
79
|
-
aliases: true
|
|
80
|
-
) || {}
|
|
81
|
-
SCHEMA = raw_yaml[:defaults] || {}
|
|
82
|
-
rescue StandardError => e
|
|
83
|
-
warn "HTM: Could not load schema from #{DEFAULTS_PATH}: #{e.message}"
|
|
84
|
-
SCHEMA = {}
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Nested section attributes (defined as hashes, converted to ConfigSection)
|
|
88
|
-
attr_config :database, :service, :embedding, :tag, :proposition,
|
|
89
|
-
:chunking, :circuit_breaker, :relevance, :job, :providers
|
|
90
|
-
|
|
91
|
-
# Top-level scalar attributes
|
|
92
|
-
attr_config :week_start, :connection_timeout, :telemetry_enabled, :log_level
|
|
64
|
+
# Auto-configure attributes and coercions from defaults.yml schema
|
|
65
|
+
# This replaces manual attr_config and coerce_types declarations
|
|
66
|
+
auto_configure!
|
|
93
67
|
|
|
94
68
|
# Custom environment detection: HTM_ENV > RAILS_ENV > RACK_ENV > 'development'
|
|
95
69
|
class << self
|
|
@@ -102,60 +76,6 @@ class HTM
|
|
|
102
76
|
end
|
|
103
77
|
end
|
|
104
78
|
|
|
105
|
-
# ==========================================================================
|
|
106
|
-
# Type Coercion
|
|
107
|
-
# ==========================================================================
|
|
108
|
-
|
|
109
|
-
TO_SYMBOL = ->(v) { v.nil? ? nil : v.to_s.to_sym }
|
|
110
|
-
|
|
111
|
-
# Create a coercion that merges incoming value with SCHEMA defaults for a section.
|
|
112
|
-
# This ensures env vars like HTM_DATABASE__URL don't lose other defaults.
|
|
113
|
-
def self.config_section_with_defaults(section_key)
|
|
114
|
-
defaults = SCHEMA[section_key] || {}
|
|
115
|
-
->(v) {
|
|
116
|
-
return v if v.is_a?(ConfigSection)
|
|
117
|
-
incoming = v || {}
|
|
118
|
-
# Deep merge: defaults first, then overlay incoming values
|
|
119
|
-
merged = deep_merge_hashes(defaults.dup, incoming)
|
|
120
|
-
ConfigSection.new(merged)
|
|
121
|
-
}
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Deep merge helper for coercion
|
|
125
|
-
def self.deep_merge_hashes(base, overlay)
|
|
126
|
-
base.merge(overlay) do |_key, old_val, new_val|
|
|
127
|
-
if old_val.is_a?(Hash) && new_val.is_a?(Hash)
|
|
128
|
-
deep_merge_hashes(old_val, new_val)
|
|
129
|
-
else
|
|
130
|
-
new_val.nil? ? old_val : new_val
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
coerce_types(
|
|
136
|
-
# Nested sections -> ConfigSection objects (with SCHEMA defaults merged)
|
|
137
|
-
database: config_section_with_defaults(:database),
|
|
138
|
-
service: config_section_with_defaults(:service),
|
|
139
|
-
embedding: config_section_with_defaults(:embedding),
|
|
140
|
-
tag: config_section_with_defaults(:tag),
|
|
141
|
-
proposition: config_section_with_defaults(:proposition),
|
|
142
|
-
chunking: config_section_with_defaults(:chunking),
|
|
143
|
-
circuit_breaker: config_section_with_defaults(:circuit_breaker),
|
|
144
|
-
relevance: config_section_with_defaults(:relevance),
|
|
145
|
-
job: config_section_with_defaults(:job),
|
|
146
|
-
providers: config_section_with_defaults(:providers),
|
|
147
|
-
|
|
148
|
-
# Top-level symbols
|
|
149
|
-
week_start: TO_SYMBOL,
|
|
150
|
-
log_level: TO_SYMBOL,
|
|
151
|
-
|
|
152
|
-
# Top-level integers
|
|
153
|
-
connection_timeout: :integer,
|
|
154
|
-
|
|
155
|
-
# Top-level booleans
|
|
156
|
-
telemetry_enabled: :boolean
|
|
157
|
-
)
|
|
158
|
-
|
|
159
79
|
# ==========================================================================
|
|
160
80
|
# Validation
|
|
161
81
|
# ==========================================================================
|
|
@@ -179,8 +99,7 @@ class HTM
|
|
|
179
99
|
# Callable Accessors (not loaded from config sources)
|
|
180
100
|
# ==========================================================================
|
|
181
101
|
|
|
182
|
-
attr_accessor :embedding_generator, :tag_extractor, :proposition_extractor
|
|
183
|
-
attr_accessor :token_counter, :logger
|
|
102
|
+
attr_accessor :embedding_generator, :tag_extractor, :proposition_extractor, :token_counter, :logger
|
|
184
103
|
|
|
185
104
|
# ==========================================================================
|
|
186
105
|
# Instance Methods
|
|
@@ -256,11 +175,11 @@ class HTM
|
|
|
256
175
|
|
|
257
176
|
# Chunking convenience accessors
|
|
258
177
|
def chunk_size
|
|
259
|
-
chunking.
|
|
178
|
+
chunking.chunk_size.to_i
|
|
260
179
|
end
|
|
261
180
|
|
|
262
181
|
def chunk_overlap
|
|
263
|
-
chunking.
|
|
182
|
+
chunking.chunk_overlap.to_i
|
|
264
183
|
end
|
|
265
184
|
|
|
266
185
|
# Circuit breaker convenience accessors
|
|
@@ -375,17 +294,8 @@ class HTM
|
|
|
375
294
|
# Environment Helpers
|
|
376
295
|
# ==========================================================================
|
|
377
296
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
def development?
|
|
383
|
-
self.class.env == 'development'
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
def production?
|
|
387
|
-
self.class.env == 'production'
|
|
388
|
-
end
|
|
297
|
+
# NOTE: test?, development?, production? are auto-generated by MywayConfig::Base
|
|
298
|
+
# based on environment keys in defaults.yml
|
|
389
299
|
|
|
390
300
|
def environment
|
|
391
301
|
self.class.env
|
|
@@ -396,17 +306,16 @@ class HTM
|
|
|
396
306
|
# ==========================================================================
|
|
397
307
|
|
|
398
308
|
# Returns list of valid environment names from bundled defaults
|
|
309
|
+
# Inherited from MywayConfig::Base - delegates to DefaultsLoader
|
|
399
310
|
#
|
|
400
311
|
# @return [Array<Symbol>] valid environment names (e.g., [:development, :production, :test])
|
|
401
|
-
|
|
402
|
-
HTM::Loaders::DefaultsLoader.valid_environments
|
|
403
|
-
end
|
|
312
|
+
# Note: valid_environments is inherited from MywayConfig::Base
|
|
404
313
|
|
|
405
314
|
# Check if current environment is valid (defined in config)
|
|
406
315
|
#
|
|
407
316
|
# @return [Boolean] true if environment has a config section
|
|
408
317
|
def self.valid_environment?
|
|
409
|
-
|
|
318
|
+
MywayConfig::Loaders::DefaultsLoader.valid_environment?(config_name, env)
|
|
410
319
|
end
|
|
411
320
|
|
|
412
321
|
# Validate that the current environment is configured
|
|
@@ -415,13 +324,13 @@ class HTM
|
|
|
415
324
|
# @return [true] if environment is valid
|
|
416
325
|
def self.validate_environment!
|
|
417
326
|
current = env
|
|
418
|
-
return true if
|
|
327
|
+
return true if valid_environment?
|
|
419
328
|
|
|
420
|
-
valid = valid_environments.
|
|
329
|
+
valid = valid_environments.join(', ')
|
|
421
330
|
raise HTM::ConfigurationError,
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
331
|
+
"Invalid environment '#{current}'. " \
|
|
332
|
+
"Valid environments are: #{valid}. " \
|
|
333
|
+
"Set HTM_ENV to a valid environment or add a '#{current}:' section to your config."
|
|
425
334
|
end
|
|
426
335
|
|
|
427
336
|
# Instance method delegates
|
|
@@ -438,21 +347,21 @@ class HTM
|
|
|
438
347
|
# ==========================================================================
|
|
439
348
|
|
|
440
349
|
def self.xdg_config_paths
|
|
441
|
-
|
|
350
|
+
MywayConfig::Loaders::XdgConfigLoader.config_paths(config_name)
|
|
442
351
|
end
|
|
443
352
|
|
|
444
353
|
def self.xdg_config_file
|
|
445
|
-
xdg_home = ENV
|
|
354
|
+
xdg_home = ENV.fetch('XDG_CONFIG_HOME', nil)
|
|
446
355
|
base = if xdg_home && !xdg_home.empty?
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
356
|
+
xdg_home
|
|
357
|
+
else
|
|
358
|
+
File.expand_path('~/.config')
|
|
359
|
+
end
|
|
451
360
|
File.join(base, 'htm', 'htm.yml')
|
|
452
361
|
end
|
|
453
362
|
|
|
454
363
|
def self.active_xdg_config_file
|
|
455
|
-
|
|
364
|
+
MywayConfig::Loaders::XdgConfigLoader.find_config_file(config_name)
|
|
456
365
|
end
|
|
457
366
|
|
|
458
367
|
# ==========================================================================
|
|
@@ -468,42 +377,8 @@ class HTM
|
|
|
468
377
|
|
|
469
378
|
def configure_ruby_llm(provider = nil)
|
|
470
379
|
require 'ruby_llm'
|
|
471
|
-
|
|
472
380
|
provider ||= embedding_provider
|
|
473
|
-
|
|
474
|
-
RubyLLM.configure do |config|
|
|
475
|
-
case provider
|
|
476
|
-
when :openai
|
|
477
|
-
config.openai_api_key = openai_api_key if openai_api_key
|
|
478
|
-
config.openai_organization = openai_organization if openai_organization && config.respond_to?(:openai_organization=)
|
|
479
|
-
config.openai_project = openai_project if openai_project && config.respond_to?(:openai_project=)
|
|
480
|
-
when :anthropic
|
|
481
|
-
config.anthropic_api_key = anthropic_api_key if anthropic_api_key
|
|
482
|
-
when :gemini
|
|
483
|
-
config.gemini_api_key = gemini_api_key if gemini_api_key
|
|
484
|
-
when :azure
|
|
485
|
-
config.azure_api_key = azure_api_key if azure_api_key && config.respond_to?(:azure_api_key=)
|
|
486
|
-
config.azure_endpoint = azure_endpoint if azure_endpoint && config.respond_to?(:azure_endpoint=)
|
|
487
|
-
config.azure_api_version = azure_api_version if azure_api_version && config.respond_to?(:azure_api_version=)
|
|
488
|
-
when :ollama
|
|
489
|
-
ollama_api_base = if ollama_url.end_with?('/v1') || ollama_url.end_with?('/v1/')
|
|
490
|
-
ollama_url.sub(%r{/+$}, '')
|
|
491
|
-
else
|
|
492
|
-
"#{ollama_url.sub(%r{/+$}, '')}/v1"
|
|
493
|
-
end
|
|
494
|
-
config.ollama_api_base = ollama_api_base
|
|
495
|
-
when :huggingface
|
|
496
|
-
config.huggingface_api_key = huggingface_api_key if huggingface_api_key && config.respond_to?(:huggingface_api_key=)
|
|
497
|
-
when :openrouter
|
|
498
|
-
config.openrouter_api_key = openrouter_api_key if openrouter_api_key && config.respond_to?(:openrouter_api_key=)
|
|
499
|
-
when :bedrock
|
|
500
|
-
config.bedrock_api_key = bedrock_access_key if bedrock_access_key && config.respond_to?(:bedrock_api_key=)
|
|
501
|
-
config.bedrock_secret_key = bedrock_secret_key if bedrock_secret_key && config.respond_to?(:bedrock_secret_key=)
|
|
502
|
-
config.bedrock_region = bedrock_region if bedrock_region && config.respond_to?(:bedrock_region=)
|
|
503
|
-
when :deepseek
|
|
504
|
-
config.deepseek_api_key = deepseek_api_key if deepseek_api_key && config.respond_to?(:deepseek_api_key=)
|
|
505
|
-
end
|
|
506
|
-
end
|
|
381
|
+
RubyLLM.configure { |config| apply_provider_config(config, provider) }
|
|
507
382
|
end
|
|
508
383
|
|
|
509
384
|
def refresh_ollama_models!
|
|
@@ -543,26 +418,73 @@ class HTM
|
|
|
543
418
|
# ==========================================================================
|
|
544
419
|
|
|
545
420
|
def coerce_nested_types
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
value = providers[provider]
|
|
550
|
-
providers[provider] = ConfigSection.new(value) if value.is_a?(Hash)
|
|
551
|
-
end
|
|
552
|
-
end
|
|
421
|
+
coerce_provider_sections
|
|
422
|
+
coerce_database_integers
|
|
423
|
+
end
|
|
553
424
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
database.pool_size = database.pool_size.to_i
|
|
560
|
-
end
|
|
561
|
-
if database&.timeout && !database.timeout.is_a?(Integer)
|
|
562
|
-
database.timeout = database.timeout.to_i
|
|
425
|
+
def coerce_provider_sections
|
|
426
|
+
return unless providers.is_a?(MywayConfig::ConfigSection)
|
|
427
|
+
%i[openai anthropic gemini azure ollama huggingface openrouter bedrock deepseek].each do |provider|
|
|
428
|
+
value = providers[provider]
|
|
429
|
+
providers[provider] = MywayConfig::ConfigSection.new(value) if value.is_a?(Hash)
|
|
563
430
|
end
|
|
564
431
|
end
|
|
565
432
|
|
|
433
|
+
def coerce_database_integers
|
|
434
|
+
return unless database
|
|
435
|
+
database.port = database.port.to_i if database.port && !database.port.is_a?(Integer)
|
|
436
|
+
database.pool_size = database.pool_size.to_i if database.pool_size && !database.pool_size.is_a?(Integer)
|
|
437
|
+
database.timeout = database.timeout.to_i if database.timeout && !database.timeout.is_a?(Integer)
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def apply_provider_config(config, provider)
|
|
441
|
+
handler = :"apply_#{provider}_provider_config"
|
|
442
|
+
send(handler, config) if respond_to?(handler, true)
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def apply_openai_provider_config(config)
|
|
446
|
+
config.openai_api_key = openai_api_key if openai_api_key
|
|
447
|
+
config.openai_organization = openai_organization if openai_organization && config.respond_to?(:openai_organization=)
|
|
448
|
+
config.openai_project = openai_project if openai_project && config.respond_to?(:openai_project=)
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def apply_anthropic_provider_config(config)
|
|
452
|
+
config.anthropic_api_key = anthropic_api_key if anthropic_api_key
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def apply_gemini_provider_config(config)
|
|
456
|
+
config.gemini_api_key = gemini_api_key if gemini_api_key
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def apply_azure_provider_config(config)
|
|
460
|
+
config.azure_api_key = azure_api_key if azure_api_key && config.respond_to?(:azure_api_key=)
|
|
461
|
+
config.azure_endpoint = azure_endpoint if azure_endpoint && config.respond_to?(:azure_endpoint=)
|
|
462
|
+
config.azure_api_version = azure_api_version if azure_api_version && config.respond_to?(:azure_api_version=)
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def apply_ollama_provider_config(config)
|
|
466
|
+
base = ollama_url.sub(%r{/+$}, '')
|
|
467
|
+
config.ollama_api_base = base.end_with?('/v1') ? base : "#{base}/v1"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
def apply_huggingface_provider_config(config)
|
|
471
|
+
config.huggingface_api_key = huggingface_api_key if huggingface_api_key && config.respond_to?(:huggingface_api_key=)
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def apply_openrouter_provider_config(config)
|
|
475
|
+
config.openrouter_api_key = openrouter_api_key if openrouter_api_key && config.respond_to?(:openrouter_api_key=)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def apply_bedrock_provider_config(config)
|
|
479
|
+
config.bedrock_api_key = bedrock_access_key if bedrock_access_key && config.respond_to?(:bedrock_api_key=)
|
|
480
|
+
config.bedrock_secret_key = bedrock_secret_key if bedrock_secret_key && config.respond_to?(:bedrock_secret_key=)
|
|
481
|
+
config.bedrock_region = bedrock_region if bedrock_region && config.respond_to?(:bedrock_region=)
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def apply_deepseek_provider_config(config)
|
|
485
|
+
config.deepseek_api_key = deepseek_api_key if deepseek_api_key && config.respond_to?(:deepseek_api_key=)
|
|
486
|
+
end
|
|
487
|
+
|
|
566
488
|
# ==========================================================================
|
|
567
489
|
# Setup Defaults Callback
|
|
568
490
|
# ==========================================================================
|
|
@@ -573,7 +495,7 @@ class HTM
|
|
|
573
495
|
@embedding_generator ||= build_default_embedding_generator
|
|
574
496
|
@tag_extractor ||= build_default_tag_extractor
|
|
575
497
|
@proposition_extractor ||= build_default_proposition_extractor
|
|
576
|
-
@token_counter
|
|
498
|
+
@token_counter = build_default_token_counter if @token_counter.nil?
|
|
577
499
|
end
|
|
578
500
|
|
|
579
501
|
def detect_job_backend
|
|
@@ -586,7 +508,5 @@ class HTM
|
|
|
586
508
|
end
|
|
587
509
|
end
|
|
588
510
|
|
|
589
|
-
#
|
|
590
|
-
#
|
|
591
|
-
require_relative 'loaders/defaults_loader'
|
|
592
|
-
require_relative 'loaders/xdg_config_loader'
|
|
511
|
+
# myway_config provides DefaultsLoader and XdgConfigLoader automatically
|
|
512
|
+
# Loaders are registered when MywayConfig.setup! is called (happens on require)
|