htm 0.0.18 → 0.0.30

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.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +119 -1
  3. data/README.md +12 -0
  4. data/Rakefile +104 -18
  5. data/db/migrate/00001_enable_extensions.rb +9 -5
  6. data/db/migrate/00002_create_robots.rb +18 -6
  7. data/db/migrate/00003_create_file_sources.rb +30 -17
  8. data/db/migrate/00004_create_nodes.rb +60 -48
  9. data/db/migrate/00005_create_tags.rb +24 -12
  10. data/db/migrate/00006_create_node_tags.rb +28 -13
  11. data/db/migrate/00007_create_robot_nodes.rb +40 -26
  12. data/db/schema.sql +17 -1
  13. data/db/seeds.rb +34 -34
  14. data/docs/api/embedding-service.md +140 -110
  15. data/docs/api/yard/HTM/ActiveRecordConfig.md +6 -0
  16. data/docs/api/yard/HTM/Config.md +173 -0
  17. data/docs/api/yard/HTM/ConfigSection.md +28 -0
  18. data/docs/api/yard/HTM/Database.md +1 -1
  19. data/docs/api/yard/HTM/Railtie.md +2 -2
  20. data/docs/api/yard/HTM.md +0 -57
  21. data/docs/api/yard/index.csv +76 -61
  22. data/docs/api/yard-reference.md +2 -1
  23. data/docs/architecture/adrs/003-ollama-embeddings.md +45 -36
  24. data/docs/architecture/adrs/004-hive-mind.md +1 -1
  25. data/docs/architecture/adrs/008-robot-identification.md +1 -1
  26. data/docs/architecture/index.md +11 -9
  27. data/docs/architecture/overview.md +11 -7
  28. data/docs/assets/images/balanced-strategy-decay.svg +41 -0
  29. data/docs/assets/images/class-hierarchy.svg +1 -1
  30. data/docs/assets/images/eviction-priority.svg +43 -0
  31. data/docs/assets/images/exception-hierarchy.svg +2 -2
  32. data/docs/assets/images/hive-mind-shared-memory.svg +52 -0
  33. data/docs/assets/images/htm-architecture-overview.svg +3 -3
  34. data/docs/assets/images/htm-core-components.svg +4 -4
  35. data/docs/assets/images/htm-layered-architecture.svg +1 -1
  36. data/docs/assets/images/htm-memory-addition-flow.svg +2 -2
  37. data/docs/assets/images/htm-memory-recall-flow.svg +2 -2
  38. data/docs/assets/images/memory-topology.svg +53 -0
  39. data/docs/assets/images/two-tier-memory-architecture.svg +55 -0
  40. data/docs/database/naming-convention.md +244 -0
  41. data/docs/database_rake_tasks.md +31 -0
  42. data/docs/development/rake-tasks.md +80 -35
  43. data/docs/development/setup.md +76 -44
  44. data/docs/examples/basic-usage.md +133 -0
  45. data/docs/examples/config-files.md +170 -0
  46. data/docs/examples/file-loading.md +208 -0
  47. data/docs/examples/index.md +116 -0
  48. data/docs/examples/llm-configuration.md +168 -0
  49. data/docs/examples/mcp-client.md +172 -0
  50. data/docs/examples/rails-integration.md +173 -0
  51. data/docs/examples/robot-groups.md +210 -0
  52. data/docs/examples/sinatra-integration.md +218 -0
  53. data/docs/examples/standalone-app.md +216 -0
  54. data/docs/examples/telemetry.md +224 -0
  55. data/docs/examples/timeframes.md +143 -0
  56. data/docs/getting-started/installation.md +97 -40
  57. data/docs/getting-started/quick-start.md +28 -11
  58. data/docs/guides/configuration.md +515 -0
  59. data/docs/guides/file-loading.md +322 -0
  60. data/docs/guides/getting-started.md +40 -9
  61. data/docs/guides/index.md +3 -3
  62. data/docs/guides/mcp-server.md +100 -13
  63. data/docs/guides/propositions.md +264 -0
  64. data/docs/guides/recalling-memories.md +4 -4
  65. data/docs/guides/search-strategies.md +3 -3
  66. data/docs/guides/tags.md +318 -0
  67. data/docs/guides/telemetry.md +229 -0
  68. data/docs/index.md +8 -16
  69. data/docs/{architecture → robots}/hive-mind.md +8 -111
  70. data/docs/robots/index.md +73 -0
  71. data/docs/{guides → robots}/multi-robot.md +3 -3
  72. data/docs/{guides → robots}/robot-groups.md +8 -7
  73. data/docs/{architecture → robots}/two-tier-memory.md +13 -149
  74. data/docs/robots/why-robots.md +85 -0
  75. data/examples/.envrc +6 -0
  76. data/examples/.gitignore +2 -0
  77. data/examples/00_create_examples_db.rb +94 -0
  78. data/examples/{basic_usage.rb → 01_basic_usage.rb} +12 -16
  79. data/examples/{custom_llm_configuration.rb → 03_custom_llm_configuration.rb} +13 -3
  80. data/examples/{file_loader_usage.rb → 04_file_loader_usage.rb} +11 -14
  81. data/examples/{timeframe_demo.rb → 05_timeframe_demo.rb} +10 -3
  82. data/examples/{example_app → 06_example_app}/app.rb +15 -15
  83. data/examples/{cli_app → 07_cli_app}/htm_cli.rb +15 -22
  84. data/examples/08_sinatra_app/Gemfile.lock +241 -0
  85. data/examples/{sinatra_app → 08_sinatra_app}/app.rb +19 -18
  86. data/examples/{mcp_client.rb → 09_mcp_client.rb} +5 -8
  87. data/examples/{telemetry → 10_telemetry}/SETUP_README.md +1 -1
  88. data/examples/{telemetry → 10_telemetry}/demo.rb +14 -10
  89. data/examples/11_robot_groups/README.md +335 -0
  90. data/examples/{robot_groups → 11_robot_groups/lib}/robot_worker.rb +17 -3
  91. data/examples/{robot_groups → 11_robot_groups}/multi_process.rb +9 -9
  92. data/examples/{robot_groups → 11_robot_groups}/same_process.rb +9 -12
  93. data/examples/{rails_app → 12_rails_app}/Gemfile +3 -0
  94. data/examples/{rails_app → 12_rails_app}/Gemfile.lock +87 -58
  95. data/examples/{rails_app → 12_rails_app}/app/controllers/dashboard_controller.rb +10 -6
  96. data/examples/{rails_app → 12_rails_app}/app/controllers/files_controller.rb +5 -5
  97. data/examples/{rails_app → 12_rails_app}/app/controllers/memories_controller.rb +11 -7
  98. data/examples/{rails_app → 12_rails_app}/app/controllers/robots_controller.rb +8 -8
  99. data/examples/12_rails_app/app/controllers/tags_controller.rb +36 -0
  100. data/examples/{rails_app → 12_rails_app}/app/views/dashboard/index.html.erb +2 -2
  101. data/examples/{rails_app → 12_rails_app}/app/views/files/new.html.erb +5 -2
  102. data/examples/{rails_app → 12_rails_app}/app/views/memories/_memory_card.html.erb +3 -3
  103. data/examples/{rails_app → 12_rails_app}/app/views/memories/deleted.html.erb +3 -3
  104. data/examples/{rails_app → 12_rails_app}/app/views/memories/edit.html.erb +3 -3
  105. data/examples/{rails_app → 12_rails_app}/app/views/memories/show.html.erb +4 -4
  106. data/examples/{rails_app → 12_rails_app}/app/views/robots/index.html.erb +2 -2
  107. data/examples/{rails_app → 12_rails_app}/app/views/robots/show.html.erb +4 -4
  108. data/examples/{rails_app → 12_rails_app}/app/views/search/index.html.erb +1 -1
  109. data/examples/{rails_app → 12_rails_app}/app/views/tags/index.html.erb +2 -2
  110. data/examples/{rails_app → 12_rails_app}/app/views/tags/show.html.erb +1 -1
  111. data/examples/12_rails_app/config/initializers/htm.rb +7 -0
  112. data/examples/12_rails_app/config/initializers/rack.rb +5 -0
  113. data/examples/README.md +230 -211
  114. data/examples/examples_helper.rb +138 -0
  115. data/lib/htm/config/builder.rb +167 -0
  116. data/lib/htm/config/database.rb +317 -0
  117. data/lib/htm/config/defaults.yml +41 -13
  118. data/lib/htm/config/section.rb +74 -0
  119. data/lib/htm/config/validator.rb +83 -0
  120. data/lib/htm/config.rb +65 -361
  121. data/lib/htm/database.rb +85 -127
  122. data/lib/htm/errors.rb +14 -0
  123. data/lib/htm/integrations/sinatra.rb +13 -44
  124. data/lib/htm/job_adapter.rb +75 -1
  125. data/lib/htm/jobs/generate_embedding_job.rb +3 -4
  126. data/lib/htm/jobs/generate_propositions_job.rb +4 -5
  127. data/lib/htm/jobs/generate_tags_job.rb +16 -15
  128. data/lib/htm/loaders/defaults_loader.rb +23 -0
  129. data/lib/htm/loaders/markdown_loader.rb +17 -15
  130. data/lib/htm/loaders/xdg_config_loader.rb +9 -9
  131. data/lib/htm/long_term_memory/fulltext_search.rb +14 -14
  132. data/lib/htm/long_term_memory/hybrid_search.rb +396 -229
  133. data/lib/htm/long_term_memory/node_operations.rb +24 -23
  134. data/lib/htm/long_term_memory/relevance_scorer.rb +23 -20
  135. data/lib/htm/long_term_memory/robot_operations.rb +4 -4
  136. data/lib/htm/long_term_memory/tag_operations.rb +91 -77
  137. data/lib/htm/long_term_memory/vector_search.rb +4 -5
  138. data/lib/htm/long_term_memory.rb +13 -13
  139. data/lib/htm/mcp/cli.rb +115 -8
  140. data/lib/htm/mcp/resources.rb +4 -3
  141. data/lib/htm/mcp/server.rb +5 -4
  142. data/lib/htm/mcp/tools.rb +37 -28
  143. data/lib/htm/migration.rb +72 -0
  144. data/lib/htm/models/file_source.rb +52 -31
  145. data/lib/htm/models/node.rb +224 -108
  146. data/lib/htm/models/node_tag.rb +49 -28
  147. data/lib/htm/models/robot.rb +38 -27
  148. data/lib/htm/models/robot_node.rb +63 -35
  149. data/lib/htm/models/tag.rb +126 -123
  150. data/lib/htm/observability.rb +45 -41
  151. data/lib/htm/proposition_service.rb +76 -7
  152. data/lib/htm/railtie.rb +2 -2
  153. data/lib/htm/robot_group.rb +30 -18
  154. data/lib/htm/sequel_config.rb +215 -0
  155. data/lib/htm/sql_builder.rb +14 -16
  156. data/lib/htm/tag_service.rb +78 -0
  157. data/lib/htm/tasks.rb +3 -0
  158. data/lib/htm/version.rb +1 -1
  159. data/lib/htm/workflows/remember_workflow.rb +213 -0
  160. data/lib/htm.rb +27 -22
  161. data/lib/tasks/db.rake +0 -2
  162. data/lib/tasks/doc.rake +2 -2
  163. data/lib/tasks/files.rake +11 -18
  164. data/lib/tasks/htm.rake +190 -62
  165. data/lib/tasks/jobs.rake +179 -54
  166. data/lib/tasks/tags.rake +8 -13
  167. data/mkdocs.yml +33 -8
  168. data/scripts/backfill_parent_tags.rb +376 -0
  169. data/scripts/normalize_plural_tags.rb +335 -0
  170. metadata +168 -86
  171. data/docs/api/yard/HTM/Configuration.md +0 -240
  172. data/docs/telemetry.md +0 -391
  173. data/examples/rails_app/app/controllers/tags_controller.rb +0 -30
  174. data/examples/sinatra_app/Gemfile.lock +0 -166
  175. data/lib/htm/active_record_config.rb +0 -104
  176. /data/examples/{config_file_example → 02_config_file_example}/README.md +0 -0
  177. /data/examples/{config_file_example → 02_config_file_example}/config/htm.local.yml +0 -0
  178. /data/examples/{config_file_example → 02_config_file_example}/custom_config.yml +0 -0
  179. /data/examples/{config_file_example → 02_config_file_example}/show_config.rb +0 -0
  180. /data/examples/{example_app → 06_example_app}/Rakefile +0 -0
  181. /data/examples/{cli_app → 07_cli_app}/README.md +0 -0
  182. /data/examples/{sinatra_app → 08_sinatra_app}/Gemfile +0 -0
  183. /data/examples/{telemetry → 10_telemetry}/README.md +0 -0
  184. /data/examples/{telemetry → 10_telemetry}/grafana/dashboards/htm-metrics.json +0 -0
  185. /data/examples/{rails_app → 12_rails_app}/.gitignore +0 -0
  186. /data/examples/{rails_app → 12_rails_app}/Procfile.dev +0 -0
  187. /data/examples/{rails_app → 12_rails_app}/README.md +0 -0
  188. /data/examples/{rails_app → 12_rails_app}/Rakefile +0 -0
  189. /data/examples/{rails_app → 12_rails_app}/app/assets/stylesheets/application.css +0 -0
  190. /data/examples/{rails_app → 12_rails_app}/app/assets/stylesheets/inter-font.css +0 -0
  191. /data/examples/{rails_app → 12_rails_app}/app/controllers/application_controller.rb +0 -0
  192. /data/examples/{rails_app → 12_rails_app}/app/controllers/search_controller.rb +0 -0
  193. /data/examples/{rails_app → 12_rails_app}/app/javascript/application.js +0 -0
  194. /data/examples/{rails_app → 12_rails_app}/app/javascript/controllers/application.js +0 -0
  195. /data/examples/{rails_app → 12_rails_app}/app/javascript/controllers/index.js +0 -0
  196. /data/examples/{rails_app → 12_rails_app}/app/views/files/index.html.erb +0 -0
  197. /data/examples/{rails_app → 12_rails_app}/app/views/files/show.html.erb +0 -0
  198. /data/examples/{rails_app → 12_rails_app}/app/views/layouts/application.html.erb +0 -0
  199. /data/examples/{rails_app → 12_rails_app}/app/views/memories/index.html.erb +0 -0
  200. /data/examples/{rails_app → 12_rails_app}/app/views/memories/new.html.erb +0 -0
  201. /data/examples/{rails_app → 12_rails_app}/app/views/robots/new.html.erb +0 -0
  202. /data/examples/{rails_app → 12_rails_app}/app/views/shared/_navbar.html.erb +0 -0
  203. /data/examples/{rails_app → 12_rails_app}/app/views/shared/_stat_card.html.erb +0 -0
  204. /data/examples/{rails_app → 12_rails_app}/bin/dev +0 -0
  205. /data/examples/{rails_app → 12_rails_app}/bin/rails +0 -0
  206. /data/examples/{rails_app → 12_rails_app}/bin/rake +0 -0
  207. /data/examples/{rails_app → 12_rails_app}/config/application.rb +0 -0
  208. /data/examples/{rails_app → 12_rails_app}/config/boot.rb +0 -0
  209. /data/examples/{rails_app → 12_rails_app}/config/database.yml +0 -0
  210. /data/examples/{rails_app → 12_rails_app}/config/environment.rb +0 -0
  211. /data/examples/{rails_app → 12_rails_app}/config/importmap.rb +0 -0
  212. /data/examples/{rails_app → 12_rails_app}/config/routes.rb +0 -0
  213. /data/examples/{rails_app → 12_rails_app}/config/tailwind.config.js +0 -0
  214. /data/examples/{rails_app → 12_rails_app}/config.ru +0 -0
  215. /data/examples/{rails_app → 12_rails_app}/log/.keep +0 -0
  216. /data/examples/{rails_app → 12_rails_app}/tmp/local_secret.txt +0 -0
