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
@@ -6,64 +6,10 @@ HTM implements a sophisticated two-tier memory architecture that balances the co
6
6
 
7
7
  The two-tier architecture addresses a fundamental challenge in LLM-based applications: LLMs have limited context windows but need to maintain awareness across long conversations spanning days, weeks, or months.
8
8
 
9
- <svg viewBox="0 0 800 500" xmlns="http://www.w3.org/2000/svg" style="background: transparent;">
10
- <!-- Title -->
11
- <text x="400" y="30" text-anchor="middle" fill="#E0E0E0" font-size="18" font-weight="bold">Two-Tier Memory Architecture</text>
12
-
13
- <!-- Working Memory (Hot Tier) -->
14
- <rect x="50" y="80" width="300" height="180" fill="rgba(33, 150, 243, 0.2)" stroke="#2196F3" stroke-width="3" rx="5"/>
15
- <text x="200" y="110" text-anchor="middle" fill="#E0E0E0" font-size="16" font-weight="bold">Working Memory (Hot)</text>
16
- <text x="80" y="140" fill="#B0B0B0" font-size="12">Capacity: Token-limited (128K)</text>
17
- <text x="80" y="160" fill="#B0B0B0" font-size="12">Storage: In-memory Ruby Hash</text>
18
- <text x="80" y="180" fill="#B0B0B0" font-size="12">Speed: O(1) lookups</text>
19
- <text x="80" y="200" fill="#B0B0B0" font-size="12">Lifetime: Process lifetime</text>
20
- <text x="80" y="220" fill="#B0B0B0" font-size="12">Eviction: Importance + Recency</text>
21
- <text x="80" y="240" fill="#4CAF50" font-size="12" font-weight="bold">Fast, Token-Aware, Volatile</text>
22
-
23
- <!-- Long-Term Memory (Cold Tier) -->
24
- <rect x="450" y="80" width="300" height="180" fill="rgba(156, 39, 176, 0.2)" stroke="#9C27B0" stroke-width="3" rx="5"/>
25
- <text x="600" y="110" text-anchor="middle" fill="#E0E0E0" font-size="16" font-weight="bold">Long-Term Memory (Cold)</text>
26
- <text x="480" y="140" fill="#B0B0B0" font-size="12">Capacity: Unlimited</text>
27
- <text x="480" y="160" fill="#B0B0B0" font-size="12">Storage: PostgreSQL + TimescaleDB</text>
28
- <text x="480" y="180" fill="#B0B0B0" font-size="12">Speed: O(log n) with indexes</text>
29
- <text x="480" y="200" fill="#B0B0B0" font-size="12">Lifetime: Permanent</text>
30
- <text x="480" y="220" fill="#B0B0B0" font-size="12">Retrieval: RAG (semantic + temporal)</text>
31
- <text x="480" y="240" fill="#4CAF50" font-size="12" font-weight="bold">Durable, Searchable, Persistent</text>
32
-
33
- <!-- Data Flow: Add Memory -->
34
- <path d="M 200 280 L 200 320 L 400 320 L 400 280" stroke="#4CAF50" stroke-width="3" fill="none" marker-end="url(#arrow-green)"/>
35
- <text x="300" y="310" text-anchor="middle" fill="#4CAF50" font-size="12" font-weight="bold">Add Memory</text>
36
- <text x="300" y="330" text-anchor="middle" fill="#B0B0B0" font-size="10">(Stored in both tiers)</text>
37
-
38
- <!-- Data Flow: Eviction -->
39
- <path d="M 350 360 L 600 360" stroke="#FF9800" stroke-width="3" marker-end="url(#arrow-orange)"/>
40
- <text x="475" y="350" text-anchor="middle" fill="#FF9800" font-size="12" font-weight="bold">Eviction</text>
41
- <text x="475" y="380" text-anchor="middle" fill="#B0B0B0" font-size="10">(Token limit → move to LTM only)</text>
42
-
43
- <!-- Data Flow: Recall -->
44
- <path d="M 600 400 L 200 400" stroke="#9C27B0" stroke-width="3" marker-end="url(#arrow-purple)"/>
45
- <text x="400" y="390" text-anchor="middle" fill="#9C27B0" font-size="12" font-weight="bold">Recall</text>
46
- <text x="400" y="420" text-anchor="middle" fill="#B0B0B0" font-size="10">(RAG search → load back to WM)</text>
47
-
48
- <!-- Never Forget Note -->
49
- <rect x="150" y="450" width="500" height="40" fill="rgba(76, 175, 80, 0.1)" stroke="#4CAF50" stroke-width="1" rx="3"/>
50
- <text x="400" y="475" text-anchor="middle" fill="#4CAF50" font-size="13" font-weight="bold">Never Forget: Evicted memories stay in LTM forever (explicit deletion only)</text>
51
-
52
- <defs>
53
- <marker id="arrow-green" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
54
- <polygon points="0 0, 10 3, 0 6" fill="#4CAF50"/>
55
- </marker>
56
- <marker id="arrow-orange" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
57
- <polygon points="0 0, 10 3, 0 6" fill="#FF9800"/>
58
- </marker>
59
- <marker id="arrow-purple" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
60
- <polygon points="0 0, 10 3, 0 6" fill="#9C27B0"/>
61
- </marker>
62
- </defs>
63
- </svg>
9
+ ![Two-Tier Memory Architecture](../assets/images/two-tier-memory-architecture.svg)
64
10
 
