htm 0.0.11 → 0.0.15
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/.dictate.toml +46 -0
- data/.envrc +2 -0
- data/CHANGELOG.md +85 -2
- data/README.md +348 -79
- data/Rakefile +14 -2
- data/bin/htm_mcp.rb +94 -0
- data/config/database.yml +20 -13
- data/db/migrate/00003_create_file_sources.rb +5 -0
- data/db/migrate/00004_create_nodes.rb +17 -0
- data/db/migrate/00005_create_tags.rb +7 -0
- data/db/migrate/00006_create_node_tags.rb +2 -0
- data/db/migrate/00007_create_robot_nodes.rb +7 -0
- data/db/schema.sql +69 -100
- data/docs/api/index.md +1 -1
- data/docs/api/yard/HTM/Configuration.md +54 -0
- data/docs/api/yard/HTM/Database.md +13 -10
- data/docs/api/yard/HTM/EmbeddingService.md +5 -1
- data/docs/api/yard/HTM/LongTermMemory.md +18 -277
- data/docs/api/yard/HTM/PropositionError.md +18 -0
- data/docs/api/yard/HTM/PropositionService.md +66 -0
- data/docs/api/yard/HTM/QueryCache.md +88 -0
- data/docs/api/yard/HTM/RobotGroup.md +481 -0
- data/docs/api/yard/HTM/SqlBuilder.md +108 -0
- data/docs/api/yard/HTM/TagService.md +4 -0
- data/docs/api/yard/HTM/Telemetry/NullInstrument.md +13 -0
- data/docs/api/yard/HTM/Telemetry/NullMeter.md +15 -0
- data/docs/api/yard/HTM/Telemetry.md +109 -0
- data/docs/api/yard/HTM/WorkingMemoryChannel.md +176 -0
- data/docs/api/yard/HTM.md +8 -22
- data/docs/api/yard/index.csv +102 -25
- data/docs/api/yard-reference.md +8 -0
- data/docs/architecture/index.md +1 -1
- data/docs/assets/images/multi-provider-failover.svg +51 -0
- data/docs/assets/images/robot-group-architecture.svg +65 -0
- data/docs/database/README.md +3 -3
- data/docs/database/public.file_sources.svg +29 -21
- data/docs/database/public.node_tags.md +2 -0
- data/docs/database/public.node_tags.svg +53 -41
- data/docs/database/public.nodes.md +2 -0
- data/docs/database/public.nodes.svg +52 -40
- data/docs/database/public.robot_nodes.md +2 -0
- data/docs/database/public.robot_nodes.svg +30 -22
- data/docs/database/public.robots.svg +16 -12
- data/docs/database/public.tags.md +3 -0
- data/docs/database/public.tags.svg +41 -33
- data/docs/database/schema.json +66 -0
- data/docs/database/schema.svg +60 -48
- data/docs/development/index.md +14 -1
- data/docs/development/rake-tasks.md +1068 -0
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/quick-start.md +144 -155
- data/docs/guides/adding-memories.md +2 -3
- data/docs/guides/context-assembly.md +185 -184
- data/docs/guides/getting-started.md +154 -148
- data/docs/guides/index.md +8 -1
- data/docs/guides/long-term-memory.md +60 -92
- data/docs/guides/mcp-server.md +617 -0
- data/docs/guides/multi-robot.md +249 -345
- data/docs/guides/recalling-memories.md +153 -163
- data/docs/guides/robot-groups.md +604 -0
- data/docs/guides/search-strategies.md +61 -58
- data/docs/guides/working-memory.md +103 -136
- data/docs/images/telemetry-architecture.svg +153 -0
- data/docs/index.md +30 -26
- data/docs/telemetry.md +391 -0
- data/examples/README.md +46 -1
- data/examples/cli_app/README.md +1 -1
- data/examples/cli_app/htm_cli.rb +1 -1
- data/examples/robot_groups/robot_worker.rb +1 -2
- data/examples/robot_groups/same_process.rb +1 -4
- data/examples/sinatra_app/app.rb +1 -1
- data/examples/telemetry/README.md +147 -0
- data/examples/telemetry/SETUP_README.md +169 -0
- data/examples/telemetry/demo.rb +498 -0
- data/examples/telemetry/grafana/dashboards/htm-metrics.json +457 -0
- data/lib/htm/configuration.rb +261 -70
- data/lib/htm/database.rb +46 -22
- data/lib/htm/embedding_service.rb +24 -14
- data/lib/htm/errors.rb +15 -1
- data/lib/htm/jobs/generate_embedding_job.rb +19 -0
- data/lib/htm/jobs/generate_propositions_job.rb +103 -0
- data/lib/htm/jobs/generate_tags_job.rb +24 -0
- data/lib/htm/loaders/markdown_chunker.rb +79 -0
- data/lib/htm/loaders/markdown_loader.rb +41 -15
- data/lib/htm/long_term_memory/fulltext_search.rb +138 -0
- data/lib/htm/long_term_memory/hybrid_search.rb +324 -0
- data/lib/htm/long_term_memory/node_operations.rb +209 -0
- data/lib/htm/long_term_memory/relevance_scorer.rb +355 -0
- data/lib/htm/long_term_memory/robot_operations.rb +34 -0
- data/lib/htm/long_term_memory/tag_operations.rb +428 -0
- data/lib/htm/long_term_memory/vector_search.rb +109 -0
- data/lib/htm/long_term_memory.rb +51 -1153
- data/lib/htm/models/node.rb +35 -2
- data/lib/htm/models/node_tag.rb +31 -0
- data/lib/htm/models/robot_node.rb +31 -0
- data/lib/htm/models/tag.rb +44 -0
- data/lib/htm/proposition_service.rb +169 -0
- data/lib/htm/query_cache.rb +214 -0
- data/lib/htm/robot_group.rb +721 -0
- data/lib/htm/sql_builder.rb +178 -0
- data/lib/htm/tag_service.rb +16 -6
- data/lib/htm/tasks.rb +8 -2
- data/lib/htm/telemetry.rb +224 -0
- data/lib/htm/version.rb +1 -1
- data/lib/htm/working_memory_channel.rb +250 -0
- data/lib/htm.rb +66 -3
- data/lib/tasks/doc.rake +1 -1
- data/lib/tasks/htm.rake +259 -13
- data/mkdocs.yml +98 -96
- metadata +55 -20
- data/.aigcm_msg +0 -1
- data/.claude/settings.local.json +0 -95
- data/CLAUDE.md +0 -603
- data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +0 -12
- data/examples/cli_app/temp.log +0 -93
- data/examples/robot_groups/lib/robot_group.rb +0 -419
- data/examples/robot_groups/lib/working_memory_channel.rb +0 -140
- data/lib/htm/loaders/paragraph_chunker.rb +0 -112
- data/notes/ARCHITECTURE_REVIEW.md +0 -1167
- data/notes/IMPLEMENTATION_SUMMARY.md +0 -606
- data/notes/MULTI_FRAMEWORK_IMPLEMENTATION.md +0 -451
- data/notes/next_steps.md +0 -100
- data/notes/plan.md +0 -627
- data/notes/tag_ontology_enhancement_ideas.md +0 -222
- data/notes/timescaledb_removal_summary.md +0 -200
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ae4db5f168c495f5afef19f740f16ee9b39136cd54403f54090921cb6952275
|
|
4
|
+
data.tar.gz: 454816f53e620a72efeae7bd8b6c0a30c459403b4f1b6a3d0ca7adf30f3cda7c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52adbf798f4004961936f9112878d245c6872bf812611efa47bc9b7808ba39510d79d0902f109db8169e1cd0d5420338094edd7719f995f67c1b3def07a2a4d2
|
|
7
|
+
data.tar.gz: 7ac9e6a8913b9b836ddfdfdb909857ac62bdd2c5d6c6c904c2a257224fc80499a118afd3d63a3a14d0daed838e11c02b2f2149eddb8c0385ebb2d5be9ab258f8
|
data/.dictate.toml
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Dictator Configuration for HTM
|
|
2
|
+
# Decree-based structural enforcement
|
|
3
|
+
# https://github.com/seuros/dictator
|
|
4
|
+
|
|
5
|
+
[decree.supreme]
|
|
6
|
+
# Universal structural rules (applies to ALL files)
|
|
7
|
+
trailing_whitespace = "deny"
|
|
8
|
+
tabs_vs_spaces = "spaces"
|
|
9
|
+
tab_width = 2
|
|
10
|
+
final_newline = "require"
|
|
11
|
+
line_endings = "lf"
|
|
12
|
+
blank_line_whitespace = "deny"
|
|
13
|
+
|
|
14
|
+
[decree.ruby]
|
|
15
|
+
# Ruby-specific structural enforcement
|
|
16
|
+
max_line_length = 120
|
|
17
|
+
max_lines = 300
|
|
18
|
+
ignore_comments = true
|
|
19
|
+
ignore_blank_lines = true
|
|
20
|
+
method_visibility_order = ["public", "protected", "private"]
|
|
21
|
+
comment_spacing = true
|
|
22
|
+
|
|
23
|
+
[decree.ruby.linter]
|
|
24
|
+
# External linter - Dictator adds: -A --format json
|
|
25
|
+
command = "rubocop"
|
|
26
|
+
|
|
27
|
+
[decree.frontmatter]
|
|
28
|
+
# YAML frontmatter ordering for .md files
|
|
29
|
+
order = ["title", "slug", "pubDate", "description", "tags", "draft"]
|
|
30
|
+
required = ["title"]
|
|
31
|
+
|
|
32
|
+
# Disable unused language decrees
|
|
33
|
+
[decree.typescript]
|
|
34
|
+
enabled = false
|
|
35
|
+
|
|
36
|
+
[decree.golang]
|
|
37
|
+
enabled = false
|
|
38
|
+
|
|
39
|
+
[decree.rust]
|
|
40
|
+
enabled = false
|
|
41
|
+
|
|
42
|
+
[decree.python]
|
|
43
|
+
enabled = false
|
|
44
|
+
|
|
45
|
+
[decree.kjr]
|
|
46
|
+
enabled = false
|
data/.envrc
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,89 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.0.15] - 2025-12-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **"Why Robots Instead of Agents?" README section** - Explains terminology choice
|
|
14
|
+
- Opens with Shakespeare quote from Romeo and Juliet
|
|
15
|
+
- Discusses semantic clarity, honest capabilities, avoiding hype cycle
|
|
16
|
+
- Critiques "agent" frameworks that are just prompt wrappers
|
|
17
|
+
- References rich heritage (Čapek's R.U.R., Asimov's Three Laws)
|
|
18
|
+
- Notes cultural personality of robots (R2-D2, Wall-E, Bender)
|
|
19
|
+
- **MCP Server documentation** - Comprehensive guide for AI assistant integration
|
|
20
|
+
- Added MCP Server section to README.md with tools/resources reference
|
|
21
|
+
- Created `docs/guides/mcp-server.md` with detailed configuration for Claude Desktop, Claude Code, and AIA
|
|
22
|
+
- Covers all 11 tools (SetRobot, Remember, Recall, Forget, Restore, ListTags, SearchTags, FindByTopic, Stats, GetRobot, GetWorkingMemory)
|
|
23
|
+
- Covers all 3 resources (statistics, tags/hierarchy, memories/recent)
|
|
24
|
+
- Usage examples, session management, and troubleshooting guide
|
|
25
|
+
- **HTM Rake Tasks Reference** - Complete documentation for all 44 rake tasks
|
|
26
|
+
- Added rake tasks summary table to README.md Development section
|
|
27
|
+
- Created `docs/development/rake-tasks.md` with detailed reference organized by namespace:
|
|
28
|
+
- Database Tasks (`htm:db:*`) - 16 tasks
|
|
29
|
+
- Documentation Tasks (`htm:doc:*`) - 9 tasks
|
|
30
|
+
- File Loading Tasks (`htm:files:*`) - 7 tasks
|
|
31
|
+
- Job Tasks (`htm:jobs:*`) - 7 tasks
|
|
32
|
+
- Tag Tasks (`htm:tags:*`) - 5 tasks
|
|
33
|
+
- Common workflows, environment variables, and troubleshooting
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- **Documentation code examples** - Fixed incorrect API usage in docs/guides/*.md
|
|
37
|
+
- `add_node()` → `remember()`
|
|
38
|
+
- `topic:` named parameter → positional argument in `recall()`
|
|
39
|
+
- `retrieve(key)` → `long_term_memory.retrieve(node_id)`
|
|
40
|
+
- `create_context()` → `working_memory.assemble_context()`
|
|
41
|
+
- Removed invalid parameters: `type:`, `importance:`, `category:`, `related_to:`
|
|
42
|
+
|
|
43
|
+
## [0.0.14] - 2025-12-05
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- **OpenTelemetry metrics** - Optional observability with zero overhead when disabled
|
|
47
|
+
- New `HTM::Telemetry` module with null object pattern
|
|
48
|
+
- Metrics: `htm.jobs` (counter), `htm.embedding.latency`, `htm.tag.latency`, `htm.search.latency` (histograms), `htm.cache.operations` (counter)
|
|
49
|
+
- Instrumented: `GenerateEmbeddingJob`, `GenerateTagsJob`, search methods, `QueryCache`
|
|
50
|
+
- Enable via `HTM_TELEMETRY_ENABLED=true` or `config.telemetry_enabled = true`
|
|
51
|
+
- Works with 50+ OTLP-compatible backends (Jaeger, Prometheus, Datadog, etc.)
|
|
52
|
+
- Comprehensive documentation in `docs/telemetry.md`
|
|
53
|
+
- 18 new telemetry tests
|
|
54
|
+
- **Telemetry demo with Grafana visualization** - `examples/telemetry/`
|
|
55
|
+
- Live dashboard showing HTM metrics (job counts, latencies, cache hit rates)
|
|
56
|
+
- Uses Homebrew-installed Prometheus and Grafana (no Docker required)
|
|
57
|
+
- Auto-configures Prometheus scrape target
|
|
58
|
+
- Pre-built Grafana dashboard JSON for easy import
|
|
59
|
+
- Interactive shutdown prompt for service management
|
|
60
|
+
- **`htm:db:create` rake task** - Create database if it doesn't exist (respects `RAILS_ENV`)
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
- **All `htm:db:*` tasks now respect `RAILS_ENV`** - Following Rails conventions
|
|
64
|
+
- Database selection based on environment: `htm_development`, `htm_test`, `htm_production`
|
|
65
|
+
- `rake test` automatically sets `RAILS_ENV=test`
|
|
66
|
+
- Example: `RAILS_ENV=test rake htm:db:setup` operates on `htm_test`
|
|
67
|
+
- **`config/database.yml` refactored** - Extracts base name from `HTM_DBURL` and appends environment suffix
|
|
68
|
+
- `HTM_DBURL=postgresql://...htm_development` + `RAILS_ENV=test` → connects to `htm_test`
|
|
69
|
+
- **`HTM::Database.default_config` now respects `RAILS_ENV`** - Uses `ActiveRecordConfig.load_database_config`
|
|
70
|
+
- **Renamed `htm:db:test` to `htm:db:verify`** - Avoids naming collision with test database namespace
|
|
71
|
+
- `htm:db:verify` verifies database connection
|
|
72
|
+
- `RAILS_ENV=test rake htm:db:*` operates on test database
|
|
73
|
+
|
|
74
|
+
## [0.0.13] - 2025-12-04
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
- **MarkdownChunker now uses Baran gem** - Replaced custom ParagraphChunker with Baran's `MarkdownSplitter`
|
|
78
|
+
- Respects markdown structure (headers, code blocks, horizontal rules)
|
|
79
|
+
- Configurable `chunk_size` and `chunk_overlap` settings
|
|
80
|
+
- Returns cursor positions for each chunk
|
|
81
|
+
- **Fuzzy tag search with trigram matching** - Tags now searchable with fuzzy matching via pg_trgm
|
|
82
|
+
- **LongTermMemory modularization** - Refactored into separate concerns for better maintainability
|
|
83
|
+
- Search optimizations for vector, fulltext, and hybrid strategies
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
- **Configurable limits** - The following are now configurable (previously hard-coded):
|
|
87
|
+
- `max_embedding_dimension` (default: 2000)
|
|
88
|
+
- `max_tag_depth` (default: 4)
|
|
89
|
+
- Circuit breaker settings: `failure_threshold`, `reset_timeout`, `half_open_max_calls`
|
|
90
|
+
- Relevance scoring weights: `semantic_weight`, `tag_weight`, `recency_weight`, `access_weight`
|
|
91
|
+
- `relevance_recency_half_life_hours` (default: 168 = 1 week)
|
|
92
|
+
|
|
10
93
|
## [0.0.11] - 2025-12-02
|
|
11
94
|
|
|
12
95
|
### Added
|
|
@@ -260,7 +343,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
260
343
|
- **Markdown file loader** - Load markdown files into long-term memory
|
|
261
344
|
- `FileSource` model to track loaded files with metadata and sync status
|
|
262
345
|
- `MarkdownLoader` with YAML frontmatter extraction
|
|
263
|
-
- `
|
|
346
|
+
- `MarkdownChunker` for splitting content into semantic chunks (uses Baran gem)
|
|
264
347
|
- DELTA_TIME tolerance (5 seconds) for reliable file change detection
|
|
265
348
|
- **New HTM API methods** for file operations:
|
|
266
349
|
- `htm.load_file(path, force: false)` - Load single markdown file
|
|
@@ -347,7 +430,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
347
430
|
## [0.0.1] - 2025-10-25
|
|
348
431
|
|
|
349
432
|
### Added
|
|
350
|
-
- Initial release of HTM (Hierarchical
|
|
433
|
+
- Initial release of HTM (Hierarchical Temporal Memory)
|
|
351
434
|
- Two-tier memory system:
|
|
352
435
|
- Working memory: Token-limited, in-memory active context
|
|
353
436
|
- Long-term memory: Durable PostgreSQL/TimescaleDB storage
|
data/README.md
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
- Cross-robot context awareness
|
|
52
52
|
- Track which robot said what
|
|
53
53
|
|
|
54
|
+
- **Robot Groups**
|
|
55
|
+
- Coordinate multiple robots with shared working memory
|
|
56
|
+
- Real-time synchronization via PostgreSQL LISTEN/NOTIFY
|
|
57
|
+
- Active/passive roles for instant failover
|
|
58
|
+
- Dynamic scaling (add/remove robots at runtime)
|
|
59
|
+
|
|
54
60
|
- **LLM-Driven Tag Extraction**
|
|
55
61
|
- Automatic hierarchical tag extraction from content
|
|
56
62
|
- Tags in colon-delimited format (e.g., `database:postgresql:performance`)
|
|
@@ -68,6 +74,12 @@
|
|
|
68
74
|
- Source file tracking with re-sync support
|
|
69
75
|
- YAML frontmatter extraction as metadata
|
|
70
76
|
|
|
77
|
+
- **Telemetry (OpenTelemetry)**
|
|
78
|
+
- Optional metrics collection via OpenTelemetry
|
|
79
|
+
- Zero overhead when disabled (null object pattern)
|
|
80
|
+
- Works with 50+ backends (Jaeger, Prometheus, Datadog, etc.)
|
|
81
|
+
- Tracks job latency, search performance, and cache effectiveness
|
|
82
|
+
|
|
71
83
|
## Installation
|
|
72
84
|
|
|
73
85
|
Add this line to your application's Gemfile:
|
|
@@ -306,6 +318,82 @@ rake htm:files:sync # Sync all files (reload changed)
|
|
|
306
318
|
rake htm:files:stats # Show file loading statistics
|
|
307
319
|
```
|
|
308
320
|
|
|
321
|
+
### Robot Groups
|
|
322
|
+
|
|
323
|
+
Robot Groups enable coordination of multiple robots with shared working memory and real-time synchronization. This is useful for high-availability setups, load balancing, and collaborative AI agents.
|
|
324
|
+
|
|
325
|
+
**Key Classes:**
|
|
326
|
+
- `HTM::RobotGroup` - Coordinates multiple robots with active/passive roles and shared working memory
|
|
327
|
+
- `HTM::WorkingMemoryChannel` - PostgreSQL LISTEN/NOTIFY pub/sub for real-time cross-process synchronization
|
|
328
|
+
|
|
329
|
+
**Basic Usage:**
|
|
330
|
+
|
|
331
|
+
```ruby
|
|
332
|
+
require 'htm'
|
|
333
|
+
|
|
334
|
+
HTM.configure do |config|
|
|
335
|
+
config.embedding_provider = :ollama
|
|
336
|
+
config.embedding_model = 'nomic-embed-text'
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# Create a robot group with primary + standby
|
|
340
|
+
group = HTM::RobotGroup.new(
|
|
341
|
+
name: 'customer-support-ha',
|
|
342
|
+
active: ['support-primary'],
|
|
343
|
+
passive: ['support-standby'],
|
|
344
|
+
max_tokens: 8000
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Add memories to the shared working memory
|
|
348
|
+
group.remember("Customer #123 prefers email communication", originator: 'support-primary')
|
|
349
|
+
|
|
350
|
+
# All robots in the group can recall shared memories
|
|
351
|
+
memories = group.recall('customer', limit: 5, strategy: :fulltext)
|
|
352
|
+
|
|
353
|
+
# Simulate failover when primary fails
|
|
354
|
+
group.failover! # Promotes standby to active
|
|
355
|
+
|
|
356
|
+
# Dynamic scaling - add more robots at runtime
|
|
357
|
+
group.add_active('support-secondary')
|
|
358
|
+
group.sync_robot('support-secondary') # Sync existing memories
|
|
359
|
+
|
|
360
|
+
# Check group status
|
|
361
|
+
status = group.status
|
|
362
|
+
# => { name: "customer-support-ha", active: [...], passive: [...], in_sync: true, ... }
|
|
363
|
+
|
|
364
|
+
# Cleanup
|
|
365
|
+
group.shutdown
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Cross-Process Synchronization:**
|
|
369
|
+
|
|
370
|
+
For multi-process deployments, use `HTM::WorkingMemoryChannel` directly:
|
|
371
|
+
|
|
372
|
+
```ruby
|
|
373
|
+
# In each worker process
|
|
374
|
+
channel = HTM::WorkingMemoryChannel.new('my-group', HTM::Database.default_config)
|
|
375
|
+
|
|
376
|
+
# Listen for memory changes from other processes
|
|
377
|
+
channel.on_change do |event, node_id, origin_robot_id|
|
|
378
|
+
case event
|
|
379
|
+
when :added # Another robot added a memory
|
|
380
|
+
when :evicted # Another robot evicted a memory
|
|
381
|
+
when :cleared # Another robot cleared working memory
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
channel.start_listening
|
|
386
|
+
|
|
387
|
+
# Notify other processes when you add a memory
|
|
388
|
+
channel.notify(:added, node_id: node.id, robot_id: my_robot_id)
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Demo Applications:**
|
|
392
|
+
|
|
393
|
+
See `examples/robot_groups/` for complete examples:
|
|
394
|
+
- `same_process.rb` - Single-process demo with multiple robots
|
|
395
|
+
- `multi_process.rb` - Multi-process demo with real-time sync
|
|
396
|
+
|
|
309
397
|
### Automatic Tag Extraction
|
|
310
398
|
|
|
311
399
|
HTM automatically extracts hierarchical tags from content using LLM analysis. Tags are inferred from the content itself - you never specify them manually.
|
|
@@ -373,6 +461,137 @@ rake htm:jobs:clear_all
|
|
|
373
461
|
|
|
374
462
|
See `rake -T htm:jobs` for complete list of job management tasks.
|
|
375
463
|
|
|
464
|
+
## Telemetry (OpenTelemetry)
|
|
465
|
+
|
|
466
|
+
HTM includes optional OpenTelemetry-based metrics for production observability. Telemetry is **disabled by default** with zero overhead when off.
|
|
467
|
+
|
|
468
|
+
### Enabling Telemetry
|
|
469
|
+
|
|
470
|
+
```ruby
|
|
471
|
+
HTM.configure do |config|
|
|
472
|
+
config.telemetry_enabled = true
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# Or via environment variable
|
|
476
|
+
# HTM_TELEMETRY_ENABLED=true
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Configuring the Destination
|
|
480
|
+
|
|
481
|
+
HTM emits metrics via standard OpenTelemetry protocols. Configure your destination using environment variables:
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
# Export to any OTLP-compatible backend
|
|
485
|
+
export OTEL_METRICS_EXPORTER="otlp"
|
|
486
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Available Metrics
|
|
490
|
+
|
|
491
|
+
| Metric | Type | Attributes | Description |
|
|
492
|
+
|--------|------|------------|-------------|
|
|
493
|
+
| `htm.jobs` | Counter | `job`, `status` | Job execution counts (embedding, tags) |
|
|
494
|
+
| `htm.embedding.latency` | Histogram | `provider`, `status` | Embedding generation time (ms) |
|
|
495
|
+
| `htm.tag.latency` | Histogram | `provider`, `status` | Tag extraction time (ms) |
|
|
496
|
+
| `htm.search.latency` | Histogram | `strategy` | Search operation time (ms) |
|
|
497
|
+
| `htm.cache.operations` | Counter | `operation` | Cache hits/misses |
|
|
498
|
+
|
|
499
|
+
### Compatible Backends
|
|
500
|
+
|
|
501
|
+
HTM works with any OTLP-compatible observability platform:
|
|
502
|
+
|
|
503
|
+
**Open Source:** Jaeger, Prometheus, Grafana Tempo/Mimir, SigNoz, Uptrace
|
|
504
|
+
|
|
505
|
+
**Commercial:** Datadog, New Relic, Honeycomb, Splunk, Dynatrace, AWS X-Ray, Google Cloud Trace, Azure Monitor
|
|
506
|
+
|
|
507
|
+
### Optional Dependencies
|
|
508
|
+
|
|
509
|
+
Users who want telemetry should add these gems:
|
|
510
|
+
|
|
511
|
+
```ruby
|
|
512
|
+
gem 'opentelemetry-sdk'
|
|
513
|
+
gem 'opentelemetry-metrics-sdk'
|
|
514
|
+
gem 'opentelemetry-exporter-otlp' # For OTLP export
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Design
|
|
518
|
+
|
|
519
|
+
HTM uses a **null object pattern** for telemetry. When disabled or when the SDK is not installed:
|
|
520
|
+
- All metric operations are no-ops
|
|
521
|
+
- Zero runtime overhead
|
|
522
|
+
- No errors or exceptions
|
|
523
|
+
|
|
524
|
+
See [docs/telemetry.md](docs/telemetry.md) for detailed configuration and usage examples.
|
|
525
|
+
|
|
526
|
+
## MCP Server (Model Context Protocol)
|
|
527
|
+
|
|
528
|
+
HTM includes an MCP server that exposes memory capabilities to AI assistants like Claude Desktop, Claude Code, and AIA. This enables any MCP-compatible client to store, recall, and manage memories through a standardized protocol.
|
|
529
|
+
|
|
530
|
+
### Available Tools
|
|
531
|
+
|
|
532
|
+
| Tool | Description |
|
|
533
|
+
|------|-------------|
|
|
534
|
+
| `SetRobotTool` | Set the robot identity for the session (call first) |
|
|
535
|
+
| `GetRobotTool` | Get current robot information |
|
|
536
|
+
| `GetWorkingMemoryTool` | Get working memory contents for session restore |
|
|
537
|
+
| `RememberTool` | Store information with optional tags and metadata |
|
|
538
|
+
| `RecallTool` | Search memories using vector, fulltext, or hybrid strategies |
|
|
539
|
+
| `ForgetTool` | Soft-delete a memory (recoverable) |
|
|
540
|
+
| `RestoreTool` | Restore a soft-deleted memory |
|
|
541
|
+
| `ListTagsTool` | List tags with optional prefix filtering |
|
|
542
|
+
| `SearchTagsTool` | Fuzzy tag search with typo tolerance |
|
|
543
|
+
| `FindByTopicTool` | Find nodes by topic with optional fuzzy matching |
|
|
544
|
+
| `StatsTool` | Get memory usage statistics |
|
|
545
|
+
|
|
546
|
+
### Available Resources
|
|
547
|
+
|
|
548
|
+
| URI | Description |
|
|
549
|
+
|-----|-------------|
|
|
550
|
+
| `htm://statistics` | Memory statistics as JSON |
|
|
551
|
+
| `htm://tags/hierarchy` | Tag hierarchy as text tree |
|
|
552
|
+
| `htm://memories/recent` | Last 20 memories |
|
|
553
|
+
|
|
554
|
+
### Client Configuration
|
|
555
|
+
|
|
556
|
+
**Claude Desktop** (`~/.config/claude/claude_desktop_config.json`):
|
|
557
|
+
```json
|
|
558
|
+
{
|
|
559
|
+
"mcpServers": {
|
|
560
|
+
"htm-memory": {
|
|
561
|
+
"command": "htm_mcp.rb",
|
|
562
|
+
"env": {
|
|
563
|
+
"HTM_DBURL": "postgresql://user@localhost:5432/htm_development"
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
**Claude Code** (`~/.claude/claude_code_config.json`):
|
|
571
|
+
```json
|
|
572
|
+
{
|
|
573
|
+
"mcpServers": {
|
|
574
|
+
"htm-memory": {
|
|
575
|
+
"command": "htm_mcp.rb",
|
|
576
|
+
"env": {
|
|
577
|
+
"HTM_DBURL": "postgresql://user@localhost:5432/htm_development"
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**AIA** (`~/.config/aia/config.yml`):
|
|
585
|
+
```yaml
|
|
586
|
+
mcp_servers:
|
|
587
|
+
htm-memory:
|
|
588
|
+
command: htm_mcp.rb
|
|
589
|
+
env:
|
|
590
|
+
HTM_DBURL: postgresql://user@localhost:5432/htm_development
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
See [docs/guides/mcp-server.md](docs/guides/mcp-server.md) for detailed configuration, usage examples, and troubleshooting.
|
|
594
|
+
|
|
376
595
|
## Configuration
|
|
377
596
|
|
|
378
597
|
HTM uses dependency injection for LLM access, allowing you to configure embedding generation, tag extraction, logging, and token counting.
|
|
@@ -1160,6 +1379,17 @@ export HTM_LOG_LEVEL="INFO" # Default
|
|
|
1160
1379
|
|
|
1161
1380
|
This is used by the default logger when `HTM.configure` is called without a custom logger.
|
|
1162
1381
|
|
|
1382
|
+
#### HTM_TELEMETRY_ENABLED
|
|
1383
|
+
|
|
1384
|
+
Enable OpenTelemetry metrics collection:
|
|
1385
|
+
|
|
1386
|
+
```bash
|
|
1387
|
+
export HTM_TELEMETRY_ENABLED="true" # Enable telemetry
|
|
1388
|
+
export HTM_TELEMETRY_ENABLED="false" # Disable (default)
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
When enabled, HTM emits metrics to configured OpenTelemetry collectors. See [Telemetry](#telemetry-opentelemetry) for details.
|
|
1392
|
+
|
|
1163
1393
|
### Quick Setup Examples
|
|
1164
1394
|
|
|
1165
1395
|
#### Local Development (PostgreSQL)
|
|
@@ -1239,50 +1469,86 @@ rake test
|
|
|
1239
1469
|
ruby examples/basic_usage.rb
|
|
1240
1470
|
```
|
|
1241
1471
|
|
|
1242
|
-
### Database Management
|
|
1243
|
-
|
|
1244
|
-
HTM provides comprehensive rake tasks under the `htm:db` namespace for managing the database:
|
|
1245
|
-
|
|
1246
|
-
```bash
|
|
1247
|
-
# List all database tasks
|
|
1248
|
-
rake -T htm:db
|
|
1249
|
-
|
|
1250
|
-
# Set up database (create schema + run migrations)
|
|
1251
|
-
rake htm:db:setup
|
|
1252
|
-
|
|
1253
|
-
# Run pending migrations only
|
|
1254
|
-
rake htm:db:migrate
|
|
1255
|
-
|
|
1256
|
-
# Show migration status (which migrations are applied)
|
|
1257
|
-
rake htm:db:status
|
|
1258
|
-
|
|
1259
|
-
# Show database info (size, tables, extensions, row counts)
|
|
1260
|
-
rake htm:db:info
|
|
1261
|
-
|
|
1262
|
-
# Test database connection
|
|
1263
|
-
rake htm:db:test
|
|
1264
|
-
|
|
1265
|
-
# Open PostgreSQL console (interactive psql session)
|
|
1266
|
-
rake htm:db:console
|
|
1267
|
-
|
|
1268
|
-
# Seed database with sample data
|
|
1269
|
-
rake htm:db:seed
|
|
1270
|
-
|
|
1271
|
-
# Drop all HTM tables (WARNING: destructive!)
|
|
1272
|
-
rake htm:db:drop
|
|
1273
|
-
|
|
1274
|
-
# Drop and recreate database (WARNING: destructive!)
|
|
1275
|
-
rake htm:db:reset
|
|
1276
|
-
```
|
|
1277
|
-
|
|
1278
1472
|
**Important**: Make sure `direnv allow` has been run once in the project directory to load database environment variables from `.envrc`. Alternatively, you can manually export the environment variables:
|
|
1279
1473
|
|
|
1280
1474
|
```bash
|
|
1281
|
-
# Manually export HTM_DBURL
|
|
1282
1475
|
export HTM_DBURL="postgresql://user:password@host:port/dbname?sslmode=require"
|
|
1283
1476
|
```
|
|
1284
1477
|
|
|
1285
|
-
|
|
1478
|
+
### HTM Rake Tasks Reference
|
|
1479
|
+
|
|
1480
|
+
HTM provides comprehensive rake tasks for database management, documentation, file loading, job processing, and tag management. Use `rake -T htm` to see all available tasks.
|
|
1481
|
+
|
|
1482
|
+
#### Database Tasks (`htm:db:*`)
|
|
1483
|
+
|
|
1484
|
+
| Task | Description |
|
|
1485
|
+
|------|-------------|
|
|
1486
|
+
| `rake htm:db:setup` | Set up HTM database schema and run migrations (sets up from scratch) |
|
|
1487
|
+
| `rake htm:db:create` | Create database if it doesn't exist (respects RAILS_ENV) |
|
|
1488
|
+
| `rake htm:db:migrate` | Run pending database migrations |
|
|
1489
|
+
| `rake htm:db:status` | Show migration status |
|
|
1490
|
+
| `rake htm:db:verify` | Verify database connection (respects RAILS_ENV) |
|
|
1491
|
+
| `rake htm:db:info` | Show database info (size, tables, extensions) |
|
|
1492
|
+
| `rake htm:db:stats` | Show record counts for all HTM tables |
|
|
1493
|
+
| `rake htm:db:console` | Open PostgreSQL console (respects RAILS_ENV) |
|
|
1494
|
+
| `rake htm:db:seed` | Seed database with sample data |
|
|
1495
|
+
| `rake htm:db:schema:dump` | Dump current schema to db/schema.sql |
|
|
1496
|
+
| `rake htm:db:schema:load` | Load schema from db/schema.sql |
|
|
1497
|
+
| `rake htm:db:rebuild:embeddings` | Rebuild embeddings for all nodes |
|
|
1498
|
+
| `rake htm:db:rebuild:propositions` | Rebuild propositions for all non-proposition nodes |
|
|
1499
|
+
| `rake htm:db:tags:cleanup` | Soft delete orphaned tags and stale node_tags entries |
|
|
1500
|
+
| `rake htm:db:drop` | Drop all HTM tables (WARNING: destructive!) |
|
|
1501
|
+
| `rake htm:db:reset` | Drop and recreate database (WARNING: destructive!) |
|
|
1502
|
+
|
|
1503
|
+
#### Documentation Tasks (`htm:doc:*`)
|
|
1504
|
+
|
|
1505
|
+
| Task | Description |
|
|
1506
|
+
|------|-------------|
|
|
1507
|
+
| `rake htm:doc:all` | Generate DB docs, YARD API docs, build site, and serve |
|
|
1508
|
+
| `rake htm:doc:yard` | Build YARD API documentation (markdown format for MkDocs) |
|
|
1509
|
+
| `rake htm:doc:db` | Generate/update database documentation in docs/database/ |
|
|
1510
|
+
| `rake htm:doc:build` | Build documentation site with MkDocs |
|
|
1511
|
+
| `rake htm:doc:serve` | Serve documentation site locally with MkDocs |
|
|
1512
|
+
| `rake htm:doc:server[port]` | Start YARD documentation server (live reload) |
|
|
1513
|
+
| `rake htm:doc:fix_anchors` | Fix YARD anchor links for MkDocs compatibility |
|
|
1514
|
+
| `rake htm:doc:stats` | Show documentation coverage statistics |
|
|
1515
|
+
| `rake htm:doc:clean` | Clean generated documentation |
|
|
1516
|
+
|
|
1517
|
+
#### File Loading Tasks (`htm:files:*`)
|
|
1518
|
+
|
|
1519
|
+
| Task | Description |
|
|
1520
|
+
|------|-------------|
|
|
1521
|
+
| `rake htm:files:load[path]` | Load a markdown file into long-term memory |
|
|
1522
|
+
| `rake htm:files:load_dir[path,pattern]` | Load all markdown files from a directory |
|
|
1523
|
+
| `rake htm:files:list` | List all loaded file sources |
|
|
1524
|
+
| `rake htm:files:info[path]` | Show details for a loaded file |
|
|
1525
|
+
| `rake htm:files:sync` | Sync all loaded files (reload changed files) |
|
|
1526
|
+
| `rake htm:files:unload[path]` | Unload a file from memory |
|
|
1527
|
+
| `rake htm:files:stats` | Show file loading statistics |
|
|
1528
|
+
|
|
1529
|
+
#### Job Processing Tasks (`htm:jobs:*`)
|
|
1530
|
+
|
|
1531
|
+
| Task | Description |
|
|
1532
|
+
|------|-------------|
|
|
1533
|
+
| `rake htm:jobs:stats` | Show statistics for nodes and async job processing |
|
|
1534
|
+
| `rake htm:jobs:process_embeddings` | Process pending embedding jobs for nodes without embeddings |
|
|
1535
|
+
| `rake htm:jobs:process_tags` | Process pending tag extraction jobs for nodes without tags |
|
|
1536
|
+
| `rake htm:jobs:process_all` | Process all pending jobs (embeddings and tags) |
|
|
1537
|
+
| `rake htm:jobs:reprocess_embeddings` | Reprocess embeddings for all nodes (force regeneration) |
|
|
1538
|
+
| `rake htm:jobs:failed` | Show nodes that failed async processing |
|
|
1539
|
+
| `rake htm:jobs:clear_all` | Clear all embeddings and tags (for testing/development) |
|
|
1540
|
+
|
|
1541
|
+
#### Tag Management Tasks (`htm:tags:*`)
|
|
1542
|
+
|
|
1543
|
+
| Task | Description |
|
|
1544
|
+
|------|-------------|
|
|
1545
|
+
| `rake htm:tags:tree[prefix]` | Display tags as a hierarchical tree (text format) |
|
|
1546
|
+
| `rake htm:tags:mermaid[prefix]` | Export tags as Mermaid flowchart to tags.md |
|
|
1547
|
+
| `rake htm:tags:svg[prefix]` | Export tags as SVG visualization to tags.svg |
|
|
1548
|
+
| `rake htm:tags:export[prefix]` | Export tags in all formats (tags.txt, tags.md, tags.svg) |
|
|
1549
|
+
| `rake htm:tags:rebuild` | Rebuild all tags from node content |
|
|
1550
|
+
|
|
1551
|
+
### Common Workflows
|
|
1286
1552
|
|
|
1287
1553
|
```bash
|
|
1288
1554
|
# Initial setup (first time)
|
|
@@ -1295,57 +1561,35 @@ rake htm:db:migrate # Run pending migrations
|
|
|
1295
1561
|
# Check database state
|
|
1296
1562
|
rake htm:db:status # See migration status
|
|
1297
1563
|
rake htm:db:info # See database details
|
|
1564
|
+
rake htm:db:stats # See record counts
|
|
1298
1565
|
|
|
1299
|
-
#
|
|
1300
|
-
rake htm:db:reset # Drops and recreates everything
|
|
1301
|
-
|
|
1302
|
-
# Open database console for debugging
|
|
1303
|
-
rake htm:db:console # Opens psql
|
|
1304
|
-
```
|
|
1305
|
-
|
|
1306
|
-
### Async Job Management
|
|
1307
|
-
|
|
1308
|
-
HTM provides rake tasks under the `htm:jobs` namespace for managing async embedding and tag extraction jobs:
|
|
1309
|
-
|
|
1310
|
-
```bash
|
|
1311
|
-
# List all job management tasks
|
|
1312
|
-
rake -T htm:jobs
|
|
1313
|
-
|
|
1314
|
-
# Show statistics for async processing
|
|
1566
|
+
# Monitor async processing
|
|
1315
1567
|
rake htm:jobs:stats
|
|
1568
|
+
rake htm:jobs:failed # Show stuck jobs
|
|
1316
1569
|
|
|
1317
|
-
# Process pending jobs
|
|
1318
|
-
rake htm:jobs:
|
|
1319
|
-
rake htm:jobs:process_tags # Process nodes without tags
|
|
1320
|
-
rake htm:jobs:process_all # Process both
|
|
1321
|
-
|
|
1322
|
-
# Reprocess all nodes (force regeneration)
|
|
1323
|
-
rake htm:jobs:reprocess_embeddings # WARNING: Prompts for confirmation
|
|
1324
|
-
|
|
1325
|
-
# Debugging and maintenance
|
|
1326
|
-
rake htm:jobs:failed # Show stuck jobs (>1 hour old)
|
|
1327
|
-
rake htm:jobs:clear_all # Clear all embeddings/tags (testing only)
|
|
1328
|
-
```
|
|
1570
|
+
# Process pending jobs manually
|
|
1571
|
+
rake htm:jobs:process_all
|
|
1329
1572
|
|
|
1330
|
-
|
|
1573
|
+
# Generate documentation
|
|
1574
|
+
rake htm:doc:all # Full documentation build
|
|
1575
|
+
rake htm:doc:serve # Local preview
|
|
1331
1576
|
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
rake htm:
|
|
1577
|
+
# Load files into memory
|
|
1578
|
+
rake 'htm:files:load[docs/guide.md]'
|
|
1579
|
+
rake 'htm:files:load_dir[docs/,**/*.md]'
|
|
1335
1580
|
|
|
1336
|
-
#
|
|
1337
|
-
rake htm:
|
|
1581
|
+
# View tag hierarchy
|
|
1582
|
+
rake htm:tags:tree
|
|
1583
|
+
rake 'htm:tags:svg[database]' # Export filtered tags
|
|
1338
1584
|
|
|
1339
|
-
#
|
|
1340
|
-
rake htm:
|
|
1341
|
-
rake htm:jobs:process_embeddings # Retry failed embeddings
|
|
1585
|
+
# Reset database (development only!)
|
|
1586
|
+
rake htm:db:reset # Drops and recreates everything
|
|
1342
1587
|
|
|
1343
|
-
#
|
|
1344
|
-
rake htm:
|
|
1345
|
-
rake htm:jobs:clear_all # Clear everything and start fresh
|
|
1588
|
+
# Open database console for debugging
|
|
1589
|
+
rake htm:db:console # Opens psql
|
|
1346
1590
|
```
|
|
1347
1591
|
|
|
1348
|
-
See the [Async Job Processing](#async-job-processing) section for more details.
|
|
1592
|
+
See the [Async Job Processing](#async-job-processing) section for more details on background jobs.
|
|
1349
1593
|
|
|
1350
1594
|
## Testing
|
|
1351
1595
|
|
|
@@ -1409,6 +1653,31 @@ This separation allows you to provide any LLM implementation while HTM handles r
|
|
|
1409
1653
|
- [x] Phase 8: Production-ready gem
|
|
1410
1654
|
|
|
1411
1655
|
|
|
1656
|
+
## Why "Robots" Instead of "Agents"?
|
|
1657
|
+
|
|
1658
|
+
> "What's in a name? That which we call a rose
|
|
1659
|
+
> By any other name would smell as sweet."
|
|
1660
|
+
> — Shakespeare, *Romeo and Juliet*
|
|
1661
|
+
|
|
1662
|
+
Shakespeare argues names are arbitrary. In software, we respectfully disagree—names shape expectations and understanding.
|
|
1663
|
+
|
|
1664
|
+
HTM uses "robots" rather than the fashionable "agents" for several reasons:
|
|
1665
|
+
|
|
1666
|
+
- **Semantic clarity**: "Agent" is overloaded—user agents, software agents, real estate agents, secret agents. "Robot" is specific to automated workers.
|
|
1667
|
+
|
|
1668
|
+
- **Honest about capabilities**: "Agent" implies autonomy and genuine decision-making. These systems follow instructions—they don't have agency. "Robot" acknowledges what they actually are: tools.
|
|
1669
|
+
|
|
1670
|
+
- **Avoiding the hype cycle**: "AI Agent" and "Agentic AI" became buzzwords in 2023-2024, often meaning nothing more than "LLM with a prompt." We prefer terminology that will age well.
|
|
1671
|
+
|
|
1672
|
+
- **Many "agent" frameworks are prompt wrappers**: Look under the hood of popular agent libraries and you'll often find a single prompt in a for-loop. Calling that an "agent" sets false expectations.
|
|
1673
|
+
|
|
1674
|
+
- **Rich heritage**: "Robot" comes from Karel Čapek's 1920 play *R.U.R.* (from Czech *robota*, meaning labor). Isaac Asimov gave us the Three Laws. There's decades of thoughtful writing about robot ethics and behavior. "Agent" has no comparable tradition.
|
|
1675
|
+
|
|
1676
|
+
- **Personality**: Robots are endearing—R2-D2, Wall-E, Bender. They have cultural weight that "agent" lacks.
|
|
1677
|
+
|
|
1678
|
+
Honest terminology leads to clearer thinking. These are robots: tireless workers with perfect memory, executing instructions on our behalf. That's exactly what HTM helps them do better.
|
|
1679
|
+
|
|
1680
|
+
|
|
1412
1681
|
## Contributing
|
|
1413
1682
|
|
|
1414
1683
|
Bug reports and pull requests are welcome on GitHub at https://github.com/madbomber/htm.
|