@@ -9,15 +9,18 @@
9
9
  # - Progress feedback
10
10
  # - Database persistence
11
11
  #
12
+ # Prerequisites:
13
+ # 1. Set up examples database: rake examples:setup
14
+ # 2. Install dependencies: bundle install
15
+ #
12
16
  # Usage:
13
- # ruby htm_cli.rb
17
+ # ruby examples/cli_app/htm_cli.rb
14
18
  #
15
19
  # Environment:
16
- # HTM_DATABASE__URL - PostgreSQL connection URL (required)
17
20
  # OLLAMA_URL - Ollama server URL (default: http://localhost:11434)
18
21
  #
19
22
 
20
- require_relative '../../lib/htm'
23
+ require_relative '../examples_helper'
21
24
  require 'io/console'
22
25
  require 'ruby_llm'
23
26
 
@@ -86,7 +89,7 @@ class HTMCli
86
89
 
87
90
  loop do
88
91
  print "\nhtm> "
89
- input = gets&.chomp
92
+ input = $stdin.gets&.chomp
90
93
  break if input.nil? || input == 'exit'
91
94
 
92
95
  handle_command(input)
@@ -139,7 +142,7 @@ class HTMCli
139
142
  puts "[✓] Stored as node #{node_id} (#{duration}ms)"