65
11
  !!! info "Related ADR"
66
- See [ADR-002: Two-Tier Memory Architecture](adrs/002-two-tier-memory.md) for the complete architectural decision record.
12
+ See [ADR-002: Two-Tier Memory Architecture](../architecture/adrs/002-two-tier-memory.md) for the complete architectural decision record.
67
13
 
68
14
  ## Working Memory (Hot Tier)
69
15
 
@@ -209,55 +155,13 @@ Nodes are evicted in this order:
209
155
  3. **High importance, old** (e.g., importance: 9.0, age: 5 days)
210
156
  4. **High importance, recent** (e.g., importance: 9.0, age: 1 hour) ← **Kept longest**
211
157
 
212
- <svg viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg" style="background: transparent;">
213
- <!-- Title -->
214
- <text x="400" y="30" text-anchor="middle" fill="#E0E0E0" font-size="16" font-weight="bold">Eviction Priority (Lower → Higher retention)</text>
215
-
216
- <!-- Priority bars -->
217
- <rect x="50" y="80" width="150" height="50" fill="rgba(244, 67, 54, 0.6)" stroke="#F44336" stroke-width="2" rx="3"/>
218
- <text x="125" y="110" text-anchor="middle" fill="#E0E0E0" font-size="12" font-weight="bold">Tier 1: Evict First</text>
219
-
220
- <rect x="220" y="80" width="150" height="50" fill="rgba(255, 152, 0, 0.6)" stroke="#FF9800" stroke-width="2" rx="3"/>
221
- <text x="295" y="110" text-anchor="middle" fill="#E0E0E0" font-size="12" font-weight="bold">Tier 2</text>
222
-
223
- <rect x="390" y="80" width="150" height="50" fill="rgba(255, 193, 7, 0.6)" stroke="#FFC107" stroke-width="2" rx="3"/>
224
- <text x="465" y="110" text-anchor="middle" fill="#E0E0E0" font-size="12" font-weight="bold">Tier 3</text>
225
-
226
- <rect x="560" y="80" width="150" height="50" fill="rgba(76, 175, 80, 0.6)" stroke="#4CAF50" stroke-width="2" rx="3"/>
227
- <text x="635" y="110" text-anchor="middle" fill="#E0E0E0" font-size="12" font-weight="bold">Tier 4: Keep Longest</text>
228
-
229
- <!-- Details -->
230
- <text x="125" y="160" text-anchor="middle" fill="#B0B0B0" font-size="11">Importance: 1.0</text>
231
- <text x="125" y="180" text-anchor="middle" fill="#B0B0B0" font-size="11">Age: 5 days</text>
232
- <text x="125" y="200" text-anchor="middle" fill="#F44336" font-size="10" font-weight="bold">Low value, stale</text>
233
-
234
- <text x="295" y="160" text-anchor="middle" fill="#B0B0B0" font-size="11">Importance: 1.0</text>
235
- <text x="295" y="180" text-anchor="middle" fill="#B0B0B0" font-size="11">Age: 1 hour</text>
236
- <text x="295" y="200" text-anchor="middle" fill="#FF9800" font-size="10" font-weight="bold">Low value, recent</text>
237
-
238
- <text x="465" y="160" text-anchor="middle" fill="#B0B0B0" font-size="11">Importance: 9.0</text>
239
- <text x="465" y="180" text-anchor="middle" fill="#B0B0B0" font-size="11">Age: 5 days</text>
240
- <text x="465" y="200" text-anchor="middle" fill="#FFC107" font-size="10" font-weight="bold">High value, older</text>
241
-
242
- <text x="635" y="160" text-anchor="middle" fill="#B0B0B0" font-size="11">Importance: 9.0</text>
243
- <text x="635" y="180" text-anchor="middle" fill="#B0B0B0" font-size="11">Age: 1 hour</text>
244
- <text x="635" y="200" text-anchor="middle" fill="#4CAF50" font-size="10" font-weight="bold">High value, fresh</text>
245
-
246
- <!-- Example scenario -->
247
- <text x="50" y="250" fill="#E0E0E0" font-size="13" font-weight="bold">Example Eviction Scenario:</text>
248
- <text x="50" y="280" fill="#B0B0B0" font-size="11">Working Memory: 127,500 / 128,000 tokens (99% full)</text>
249
- <text x="50" y="300" fill="#B0B0B0" font-size="11">New memory to add: 5,000 tokens</text>
250
- <text x="50" y="320" fill="#B0B0B0" font-size="11">Need to free: 4,500 tokens</text>
251
-
252
- <text x="50" y="350" fill="#4CAF50" font-size="11">Eviction: Remove Tier 1 and Tier 2 nodes until 4,500+ tokens freed</text>
253
- <text x="50" y="370" fill="#4CAF50" font-size="11">Result: Tier 3 and Tier 4 nodes preserved (high importance)</text>
254
- </svg>
158
+ ![Eviction Priority](../assets/images/eviction-priority.svg)
255
159
 
