htm 0.0.2 → 0.0.11

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 (129) hide show
  1. checksums.yaml +4 -4
  2. data/.aigcm_msg +1 -0
  3. data/.architecture/reviews/comprehensive-codebase-review.md +577 -0
  4. data/.claude/settings.local.json +95 -0
  5. data/.irbrc +283 -80
  6. data/.tbls.yml +2 -1
  7. data/CHANGELOG.md +327 -26
  8. data/CLAUDE.md +603 -0
  9. data/README.md +83 -12
  10. data/Rakefile +5 -0
  11. data/bin/htm_mcp.rb +527 -0
  12. data/db/migrate/{20250101000001_enable_extensions.rb → 00001_enable_extensions.rb} +0 -1
  13. data/db/migrate/00002_create_robots.rb +11 -0
  14. data/db/migrate/00003_create_file_sources.rb +20 -0
  15. data/db/migrate/00004_create_nodes.rb +65 -0
  16. data/db/migrate/00005_create_tags.rb +13 -0
  17. data/db/migrate/00006_create_node_tags.rb +18 -0
  18. data/db/migrate/00007_create_robot_nodes.rb +26 -0
  19. data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +12 -0
  20. data/db/schema.sql +172 -1
  21. data/docs/api/database.md +1 -2
  22. data/docs/api/htm.md +197 -2
  23. data/docs/api/yard/HTM/ActiveRecordConfig.md +23 -0
  24. data/docs/api/yard/HTM/AuthorizationError.md +11 -0
  25. data/docs/api/yard/HTM/CircuitBreaker.md +92 -0
  26. data/docs/api/yard/HTM/CircuitBreakerOpenError.md +34 -0
  27. data/docs/api/yard/HTM/Configuration.md +175 -0
  28. data/docs/api/yard/HTM/Database.md +99 -0
  29. data/docs/api/yard/HTM/DatabaseError.md +14 -0
  30. data/docs/api/yard/HTM/EmbeddingError.md +18 -0
  31. data/docs/api/yard/HTM/EmbeddingService.md +58 -0
  32. data/docs/api/yard/HTM/Error.md +11 -0
  33. data/docs/api/yard/HTM/JobAdapter.md +39 -0
  34. data/docs/api/yard/HTM/LongTermMemory.md +342 -0
  35. data/docs/api/yard/HTM/NotFoundError.md +17 -0
  36. data/docs/api/yard/HTM/Observability.md +107 -0
  37. data/docs/api/yard/HTM/QueryTimeoutError.md +19 -0
  38. data/docs/api/yard/HTM/Railtie.md +27 -0
  39. data/docs/api/yard/HTM/ResourceExhaustedError.md +13 -0
  40. data/docs/api/yard/HTM/TagError.md +18 -0
  41. data/docs/api/yard/HTM/TagService.md +67 -0
  42. data/docs/api/yard/HTM/Timeframe/Result.md +24 -0
  43. data/docs/api/yard/HTM/Timeframe.md +40 -0
  44. data/docs/api/yard/HTM/TimeframeExtractor/Result.md +24 -0
  45. data/docs/api/yard/HTM/TimeframeExtractor.md +45 -0
  46. data/docs/api/yard/HTM/ValidationError.md +20 -0
  47. data/docs/api/yard/HTM/WorkingMemory.md +131 -0
  48. data/docs/api/yard/HTM.md +80 -0
  49. data/docs/api/yard/index.csv +179 -0
  50. data/docs/api/yard-reference.md +51 -0
  51. data/docs/database/README.md +128 -128
  52. data/docs/database/public.file_sources.md +42 -0
  53. data/docs/database/public.file_sources.svg +211 -0
  54. data/docs/database/public.node_tags.md +4 -4
  55. data/docs/database/public.node_tags.svg +212 -79
  56. data/docs/database/public.nodes.md +22 -12
  57. data/docs/database/public.nodes.svg +246 -127
  58. data/docs/database/public.robot_nodes.md +11 -9
  59. data/docs/database/public.robot_nodes.svg +220 -98
  60. data/docs/database/public.robots.md +2 -2
  61. data/docs/database/public.robots.svg +136 -81
  62. data/docs/database/public.tags.md +3 -3
  63. data/docs/database/public.tags.svg +118 -39
  64. data/docs/database/schema.json +850 -771
  65. data/docs/database/schema.svg +256 -197
  66. data/docs/development/schema.md +67 -2
  67. data/docs/guides/adding-memories.md +93 -7
  68. data/docs/guides/recalling-memories.md +36 -1
  69. data/examples/README.md +405 -0
  70. data/examples/cli_app/htm_cli.rb +65 -5
  71. data/examples/cli_app/temp.log +93 -0
  72. data/examples/file_loader_usage.rb +177 -0
  73. data/examples/mcp_client.rb +529 -0
  74. data/examples/robot_groups/lib/robot_group.rb +419 -0
  75. data/examples/robot_groups/lib/working_memory_channel.rb +140 -0
  76. data/examples/robot_groups/multi_process.rb +286 -0
  77. data/examples/robot_groups/robot_worker.rb +136 -0
  78. data/examples/robot_groups/same_process.rb +229 -0
  79. data/examples/timeframe_demo.rb +276 -0
  80. data/lib/htm/active_record_config.rb +1 -1
  81. data/lib/htm/circuit_breaker.rb +202 -0
  82. data/lib/htm/configuration.rb +59 -13
  83. data/lib/htm/database.rb +67 -36
  84. data/lib/htm/embedding_service.rb +39 -2
  85. data/lib/htm/errors.rb +131 -11
  86. data/lib/htm/jobs/generate_embedding_job.rb +5 -4
  87. data/lib/htm/jobs/generate_tags_job.rb +4 -0
  88. data/lib/htm/loaders/markdown_loader.rb +263 -0
  89. data/lib/htm/loaders/paragraph_chunker.rb +112 -0
  90. data/lib/htm/long_term_memory.rb +460 -343
  91. data/lib/htm/models/file_source.rb +99 -0
  92. data/lib/htm/models/node.rb +80 -5
  93. data/lib/htm/models/robot.rb +24 -1
  94. data/lib/htm/models/robot_node.rb +1 -0
  95. data/lib/htm/models/tag.rb +254 -4
  96. data/lib/htm/observability.rb +395 -0
  97. data/lib/htm/tag_service.rb +60 -3
  98. data/lib/htm/tasks.rb +26 -1
  99. data/lib/htm/timeframe.rb +194 -0
  100. data/lib/htm/timeframe_extractor.rb +307 -0
  101. data/lib/htm/version.rb +1 -1
  102. data/lib/htm/working_memory.rb +165 -70
  103. data/lib/htm.rb +328 -130
  104. data/lib/tasks/doc.rake +300 -0
  105. data/lib/tasks/files.rake +299 -0
  106. data/lib/tasks/htm.rake +158 -3
  107. data/lib/tasks/jobs.rake +3 -9
  108. data/lib/tasks/tags.rake +166 -6
  109. data/mkdocs.yml +36 -1
  110. data/notes/ARCHITECTURE_REVIEW.md +1167 -0
  111. data/notes/IMPLEMENTATION_SUMMARY.md +606 -0
  112. data/notes/MULTI_FRAMEWORK_IMPLEMENTATION.md +451 -0
  113. data/notes/next_steps.md +100 -0
  114. data/notes/plan.md +627 -0
  115. data/notes/tag_ontology_enhancement_ideas.md +222 -0
  116. data/notes/timescaledb_removal_summary.md +200 -0
  117. metadata +158 -17
  118. data/db/migrate/20250101000002_create_robots.rb +0 -14
  119. data/db/migrate/20250101000003_create_nodes.rb +0 -42
  120. data/db/migrate/20250101000005_create_tags.rb +0 -38
  121. data/db/migrate/20250101000007_add_node_vector_indexes.rb +0 -30
  122. data/db/migrate/20250125000001_add_content_hash_to_nodes.rb +0 -14
  123. data/db/migrate/20250125000002_create_robot_nodes.rb +0 -35
  124. data/db/migrate/20250125000003_remove_source_and_robot_id_from_nodes.rb +0 -28
  125. data/db/migrate/20250126000001_create_working_memories.rb +0 -19
  126. data/db/migrate/20250126000002_remove_unused_columns.rb +0 -12
  127. data/docs/database/public.working_memories.md +0 -40
  128. data/docs/database/public.working_memories.svg +0 -112
  129. data/lib/htm/models/working_memory_entry.rb +0 -88