140
143
 
141
144
  # Show what was generated (inline mode, so already complete)
142
- node = HTM::Models::Node.includes(:tags).find(node_id)
145
+ node = HTM::Models::Node[node_id]
143
146
 
144
147
  if node.embedding
145
148
  puts " Embedding: #{node.embedding_dimension} dimensions"
@@ -217,7 +220,7 @@ class HTMCli
217
220
  end
218
221
 
219
222
  # Show tags if any
220
- node = HTM::Models::Node.includes(:tags).find(memory['id'])
223
+ node = HTM::Models::Node[memory['id']]
221
224
  if node.tags.any?
222
225
  puts " Tags: #{node.tags.map(&:name).join(', ')}"
223
226
  else
@@ -259,10 +262,10 @@ class HTMCli
259
262
  puts
260
263
 
261
264
  # Get all tags with their nodes, optionally filtered by prefix
262
- tags_query = HTM::Models::Tag.includes(:nodes).order(:name)
263
- tags_query = tags_query.where("name LIKE ?", "#{filter}%") if filter && !filter.empty?
265
+ tags_query = HTM::Models::Tag.order(:name)
266
+ tags_query = tags_query.where(Sequel.like(:name, "#{filter}%")) if filter && !filter.empty?
264
267
 
265
- tags = tags_query.to_a
268
+ tags = tags_query.eager(:nodes).all
266
269
 