256
160
  !!! warning "Importance Matters"
257
161
  **Assign meaningful importance scores!** Low-importance memories (1.0-3.0) will be evicted first. Use higher scores (7.0-10.0) for critical information like architectural decisions, user preferences, and long-term facts.
258
162
 
259
163
  !!! info "Related ADR"
260
- See [ADR-007: Working Memory Eviction Strategy](adrs/007-eviction-strategy.md) for detailed rationale and alternatives considered.
164
+ See [ADR-007: Working Memory Eviction Strategy](../architecture/adrs/007-eviction-strategy.md) for detailed rationale and alternatives considered.
261
165
 
262
166
  ### Context Assembly Strategies
263
167
 
@@ -352,50 +256,10 @@ context = htm.create_context(strategy: :balanced)
352
256
  # Recent debugging context + important architectural decisions
353
257
  ```
354
258
 
355
- <svg viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg" style="background: transparent;">
356
- <!-- Title -->
357
- <text x="400" y="30" text-anchor="middle" fill="#E0E0E0" font-size="16" font-weight="bold">Balanced Strategy: Importance Decay Over Time</text>
358
-
359
- <!-- Axes -->
360
- <line x1="100" y1="350" x2="700" y2="350" stroke="#808080" stroke-width="2"/>
361
- <line x1="100" y1="350" x2="100" y2="80" stroke="#808080" stroke-width="2"/>
362
-
363
- <!-- X-axis labels -->
364
- <text x="100" y="375" text-anchor="middle" fill="#B0B0B0" font-size="11">0h</text>
365
- <text x="250" y="375" text-anchor="middle" fill="#B0B0B0" font-size="11">1h</text>
366
- <text x="400" y="375" text-anchor="middle" fill="#B0B0B0" font-size="11">3h</text>
367
- <text x="550" y="375" text-anchor="middle" fill="#B0B0B0" font-size="11">6h</text>
368
- <text x="700" y="375" text-anchor="middle" fill="#B0B0B0" font-size="11">24h</text>
369
- <text x="400" y="395" text-anchor="middle" fill="#E0E0E0" font-size="12" font-weight="bold">Time Since Added (hours)</text>
370
-
371
- <!-- Y-axis labels -->
372
- <text x="85" y="355" text-anchor="end" fill="#B0B0B0" font-size="11">0</text>
373
- <text x="85" y="280" text-anchor="end" fill="#B0B0B0" font-size="11">3</text>
374
- <text x="85" y="205" text-anchor="end" fill="#B0B0B0" font-size="11">6</text>
375
- <text x="85" y="130" text-anchor="end" fill="#B0B0B0" font-size="11">9</text>
376
- <text x="85" y="85" text-anchor="end" fill="#B0B0B0" font-size="11">10</text>
377
- <text x="40" y="220" text-anchor="middle" fill="#E0E0E0" font-size="12" font-weight="bold" transform="rotate(-90 40 220)">Effective Score</text>
378
-
379
- <!-- Decay curves for different importance levels -->
380
- <!-- Importance 10.0 -->
381
- <path d="M 100 80 Q 250 105 400 155 T 700 320" stroke="#4CAF50" stroke-width="3" fill="none"/>
382
- <text x="710" y="320" fill="#4CAF50" font-size="11" font-weight="bold">Imp: 10.0</text>
383
-
384
- <!-- Importance 5.0 -->
385
- <path d="M 100 205 Q 250 230 400 255 T 700 335" stroke="#2196F3" stroke-width="3" fill="none"/>
386
- <text x="710" y="335" fill="#2196F3" font-size="11" font-weight="bold">Imp: 5.0</text>
387
-
388
- <!-- Importance 1.0 -->
389
- <path d="M 100 330 Q 250 340 400 345 T 700 348" stroke="#FF9800" stroke-width="3" fill="none"/>
390
- <text x="710" y="348" fill="#FF9800" font-size="11" font-weight="bold">Imp: 1.0</text>
391
-
392
- <!-- Key insight -->
393
- <rect x="150" y="50" width="500" height="25" fill="rgba(76, 175, 80, 0.1)" stroke="#4CAF50" stroke-width="1" rx="3"/>
394
- <text x="400" y="68" text-anchor="middle" fill="#4CAF50" font-size="12">High-importance memories retain value longer, but recency still matters</text>
395
- </svg>
259
+ ![Balanced Strategy: Importance Decay Over Time](../assets/images/balanced-strategy-decay.svg)
396
260
 
397
261
  !!! info "Related ADR"
398
- See [ADR-006: Context Assembly Strategies](adrs/006-context-assembly.md) for detailed strategy analysis.
262
+ See [ADR-006: Context Assembly Strategies](../architecture/adrs/006-context-assembly.md) for detailed strategy analysis.
399
263
 
400
264
  ### Performance Characteristics
401
265
 
@@ -474,7 +338,7 @@ CREATE INDEX idx_nodes_value_gin ON nodes
474
338
  - Retention policies for data lifecycle
475
339
 
476
340
  !!! info "Related ADR"
477
- See [ADR-001: Use PostgreSQL with TimescaleDB for Storage](adrs/001-postgresql-timescaledb.md) for complete rationale.
341
+ See [ADR-001: Use PostgreSQL with TimescaleDB for Storage](../architecture/adrs/001-postgresql-timescaledb.md) for complete rationale.
478
342
 
479
343
  ### Long-Term Memory Operations
480
344
 
@@ -560,7 +424,7 @@ end
560
424
  ```
