htm 0.0.1 → 0.0.10
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/.aigcm_msg +1 -0
- data/.architecture/reviews/comprehensive-codebase-review.md +577 -0
- data/.claude/settings.local.json +92 -0
- data/.envrc +1 -0
- data/.irbrc +283 -80
- data/.tbls.yml +31 -0
- data/CHANGELOG.md +314 -16
- data/CLAUDE.md +603 -0
- data/README.md +76 -5
- data/Rakefile +5 -0
- data/SETUP.md +132 -101
- data/db/migrate/{20250101000001_enable_extensions.rb → 00001_enable_extensions.rb} +0 -1
- data/db/migrate/00002_create_robots.rb +11 -0
- data/db/migrate/00003_create_file_sources.rb +20 -0
- data/db/migrate/00004_create_nodes.rb +65 -0
- data/db/migrate/00005_create_tags.rb +13 -0
- data/db/migrate/00006_create_node_tags.rb +18 -0
- data/db/migrate/00007_create_robot_nodes.rb +26 -0
- data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +12 -0
- data/db/schema.sql +390 -36
- data/docs/api/database.md +19 -232
- data/docs/api/embedding-service.md +1 -7
- data/docs/api/htm.md +305 -364
- data/docs/api/index.md +1 -7
- data/docs/api/long-term-memory.md +342 -590
- data/docs/api/yard/HTM/ActiveRecordConfig.md +23 -0
- data/docs/api/yard/HTM/AuthorizationError.md +11 -0
- data/docs/api/yard/HTM/CircuitBreaker.md +92 -0
- data/docs/api/yard/HTM/CircuitBreakerOpenError.md +34 -0
- data/docs/api/yard/HTM/Configuration.md +175 -0
- data/docs/api/yard/HTM/Database.md +99 -0
- data/docs/api/yard/HTM/DatabaseError.md +14 -0
- data/docs/api/yard/HTM/EmbeddingError.md +18 -0
- data/docs/api/yard/HTM/EmbeddingService.md +58 -0
- data/docs/api/yard/HTM/Error.md +11 -0
- data/docs/api/yard/HTM/JobAdapter.md +39 -0
- data/docs/api/yard/HTM/LongTermMemory.md +342 -0
- data/docs/api/yard/HTM/NotFoundError.md +17 -0
- data/docs/api/yard/HTM/Observability.md +107 -0
- data/docs/api/yard/HTM/QueryTimeoutError.md +19 -0
- data/docs/api/yard/HTM/Railtie.md +27 -0
- data/docs/api/yard/HTM/ResourceExhaustedError.md +13 -0
- data/docs/api/yard/HTM/TagError.md +18 -0
- data/docs/api/yard/HTM/TagService.md +67 -0
- data/docs/api/yard/HTM/Timeframe/Result.md +24 -0
- data/docs/api/yard/HTM/Timeframe.md +40 -0
- data/docs/api/yard/HTM/TimeframeExtractor/Result.md +24 -0
- data/docs/api/yard/HTM/TimeframeExtractor.md +45 -0
- data/docs/api/yard/HTM/ValidationError.md +20 -0
- data/docs/api/yard/HTM/WorkingMemory.md +131 -0
- data/docs/api/yard/HTM.md +80 -0
- data/docs/api/yard/index.csv +179 -0
- data/docs/api/yard-reference.md +51 -0
- data/docs/architecture/adrs/001-postgresql-timescaledb.md +1 -1
- data/docs/architecture/adrs/003-ollama-embeddings.md +1 -1
- data/docs/architecture/adrs/010-redis-working-memory-rejected.md +2 -27
- data/docs/architecture/adrs/index.md +2 -13
- data/docs/architecture/hive-mind.md +165 -166
- data/docs/architecture/index.md +2 -2
- data/docs/architecture/overview.md +5 -171
- data/docs/architecture/two-tier-memory.md +1 -35
- data/docs/assets/images/adr-010-current-architecture.svg +37 -0
- data/docs/assets/images/adr-010-proposed-architecture.svg +48 -0
- data/docs/assets/images/adr-dependency-tree.svg +93 -0
- data/docs/assets/images/class-hierarchy.svg +55 -0
- data/docs/assets/images/exception-hierarchy.svg +45 -0
- data/docs/assets/images/htm-architecture-overview.svg +83 -0
- data/docs/assets/images/htm-complete-memory-flow.svg +160 -0
- data/docs/assets/images/htm-context-assembly-flow.svg +148 -0
- data/docs/assets/images/htm-eviction-process.svg +141 -0
- data/docs/assets/images/htm-memory-addition-flow.svg +138 -0
- data/docs/assets/images/htm-memory-recall-flow.svg +152 -0
- data/docs/assets/images/htm-node-states.svg +123 -0
- data/docs/assets/images/project-structure.svg +78 -0
- data/docs/assets/images/test-directory-structure.svg +38 -0
- data/{dbdoc → docs/database}/README.md +127 -125
- data/docs/database/public.file_sources.md +42 -0
- data/docs/database/public.file_sources.svg +211 -0
- data/{dbdoc → docs/database}/public.node_tags.md +7 -8
- data/docs/database/public.node_tags.svg +239 -0
- data/{dbdoc → docs/database}/public.nodes.md +22 -17
- data/docs/database/public.nodes.svg +271 -0
- data/docs/database/public.robot_nodes.md +46 -0
- data/docs/database/public.robot_nodes.svg +243 -0
- data/{dbdoc → docs/database}/public.robots.md +2 -3
- data/docs/database/public.robots.svg +161 -0
- data/docs/database/public.tags.svg +139 -0
- data/{dbdoc → docs/database}/schema.json +941 -630
- data/docs/database/schema.svg +282 -0
- data/docs/development/index.md +1 -29
- data/docs/development/schema.md +134 -309
- data/docs/development/testing.md +1 -9
- data/docs/getting-started/index.md +47 -0
- data/docs/{installation.md → getting-started/installation.md} +2 -2
- data/docs/{quick-start.md → getting-started/quick-start.md} +5 -5
- data/docs/guides/adding-memories.md +295 -643
- data/docs/guides/recalling-memories.md +36 -1
- data/docs/guides/search-strategies.md +85 -51
- data/docs/images/htm-er-diagram.svg +156 -0
- data/docs/index.md +16 -31
- data/docs/multi_framework_support.md +4 -4
- data/examples/README.md +280 -0
- data/examples/basic_usage.rb +18 -16
- data/examples/cli_app/htm_cli.rb +146 -8
- data/examples/cli_app/temp.log +93 -0
- data/examples/custom_llm_configuration.rb +1 -2
- data/examples/example_app/app.rb +11 -14
- data/examples/file_loader_usage.rb +177 -0
- data/examples/robot_groups/lib/robot_group.rb +419 -0
- data/examples/robot_groups/lib/working_memory_channel.rb +140 -0
- data/examples/robot_groups/multi_process.rb +286 -0
- data/examples/robot_groups/robot_worker.rb +136 -0
- data/examples/robot_groups/same_process.rb +229 -0
- data/examples/sinatra_app/Gemfile +1 -0
- data/examples/sinatra_app/Gemfile.lock +166 -0
- data/examples/sinatra_app/app.rb +219 -24
- data/examples/timeframe_demo.rb +276 -0
- data/lib/htm/active_record_config.rb +10 -3
- data/lib/htm/circuit_breaker.rb +202 -0
- data/lib/htm/configuration.rb +313 -80
- data/lib/htm/database.rb +67 -36
- data/lib/htm/embedding_service.rb +39 -2
- data/lib/htm/errors.rb +131 -11
- data/lib/htm/{sinatra.rb → integrations/sinatra.rb} +87 -12
- data/lib/htm/job_adapter.rb +10 -3
- data/lib/htm/jobs/generate_embedding_job.rb +5 -4
- data/lib/htm/jobs/generate_tags_job.rb +4 -0
- data/lib/htm/loaders/markdown_loader.rb +263 -0
- data/lib/htm/loaders/paragraph_chunker.rb +112 -0
- data/lib/htm/long_term_memory.rb +601 -321
- data/lib/htm/models/file_source.rb +99 -0
- data/lib/htm/models/node.rb +116 -12
- data/lib/htm/models/robot.rb +53 -4
- data/lib/htm/models/robot_node.rb +51 -0
- data/lib/htm/models/tag.rb +302 -0
- data/lib/htm/observability.rb +395 -0
- data/lib/htm/tag_service.rb +60 -3
- data/lib/htm/tasks.rb +29 -0
- data/lib/htm/timeframe.rb +194 -0
- data/lib/htm/timeframe_extractor.rb +307 -0
- data/lib/htm/version.rb +1 -1
- data/lib/htm/working_memory.rb +165 -70
- data/lib/htm.rb +352 -133
- data/lib/tasks/doc.rake +300 -0
- data/lib/tasks/files.rake +299 -0
- data/lib/tasks/htm.rake +188 -2
- data/lib/tasks/jobs.rake +10 -12
- data/lib/tasks/tags.rake +194 -0
- data/mkdocs.yml +91 -9
- data/notes/ARCHITECTURE_REVIEW.md +1167 -0
- data/notes/IMPLEMENTATION_SUMMARY.md +606 -0
- data/notes/MULTI_FRAMEWORK_IMPLEMENTATION.md +451 -0
- data/notes/next_steps.md +100 -0
- data/notes/plan.md +627 -0
- data/notes/tag_ontology_enhancement_ideas.md +222 -0
- data/notes/timescaledb_removal_summary.md +200 -0
- metadata +177 -37
- data/db/migrate/20250101000002_create_robots.rb +0 -14
- data/db/migrate/20250101000003_create_nodes.rb +0 -42
- data/db/migrate/20250101000005_create_tags.rb +0 -38
- data/db/migrate/20250101000007_add_node_vector_indexes.rb +0 -30
- data/dbdoc/public.node_tags.svg +0 -112
- data/dbdoc/public.nodes.svg +0 -118
- data/dbdoc/public.robots.svg +0 -90
- data/dbdoc/public.tags.svg +0 -60
- data/dbdoc/schema.svg +0 -154
- data/{dbdoc → docs/database}/public.node_stats.md +0 -0
- data/{dbdoc → docs/database}/public.node_stats.svg +0 -0
- data/{dbdoc → docs/database}/public.nodes_tags.md +0 -0
- data/{dbdoc → docs/database}/public.nodes_tags.svg +0 -0
- data/{dbdoc → docs/database}/public.ontology_structure.md +0 -0
- data/{dbdoc → docs/database}/public.ontology_structure.svg +0 -0
- data/{dbdoc → docs/database}/public.operations_log.md +0 -0
- data/{dbdoc → docs/database}/public.operations_log.svg +0 -0
- data/{dbdoc → docs/database}/public.relationships.md +0 -0
- data/{dbdoc → docs/database}/public.relationships.svg +0 -0
- data/{dbdoc → docs/database}/public.robot_activity.md +0 -0
- data/{dbdoc → docs/database}/public.robot_activity.svg +0 -0
- data/{dbdoc → docs/database}/public.schema_migrations.md +0 -0
- data/{dbdoc → docs/database}/public.schema_migrations.svg +0 -0
- data/{dbdoc → docs/database}/public.tags.md +3 -3
- /data/{dbdoc → docs/database}/public.topic_relationships.md +0 -0
- /data/{dbdoc → docs/database}/public.topic_relationships.svg +0 -0
data/lib/tasks/htm.rake
CHANGED
|
@@ -124,6 +124,161 @@ namespace :htm do
|
|
|
124
124
|
HTM::Database.info
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
+
desc "Show record counts for all HTM tables"
|
|
128
|
+
task :stats do
|
|
129
|
+
require 'htm'
|
|
130
|
+
|
|
131
|
+
# Ensure database connection
|
|
132
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
133
|
+
|
|
134
|
+
puts "\nHTM Database Statistics"
|
|
135
|
+
puts "=" * 50
|
|
136
|
+
|
|
137
|
+
# Define tables with their models and optional extra info
|
|
138
|
+
tables = [
|
|
139
|
+
{ name: 'robots', model: HTM::Models::Robot },
|
|
140
|
+
{ name: 'nodes', model: HTM::Models::Node, extras: ->(m) {
|
|
141
|
+
# Node uses default_scope for active nodes, so m.count is active count
|
|
142
|
+
active = m.count
|
|
143
|
+
deleted = m.deleted.count
|
|
144
|
+
with_embedding = m.where.not(embedding: nil).count
|
|
145
|
+
" (active: #{active}, deleted: #{deleted}, with embeddings: #{with_embedding})"
|
|
146
|
+
}},
|
|
147
|
+
{ name: 'tags', model: HTM::Models::Tag },
|
|
148
|
+
{ name: 'nodes_tags', model: HTM::Models::NodeTag },
|
|
149
|
+
{ name: 'file_sources', model: HTM::Models::FileSource }
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
total = 0
|
|
153
|
+
max_name_len = tables.map { |t| t[:name].length }.max
|
|
154
|
+
|
|
155
|
+
tables.each do |table|
|
|
156
|
+
count = table[:model].count
|
|
157
|
+
total += count
|
|
158
|
+
extras = table[:extras] ? table[:extras].call(table[:model]) : ''
|
|
159
|
+
|
|
160
|
+
printf " %-#{max_name_len}s %8d%s\n", table[:name], count, extras
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
puts "-" * 50
|
|
164
|
+
printf " %-#{max_name_len}s %8d\n", "Total", total
|
|
165
|
+
|
|
166
|
+
# Additional stats
|
|
167
|
+
puts "\nAdditional Statistics:"
|
|
168
|
+
|
|
169
|
+
# Nodes per robot (via robot_nodes join table)
|
|
170
|
+
robot_counts = HTM::Models::RobotNode
|
|
171
|
+
.joins(:node)
|
|
172
|
+
.where(nodes: { deleted_at: nil })
|
|
173
|
+
.group(:robot_id)
|
|
174
|
+
.count
|
|
175
|
+
.transform_keys { |id| HTM::Models::Robot.find(id).name rescue "Unknown (#{id})" }
|
|
176
|
+
.sort_by { |_, count| -count }
|
|
177
|
+
.first(5)
|
|
178
|
+
|
|
179
|
+
if robot_counts.any?
|
|
180
|
+
puts " Top robots by node count:"
|
|
181
|
+
robot_counts.each do |name, count|
|
|
182
|
+
puts " #{name}: #{count}"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Tag distribution
|
|
187
|
+
top_root_tags = HTM::Models::Tag
|
|
188
|
+
.select("split_part(name, ':', 1) as root, count(*) as cnt")
|
|
189
|
+
.group("split_part(name, ':', 1)")
|
|
190
|
+
.order("cnt DESC")
|
|
191
|
+
.limit(5)
|
|
192
|
+
.map { |t| [t.root, t.cnt] }
|
|
193
|
+
|
|
194
|
+
if top_root_tags.any?
|
|
195
|
+
puts " Top root tag categories:"
|
|
196
|
+
top_root_tags.each do |root, count|
|
|
197
|
+
puts " #{root}: #{count}"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
puts
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
namespace :rebuild do
|
|
205
|
+
desc "Rebuild embeddings for all nodes. Clears existing embeddings and regenerates via LLM."
|
|
206
|
+
task :embeddings do
|
|
207
|
+
require 'htm'
|
|
208
|
+
require 'ruby-progressbar'
|
|
209
|
+
|
|
210
|
+
# Ensure database connection
|
|
211
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
212
|
+
|
|
213
|
+
# Node uses default_scope for active (non-deleted) nodes
|
|
214
|
+
node_count = HTM::Models::Node.count
|
|
215
|
+
with_embeddings = HTM::Models::Node.where.not(embedding: nil).count
|
|
216
|
+
without_embeddings = node_count - with_embeddings
|
|
217
|
+
|
|
218
|
+
puts "\nHTM Embeddings Rebuild"
|
|
219
|
+
puts "=" * 50
|
|
220
|
+
puts "Current state:"
|
|
221
|
+
puts " Total active nodes: #{node_count}"
|
|
222
|
+
puts " With embeddings: #{with_embeddings}"
|
|
223
|
+
puts " Without embeddings: #{without_embeddings}"
|
|
224
|
+
puts "\nThis will regenerate embeddings for ALL #{node_count} nodes."
|
|
225
|
+
puts "This operation may take a long time depending on your LLM provider."
|
|
226
|
+
print "\nType 'yes' to confirm: "
|
|
227
|
+
|
|
228
|
+
confirmation = $stdin.gets&.strip
|
|
229
|
+
unless confirmation == 'yes'
|
|
230
|
+
puts "Aborted."
|
|
231
|
+
next
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
puts "\nClearing existing embeddings..."
|
|
235
|
+
cleared = HTM::Models::Node.where.not(embedding: nil).update_all(embedding: nil)
|
|
236
|
+
puts " Cleared #{cleared} embeddings"
|
|
237
|
+
|
|
238
|
+
puts "\nGenerating embeddings for #{node_count} nodes..."
|
|
239
|
+
puts "(This may take a while depending on your LLM provider)\n"
|
|
240
|
+
|
|
241
|
+
# Create progress bar with ETA
|
|
242
|
+
progressbar = ProgressBar.create(
|
|
243
|
+
total: node_count,
|
|
244
|
+
format: '%t: |%B| %c/%C (%p%%) %e',
|
|
245
|
+
title: 'Embedding',
|
|
246
|
+
output: $stdout,
|
|
247
|
+
smoothing: 0.5
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
# Process each active node (default_scope excludes deleted)
|
|
251
|
+
errors = 0
|
|
252
|
+
success = 0
|
|
253
|
+
|
|
254
|
+
HTM::Models::Node.find_each do |node|
|
|
255
|
+
begin
|
|
256
|
+
# Generate embedding directly (not via job since we cleared them)
|
|
257
|
+
result = HTM::EmbeddingService.generate(node.content)
|
|
258
|
+
|
|
259
|
+
node.update!(embedding: result[:storage_embedding])
|
|
260
|
+
success += 1
|
|
261
|
+
rescue StandardError => e
|
|
262
|
+
errors += 1
|
|
263
|
+
progressbar.log " Error on node #{node.id}: #{e.message}"
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
progressbar.increment
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
progressbar.finish
|
|
270
|
+
|
|
271
|
+
# Final stats
|
|
272
|
+
final_with_embeddings = HTM::Models::Node.where.not(embedding: nil).count
|
|
273
|
+
|
|
274
|
+
puts "\nRebuild complete!"
|
|
275
|
+
puts " Nodes processed: #{node_count}"
|
|
276
|
+
puts " Successful: #{success}"
|
|
277
|
+
puts " Errors: #{errors}"
|
|
278
|
+
puts " Nodes with embeddings: #{final_with_embeddings}"
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
127
282
|
namespace :schema do
|
|
128
283
|
desc "Dump current schema to db/schema.sql"
|
|
129
284
|
task :dump do
|
|
@@ -138,10 +293,41 @@ namespace :htm do
|
|
|
138
293
|
end
|
|
139
294
|
end
|
|
140
295
|
|
|
141
|
-
|
|
142
|
-
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
namespace :doc do
|
|
299
|
+
desc "Generate/update database documentation in docs/database/ (uses .tbls.yml)"
|
|
300
|
+
task :db do
|
|
301
|
+
unless system("which tbls > /dev/null 2>&1")
|
|
302
|
+
puts "Error: 'tbls' is not installed."
|
|
303
|
+
puts "Install it with: brew install tbls"
|
|
304
|
+
exit 1
|
|
305
|
+
end
|
|
143
306
|
require 'htm'
|
|
144
307
|
HTM::Database.generate_docs
|
|
145
308
|
end
|
|
309
|
+
|
|
310
|
+
desc "Build documentation site with MkDocs"
|
|
311
|
+
task :build do
|
|
312
|
+
unless system("which mkdocs > /dev/null 2>&1")
|
|
313
|
+
puts "Error: 'mkdocs' is not installed."
|
|
314
|
+
puts "Install it with: brew install mkdocs"
|
|
315
|
+
exit 1
|
|
316
|
+
end
|
|
317
|
+
sh "mkdocs build"
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
desc "Serve documentation site locally with MkDocs"
|
|
321
|
+
task :serve do
|
|
322
|
+
unless system("which mkdocs > /dev/null 2>&1")
|
|
323
|
+
puts "Error: 'mkdocs' is not installed."
|
|
324
|
+
puts "Install it with: brew install mkdocs"
|
|
325
|
+
exit 1
|
|
326
|
+
end
|
|
327
|
+
sh "mkdocs serve"
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
desc "Generate DB docs, YARD API docs, build site, and serve locally"
|
|
331
|
+
task :all => [:db, :yard, :build, :serve]
|
|
146
332
|
end
|
|
147
333
|
end
|
data/lib/tasks/jobs.rake
CHANGED
|
@@ -42,9 +42,13 @@ namespace :htm do
|
|
|
42
42
|
# Tags by depth
|
|
43
43
|
if total_tags > 0
|
|
44
44
|
puts "\nTag hierarchy breakdown:"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
depth_counts = Hash.new(0)
|
|
46
|
+
HTM::Models::Tag.pluck(:name).each do |name|
|
|
47
|
+
depth = name.count(':')
|
|
48
|
+
depth_counts[depth] += 1
|
|
49
|
+
end
|
|
50
|
+
depth_counts.keys.sort.each do |depth|
|
|
51
|
+
puts " Depth #{depth}: #{depth_counts[depth]} tags"
|
|
48
52
|
end
|
|
49
53
|
end
|
|
50
54
|
|
|
@@ -84,10 +88,7 @@ namespace :htm do
|
|
|
84
88
|
begin
|
|
85
89
|
# Use the service class directly (same as job)
|
|
86
90
|
result = HTM::EmbeddingService.generate(node.content)
|
|
87
|
-
node.update!(
|
|
88
|
-
embedding: result[:storage_embedding],
|
|
89
|
-
embedding_dimension: result[:dimension]
|
|
90
|
-
)
|
|
91
|
+
node.update!(embedding: result[:storage_embedding])
|
|
91
92
|
processed += 1
|
|
92
93
|
print "\rProcessed: #{processed}/#{total}"
|
|
93
94
|
rescue StandardError => e
|
|
@@ -187,10 +188,7 @@ namespace :htm do
|
|
|
187
188
|
begin
|
|
188
189
|
# Use the service class directly to regenerate
|
|
189
190
|
result = HTM::EmbeddingService.generate(node.content)
|
|
190
|
-
node.update!(
|
|
191
|
-
embedding: result[:storage_embedding],
|
|
192
|
-
embedding_dimension: result[:dimension]
|
|
193
|
-
)
|
|
191
|
+
node.update!(embedding: result[:storage_embedding])
|
|
194
192
|
processed += 1
|
|
195
193
|
print "\rProcessed: #{processed}/#{total}"
|
|
196
194
|
rescue StandardError => e
|
|
@@ -270,7 +268,7 @@ namespace :htm do
|
|
|
270
268
|
HTM::ActiveRecordConfig.establish_connection!
|
|
271
269
|
|
|
272
270
|
puts "Clearing embeddings..."
|
|
273
|
-
HTM::Models::Node.update_all(embedding: nil
|
|
271
|
+
HTM::Models::Node.update_all(embedding: nil)
|
|
274
272
|
|
|
275
273
|
puts "Clearing tags..."
|
|
276
274
|
HTM::Models::NodeTag.delete_all
|
data/lib/tasks/tags.rake
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# HTM Tag Management Tasks
|
|
4
|
+
#
|
|
5
|
+
# These tasks are available to any application using the HTM gem.
|
|
6
|
+
# Add to your application's Rakefile:
|
|
7
|
+
#
|
|
8
|
+
# require 'htm/tasks'
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
namespace :htm do
|
|
12
|
+
namespace :tags do
|
|
13
|
+
desc "Display tags as a hierarchical tree (text format). Optional prefix filter."
|
|
14
|
+
task :tree, [:prefix] do |_t, args|
|
|
15
|
+
require 'htm'
|
|
16
|
+
|
|
17
|
+
# Ensure database connection
|
|
18
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
19
|
+
|
|
20
|
+
tags = args[:prefix] ? HTM::Models::Tag.with_prefix(args[:prefix]) : HTM::Models::Tag.all
|
|
21
|
+
count = tags.count
|
|
22
|
+
|
|
23
|
+
if count.zero?
|
|
24
|
+
puts args[:prefix] ? "No tags found with prefix '#{args[:prefix]}'." : "No tags found in database."
|
|
25
|
+
next
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Display tree using Tag model method
|
|
29
|
+
puts "\nHTM Tags Tree#{args[:prefix] ? " (prefix: #{args[:prefix]})" : ''}"
|
|
30
|
+
puts "=" * 40
|
|
31
|
+
print tags.tree_string
|
|
32
|
+
puts "\nTotal tags: #{count}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc "Export tags as Mermaid flowchart to tags.md. Optional prefix filter."
|
|
36
|
+
task :mermaid, [:prefix] do |_t, args|
|
|
37
|
+
require 'htm'
|
|
38
|
+
|
|
39
|
+
# Ensure database connection
|
|
40
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
41
|
+
|
|
42
|
+
tags = args[:prefix] ? HTM::Models::Tag.with_prefix(args[:prefix]) : HTM::Models::Tag.all
|
|
43
|
+
count = tags.count
|
|
44
|
+
|
|
45
|
+
if count.zero?
|
|
46
|
+
puts args[:prefix] ? "No tags found with prefix '#{args[:prefix]}'." : "No tags found in database."
|
|
47
|
+
next
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
mermaid = tags.tree_mermaid(direction: 'TD')
|
|
51
|
+
File.write('tags.md', mermaid)
|
|
52
|
+
|
|
53
|
+
puts "Mermaid flowchart written to: tags.md"
|
|
54
|
+
puts "Tags exported: #{count}#{args[:prefix] ? " (prefix: #{args[:prefix]})" : ''}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc "Export tags as SVG visualization to tags.svg. Optional prefix filter."
|
|
58
|
+
task :svg, [:prefix] do |_t, args|
|
|
59
|
+
require 'htm'
|
|
60
|
+
|
|
61
|
+
# Ensure database connection
|
|
62
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
63
|
+
|
|
64
|
+
tags = args[:prefix] ? HTM::Models::Tag.with_prefix(args[:prefix]) : HTM::Models::Tag.all
|
|
65
|
+
count = tags.count
|
|
66
|
+
|
|
67
|
+
if count.zero?
|
|
68
|
+
puts args[:prefix] ? "No tags found with prefix '#{args[:prefix]}'." : "No tags found in database."
|
|
69
|
+
next
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
title = args[:prefix] ? "HTM Tags: #{args[:prefix]}*" : 'HTM Tag Hierarchy'
|
|
73
|
+
svg = tags.tree_svg(title: title)
|
|
74
|
+
File.write('tags.svg', svg)
|
|
75
|
+
|
|
76
|
+
puts "SVG visualization written to: tags.svg"
|
|
77
|
+
puts "Tags exported: #{count}#{args[:prefix] ? " (prefix: #{args[:prefix]})" : ''}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
desc "Rebuild all tags from node content. Clears existing tags and regenerates using LLM."
|
|
81
|
+
task :rebuild do
|
|
82
|
+
require 'htm'
|
|
83
|
+
|
|
84
|
+
# Ensure database connection
|
|
85
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
86
|
+
|
|
87
|
+
# Node uses default_scope for active (non-deleted) nodes
|
|
88
|
+
node_count = HTM::Models::Node.count
|
|
89
|
+
tag_count = HTM::Models::Tag.count
|
|
90
|
+
node_tag_count = HTM::Models::NodeTag.count
|
|
91
|
+
|
|
92
|
+
puts "\nHTM Tags Rebuild"
|
|
93
|
+
puts "=" * 40
|
|
94
|
+
puts "This will:"
|
|
95
|
+
puts " - Delete #{node_tag_count} node-tag associations"
|
|
96
|
+
puts " - Delete #{tag_count} tags"
|
|
97
|
+
puts " - Regenerate tags for #{node_count} nodes using LLM"
|
|
98
|
+
puts "\nThis operation cannot be undone."
|
|
99
|
+
print "\nType 'yes' to confirm: "
|
|
100
|
+
|
|
101
|
+
confirmation = $stdin.gets&.strip
|
|
102
|
+
unless confirmation == 'yes'
|
|
103
|
+
puts "Aborted."
|
|
104
|
+
next
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
puts "\nClearing existing tags..."
|
|
108
|
+
|
|
109
|
+
# Clear join table first (foreign key constraint)
|
|
110
|
+
deleted_associations = HTM::Models::NodeTag.delete_all
|
|
111
|
+
puts " Deleted #{deleted_associations} node-tag associations"
|
|
112
|
+
|
|
113
|
+
# Clear tags table
|
|
114
|
+
deleted_tags = HTM::Models::Tag.delete_all
|
|
115
|
+
puts " Deleted #{deleted_tags} tags"
|
|
116
|
+
|
|
117
|
+
puts "\nRegenerating tags for #{node_count} nodes..."
|
|
118
|
+
puts "(This may take a while depending on your LLM provider)\n"
|
|
119
|
+
|
|
120
|
+
require 'ruby-progressbar'
|
|
121
|
+
|
|
122
|
+
# Create progress bar with ETA
|
|
123
|
+
progressbar = ProgressBar.create(
|
|
124
|
+
total: node_count,
|
|
125
|
+
format: '%t: |%B| %c/%C (%p%%) %e',
|
|
126
|
+
title: 'Processing',
|
|
127
|
+
output: $stdout,
|
|
128
|
+
smoothing: 0.5
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Process each active node (default_scope excludes deleted)
|
|
132
|
+
errors = 0
|
|
133
|
+
|
|
134
|
+
HTM::Models::Node.find_each do |node|
|
|
135
|
+
begin
|
|
136
|
+
HTM::Jobs::GenerateTagsJob.perform(node_id: node.id)
|
|
137
|
+
rescue StandardError => e
|
|
138
|
+
errors += 1
|
|
139
|
+
progressbar.log " Error on node #{node.id}: #{e.message}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
progressbar.increment
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
progressbar.finish
|
|
146
|
+
|
|
147
|
+
# Final stats
|
|
148
|
+
new_tag_count = HTM::Models::Tag.count
|
|
149
|
+
new_association_count = HTM::Models::NodeTag.count
|
|
150
|
+
|
|
151
|
+
puts "\nRebuild complete!"
|
|
152
|
+
puts " Nodes processed: #{node_count}"
|
|
153
|
+
puts " Errors: #{errors}"
|
|
154
|
+
puts " Tags created: #{new_tag_count}"
|
|
155
|
+
puts " Node-tag associations: #{new_association_count}"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
desc "Export tags in all formats (tags.txt, tags.md, tags.svg). Optional prefix filter."
|
|
159
|
+
task :export, [:prefix] do |_t, args|
|
|
160
|
+
require 'htm'
|
|
161
|
+
|
|
162
|
+
# Ensure database connection
|
|
163
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
164
|
+
|
|
165
|
+
tags = args[:prefix] ? HTM::Models::Tag.with_prefix(args[:prefix]) : HTM::Models::Tag.all
|
|
166
|
+
count = tags.count
|
|
167
|
+
|
|
168
|
+
if count.zero?
|
|
169
|
+
puts args[:prefix] ? "No tags found with prefix '#{args[:prefix]}'." : "No tags found in database."
|
|
170
|
+
next
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
prefix_note = args[:prefix] ? " (prefix: #{args[:prefix]})" : ''
|
|
174
|
+
title = args[:prefix] ? "HTM Tags: #{args[:prefix]}*" : 'HTM Tag Hierarchy'
|
|
175
|
+
|
|
176
|
+
# Export text tree
|
|
177
|
+
text_content = "HTM Tags Tree#{prefix_note}\n" + ("=" * 40) + "\n"
|
|
178
|
+
text_content += tags.tree_string
|
|
179
|
+
text_content += "\nTotal tags: #{count}\n"
|
|
180
|
+
File.write('tags.txt', text_content)
|
|
181
|
+
puts "Text tree written to: tags.txt"
|
|
182
|
+
|
|
183
|
+
# Export Mermaid
|
|
184
|
+
File.write('tags.md', tags.tree_mermaid)
|
|
185
|
+
puts "Mermaid flowchart written to: tags.md"
|
|
186
|
+
|
|
187
|
+
# Export SVG
|
|
188
|
+
File.write('tags.svg', tags.tree_svg(title: title))
|
|
189
|
+
puts "SVG visualization written to: tags.svg"
|
|
190
|
+
|
|
191
|
+
puts "\nTags exported: #{count}#{prefix_note}"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
data/mkdocs.yml
CHANGED
|
@@ -13,21 +13,21 @@ edit_uri: edit/main/docs/
|
|
|
13
13
|
# Configuration
|
|
14
14
|
theme:
|
|
15
15
|
name: material
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
# Color scheme - Default to light mode
|
|
18
18
|
palette:
|
|
19
19
|
# Palette toggle for light mode (default)
|
|
20
20
|
- scheme: default
|
|
21
|
-
primary:
|
|
22
|
-
accent:
|
|
21
|
+
primary: indigo
|
|
22
|
+
accent: deep purple
|
|
23
23
|
toggle:
|
|
24
24
|
icon: material/brightness-7
|
|
25
25
|
name: Switch to dark mode
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
# Palette toggle for dark mode
|
|
28
28
|
- scheme: slate
|
|
29
|
-
primary:
|
|
30
|
-
accent:
|
|
29
|
+
primary: indigo
|
|
30
|
+
accent: deep purple
|
|
31
31
|
toggle:
|
|
32
32
|
icon: material/brightness-4
|
|
33
33
|
name: Switch to light mode
|
|
@@ -37,6 +37,10 @@ theme:
|
|
|
37
37
|
text: Roboto
|
|
38
38
|
code: Roboto Mono
|
|
39
39
|
|
|
40
|
+
# Logo and icon
|
|
41
|
+
icon:
|
|
42
|
+
repo: fontawesome/brands/github
|
|
43
|
+
|
|
40
44
|
# Theme features
|
|
41
45
|
features:
|
|
42
46
|
# Navigation
|
|
@@ -48,6 +52,7 @@ theme:
|
|
|
48
52
|
- navigation.path
|
|
49
53
|
- navigation.indexes
|
|
50
54
|
- navigation.top
|
|
55
|
+
- navigation.footer
|
|
51
56
|
|
|
52
57
|
# Table of contents
|
|
53
58
|
- toc.follow
|
|
@@ -72,6 +77,7 @@ theme:
|
|
|
72
77
|
plugins:
|
|
73
78
|
- search:
|
|
74
79
|
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
|
|
80
|
+
- tags
|
|
75
81
|
|
|
76
82
|
# Extensions
|
|
77
83
|
markdown_extensions:
|
|
@@ -82,6 +88,7 @@ markdown_extensions:
|
|
|
82
88
|
- def_list
|
|
83
89
|
- footnotes
|
|
84
90
|
- md_in_html
|
|
91
|
+
- tables
|
|
85
92
|
- toc:
|
|
86
93
|
permalink: true
|
|
87
94
|
title: On this page
|
|
@@ -92,6 +99,7 @@ markdown_extensions:
|
|
|
92
99
|
- pymdownx.betterem:
|
|
93
100
|
smart_enable: all
|
|
94
101
|
- pymdownx.caret
|
|
102
|
+
- pymdownx.critic
|
|
95
103
|
- pymdownx.details
|
|
96
104
|
- pymdownx.emoji:
|
|
97
105
|
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
|
@@ -106,8 +114,11 @@ markdown_extensions:
|
|
|
106
114
|
repo_url_shorthand: true
|
|
107
115
|
user: madbomber
|
|
108
116
|
repo: htm
|
|
117
|
+
normalize_issue_symbols: true
|
|
109
118
|
- pymdownx.mark
|
|
110
119
|
- pymdownx.smartsymbols
|
|
120
|
+
- pymdownx.snippets:
|
|
121
|
+
check_paths: true
|
|
111
122
|
- pymdownx.superfences:
|
|
112
123
|
custom_fences:
|
|
113
124
|
- name: mermaid
|
|
@@ -138,11 +149,28 @@ extra:
|
|
|
138
149
|
link: https://rubygems.org/gems/htm
|
|
139
150
|
name: HTM on RubyGems
|
|
140
151
|
|
|
152
|
+
analytics:
|
|
153
|
+
feedback:
|
|
154
|
+
title: Was this page helpful?
|
|
155
|
+
ratings:
|
|
156
|
+
- icon: material/emoticon-happy-outline
|
|
157
|
+
name: This page was helpful
|
|
158
|
+
data: 1
|
|
159
|
+
note: >-
|
|
160
|
+
Thanks for your feedback!
|
|
161
|
+
- icon: material/emoticon-sad-outline
|
|
162
|
+
name: This page could be improved
|
|
163
|
+
data: 0
|
|
164
|
+
note: >-
|
|
165
|
+
Thanks for your feedback! Help us improve by creating an issue.
|
|
166
|
+
|
|
141
167
|
# Navigation
|
|
142
168
|
nav:
|
|
143
169
|
- Home: index.md
|
|
144
|
-
-
|
|
145
|
-
|
|
170
|
+
- Getting Started:
|
|
171
|
+
- getting-started/index.md
|
|
172
|
+
- Installation: getting-started/installation.md
|
|
173
|
+
- Quick Start: getting-started/quick-start.md
|
|
146
174
|
- Architecture:
|
|
147
175
|
- architecture/index.md
|
|
148
176
|
- Overview: architecture/overview.md
|
|
@@ -178,13 +206,67 @@ nav:
|
|
|
178
206
|
- Long-Term Memory: api/long-term-memory.md
|
|
179
207
|
- Embedding Service: api/embedding-service.md
|
|
180
208
|
- Database: api/database.md
|
|
209
|
+
- YARD Reference:
|
|
210
|
+
- api/yard-reference.md
|
|
211
|
+
- HTM Module: api/yard/HTM.md
|
|
212
|
+
- Core Classes:
|
|
213
|
+
- Configuration: api/yard/HTM/Configuration.md
|
|
214
|
+
- Database: api/yard/HTM/Database.md
|
|
215
|
+
- LongTermMemory: api/yard/HTM/LongTermMemory.md
|
|
216
|
+
- WorkingMemory: api/yard/HTM/WorkingMemory.md
|
|
217
|
+
- Services:
|
|
218
|
+
- EmbeddingService: api/yard/HTM/EmbeddingService.md
|
|
219
|
+
- TagService: api/yard/HTM/TagService.md
|
|
220
|
+
- JobAdapter: api/yard/HTM/JobAdapter.md
|
|
221
|
+
- Utilities:
|
|
222
|
+
- CircuitBreaker: api/yard/HTM/CircuitBreaker.md
|
|
223
|
+
- Observability: api/yard/HTM/Observability.md
|
|
224
|
+
- Timeframe: api/yard/HTM/Timeframe.md
|
|
225
|
+
- TimeframeExtractor: api/yard/HTM/TimeframeExtractor.md
|
|
226
|
+
- Internal:
|
|
227
|
+
- ActiveRecordConfig: api/yard/HTM/ActiveRecordConfig.md
|
|
228
|
+
- Railtie: api/yard/HTM/Railtie.md
|
|
229
|
+
- Errors:
|
|
230
|
+
- Error: api/yard/HTM/Error.md
|
|
231
|
+
- AuthorizationError: api/yard/HTM/AuthorizationError.md
|
|
232
|
+
- CircuitBreakerOpenError: api/yard/HTM/CircuitBreakerOpenError.md
|
|
233
|
+
- DatabaseError: api/yard/HTM/DatabaseError.md
|
|
234
|
+
- EmbeddingError: api/yard/HTM/EmbeddingError.md
|
|
235
|
+
- NotFoundError: api/yard/HTM/NotFoundError.md
|
|
236
|
+
- QueryTimeoutError: api/yard/HTM/QueryTimeoutError.md
|
|
237
|
+
- ResourceExhaustedError: api/yard/HTM/ResourceExhaustedError.md
|
|
238
|
+
- TagError: api/yard/HTM/TagError.md
|
|
239
|
+
- ValidationError: api/yard/HTM/ValidationError.md
|
|
240
|
+
- Result Types:
|
|
241
|
+
- Timeframe Result: api/yard/HTM/Timeframe/Result.md
|
|
242
|
+
- TimeframeExtractor Result: api/yard/HTM/TimeframeExtractor/Result.md
|
|
181
243
|
- Development:
|
|
182
244
|
- development/index.md
|
|
183
245
|
- Setup: development/setup.md
|
|
184
246
|
- Testing: development/testing.md
|
|
185
247
|
- Contributing: development/contributing.md
|
|
186
248
|
- Database Schema: development/schema.md
|
|
249
|
+
- Database Tables:
|
|
250
|
+
- database/README.md
|
|
251
|
+
- Core Tables:
|
|
252
|
+
- Robots: database/public.robots.md
|
|
253
|
+
- Nodes: database/public.nodes.md
|
|
254
|
+
- Tags: database/public.tags.md
|
|
255
|
+
- File Sources: database/public.file_sources.md
|
|
256
|
+
- Join Tables:
|
|
257
|
+
- Node Tags: database/public.node_tags.md
|
|
258
|
+
- Nodes Tags (Legacy): database/public.nodes_tags.md
|
|
259
|
+
- Robot Nodes: database/public.robot_nodes.md
|
|
260
|
+
- Views & Stats:
|
|
261
|
+
- Node Stats: database/public.node_stats.md
|
|
262
|
+
- Robot Activity: database/public.robot_activity.md
|
|
263
|
+
- Topic Relationships: database/public.topic_relationships.md
|
|
264
|
+
- Ontology Structure: database/public.ontology_structure.md
|
|
265
|
+
- Relationships: database/public.relationships.md
|
|
266
|
+
- System:
|
|
267
|
+
- Operations Log: database/public.operations_log.md
|
|
268
|
+
- Schema Migrations: database/public.schema_migrations.md
|
|
187
269
|
- Multi-Framework Support: multi_framework_support.md
|
|
188
270
|
- Database Rake Tasks: database_rake_tasks.md
|
|
189
271
|
- Using Rake Tasks: using_rake_tasks_in_your_app.md
|
|
190
|
-
- Setup Local Database: setup_local_database.md
|
|
272
|
+
- Setup Local Database: setup_local_database.md
|