267
270
  if tags.empty?
268
271
  if filter
@@ -308,8 +311,8 @@ class HTMCli
308
311
  puts
309
312
 
310
313
  total_nodes = HTM::Models::Node.count
311
- nodes_with_embeddings = HTM::Models::Node.where.not(embedding: nil).count
312
- nodes_with_tags = HTM::Models::Node.joins(:tags).distinct.count
314
+ nodes_with_embeddings = HTM::Models::Node.exclude(embedding: nil).count
315
+ nodes_with_tags = HTM::Models::NodeTag.distinct.select(:node_id).count
313
316
  total_tags = HTM::Models::Tag.count
314
317
  total_robots = HTM::Models::Robot.count
315
318
 
@@ -376,17 +379,7 @@ class HTMCli
376
379
  end
377
380
 
378
381
  # Check database configuration
379
- unless ENV['HTM_DATABASE__URL']
380
- puts
381
- puts "[✗] Error: HTM_DATABASE__URL environment variable not set"
382
- puts
383
- puts "Please set your database connection URL:"
384
- puts " export HTM_DATABASE__URL='postgresql://postgres@localhost:5432/htm_development'"
385
- puts
386
- puts "See SETUP.md for database setup instructions."
387
- puts
388
- exit 1
389
- end
382
+ ExamplesHelper.require_database!
390
383
 