561
425
 
562
426
  !!! info "Related ADR"
563
- See [ADR-005: RAG-Based Retrieval with Hybrid Search](adrs/005-rag-retrieval.md) for search strategy details.
427
+ See [ADR-005: RAG-Based Retrieval with Hybrid Search](../architecture/adrs/005-rag-retrieval.md) for search strategy details.
564
428
 
565
429
  ### RAG-Based Retrieval
566
430
 
@@ -831,9 +695,9 @@ LIMIT 20;
831
695
 
832
696
  ## Related Documentation
833
697
 
834
- - [Architecture Index](index.md) - System overview and component summary
835
- - [Architecture Overview](overview.md) - Detailed architecture and data flows
698
+ - [Architecture Index](../architecture/index.md) - System overview and component summary
699
+ - [Architecture Overview](../architecture/overview.md) - Detailed architecture and data flows
836
700
  - [Hive Mind Architecture](hive-mind.md) - Multi-robot shared memory
837
- - [ADR-002: Two-Tier Memory Architecture](adrs/002-two-tier-memory.md)
838
- - [ADR-006: Context Assembly Strategies](adrs/006-context-assembly.md)
839
- - [ADR-007: Working Memory Eviction Strategy](adrs/007-eviction-strategy.md)
701
+ - [ADR-002: Two-Tier Memory Architecture](../architecture/adrs/002-two-tier-memory.md)
702
+ - [ADR-006: Context Assembly Strategies](../architecture/adrs/006-context-assembly.md)
703
+ - [ADR-007: Working Memory Eviction Strategy](../architecture/adrs/007-eviction-strategy.md)
@@ -0,0 +1,85 @@
1
+ # Why "Robots" Instead of "Agents"?
2
+
3
+ > "What's in a name? That which we call a rose
4
+ > By any other name would smell as sweet."
5
+ > — Shakespeare, *Romeo and Juliet*
6
+
7
+ Shakespeare argues names are arbitrary. In software, we respectfully disagree—names shape expectations and understanding. The words we choose frame how we think about systems, what we expect from them, and how we architect their capabilities.
8
+
9
+ HTM uses **robots** rather than the fashionable "agents" deliberately and thoughtfully.
10
+
11
+ ## The Problem with "Agent"
12
+
13
+ The term "agent" carries philosophical baggage it cannot support:
14
+
15
+ - **Semantic overload**: User agents, software agents, real estate agents, secret agents, FBI agents, travel agents. The word means everything and therefore nothing. When you say "AI agent," what mental model does your listener construct?
16
+
17
+ - **False autonomy**: "Agent" implies genuine decision-making, independent action, perhaps even free will. These systems follow instructions. They predict the next token. They don't have *agency* in any meaningful philosophical sense. Calling them agents sets expectations the technology cannot meet.
18
+
19
+ - **The hype cycle problem**: "AI Agent" and "Agentic AI" became buzzwords in 2023-2024, often meaning nothing more than "LLM with a prompt and a while loop." We prefer terminology that will age gracefully rather than become an embarrassing artifact of a particular moment's enthusiasm.
20
+
21
+ - **Implementation reality**: Look under the hood of popular "agent" frameworks. You'll often find a system prompt, a for-loop, and some JSON parsing. Calling that an "agent" is marketing, not engineering.
22
+
23
+ ## The Case for "Robot"
24
+
25
+ "Robot" has heritage, honesty, and heart:
26
+
27
+ - **Rich literary tradition**: The word comes from Karel Čapek's 1920 play *R.U.R.* (Rossum's Universal Robots), derived from Czech *robota*, meaning forced labor or drudgery. Isaac Asimov gave us the Three Laws of Robotics and decades of thoughtful exploration of robot ethics, identity, and purpose. There's a century of serious thinking about what robots are and how they should behave. "Agent" has no comparable intellectual foundation.
28
+
29
+ - **Honest about the relationship**: Robots work for us. They're tireless, reliable, and purpose-built. They don't pretend to have goals independent of their creators. This honesty about the master-worker relationship is healthier than the ambiguity of "agent."
30
+
31
+ - **Cultural resonance**: Robots are endearing. R2-D2. Wall-E. Bender. Data. The Iron Giant. Baymax. We've spent a century telling stories about robots, developing affection for them, and exploring their place alongside humanity. "Agent" has no such cultural weight—it's the language of bureaucracy and espionage.
32
+
33
+ - **Technical precision**: In HTM, each robot has an identity (`robot_id`), a name, and a history of contributions. Robots are registered in a table. They're tracked. They're *things* with identity and persistence. "Agent" suggests ephemerality; "robot" suggests durability.
34
+
35
+ ## Robots in the Hive Mind
36
+
37
+ HTM's architecture reinforces the robot metaphor in a specific way: **all robots share a common long-term memory**.
38
+
39
+ This is the *hive mind* pattern. Individual robots have their own working memory—their own immediate context and focus—but they draw from and contribute to a shared pool of knowledge. Like worker bees serving a hive, each robot is both individual and part of something larger.
40
+
41
+ ```
42
+ ┌─────────────────────────────────────────────────────┐
43
+ │ Shared Long-Term Memory │
44
+ │ (The Hive Mind / Collective) │
45
+ │ │
46
+ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
47
+ │ │ Memory │ │ Memory │ │ Memory │ ... │
48
+ │ └─────────┘ └─────────┘ └─────────┘ │
49
+ └─────────────────────────────────────────────────────┘
50
+ ▲ ▲ ▲
51
+ │ │ │
52
+ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐
53
+ │ Robot A │ │ Robot B │ │ Robot C │
54
+ │ │ │ │ │ │
55
+ │ Working │ │ Working │ │ Working │
56
+ │ Memory │ │ Memory │ │ Memory │
57
+ └─────────┘ └─────────┘ └─────────┘
58
+ ```
59
+
60
+ This architecture maps naturally to the robot metaphor:
61
+
62
+ - **Robots are workers**: They execute tasks, store memories, recall information
63
+ - **Robots are individuals**: Each has its own name, identity, and working context
64
+ - **Robots are collective**: They share knowledge, learn from each other's experiences
65
+ - **Robots are persistent**: They're registered, tracked, and their contributions are attributed
66
+
67
+ "Agent" suggests independence and autonomy. "Robot" suggests collaboration and purpose. HTM's robots work together, building collective intelligence. That's what the terminology should convey.
68
+
69
+ ## Robots Never Forget
70
+
71
+ HTM follows a **never-forget philosophy** (see [ADR-009](../architecture/adrs/009-never-forget.md)). Memories are never truly deleted—only soft-deleted, always recoverable. This aligns with the robot metaphor:
72
+
73
+ A good robot doesn't lose your data. A good robot remembers what you told it, years later if necessary. A good robot is *reliable* in a way that ephemeral "agents" are not.
74
+
75
+ When you tell an HTM robot something important, it stores that information in the collective memory. Other robots can access it. Future robots can learn from it. The knowledge persists, attributed to the robot that first contributed it.
76
+
77
+ This is robot memory done right: durable, shared, and faithful.
78
+
79
+ ## Honest Terminology, Clear Thinking
80
+
81
+ Language shapes thought. When we call these systems "agents," we prime ourselves to expect agency—goals, autonomy, perhaps even consciousness. When we call them "robots," we remind ourselves what they actually are: sophisticated tools, tireless workers, faithful servants of the instructions we give them.
82
+
83
+ HTM helps robots do their job better: remember perfectly, recall intelligently, share knowledge generously, and serve reliably. That's not agency. That's good engineering.
84
+
85
+ These are robots. Let's call them what they are.
data/examples/.envrc ADDED
@@ -0,0 +1,6 @@
1
+ # htm/examples/.envrc
2
+
3
+ source_up
4
+
5
+ export HTM_ENV=examples
6
+ export HTM_DATABASE__URL="postgresql://dewayne@localhost:5432/htm_$HTM_ENV"
@@ -0,0 +1,2 @@
1
+ *.log
2
+ *.log.0
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Creates and sets up the htm_examples database
5
+ #
6
+ # This script should be run before any other examples to ensure
7
+ # the examples database exists and has the correct schema.
8
+ #
9
+ # Run via:
10
+ # ruby examples/00_create_examples_db.rb
11
+ # # or
12
+ # ./examples/00_create_examples_db.rb
13
+
14
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
15
+
16
+ # Set examples environment BEFORE loading HTM
17
+ ENV['HTM_ENV'] = 'examples'
18
+
19
+ service_name = ENV['HTM_SERVICE__NAME'] || 'htm'
20
+ db_name = "#{service_name}_examples"
21
+ db_url = "postgresql://#{ENV['USER']}@localhost:5432/#{db_name}"
22
+
23
+ ENV['HTM_DATABASE__URL'] = db_url
24
+
25
+ puts <<~HEADER
26
+
27
+ ==========================================
28
+ == HTM Examples Database Setup ==
29
+ ==========================================
30
+
31
+ Database: #{db_name}
32
+
33
+ HEADER
34
+
35
+ # Step 1: Create database if it doesn't exist
36
+ puts "1. Checking if database exists..."
37
+
38
+ check_cmd = "psql -lqt | cut -d \\| -f 1 | grep -qw #{db_name}"
39
+ db_exists = system(check_cmd)
40
+
41
+ if db_exists
42
+ puts " Database '#{db_name}' already exists."
43
+ else
44
+ puts " Creating database '#{db_name}'..."
45
+ unless system("createdb #{db_name}")
46
+ abort " ERROR: Failed to create database '#{db_name}'"
47
+ end
48
+ puts " Database created."
49
+ end
50
+
51
+ # Step 2: Enable extensions
52
+ puts "\n2. Enabling PostgreSQL extensions..."
53
+
54
+ extensions_sql = <<~SQL
55
+ CREATE EXTENSION IF NOT EXISTS vector;
56
+ CREATE EXTENSION IF NOT EXISTS pg_trgm;
57
+ SQL
58
+
59
+ unless system("psql -d #{db_name} -c \"#{extensions_sql}\" > /dev/null 2>&1")
60
+ abort " ERROR: Failed to enable extensions"
61
+ end
62
+ puts " Extensions enabled (pgvector, pg_trgm)."
63
+
64
+ # Step 3: Run migrations
65
+ puts "\n3. Running schema migrations..."
66
+
67
+ require "htm"
68
+
69
+ HTM.configure do |config|
70
+ config.job.backend = :inline
71
+ config.log_level = :info
72
+ config.telemetry_enabled = false
73
+ end
74
+
75
+ begin
76
+ HTM::SequelConfig.establish_connection!
77
+ HTM::Database.setup
78
+ puts " Schema setup complete."
79
+ rescue => e
80
+ abort " ERROR: #{e.message}"
81
+ end
82
+
83
+ puts <<~FOOTER
84
+
85
+ ==========================================
86
+ Examples database is ready!
87
+
88
+ You can now run examples:
89
+ ruby examples/basic_usage.rb
90
+ rake examples:basic
91
+ rake examples:all
92
+ ==========================================
93
+
94
+ FOOTER
@@ -4,25 +4,21 @@
4
4
  # Basic usage example for HTM