@@ -1,112 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
- <!-- Generated by graphviz version 12.1.2 (20240928.0832)
5
- -->
6
- <!-- Title: public.working_memories Pages: 1 -->
7
- <svg width="1046pt" height="756pt"
8
- viewBox="0.00 0.00 1046.14 756.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
- <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 752)">
10
- <title>public.working_memories</title>
11
- <polygon fill="white" stroke="none" points="-4,4 -4,-752 1042.14,-752 1042.14,4 -4,4"/>
12
- <!-- public.working_memories -->
13
- <g id="node1" class="node">
14
- <title>public.working_memories</title>
15
- <polygon fill="#efefef" stroke="none" points="355.64,-666.2 355.64,-701.8 683.59,-701.8 683.59,-666.2 355.64,-666.2"/>
16
- <polygon fill="none" stroke="black" points="355.64,-666.2 355.64,-701.8 683.59,-701.8 683.59,-666.2 355.64,-666.2"/>
17
- <text text-anchor="start" x="362.64" y="-679.6" font-family="Arial Bold" font-size="18.00">public.working_memories</text>
18
- <text text-anchor="start" x="552.11" y="-679.6" font-family="Arial" font-size="14.00">    </text>
19
- <text text-anchor="start" x="583.22" y="-679.6" font-family="Arial" font-size="14.00" fill="#666666">[BASE TABLE]</text>
20
- <polygon fill="none" stroke="black" points="355.64,-635.4 355.64,-666.2 683.59,-666.2 683.59,-635.4 355.64,-635.4"/>
21
- <text text-anchor="start" x="362.64" y="-647.6" font-family="Arial" font-size="14.00">id </text>
22
- <text text-anchor="start" x="377.43" y="-647.6" font-family="Arial" font-size="14.00" fill="#666666">[bigint]</text>
23
- <polygon fill="none" stroke="black" points="355.64,-604.6 355.64,-635.4 683.59,-635.4 683.59,-604.6 355.64,-604.6"/>
24
- <text text-anchor="start" x="362.64" y="-616.8" font-family="Arial" font-size="14.00">robot_id </text>
25
- <text text-anchor="start" x="417.12" y="-616.8" font-family="Arial" font-size="14.00" fill="#666666">[bigint]</text>
26
- <polygon fill="none" stroke="black" points="355.64,-573.8 355.64,-604.6 683.59,-604.6 683.59,-573.8 355.64,-573.8"/>
27
- <text text-anchor="start" x="362.64" y="-586" font-family="Arial" font-size="14.00">node_id </text>
28
- <text text-anchor="start" x="416.36" y="-586" font-family="Arial" font-size="14.00" fill="#666666">[bigint]</text>
29
- <polygon fill="none" stroke="black" points="355.64,-543 355.64,-573.8 683.59,-573.8 683.59,-543 355.64,-543"/>
30
- <text text-anchor="start" x="362.64" y="-555.2" font-family="Arial" font-size="14.00">added_at </text>
31
- <text text-anchor="start" x="424.92" y="-555.2" font-family="Arial" font-size="14.00" fill="#666666">[timestamp with time zone]</text>
32
- <polygon fill="none" stroke="black" points="355.64,-512.2 355.64,-543 683.59,-543 683.59,-512.2 355.64,-512.2"/>
33
- <text text-anchor="start" x="362.64" y="-524.4" font-family="Arial" font-size="14.00">token_count </text>
34
- <text text-anchor="start" x="442.81" y="-524.4" font-family="Arial" font-size="14.00" fill="#666666">[integer]</text>
35
- <polygon fill="none" stroke="black" stroke-width="3" points="354.14,-510.7 354.14,-703.3 685.09,-703.3 685.09,-510.7 354.14,-510.7"/>
36
- </g>
37
- <!-- public.robots -->
38
- <g id="node2" class="node">
39
- <title>public.robots</title>
40
- <polygon fill="#efefef" stroke="none" points="212.73,-258.8 212.73,-294.4 462.5,-294.4 462.5,-258.8 212.73,-258.8"/>
41
- <polygon fill="none" stroke="black" points="212.73,-258.8 212.73,-294.4 462.5,-294.4 462.5,-258.8 212.73,-258.8"/>
42
- <text text-anchor="start" x="228.13" y="-272.2" font-family="Arial Bold" font-size="18.00">public.robots</text>
43
- <text text-anchor="start" x="322.62" y="-272.2" font-family="Arial" font-size="14.00">    </text>
44
- <text text-anchor="start" x="353.74" y="-272.2" font-family="Arial" font-size="14.00" fill="#666666">[BASE TABLE]</text>
45
- <polygon fill="none" stroke="black" points="212.73,-228 212.73,-258.8 462.5,-258.8 462.5,-228 212.73,-228"/>
46
- <text text-anchor="start" x="219.73" y="-240.2" font-family="Arial" font-size="14.00">id </text>
47
- <text text-anchor="start" x="234.52" y="-240.2" font-family="Arial" font-size="14.00" fill="#666666">[bigint]</text>
48
- <polygon fill="none" stroke="black" points="212.73,-197.2 212.73,-228 462.5,-228 462.5,-197.2 212.73,-197.2"/>
49
- <text text-anchor="start" x="219.73" y="-209.4" font-family="Arial" font-size="14.00">name </text>
50
- <text text-anchor="start" x="258.64" y="-209.4" font-family="Arial" font-size="14.00" fill="#666666">[text]</text>
51
- <polygon fill="none" stroke="black" points="212.73,-166.4 212.73,-197.2 462.5,-197.2 462.5,-166.4 212.73,-166.4"/>
52
- <text text-anchor="start" x="219.73" y="-178.6" font-family="Arial" font-size="14.00">created_at </text>
53
- <text text-anchor="start" x="289.78" y="-178.6" font-family="Arial" font-size="14.00" fill="#666666">[timestamp with time zone]</text>
54
- <polygon fill="none" stroke="black" points="212.73,-135.6 212.73,-166.4 462.5,-166.4 462.5,-135.6 212.73,-135.6"/>
55
- <text text-anchor="start" x="219.73" y="-147.8" font-family="Arial" font-size="14.00">last_active </text>
56
- <text text-anchor="start" x="289.77" y="-147.8" font-family="Arial" font-size="14.00" fill="#666666">[timestamp with time zone]</text>
57
- </g>
58
- <!-- public.working_memories&#45;&gt;public.robots -->
59
- <g id="edge1" class="edge">
60
- <title>public.working_memories:robot_id&#45;&gt;public.robots:id</title>
61
- <path fill="none" stroke="black" d="M344.41,-619.21C291.15,-610.26 333.43,-526.77 355.64,-466 381.12,-396.26 436.88,-407.28 462.5,-337.6 476.95,-298.3 505.37,-243.4 463.5,-243.4"/>
62
- <polygon fill="black" stroke="black" points="344.34,-619.21 353.96,-624.46 349.65,-619.62 353.97,-619.95 353.97,-619.95 353.97,-619.95 349.65,-619.62 354.65,-615.49 344.34,-619.21"/>
63
- <text text-anchor="start" x="7" y="-630" font-family="Arial" font-size="10.00">FOREIGN KEY (robot_id) REFERENCES robots(id) ON DELETE CASCADE</text>
64
- </g>
65
- <!-- public.nodes -->
66
- <g id="node3" class="node">
67
- <title>public.nodes</title>
68
- <polygon fill="#efefef" stroke="none" points="566.45,-351.2 566.45,-386.8 838.78,-386.8 838.78,-351.2 566.45,-351.2"/>
69
- <polygon fill="none" stroke="black" points="566.45,-351.2 566.45,-386.8 838.78,-386.8 838.78,-351.2 566.45,-351.2"/>
70
- <text text-anchor="start" x="594.63" y="-364.6" font-family="Arial Bold" font-size="18.00">public.nodes</text>
71
- <text text-anchor="start" x="686.12" y="-364.6" font-family="Arial" font-size="14.00">    </text>
72
- <text text-anchor="start" x="717.23" y="-364.6" font-family="Arial" font-size="14.00" fill="#666666">[BASE TABLE]</text>
73
- <polygon fill="none" stroke="black" points="566.45,-320.4 566.45,-351.2 838.78,-351.2 838.78,-320.4 566.45,-320.4"/>
74
- <text text-anchor="start" x="573.45" y="-332.6" font-family="Arial" font-size="14.00">id </text>
75
- <text text-anchor="start" x="588.24" y="-332.6" font-family="Arial" font-size="14.00" fill="#666666">[bigint]</text>
76
- <polygon fill="none" stroke="black" points="566.45,-289.6 566.45,-320.4 838.78,-320.4 838.78,-289.6 566.45,-289.6"/>
77
- <text text-anchor="start" x="573.45" y="-301.8" font-family="Arial" font-size="14.00">content </text>
78
- <text text-anchor="start" x="623.27" y="-301.8" font-family="Arial" font-size="14.00" fill="#666666">[text]</text>
79
- <polygon fill="none" stroke="black" points="566.45,-258.8 566.45,-289.6 838.78,-289.6 838.78,-258.8 566.45,-258.8"/>
80
- <text text-anchor="start" x="573.45" y="-271" font-family="Arial" font-size="14.00">access_count </text>
81
- <text text-anchor="start" x="662.95" y="-271" font-family="Arial" font-size="14.00" fill="#666666">[integer]</text>
82
- <polygon fill="none" stroke="black" points="566.45,-228 566.45,-258.8 838.78,-258.8 838.78,-228 566.45,-228"/>
83
- <text text-anchor="start" x="573.45" y="-240.2" font-family="Arial" font-size="14.00">created_at </text>
84
- <text text-anchor="start" x="643.5" y="-240.2" font-family="Arial" font-size="14.00" fill="#666666">[timestamp with time zone]</text>
85
- <polygon fill="none" stroke="black" points="566.45,-197.2 566.45,-228 838.78,-228 838.78,-197.2 566.45,-197.2"/>
86
- <text text-anchor="start" x="573.45" y="-209.4" font-family="Arial" font-size="14.00">updated_at </text>
87
- <text text-anchor="start" x="647.41" y="-209.4" font-family="Arial" font-size="14.00" fill="#666666">[timestamp with time zone]</text>
88
- <polygon fill="none" stroke="black" points="566.45,-166.4 566.45,-197.2 838.78,-197.2 838.78,-166.4 566.45,-166.4"/>
89
- <text text-anchor="start" x="573.45" y="-178.6" font-family="Arial" font-size="14.00">last_accessed </text>
90
- <text text-anchor="start" x="666.06" y="-178.6" font-family="Arial" font-size="14.00" fill="#666666">[timestamp with time zone]</text>
91
- <polygon fill="none" stroke="black" points="566.45,-135.6 566.45,-166.4 838.78,-166.4 838.78,-135.6 566.45,-135.6"/>
92
- <text text-anchor="start" x="573.45" y="-147.8" font-family="Arial" font-size="14.00">token_count </text>
93
- <text text-anchor="start" x="653.62" y="-147.8" font-family="Arial" font-size="14.00" fill="#666666">[integer]</text>
94
- <polygon fill="none" stroke="black" points="566.45,-104.8 566.45,-135.6 838.78,-135.6 838.78,-104.8 566.45,-104.8"/>
95
- <text text-anchor="start" x="573.45" y="-117" font-family="Arial" font-size="14.00">embedding </text>
96
- <text text-anchor="start" x="646.62" y="-117" font-family="Arial" font-size="14.00" fill="#666666">[vector(2000)]</text>
97
- <polygon fill="none" stroke="black" points="566.45,-74 566.45,-104.8 838.78,-104.8 838.78,-74 566.45,-74"/>
98
- <text text-anchor="start" x="573.45" y="-86.2" font-family="Arial" font-size="14.00">embedding_dimension </text>
99
- <text text-anchor="start" x="718.22" y="-86.2" font-family="Arial" font-size="14.00" fill="#666666">[integer]</text>
100
- <polygon fill="none" stroke="black" points="566.45,-43.2 566.45,-74 838.78,-74 838.78,-43.2 566.45,-43.2"/>
101
- <text text-anchor="start" x="573.45" y="-55.4" font-family="Arial" font-size="14.00">content_hash </text>
102
- <text text-anchor="start" x="661.41" y="-55.4" font-family="Arial" font-size="14.00" fill="#666666">[varchar(64)]</text>
103
- </g>
104
- <!-- public.working_memories&#45;&gt;public.nodes -->
105
- <g id="edge2" class="edge">
106
- <title>public.working_memories:node_id&#45;&gt;public.nodes:id</title>
107
- <path fill="none" stroke="black" d="M694.76,-588.13C736.16,-578.52 714.08,-506.91 683.59,-466 651.05,-422.32 599.05,-473.63 566.45,-430 541.39,-396.46 523.58,-335.8 565.45,-335.8"/>
108
- <polygon fill="black" stroke="black" points="694.87,-588.11 684.45,-584.69 689.57,-588.67 685.26,-589.13 685.26,-589.13 685.26,-589.13 689.57,-588.67 685.4,-593.64 694.87,-588.11"/>
109
- <text text-anchor="start" x="691.59" y="-599.2" font-family="Arial" font-size="10.00">FOREIGN KEY (node_id) REFERENCES nodes(id) ON DELETE CASCADE</text>
110
- </g>
111
- </g>
112
- </svg>
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class HTM
4
- module Models
5
- # WorkingMemoryEntry - Tracks which nodes are in each robot's working memory
6
- #
7
- # This provides optional database persistence for working memory state.
8
- # Useful for:
9
- # - Restoring working memory after process restart
10
- # - Querying what nodes robots are actively working with
11
- # - Debugging/monitoring working memory across robots
12
- #
13
- # Note: The in-memory WorkingMemory class remains the primary interface.
14
- # This table is for persistence/observability, not required for operation.
15
- #
16
- class WorkingMemoryEntry < ActiveRecord::Base
17
- self.table_name = 'working_memories'
18
-
19
- belongs_to :robot, class_name: 'HTM::Models::Robot'
20
- belongs_to :node, class_name: 'HTM::Models::Node'
21
-
22
- validates :robot_id, presence: true
23
- validates :node_id, presence: true
24
- validates :robot_id, uniqueness: { scope: :node_id, message: 'already has this node in working memory' }
25
-
26
- # Scopes
27
- scope :by_robot, ->(robot_id) { where(robot_id: robot_id) }
28
- scope :recent, -> { order(added_at: :desc) }
29
-
30
- # Class methods
31
-
32
- # Sync working memory state from in-memory hash to database
33
- #
34
- # @param robot_id [Integer] Robot ID
35
- # @param node_entries [Hash] Hash of node_id => { token_count:, ... }
36
- #
37
- def self.sync_from_memory(robot_id, node_entries)
38
- transaction do
39
- # Clear existing entries for this robot
40
- where(robot_id: robot_id).delete_all
41
-
42
- # Insert current entries
43
- node_entries.each do |node_id, data|
44
- create!(
45
- robot_id: robot_id,
46
- node_id: node_id,
47
- token_count: data[:token_count],
48
- added_at: data[:added_at] || Time.current
49
- )
50
- end
51
- end
52
- end
53
-
54
- # Load working memory state from database
55
- #
56
- # @param robot_id [Integer] Robot ID
57
- # @return [Hash] Hash suitable for WorkingMemory restoration
58
- #
59
- def self.load_for_robot(robot_id)
60
- by_robot(robot_id).includes(:node).each_with_object({}) do |entry, hash|
61
- hash[entry.node_id] = {
62
- content: entry.node.content,
63
- token_count: entry.token_count,
64
- added_at: entry.added_at,
65
- access_count: entry.node.access_count
66
- }
67
- end
68
- end
69
-
70
- # Clear working memory for a robot
71
- #
72
- # @param robot_id [Integer] Robot ID
73
- #
74
- def self.clear_for_robot(robot_id)
75
- where(robot_id: robot_id).delete_all
76
- end
77
-
78
- # Get total token count for a robot's working memory
79
- #
80
- # @param robot_id [Integer] Robot ID
81
- # @return [Integer] Total tokens
82
- #
83
- def self.total_tokens_for_robot(robot_id)
84
- where(robot_id: robot_id).sum(:token_count)
85
- end
86
- end
87
- end
88
- end