391
384
  # Check Ollama connection (optional but recommended)
392
385
  begin
@@ -0,0 +1,241 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ htm (0.0.21)
5
+ activesupport
6
+ anyway_config (>= 2.6)
7
+ async (~> 2.0)
8
+ baran
9
+ chronic
10
+ fast-mcp
11
+ lru_redux
12
+ pg (>= 1.5.0)
13
+ ruby-progressbar
14
+ ruby_llm
15
+ sequel (>= 5.0)
16
+ sequel_pg
17
+ simple_flow
18
+ tiktoken_ruby
19
+
20
+ GEM
21
+ remote: https://rubygems.org/
22
+ specs:
23
+ activesupport (8.1.2)
24
+ base64
25
+ bigdecimal
26
+ concurrent-ruby (~> 1.0, >= 1.3.1)
27
+ connection_pool (>= 2.2.5)
28
+ drb
29
+ i18n (>= 1.6, < 2)
30
+ json
31
+ logger (>= 1.4.2)
32
+ minitest (>= 5.1)
33
+ securerandom (>= 0.3)
34
+ tzinfo (~> 2.0, >= 2.0.5)
35
+ uri (>= 0.13.1)
36
+ addressable (2.8.8)
37
+ public_suffix (>= 2.0.2, < 8.0)
38
+ anyway_config (2.7.2)
39
+ ruby-next-core (~> 1.0)
40
+ async (2.36.0)
41
+ console (~> 1.29)
42
+ fiber-annotation
43
+ io-event (~> 1.11)
44
+ metrics (~> 0.12)
45
+ traces (~> 0.18)
46
+ baran (0.2.1)
47
+ base64 (0.3.0)
48
+ bigdecimal (4.0.1)
49
+ chronic (0.10.2)
50
+ concurrent-ruby (1.3.6)
51
+ connection_pool (3.0.2)
52
+ console (1.34.2)
53
+ fiber-annotation
54
+ fiber-local (~> 1.1)
55
+ json
56
+ drb (2.2.3)
57
+ dry-configurable (1.3.0)
58
+ dry-core (~> 1.1)
59
+ zeitwerk (~> 2.6)
60
+ dry-core (1.2.0)
61
+ concurrent-ruby (~> 1.0)
62
+ logger
63
+ zeitwerk (~> 2.6)
64
+ dry-inflector (1.3.1)
65
+ dry-initializer (3.2.0)
66
+ dry-logic (1.6.0)
67
+ bigdecimal
68
+ concurrent-ruby (~> 1.0)
69
+ dry-core (~> 1.1)
70
+ zeitwerk (~> 2.6)
71
+ dry-schema (1.15.0)
72
+ concurrent-ruby (~> 1.0)
73
+ dry-configurable (~> 1.0, >= 1.0.1)
74
+ dry-core (~> 1.1)
75
+ dry-initializer (~> 3.2)
76
+ dry-logic (~> 1.6)
77
+ dry-types (~> 1.8)
78
+ zeitwerk (~> 2.6)
79
+ dry-types (1.9.0)
80
+ bigdecimal (>= 3.0)
81
+ concurrent-ruby (~> 1.0)
82
+ dry-core (~> 1.0)
83
+ dry-inflector (~> 1.0)
84
+ dry-logic (~> 1.4)
85
+ zeitwerk (~> 2.6)
86
+ event_stream_parser (1.0.0)
87
+ faraday (2.14.0)
88
+ faraday-net_http (>= 2.0, < 3.5)
89
+ json
90
+ logger
91
+ faraday-multipart (1.2.0)
92
+ multipart-post (~> 2.0)
93
+ faraday-net_http (3.4.2)
94
+ net-http (~> 0.5)
95
+ faraday-retry (2.4.0)
96
+ faraday (~> 2.0)
97
+ fast-mcp (1.6.0)
98
+ addressable (~> 2.8)
99
+ base64
100
+ dry-schema (~> 1.14)
101
+ json (~> 2.0)
102
+ mime-types (~> 3.4)
103
+ rack (>= 2.0, < 4.0)
104
+ ffi (1.17.3-aarch64-linux-gnu)
105
+ ffi (1.17.3-aarch64-linux-musl)
106
+ ffi (1.17.3-arm-linux-gnu)
107
+ ffi (1.17.3-arm-linux-musl)
108
+ ffi (1.17.3-arm64-darwin)
109
+ ffi (1.17.3-x86_64-darwin)
110
+ ffi (1.17.3-x86_64-linux-gnu)
111
+ ffi (1.17.3-x86_64-linux-musl)
112
+ fiber-annotation (0.2.0)
113
+ fiber-local (1.1.0)
114
+ fiber-storage
115
+ fiber-storage (1.0.1)
116
+ i18n (1.14.8)
117
+ concurrent-ruby (~> 1.0)
118
+ io-event (1.14.2)
119
+ json (2.18.0)
120
+ listen (3.10.0)
121
+ logger
122
+ rb-fsevent (~> 0.10, >= 0.10.3)
123
+ rb-inotify (~> 0.9, >= 0.9.10)
124
+ logger (1.7.0)
125
+ lru_redux (1.1.0)
126
+ marcel (1.1.0)
127
+ metrics (0.15.0)
128
+ mime-types (3.7.0)
129
+ logger
130
+ mime-types-data (~> 3.2025, >= 3.2025.0507)
131
+ mime-types-data (3.2026.0113)
132
+ minitest (6.0.1)
133
+ prism (~> 1.5)
134
+ multi_json (1.19.1)
135
+ multipart-post (2.4.1)
136
+ mustermann (3.0.4)
137
+ ruby2_keywords (~> 0.0.1)
138
+ net-http (0.9.1)
139
+ uri (>= 0.11.1)
140
+ nio4r (2.7.5)
141
+ pg (1.6.3)
142
+ pg (1.6.3-aarch64-linux)
143
+ pg (1.6.3-aarch64-linux-musl)
144
+ pg (1.6.3-arm64-darwin)
145
+ pg (1.6.3-x86_64-darwin)
146
+ pg (1.6.3-x86_64-linux)
147
+ pg (1.6.3-x86_64-linux-musl)
148
+ prism (1.8.0)
149
+ public_suffix (7.0.2)
150
+ puma (6.6.1)
151
+ nio4r (~> 2.0)
152
+ rack (2.2.21)
153
+ rack-protection (3.2.0)
154
+ base64 (>= 0.1.0)
155
+ rack (~> 2.2, >= 2.2.4)
156
+ rb-fsevent (0.11.2)
157
+ rb-inotify (0.11.1)
158
+ ffi (~> 1.0)
159
+ redis (5.4.1)
160
+ redis-client (>= 0.22.0)
161
+ redis-client (0.26.3)
162
+ connection_pool
163
+ rerun (0.14.0)
164
+ listen (~> 3.0)
165
+ ruby-next-core (1.2.0)
166
+ ruby-progressbar (1.13.0)
167
+ ruby2_keywords (0.0.5)
168
+ ruby_llm (1.11.0)
169
+ base64
170
+ event_stream_parser (~> 1)
171
+ faraday (>= 1.10.0)
172
+ faraday-multipart (>= 1)
173
+ faraday-net_http (>= 1)
174
+ faraday-retry (>= 1)
175
+ marcel (~> 1.0)
176
+ ruby_llm-schema (~> 0.2.1)
177
+ zeitwerk (~> 2)
178
+ ruby_llm-schema (0.2.5)
179
+ securerandom (0.4.1)
180
+ sequel (5.100.0)
181
+ bigdecimal
182
+ sequel_pg (1.18.2)
183
+ pg (>= 0.18.0, != 1.2.0)
184
+ sequel (>= 4.38.0)
185
+ sidekiq (7.3.9)
186
+ base64
187
+ connection_pool (>= 2.3.0)
188
+ logger
189
+ rack (>= 2.2.4)
190
+ redis-client (>= 0.22.2)
191
+ simple_flow (0.3.0)
192
+ sinatra (3.2.0)
193
+ mustermann (~> 3.0)
194
+ rack (~> 2.2, >= 2.2.4)
195
+ rack-protection (= 3.2.0)
196
+ tilt (~> 2.0)
197
+ sinatra-contrib (3.2.0)
198
+ multi_json (>= 0.0.2)
199
+ mustermann (~> 3.0)
200
+ rack-protection (= 3.2.0)
201
+ sinatra (= 3.2.0)
202
+ tilt (~> 2.0)
203
+ tiktoken_ruby (0.0.15.1-aarch64-linux)
204
+ tiktoken_ruby (0.0.15.1-aarch64-linux-musl)
205
+ tiktoken_ruby (0.0.15.1-arm-linux)
206
+ tiktoken_ruby (0.0.15.1-arm64-darwin)
207
+ tiktoken_ruby (0.0.15.1-x86_64-darwin)
208
+ tiktoken_ruby (0.0.15.1-x86_64-linux)
209
+ tiktoken_ruby (0.0.15.1-x86_64-linux-musl)
210
+ tilt (2.7.0)
211
+ traces (0.18.2)
212
+ tzinfo (2.0.6)
213
+ concurrent-ruby (~> 1.0)
214
+ uri (1.1.1)
215
+ zeitwerk (2.7.4)
216
+
217
+ PLATFORMS
218
+ aarch64-linux
219
+ aarch64-linux-gnu
220
+ aarch64-linux-musl
221
+ arm-linux
222
+ arm-linux-gnu
223
+ arm-linux-musl
224
+ arm64-darwin
225
+ x86_64-darwin
226
+ x86_64-linux
227
+ x86_64-linux-gnu
228
+ x86_64-linux-musl
229
+
230
+ DEPENDENCIES
231
+ htm!
232
+ multi_json
233
+ puma (~> 6.0)
234
+ redis (~> 5.0)
235
+ rerun
236
+ sidekiq (~> 7.0)
237
+ sinatra (~> 3.0)
238
+ sinatra-contrib (~> 3.0)
239
+
240
+ BUNDLED WITH
241
+ 2.7.2
@@ -9,12 +9,15 @@
9
9
  # - RESTful API endpoints