5
5
  #
6
6
  # Prerequisites:
7
- # 1. Configure database via environment or config file:
8
- # - HTM_DATABASE__URL="postgresql://user@localhost:5432/htm_development"
9
- # - Or individual vars: HTM_DATABASE__HOST, HTM_DATABASE__NAME, etc.
10
- # 2. Initialize database schema: rake htm:db:setup
11
- # 3. Install dependencies: bundle install
7
+ # 1. Set up examples database: rake examples:setup
8
+ # 2. Install dependencies: bundle install
9
+ #
10
+ # Run via:
11
+ # rake examples:basic
12
+ # # or
13
+ # ruby examples/basic_usage.rb
12
14
 
13
- require_relative '../lib/htm'
15
+ require_relative 'examples_helper'
14
16
 
15
- puts "HTM Basic Usage Example"
16
- puts "=" * 60
17
+ ExamplesHelper.section "HTM Basic Usage Example"
18
+ ExamplesHelper.print_environment
17
19
 
18
- # Check database configuration using the config system
19
- unless HTM.config.database_configured?
20
- puts "ERROR: Database not configured. Set one of:"
21
- puts " export HTM_DATABASE__URL=\"postgresql://user@localhost:5432/htm_development\""
22
- puts " Or configure in ~/.config/htm/htm.yml"
23
- puts "Run 'bin/htm_mcp help' for all configuration options."
24
- exit 1
25
- end
20
+ # Verify database is available
21
+ ExamplesHelper.require_database!
26
22
 