10
10
  # - Thread-safe concurrent request handling
11
11
  #
12
+ # Prerequisites:
13
+ # 1. Set up examples database: rake examples:setup
14
+ # 2. Install dependencies: cd examples/sinatra_app && bundle install
15
+ #
12
16
  # Usage:
13
- # bundle install
17
+ # cd examples/sinatra_app
14
18
  # bundle exec ruby app.rb
15
19
  #
16
20
  # Environment:
17
- # HTM_DATABASE__URL - PostgreSQL connection URL (required)
18
21
  # REDIS_URL - Redis connection URL (for Sidekiq, default: redis://localhost:6379/0)
19
22
  # OLLAMA_URL - Ollama server URL (default: http://localhost:11434)
20
23
  #
@@ -23,7 +26,7 @@ require 'sinatra'
23
26
  require 'sinatra/json'
24
27
  require 'sidekiq'
25
28
  require 'securerandom'
26
- require_relative '../../lib/htm'
29
+ require_relative '../examples_helper'
27
30
  require_relative '../../lib/htm/integrations/sinatra'
28
31
 
29
32
  # Sidekiq configuration
@@ -112,8 +115,8 @@ class HTMApp < Sinatra::Base
112
115
  # API: Get memory statistics
113
116
  get '/api/stats' do
114
117
  total_nodes = HTM::Models::Node.count
115
- nodes_with_embeddings = HTM::Models::Node.where.not(embedding: nil).count
116
- nodes_with_tags = HTM::Models::Node.joins(:tags).distinct.count
118
+ nodes_with_embeddings = HTM::Models::Node.exclude(embedding: nil).count
119
+ nodes_with_tags = HTM::Models::NodeTag.distinct.select(:node_id).count
117
120
  total_tags = HTM::Models::Tag.count
118
121
 
119
122
  robot_nodes = HTM::Models::RobotNode.where(robot_id: htm.robot_id).count
@@ -139,19 +142,17 @@ class HTMApp < Sinatra::Base
139
142
  json(
140
143
  status: 'ok',
141
144
  job_backend: HTM.configuration.job_backend,
142
- database: HTM::ActiveRecordConfig.connected?,
145
+ database: HTM::SequelConfig.connected?,
143
146
  timestamp: Time.now.iso8601
144
147
  )
145
148
  end
146
149
 
147
150
  # API: Get all tags as a tree structure
148
151
  get '/api/tags' do
149
- tags = HTM::Models::Tag.all
150
-
151
152
  json(
152
153
  status: 'ok',
153
- count: tags.count,
154
- tree: tags.tree
154
+ count: HTM::Models::Tag.count,
155
+ tree: HTM::Models::Tag.tree_string
155
156
  )
156
157
  end
157
158
 
@@ -182,11 +183,11 @@ class HTMApp < Sinatra::Base
182
183
  token_count: memory['token_count']
183
184
  }
184
185
 
185
- # Include hybrid search scoring if available
186
- if memory['similarity']
186
+ # Include hybrid search scoring if available (RRF-based)
187
+ if memory['rrf_score']
187
188
  result[:similarity] = memory['similarity'].to_f.round(4)
188
- result[:tag_boost] = memory['tag_boost'].to_f.round(4)
189
- result[:combined_score] = memory['combined_score'].to_f.round(4)
189
+ result[:tag_depth_score] = memory['tag_depth_score'].to_f.round(4)
190
+ result[:rrf_score] = memory['rrf_score'].to_f.round(4)
190
191
  end
191
192
 
192
193
  result
@@ -292,7 +293,7 @@ __END__
292
293
 
293
294
  <div class="section">
294
295
  <h2>Recall Memories</h2>
295
- <p><small>Hybrid search uses combined scoring: (similarity × 0.7) + (tag_boost × 0.3)</small></p>
296
+ <p><small>Hybrid search uses Reciprocal Rank Fusion (RRF) combining vector, fulltext, and tag results</small></p>
296
297
  <input type="text" id="recallTopic" placeholder="Enter topic to search...">
297
298
  <div class="filter-row">
298
299
  <select id="recallStrategy">
@@ -382,10 +383,10 @@ __END__
382
383
  // Format timeframe for display
383
384
  const timeframeDisplay = formatTimeframe(data.timeframe);