27
23
  begin
28
24
  # Configure HTM globally (uses Ollama by default from defaults.yml)
@@ -5,11 +5,21 @@
5
5
  #
6
6
  # This example demonstrates how to configure HTM with custom LLM methods
7
7
  # for embedding generation and tag extraction, as well as using defaults.
8
+ #
9
+ # Prerequisites:
10
+ # 1. Set up examples database: rake examples:setup
11
+ # 2. Install dependencies: bundle install
12
+ #
13
+ # Run via:
14
+ # ruby examples/custom_llm_configuration.rb
8
15
 
9
- require_relative '../lib/htm'
16
+ require_relative 'examples_helper'
10
17
 
11
- puts "HTM Custom LLM Configuration Example"
12
- puts "=" * 50
18
+ ExamplesHelper.section "HTM Custom LLM Configuration Example"
19
+ ExamplesHelper.print_environment
20
+
21
+ # Verify database is available
22
+ ExamplesHelper.require_database!
13
23
 
14
24
  # Example 1: Use Default Configuration (RubyLLM with Ollama)
15
25
  puts "\n1. Using Default Configuration (RubyLLM + Ollama)"
@@ -10,24 +10,21 @@
10
10
  # - Unloading files
11
11
  #
12
12
  # Prerequisites:
13
- # 1. Set HTM_DATABASE__URL environment variable (see SETUP.md)
14
- # 2. Initialize database schema: rake db_setup
15
- # 3. Install dependencies: bundle install
13
+ # 1. Set up examples database: rake examples:setup
14
+ # 2. Install dependencies: bundle install
15
+ #
16
+ # Run via:
17
+ # ruby examples/file_loader_usage.rb
16
18
 