384
385
  const memoriesHtml = data.memories.map(m => {
385
- // Build scoring info if available (hybrid search)
386
+ // Build scoring info if available (hybrid search with RRF)
386
387
  let scoreInfo = '';
387
- if (m.combined_score !== undefined) {
388
- scoreInfo = `<br><small class="scores">Score: ${m.combined_score.toFixed(3)} (similarity: ${m.similarity.toFixed(3)}, tag boost: ${m.tag_boost.toFixed(3)})</small>`;
388
+ if (m.rrf_score !== undefined) {
389
+ scoreInfo = `<br><small class="scores">RRF Score: ${m.rrf_score.toFixed(3)} (similarity: ${m.similarity.toFixed(3)}, tag depth: ${m.tag_depth_score.toFixed(3)})</small>`;
389
390
  }
390
391
  // Calculate age of memory
391
392
  const age = formatAge(m.created_at);
@@ -8,9 +8,9 @@
8
8
  # using a local Ollama model.
9
9
  #
10
10
  # Prerequisites:
11
- # 1. Install gems: gem install ruby_llm-mcp
12
- # 2. Have Ollama running with gpt-oss model: ollama pull gpt-oss
13
- # 3. Set HTM_DATABASE__URL environment variable
11
+ # 1. Set up examples database: rake examples:setup
12
+ # 2. Install gems: gem install ruby_llm-mcp
13
+ # 3. Have Ollama running with gpt-oss model: ollama pull gpt-oss
14
14
  # 4. The htm_mcp executable must be available (this client will launch it)
15
15
  #
16
16
  # Usage:
@@ -23,6 +23,7 @@
23
23
  # - List tags and statistics
24
24
  # - All through conversational AI with tool calling
25
25
 
26
+ require_relative 'examples_helper'
26
27
  require 'ruby_llm'
27
28
  require 'ruby_llm/mcp'
28
29
 
@@ -57,11 +58,7 @@ class HTMMcpClient
57
58
  private
58
59
 
59
60
  def validate_environment
60
- unless ENV['HTM_DATABASE__URL']
61
- warn 'Error: HTM_DATABASE__URL not set.'
62
- warn ' export HTM_DATABASE__URL="postgresql://postgres@localhost:5432/htm_development"'
63
- exit 1
64
- end
61
+ ExamplesHelper.require_database!
65
62
 
66
63
  unless File.exist?(MCP_SERVER_PATH)
67
64
  warn "Error: MCP server not found at #{MCP_SERVER_PATH}"
@@ -1,6 +1,6 @@
1
1
  # HTM Telemetry Demo Setup
2
2
 
3
- This guide walks you through setting up Prometheus and Grafana to visualize HTM metrics.
3
+ This guide walks you through setting up Prometheus and Grafana to visualize HTM metrics. Its intended as a guid for your own applications. The demo.rb program in this directory takes care of all of the setup steps before it starts it HTM process to generate the telemetry.
4
4
 
5
5
  ## Prerequisites
6
6
 
@@ -7,8 +7,9 @@
7
7
  # locally installed Prometheus and Grafana (via Homebrew).
8
8
  #
9
9
  # Prerequisites:
10
- # brew install grafana prometheus
11
- # gem install prometheus-client webrick
10
+ # 1. Set up examples database: rake examples:setup
11
+ # 2. brew install grafana prometheus
12
+ # 3. gem install prometheus-client webrick
12
13
  #
13
14
  # Usage:
14
15
  # cd examples/telemetry
@@ -101,11 +102,14 @@ class TelemetryDemo
101
102
  def load_htm
102
103
  puts "Loading HTM..."
103
104
 
104
- # Use bundler for HTM and its dependencies
105
- require 'bundler/setup'
106
- require_relative '../../lib/htm'
105
+ # Use examples_helper which sets up examples environment and database
106
+ require_relative '../examples_helper'
107
107
 
108
108
  puts " [OK] HTM #{HTM::VERSION}"
109
+ puts " [OK] Environment: #{HTM.config.environment}"
110
+ puts " [OK] Database: #{HTM.config.actual_database_name}"
111
+
112
+ ExamplesHelper.require_database!
109
113
  puts
110
114
  end
111
115
 
@@ -306,21 +310,21 @@ class TelemetryDemo
306
310
 
307
311
  begin
308
312
  # Find the robot
309
- robot = HTM::Models::Robot.find_by(name: ROBOT_NAME)
313
+ robot = HTM::Models::Robot.first(name: ROBOT_NAME)
310
314
 
311
315
  if robot
312
316
  # Find all nodes associated with this robot
313
- node_ids = HTM::Models::RobotNode.where(robot_id: robot.id).pluck(:node_id)
317
+ node_ids = HTM::Models::RobotNode.where(robot_id: robot.id).select_map(:node_id)
314
318
 
315
319
  if node_ids.any?
316
320
  # Hard delete the nodes
317
- deleted_count = HTM::Models::Node.where(id: node_ids).delete_all
321
+ deleted_count = HTM::Models::Node.where(id: node_ids).delete
318
322
 
319
323
  # Clean up robot_nodes join table
320
- HTM::Models::RobotNode.where(robot_id: robot.id).delete_all
324
+ HTM::Models::RobotNode.where(robot_id: robot.id).delete
321
325
 
322
326
  # Clean up any orphaned node_tags
323
- HTM::Models::NodeTag.where(node_id: node_ids).delete_all
327
+ HTM::Models::NodeTag.where(node_id: node_ids).delete
324
328
 
325
329
  puts " [OK] Deleted #{deleted_count} previous demo nodes"
326
330
  else