17
- require_relative '../lib/htm'
19
+ require_relative 'examples_helper'
18
20
  require 'tempfile'
19
21
  require 'fileutils'
20
22
 
21
- puts "HTM File Loader Example"
22
- puts "=" * 60
23
+ ExamplesHelper.section "HTM File Loader Example"
24
+ ExamplesHelper.print_environment
23
25
 
24
- # Check environment
25
- unless ENV['HTM_DATABASE__URL']
26
- puts "ERROR: HTM_DATABASE__URL not set. Please set it:"
27
- puts " export HTM_DATABASE__URL=\"postgresql://postgres@localhost:5432/htm_development\""
28
- puts "See SETUP.md for details."
29
- exit 1
30
- end
26
+ # Verify database is available
27
+ ExamplesHelper.require_database!
31
28
 
32
29
  begin
33
30
  # Configure HTM globally (uses Ollama by default)
@@ -102,7 +99,7 @@ begin
102
99
  puts " Skipped: #{result[:skipped]}"
103
100
 
104
101
  # Access the file source to show frontmatter
105
- source = HTM::Models::FileSource.find(result[:file_source_id])
102
+ source = HTM::Models::FileSource[result[:file_source_id]]
106
103
  puts " Frontmatter title: #{source.title}"
107
104
  puts " Frontmatter author: #{source.author}"
108
105
  puts " Frontmatter tags: #{source.frontmatter_tags.join(', ')}"
@@ -3,10 +3,17 @@
3
3
 
4
4
  # Timeframe Demo - Demonstrates the various ways to use timeframes with recall
5
5
  #
6
- # Run with:
7
- # HTM_DATABASE__URL="postgresql://localhost/htm_development" ruby examples/timeframe_demo.rb
6
+ # Prerequisites:
7
+ # 1. Set up examples database: rake examples:setup
8
+ # 2. Install dependencies: bundle install
9
+ #
10
+ # Run via:
11
+ # rake examples:basic # runs basic_usage.rb
12
+ # ruby examples/timeframe_demo.rb
13
+
14
+ require_relative 'examples_helper'
8
15
 
9
- require_relative "../lib/htm"
16
+ ExamplesHelper.require_database!
10
17
 
11
18
  puts <<~HEADER
12
19
  ╔══════════════════════════════════════════════════════════════════╗
@@ -2,27 +2,27 @@
2
2
  # Example HTM Application
3
3
  #
4
4
  # This demonstrates a simple application using the HTM gem with full RubyLLM integration.
5
+ #
6
+ # Prerequisites:
7
+ # 1. Set up examples database: rake examples:setup
8
+ # 2. Install dependencies: bundle install
9
+ #
10
+ # Run via:
11
+ # ruby examples/example_app/app.rb
5
12
 
6
- require_relative '../../lib/htm'
13
+ require_relative '../examples_helper'
7
14
  require 'ruby_llm'
8
15
  require 'logger'
9
16
 
10
17
  class ExampleApp
11
18
  def self.run
12
19
  puts "\n=== HTM Full-Featured Example Application ==="
13
- puts "\nChecking database connection..."
14
-
15
- # Check if database is configured
16
- config = HTM::Database.default_config
17
- unless config
18
- puts "\n⚠ Database not configured!"
19
- puts "Set HTM_DATABASE__URL environment variable:"
20
- puts " export HTM_DATABASE__URL='postgresql://user:pass@host:port/dbname'"
21
- puts "\nOr run: rake app:bootstrap"
22
- return
23
- end
20
+ ExamplesHelper.print_environment
21
+
22
+ # Verify database is available
23
+ ExamplesHelper.require_database!
24
24
 
25
- puts "Database configured: #{config[:dbname]} @ #{config[:host]}"
25
+ puts "Database configured: #{HTM.config.actual_database_name}"
26
26
 
27
27
  # Configure HTM with RubyLLM for embeddings and tag generation
28
28
  puts "\nConfiguring HTM with RubyLLM..."
@@ -95,7 +95,7 @@ class ExampleApp
95
95
  # Check what was generated
96
96
  puts "\n--- Generated Tags ---"
97
97
  [node_1, node_2, node_3].each do |node_id|
98
- node = HTM::Models::Node.includes(:tags).find(node_id)
98
+ node = HTM::Models::Node[node_id]
99
99
  if node.tags.any?
100
100
  puts "Node #{node_id}:"
101
101
  node.tags.each { |tag| puts " - #{tag.name}" }
@@ -107,7 +107,7 @@ class ExampleApp
107
107
  # Check embeddings
108
108
  puts "\n--- Embedding Status ---"
109
109
  [node_1, node_2, node_3].each do |node_id|
110
- node = HTM::Models::Node.find(node_id)
110
+ node = HTM::Models::Node[node_id]
111
111
  if node.embedding
112
112
  dimensions = node.embedding.is_a?(Array) ? node.embedding.size : node.embedding_dimension
113
113
  status = "✓ Generated (#{dimensions} dimensions)"