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.
Files changed (184) 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 +92 -0
  5. data/.envrc +1 -0
  6. data/.irbrc +283 -80
  7. data/.tbls.yml +31 -0
  8. data/CHANGELOG.md +314 -16
  9. data/CLAUDE.md +603 -0
  10. data/README.md +76 -5
  11. data/Rakefile +5 -0
  12. data/SETUP.md +132 -101
  13. data/db/migrate/{20250101000001_enable_extensions.rb → 00001_enable_extensions.rb} +0 -1
  14. data/db/migrate/00002_create_robots.rb +11 -0
  15. data/db/migrate/00003_create_file_sources.rb +20 -0
  16. data/db/migrate/00004_create_nodes.rb +65 -0
  17. data/db/migrate/00005_create_tags.rb +13 -0
  18. data/db/migrate/00006_create_node_tags.rb +18 -0
  19. data/db/migrate/00007_create_robot_nodes.rb +26 -0
  20. data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +12 -0
  21. data/db/schema.sql +390 -36
  22. data/docs/api/database.md +19 -232
  23. data/docs/api/embedding-service.md +1 -7
  24. data/docs/api/htm.md +305 -364
  25. data/docs/api/index.md +1 -7
  26. data/docs/api/long-term-memory.md +342 -590
  27. data/docs/api/yard/HTM/ActiveRecordConfig.md +23 -0
  28. data/docs/api/yard/HTM/AuthorizationError.md +11 -0
  29. data/docs/api/yard/HTM/CircuitBreaker.md +92 -0
  30. data/docs/api/yard/HTM/CircuitBreakerOpenError.md +34 -0
  31. data/docs/api/yard/HTM/Configuration.md +175 -0
  32. data/docs/api/yard/HTM/Database.md +99 -0
  33. data/docs/api/yard/HTM/DatabaseError.md +14 -0
  34. data/docs/api/yard/HTM/EmbeddingError.md +18 -0
  35. data/docs/api/yard/HTM/EmbeddingService.md +58 -0
  36. data/docs/api/yard/HTM/Error.md +11 -0
  37. data/docs/api/yard/HTM/JobAdapter.md +39 -0
  38. data/docs/api/yard/HTM/LongTermMemory.md +342 -0
  39. data/docs/api/yard/HTM/NotFoundError.md +17 -0
  40. data/docs/api/yard/HTM/Observability.md +107 -0
  41. data/docs/api/yard/HTM/QueryTimeoutError.md +19 -0
  42. data/docs/api/yard/HTM/Railtie.md +27 -0
  43. data/docs/api/yard/HTM/ResourceExhaustedError.md +13 -0
  44. data/docs/api/yard/HTM/TagError.md +18 -0
  45. data/docs/api/yard/HTM/TagService.md +67 -0
  46. data/docs/api/yard/HTM/Timeframe/Result.md +24 -0
  47. data/docs/api/yard/HTM/Timeframe.md +40 -0
  48. data/docs/api/yard/HTM/TimeframeExtractor/Result.md +24 -0
  49. data/docs/api/yard/HTM/TimeframeExtractor.md +45 -0
  50. data/docs/api/yard/HTM/ValidationError.md +20 -0
  51. data/docs/api/yard/HTM/WorkingMemory.md +131 -0
  52. data/docs/api/yard/HTM.md +80 -0
  53. data/docs/api/yard/index.csv +179 -0
  54. data/docs/api/yard-reference.md +51 -0
  55. data/docs/architecture/adrs/001-postgresql-timescaledb.md +1 -1
  56. data/docs/architecture/adrs/003-ollama-embeddings.md +1 -1
  57. data/docs/architecture/adrs/010-redis-working-memory-rejected.md +2 -27
  58. data/docs/architecture/adrs/index.md +2 -13
  59. data/docs/architecture/hive-mind.md +165 -166
  60. data/docs/architecture/index.md +2 -2
  61. data/docs/architecture/overview.md +5 -171
  62. data/docs/architecture/two-tier-memory.md +1 -35
  63. data/docs/assets/images/adr-010-current-architecture.svg +37 -0
  64. data/docs/assets/images/adr-010-proposed-architecture.svg +48 -0
  65. data/docs/assets/images/adr-dependency-tree.svg +93 -0
  66. data/docs/assets/images/class-hierarchy.svg +55 -0
  67. data/docs/assets/images/exception-hierarchy.svg +45 -0
  68. data/docs/assets/images/htm-architecture-overview.svg +83 -0
  69. data/docs/assets/images/htm-complete-memory-flow.svg +160 -0
  70. data/docs/assets/images/htm-context-assembly-flow.svg +148 -0
  71. data/docs/assets/images/htm-eviction-process.svg +141 -0
  72. data/docs/assets/images/htm-memory-addition-flow.svg +138 -0
  73. data/docs/assets/images/htm-memory-recall-flow.svg +152 -0
  74. data/docs/assets/images/htm-node-states.svg +123 -0
  75. data/docs/assets/images/project-structure.svg +78 -0
  76. data/docs/assets/images/test-directory-structure.svg +38 -0
  77. data/{dbdoc → docs/database}/README.md +127 -125
  78. data/docs/database/public.file_sources.md +42 -0
  79. data/docs/database/public.file_sources.svg +211 -0
  80. data/{dbdoc → docs/database}/public.node_tags.md +7 -8
  81. data/docs/database/public.node_tags.svg +239 -0
  82. data/{dbdoc → docs/database}/public.nodes.md +22 -17
  83. data/docs/database/public.nodes.svg +271 -0
  84. data/docs/database/public.robot_nodes.md +46 -0
  85. data/docs/database/public.robot_nodes.svg +243 -0
  86. data/{dbdoc → docs/database}/public.robots.md +2 -3
  87. data/docs/database/public.robots.svg +161 -0
  88. data/docs/database/public.tags.svg +139 -0
  89. data/{dbdoc → docs/database}/schema.json +941 -630
  90. data/docs/database/schema.svg +282 -0
  91. data/docs/development/index.md +1 -29
  92. data/docs/development/schema.md +134 -309
  93. data/docs/development/testing.md +1 -9
  94. data/docs/getting-started/index.md +47 -0
  95. data/docs/{installation.md → getting-started/installation.md} +2 -2
  96. data/docs/{quick-start.md → getting-started/quick-start.md} +5 -5
  97. data/docs/guides/adding-memories.md +295 -643
  98. data/docs/guides/recalling-memories.md +36 -1
  99. data/docs/guides/search-strategies.md +85 -51
  100. data/docs/images/htm-er-diagram.svg +156 -0
  101. data/docs/index.md +16 -31
  102. data/docs/multi_framework_support.md +4 -4
  103. data/examples/README.md +280 -0
  104. data/examples/basic_usage.rb +18 -16
  105. data/examples/cli_app/htm_cli.rb +146 -8
  106. data/examples/cli_app/temp.log +93 -0
  107. data/examples/custom_llm_configuration.rb +1 -2
  108. data/examples/example_app/app.rb +11 -14
  109. data/examples/file_loader_usage.rb +177 -0
  110. data/examples/robot_groups/lib/robot_group.rb +419 -0
  111. data/examples/robot_groups/lib/working_memory_channel.rb +140 -0
  112. data/examples/robot_groups/multi_process.rb +286 -0
  113. data/examples/robot_groups/robot_worker.rb +136 -0
  114. data/examples/robot_groups/same_process.rb +229 -0
  115. data/examples/sinatra_app/Gemfile +1 -0
  116. data/examples/sinatra_app/Gemfile.lock +166 -0
  117. data/examples/sinatra_app/app.rb +219 -24
  118. data/examples/timeframe_demo.rb +276 -0
  119. data/lib/htm/active_record_config.rb +10 -3
  120. data/lib/htm/circuit_breaker.rb +202 -0
  121. data/lib/htm/configuration.rb +313 -80
  122. data/lib/htm/database.rb +67 -36
  123. data/lib/htm/embedding_service.rb +39 -2
  124. data/lib/htm/errors.rb +131 -11
  125. data/lib/htm/{sinatra.rb → integrations/sinatra.rb} +87 -12
  126. data/lib/htm/job_adapter.rb +10 -3
  127. data/lib/htm/jobs/generate_embedding_job.rb +5 -4
  128. data/lib/htm/jobs/generate_tags_job.rb +4 -0
  129. data/lib/htm/loaders/markdown_loader.rb +263 -0
  130. data/lib/htm/loaders/paragraph_chunker.rb +112 -0
  131. data/lib/htm/long_term_memory.rb +601 -321
  132. data/lib/htm/models/file_source.rb +99 -0
  133. data/lib/htm/models/node.rb +116 -12
  134. data/lib/htm/models/robot.rb +53 -4
  135. data/lib/htm/models/robot_node.rb +51 -0
  136. data/lib/htm/models/tag.rb +302 -0
  137. data/lib/htm/observability.rb +395 -0
  138. data/lib/htm/tag_service.rb +60 -3
  139. data/lib/htm/tasks.rb +29 -0
  140. data/lib/htm/timeframe.rb +194 -0
  141. data/lib/htm/timeframe_extractor.rb +307 -0
  142. data/lib/htm/version.rb +1 -1
  143. data/lib/htm/working_memory.rb +165 -70
  144. data/lib/htm.rb +352 -133
  145. data/lib/tasks/doc.rake +300 -0
  146. data/lib/tasks/files.rake +299 -0
  147. data/lib/tasks/htm.rake +188 -2
  148. data/lib/tasks/jobs.rake +10 -12
  149. data/lib/tasks/tags.rake +194 -0
  150. data/mkdocs.yml +91 -9
  151. data/notes/ARCHITECTURE_REVIEW.md +1167 -0
  152. data/notes/IMPLEMENTATION_SUMMARY.md +606 -0
  153. data/notes/MULTI_FRAMEWORK_IMPLEMENTATION.md +451 -0
  154. data/notes/next_steps.md +100 -0
  155. data/notes/plan.md +627 -0
  156. data/notes/tag_ontology_enhancement_ideas.md +222 -0
  157. data/notes/timescaledb_removal_summary.md +200 -0
  158. metadata +177 -37
  159. data/db/migrate/20250101000002_create_robots.rb +0 -14
  160. data/db/migrate/20250101000003_create_nodes.rb +0 -42
  161. data/db/migrate/20250101000005_create_tags.rb +0 -38
  162. data/db/migrate/20250101000007_add_node_vector_indexes.rb +0 -30
  163. data/dbdoc/public.node_tags.svg +0 -112
  164. data/dbdoc/public.nodes.svg +0 -118
  165. data/dbdoc/public.robots.svg +0 -90
  166. data/dbdoc/public.tags.svg +0 -60
  167. data/dbdoc/schema.svg +0 -154
  168. data/{dbdoc → docs/database}/public.node_stats.md +0 -0
  169. data/{dbdoc → docs/database}/public.node_stats.svg +0 -0
  170. data/{dbdoc → docs/database}/public.nodes_tags.md +0 -0
  171. data/{dbdoc → docs/database}/public.nodes_tags.svg +0 -0
  172. data/{dbdoc → docs/database}/public.ontology_structure.md +0 -0
  173. data/{dbdoc → docs/database}/public.ontology_structure.svg +0 -0
  174. data/{dbdoc → docs/database}/public.operations_log.md +0 -0
  175. data/{dbdoc → docs/database}/public.operations_log.svg +0 -0
  176. data/{dbdoc → docs/database}/public.relationships.md +0 -0
  177. data/{dbdoc → docs/database}/public.relationships.svg +0 -0
  178. data/{dbdoc → docs/database}/public.robot_activity.md +0 -0
  179. data/{dbdoc → docs/database}/public.robot_activity.svg +0 -0
  180. data/{dbdoc → docs/database}/public.schema_migrations.md +0 -0
  181. data/{dbdoc → docs/database}/public.schema_migrations.svg +0 -0
  182. data/{dbdoc → docs/database}/public.tags.md +3 -3
  183. /data/{dbdoc → docs/database}/public.topic_relationships.md +0 -0
  184. /data/{dbdoc → docs/database}/public.topic_relationships.svg +0 -0
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateNodeTags < ActiveRecord::Migration[7.1]
4
+ def change
5
+ create_table :node_tags, comment: 'Join table connecting nodes to tags (many-to-many)' do |t|
6
+ t.bigint :node_id, null: false, comment: 'ID of the node being tagged'
7
+ t.bigint :tag_id, null: false, comment: 'ID of the tag being applied'
8
+ t.timestamptz :created_at, default: -> { 'CURRENT_TIMESTAMP' }, comment: 'When this association was created'
9
+ end
10
+
11
+ add_index :node_tags, [:node_id, :tag_id], unique: true, name: 'idx_node_tags_unique'
12
+ add_index :node_tags, :node_id, name: 'idx_node_tags_node_id'
13
+ add_index :node_tags, :tag_id, name: 'idx_node_tags_tag_id'
14
+
15
+ add_foreign_key :node_tags, :nodes, column: :node_id, on_delete: :cascade
16
+ add_foreign_key :node_tags, :tags, column: :tag_id, on_delete: :cascade
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateRobotNodes < ActiveRecord::Migration[7.1]
4
+ def change
5
+ create_table :robot_nodes, comment: 'Join table connecting robots to nodes (many-to-many)' do |t|
6
+ t.bigint :robot_id, null: false, comment: 'ID of the robot that remembered this node'
7
+ t.bigint :node_id, null: false, comment: 'ID of the node being remembered'
8
+ t.timestamptz :first_remembered_at, default: -> { 'CURRENT_TIMESTAMP' },
9
+ comment: 'When this robot first remembered this content'
10
+ t.timestamptz :last_remembered_at, default: -> { 'CURRENT_TIMESTAMP' },
11
+ comment: 'When this robot last tried to remember this content'
12
+ t.integer :remember_count, default: 1, null: false,
13
+ comment: 'Number of times this robot has tried to remember this content'
14
+ t.timestamptz :created_at, default: -> { 'CURRENT_TIMESTAMP' }
15
+ t.timestamptz :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
16
+ end
17
+
18
+ add_index :robot_nodes, [:robot_id, :node_id], unique: true, name: 'idx_robot_nodes_unique'
19
+ add_index :robot_nodes, :robot_id, name: 'idx_robot_nodes_robot_id'
20
+ add_index :robot_nodes, :node_id, name: 'idx_robot_nodes_node_id'
21
+ add_index :robot_nodes, :last_remembered_at, name: 'idx_robot_nodes_last_remembered_at'
22
+
23
+ add_foreign_key :robot_nodes, :robots, column: :robot_id, on_delete: :cascade
24
+ add_foreign_key :robot_nodes, :nodes, column: :node_id, on_delete: :cascade
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddWorkingMemoryToRobotNodes < ActiveRecord::Migration[7.1]
4
+ def change
5
+ add_column :robot_nodes, :working_memory, :boolean, default: false, null: false,
6
+ comment: 'True if this node is currently in the robot working memory'
7
+
8
+ add_index :robot_nodes, [:robot_id, :working_memory],
9
+ where: 'working_memory = true',
10
+ name: 'idx_robot_nodes_working_memory'
11
+ end
12
+ end
data/db/schema.sql CHANGED
@@ -23,6 +23,81 @@ CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA public;
23
23
  -- Name: EXTENSION vector; Type: COMMENT; Schema: -; Owner: -
24
24
  --
25
25
 
26
+ --
27
+ -- Name: file_sources; Type: TABLE; Schema: public; Owner: -
28
+ --
29
+
30
+ CREATE TABLE public.file_sources (
31
+ id bigint NOT NULL,
32
+ file_path text NOT NULL,
33
+ file_hash character varying(64),
34
+ mtime timestamp with time zone,
35
+ file_size integer,
36
+ frontmatter jsonb DEFAULT '{}'::jsonb,
37
+ last_synced_at timestamp with time zone,
38
+ created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
39
+ updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP
40
+ );
41
+
42
+ --
43
+ -- Name: TABLE file_sources; Type: COMMENT; Schema: public; Owner: -
44
+ --
45
+
46
+ COMMENT ON TABLE public.file_sources IS 'Source file metadata for loaded documents';
47
+
48
+ --
49
+ -- Name: COLUMN file_sources.file_path; Type: COMMENT; Schema: public; Owner: -
50
+ --
51
+
52
+ COMMENT ON COLUMN public.file_sources.file_path IS 'Absolute path to source file';
53
+
54
+ --
55
+ -- Name: COLUMN file_sources.file_hash; Type: COMMENT; Schema: public; Owner: -
56
+ --
57
+
58
+ COMMENT ON COLUMN public.file_sources.file_hash IS 'SHA-256 hash of file content';
59
+
60
+ --
61
+ -- Name: COLUMN file_sources.mtime; Type: COMMENT; Schema: public; Owner: -
62
+ --
63
+
64
+ COMMENT ON COLUMN public.file_sources.mtime IS 'File modification time';
65
+
66
+ --
67
+ -- Name: COLUMN file_sources.file_size; Type: COMMENT; Schema: public; Owner: -
68
+ --
69
+
70
+ COMMENT ON COLUMN public.file_sources.file_size IS 'File size in bytes';
71
+
72
+ --
73
+ -- Name: COLUMN file_sources.frontmatter; Type: COMMENT; Schema: public; Owner: -
74
+ --
75
+
76
+ COMMENT ON COLUMN public.file_sources.frontmatter IS 'Parsed YAML frontmatter';
77
+
78
+ --
79
+ -- Name: COLUMN file_sources.last_synced_at; Type: COMMENT; Schema: public; Owner: -
80
+ --
81
+
82
+ COMMENT ON COLUMN public.file_sources.last_synced_at IS 'When file was last synced to HTM';
83
+
84
+ --
85
+ -- Name: file_sources_id_seq; Type: SEQUENCE; Schema: public; Owner: -
86
+ --
87
+
88
+ CREATE SEQUENCE public.file_sources_id_seq
89
+ START WITH 1
90
+ INCREMENT BY 1
91
+ NO MINVALUE
92
+ NO MAXVALUE
93
+ CACHE 1;
94
+
95
+ --
96
+ -- Name: file_sources_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
97
+ --
98
+
99
+ ALTER SEQUENCE public.file_sources_id_seq OWNED BY public.file_sources.id;
100
+
26
101
  --
27
102
  -- Name: node_tags; Type: TABLE; Schema: public; Owner: -
28
103
  --
@@ -82,16 +157,18 @@ ALTER SEQUENCE public.node_tags_id_seq OWNED BY public.node_tags.id;
82
157
  CREATE TABLE public.nodes (
83
158
  id bigint NOT NULL,
84
159
  content text NOT NULL,
85
- source text DEFAULT ''::text,
86
160
  access_count integer DEFAULT 0 NOT NULL,
87
161
  created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
88
162
  updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
89
163
  last_accessed timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
90
164
  token_count integer,
91
- in_working_memory boolean DEFAULT false,
92
- robot_id bigint NOT NULL,
93
165
  embedding public.vector(2000),
94
166
  embedding_dimension integer,
167
+ content_hash character varying(64),
168
+ deleted_at timestamp with time zone,
169
+ source_id bigint,
170
+ chunk_position integer,
171
+ metadata jsonb DEFAULT '{}'::jsonb NOT NULL,
95
172
  CONSTRAINT check_embedding_dimension CHECK (((embedding_dimension IS NULL) OR ((embedding_dimension > 0) AND (embedding_dimension <= 2000))))
96
173
  );
97
174
 
@@ -107,12 +184,6 @@ COMMENT ON TABLE public.nodes IS 'Core memory storage for conversation messages
107
184
 
108
185
  COMMENT ON COLUMN public.nodes.content IS 'The conversation message/utterance content';
109
186
 
110
- --
111
- -- Name: COLUMN nodes.source; Type: COMMENT; Schema: public; Owner: -
112
- --
113
-
114
- COMMENT ON COLUMN public.nodes.source IS 'From where the content came (empty string if unknown)';
115
-
116
187
  --
117
188
  -- Name: COLUMN nodes.access_count; Type: COMMENT; Schema: public; Owner: -
118
189
  --
@@ -144,28 +215,46 @@ COMMENT ON COLUMN public.nodes.last_accessed IS 'When this memory was last acces
144
215
  COMMENT ON COLUMN public.nodes.token_count IS 'Number of tokens in the content (for context budget management)';
145
216
 
146
217
  --
147
- -- Name: COLUMN nodes.in_working_memory; Type: COMMENT; Schema: public; Owner: -
218
+ -- Name: COLUMN nodes.embedding; Type: COMMENT; Schema: public; Owner: -
219
+ --
220
+
221
+ COMMENT ON COLUMN public.nodes.embedding IS 'Vector embedding (max 2000 dimensions) for semantic search';
222
+
223
+ --
224
+ -- Name: COLUMN nodes.embedding_dimension; Type: COMMENT; Schema: public; Owner: -
148
225
  --
149
226
 
150
- COMMENT ON COLUMN public.nodes.in_working_memory IS 'Whether this memory is currently in working memory';
227
+ COMMENT ON COLUMN public.nodes.embedding_dimension IS 'Actual number of dimensions used in the embedding vector (max 2000)';
151
228
 
152
229
  --
153
- -- Name: COLUMN nodes.robot_id; Type: COMMENT; Schema: public; Owner: -
230
+ -- Name: COLUMN nodes.content_hash; Type: COMMENT; Schema: public; Owner: -
154
231
  --
155
232
 
156
- COMMENT ON COLUMN public.nodes.robot_id IS 'ID of the robot that owns this memory';
233
+ COMMENT ON COLUMN public.nodes.content_hash IS 'SHA-256 hash of content for deduplication';
157
234
 
158
235
  --
159
- -- Name: COLUMN nodes.embedding; Type: COMMENT; Schema: public; Owner: -
236
+ -- Name: COLUMN nodes.deleted_at; Type: COMMENT; Schema: public; Owner: -
160
237
  --
161
238
 
162
- COMMENT ON COLUMN public.nodes.embedding IS 'Vector embedding (max 2000 dimensions) for semantic search';
239
+ COMMENT ON COLUMN public.nodes.deleted_at IS 'Soft delete timestamp - node is considered deleted when set';
163
240
 
164
241
  --
165
- -- Name: COLUMN nodes.embedding_dimension; Type: COMMENT; Schema: public; Owner: -
242
+ -- Name: COLUMN nodes.source_id; Type: COMMENT; Schema: public; Owner: -
166
243
  --
167
244
 
168
- COMMENT ON COLUMN public.nodes.embedding_dimension IS 'Actual number of dimensions used in the embedding vector (max 2000)';
245
+ COMMENT ON COLUMN public.nodes.source_id IS 'Reference to source file (for file-loaded nodes)';
246
+
247
+ --
248
+ -- Name: COLUMN nodes.chunk_position; Type: COMMENT; Schema: public; Owner: -
249
+ --
250
+
251
+ COMMENT ON COLUMN public.nodes.chunk_position IS 'Position within source file (0-indexed)';
252
+
253
+ --
254
+ -- Name: COLUMN nodes.metadata; Type: COMMENT; Schema: public; Owner: -
255
+ --
256
+
257
+ COMMENT ON COLUMN public.nodes.metadata IS 'Flexible metadata storage (memory_type, importance, source, etc.)';
169
258
 
170
259
  --
171
260
  -- Name: nodes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
@@ -184,6 +273,74 @@ CREATE SEQUENCE public.nodes_id_seq
184
273
 
185
274
  ALTER SEQUENCE public.nodes_id_seq OWNED BY public.nodes.id;
186
275
 
276
+ --
277
+ -- Name: robot_nodes; Type: TABLE; Schema: public; Owner: -
278
+ --
279
+
280
+ CREATE TABLE public.robot_nodes (
281
+ id bigint NOT NULL,
282
+ robot_id bigint NOT NULL,
283
+ node_id bigint NOT NULL,
284
+ first_remembered_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
285
+ last_remembered_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
286
+ remember_count integer DEFAULT 1 NOT NULL,
287
+ created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
288
+ updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP
289
+ );
290
+
291
+ --
292
+ -- Name: TABLE robot_nodes; Type: COMMENT; Schema: public; Owner: -
293
+ --
294
+
295
+ COMMENT ON TABLE public.robot_nodes IS 'Join table connecting robots to nodes (many-to-many)';
296
+
297
+ --
298
+ -- Name: COLUMN robot_nodes.robot_id; Type: COMMENT; Schema: public; Owner: -
299
+ --
300
+
301
+ COMMENT ON COLUMN public.robot_nodes.robot_id IS 'ID of the robot that remembered this node';
302
+
303
+ --
304
+ -- Name: COLUMN robot_nodes.node_id; Type: COMMENT; Schema: public; Owner: -
305
+ --
306
+
307
+ COMMENT ON COLUMN public.robot_nodes.node_id IS 'ID of the node being remembered';
308
+
309
+ --
310
+ -- Name: COLUMN robot_nodes.first_remembered_at; Type: COMMENT; Schema: public; Owner: -
311
+ --
312
+
313
+ COMMENT ON COLUMN public.robot_nodes.first_remembered_at IS 'When this robot first remembered this content';
314
+
315
+ --
316
+ -- Name: COLUMN robot_nodes.last_remembered_at; Type: COMMENT; Schema: public; Owner: -
317
+ --
318
+
319
+ COMMENT ON COLUMN public.robot_nodes.last_remembered_at IS 'When this robot last tried to remember this content';
320
+
321
+ --
322
+ -- Name: COLUMN robot_nodes.remember_count; Type: COMMENT; Schema: public; Owner: -
323
+ --
324
+
325
+ COMMENT ON COLUMN public.robot_nodes.remember_count IS 'Number of times this robot has tried to remember this content';
326
+
327
+ --
328
+ -- Name: robot_nodes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
329
+ --
330
+
331
+ CREATE SEQUENCE public.robot_nodes_id_seq
332
+ START WITH 1
333
+ INCREMENT BY 1
334
+ NO MINVALUE
335
+ NO MAXVALUE
336
+ CACHE 1;
337
+
338
+ --
339
+ -- Name: robot_nodes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
340
+ --
341
+
342
+ ALTER SEQUENCE public.robot_nodes_id_seq OWNED BY public.robot_nodes.id;
343
+
187
344
  --
188
345
  -- Name: robots; Type: TABLE; Schema: public; Owner: -
189
346
  --
@@ -192,8 +349,7 @@ CREATE TABLE public.robots (
192
349
  id bigint NOT NULL,
193
350
  name text,
194
351
  created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
195
- last_active timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
196
- metadata jsonb
352
+ last_active timestamp with time zone DEFAULT CURRENT_TIMESTAMP
197
353
  );
198
354
 
199
355
  --
@@ -220,12 +376,6 @@ COMMENT ON COLUMN public.robots.created_at IS 'When the robot was first register
220
376
 
221
377
  COMMENT ON COLUMN public.robots.last_active IS 'Last time the robot accessed the system';
222
378
 
223
- --
224
- -- Name: COLUMN robots.metadata; Type: COMMENT; Schema: public; Owner: -
225
- --
226
-
227
- COMMENT ON COLUMN public.robots.metadata IS 'Robot-specific configuration and metadata';
228
-
229
379
  --
230
380
  -- Name: robots_id_seq; Type: SEQUENCE; Schema: public; Owner: -
231
381
  --
@@ -296,6 +446,71 @@ CREATE SEQUENCE public.tags_id_seq
296
446
 
297
447
  ALTER SEQUENCE public.tags_id_seq OWNED BY public.tags.id;
298
448
 
449
+ --
450
+ -- Name: working_memories; Type: TABLE; Schema: public; Owner: -
451
+ --
452
+
453
+ CREATE TABLE public.working_memories (
454
+ id bigint NOT NULL,
455
+ robot_id bigint NOT NULL,
456
+ node_id bigint NOT NULL,
457
+ added_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
458
+ token_count integer
459
+ );
460
+
461
+ --
462
+ -- Name: TABLE working_memories; Type: COMMENT; Schema: public; Owner: -
463
+ --
464
+
465
+ COMMENT ON TABLE public.working_memories IS 'Per-robot working memory state (optional persistence)';
466
+
467
+ --
468
+ -- Name: COLUMN working_memories.robot_id; Type: COMMENT; Schema: public; Owner: -
469
+ --
470
+
471
+ COMMENT ON COLUMN public.working_memories.robot_id IS 'Robot whose working memory this belongs to';
472
+
473
+ --
474
+ -- Name: COLUMN working_memories.node_id; Type: COMMENT; Schema: public; Owner: -
475
+ --
476
+
477
+ COMMENT ON COLUMN public.working_memories.node_id IS 'Node currently in working memory';
478
+
479
+ --
480
+ -- Name: COLUMN working_memories.added_at; Type: COMMENT; Schema: public; Owner: -
481
+ --
482
+
483
+ COMMENT ON COLUMN public.working_memories.added_at IS 'When node was added to working memory';
484
+
485
+ --
486
+ -- Name: COLUMN working_memories.token_count; Type: COMMENT; Schema: public; Owner: -
487
+ --
488
+
489
+ COMMENT ON COLUMN public.working_memories.token_count IS 'Cached token count for budget tracking';
490
+
491
+ --
492
+ -- Name: working_memories_id_seq; Type: SEQUENCE; Schema: public; Owner: -
493
+ --
494
+
495
+ CREATE SEQUENCE public.working_memories_id_seq
496
+ START WITH 1
497
+ INCREMENT BY 1
498
+ NO MINVALUE
499
+ NO MAXVALUE
500
+ CACHE 1;
501
+
502
+ --
503
+ -- Name: working_memories_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
504
+ --
505
+
506
+ ALTER SEQUENCE public.working_memories_id_seq OWNED BY public.working_memories.id;
507
+
508
+ --
509
+ -- Name: file_sources id; Type: DEFAULT; Schema: public; Owner: -
510
+ --
511
+
512
+ ALTER TABLE ONLY public.file_sources ALTER COLUMN id SET DEFAULT nextval('public.file_sources_id_seq'::regclass);
513
+
299
514
  --
300
515
  -- Name: node_tags id; Type: DEFAULT; Schema: public; Owner: -
301
516
  --
@@ -308,6 +523,12 @@ ALTER TABLE ONLY public.node_tags ALTER COLUMN id SET DEFAULT nextval('public.no
308
523
 
309
524
  ALTER TABLE ONLY public.nodes ALTER COLUMN id SET DEFAULT nextval('public.nodes_id_seq'::regclass);
310
525
 
526
+ --
527
+ -- Name: robot_nodes id; Type: DEFAULT; Schema: public; Owner: -
528
+ --
529
+
530
+ ALTER TABLE ONLY public.robot_nodes ALTER COLUMN id SET DEFAULT nextval('public.robot_nodes_id_seq'::regclass);
531
+
311
532
  --
312
533
  -- Name: robots id; Type: DEFAULT; Schema: public; Owner: -
313
534
  --
@@ -320,6 +541,19 @@ ALTER TABLE ONLY public.robots ALTER COLUMN id SET DEFAULT nextval('public.robot
320
541
 
321
542
  ALTER TABLE ONLY public.tags ALTER COLUMN id SET DEFAULT nextval('public.tags_id_seq'::regclass);
322
543
 
544
+ --
545
+ -- Name: working_memories id; Type: DEFAULT; Schema: public; Owner: -
546
+ --
547
+
548
+ ALTER TABLE ONLY public.working_memories ALTER COLUMN id SET DEFAULT nextval('public.working_memories_id_seq'::regclass);
549
+
550
+ --
551
+ -- Name: file_sources file_sources_pkey; Type: CONSTRAINT; Schema: public; Owner: -
552
+ --
553
+
554
+ ALTER TABLE ONLY public.file_sources
555
+ ADD CONSTRAINT file_sources_pkey PRIMARY KEY (id);
556
+
323
557
  --
324
558
  -- Name: node_tags node_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: -
325
559
  --
@@ -334,6 +568,13 @@ ALTER TABLE ONLY public.node_tags
334
568
  ALTER TABLE ONLY public.nodes
335
569
  ADD CONSTRAINT nodes_pkey PRIMARY KEY (id);
336
570
 
571
+ --
572
+ -- Name: robot_nodes robot_nodes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
573
+ --
574
+
575
+ ALTER TABLE ONLY public.robot_nodes
576
+ ADD CONSTRAINT robot_nodes_pkey PRIMARY KEY (id);
577
+
337
578
  --
338
579
  -- Name: robots robots_pkey; Type: CONSTRAINT; Schema: public; Owner: -
339
580
  --
@@ -355,6 +596,31 @@ ALTER TABLE ONLY public.schema_migrations
355
596
  ALTER TABLE ONLY public.tags
356
597
  ADD CONSTRAINT tags_pkey PRIMARY KEY (id);
357
598
 
599
+ --
600
+ -- Name: working_memories working_memories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
601
+ --
602
+
603
+ ALTER TABLE ONLY public.working_memories
604
+ ADD CONSTRAINT working_memories_pkey PRIMARY KEY (id);
605
+
606
+ --
607
+ -- Name: idx_file_sources_hash; Type: INDEX; Schema: public; Owner: -
608
+ --
609
+
610
+ CREATE INDEX idx_file_sources_hash ON public.file_sources USING btree (file_hash);
611
+
612
+ --
613
+ -- Name: idx_file_sources_last_synced; Type: INDEX; Schema: public; Owner: -
614
+ --
615
+
616
+ CREATE INDEX idx_file_sources_last_synced ON public.file_sources USING btree (last_synced_at);
617
+
618
+ --
619
+ -- Name: idx_file_sources_path_unique; Type: INDEX; Schema: public; Owner: -
620
+ --
621
+
622
+ CREATE UNIQUE INDEX idx_file_sources_path_unique ON public.file_sources USING btree (file_path);
623
+
358
624
  --
359
625
  -- Name: idx_node_tags_node_id; Type: INDEX; Schema: public; Owner: -
360
626
  --
@@ -385,6 +651,12 @@ CREATE INDEX idx_nodes_access_count ON public.nodes USING btree (access_count);
385
651
 
386
652
  CREATE INDEX idx_nodes_content_gin ON public.nodes USING gin (to_tsvector('english'::regconfig, content));
387
653
 
654
+ --
655
+ -- Name: idx_nodes_content_hash_unique; Type: INDEX; Schema: public; Owner: -
656
+ --
657
+
658
+ CREATE UNIQUE INDEX idx_nodes_content_hash_unique ON public.nodes USING btree (content_hash);
659
+
388
660
  --
389
661
  -- Name: idx_nodes_content_trgm; Type: INDEX; Schema: public; Owner: -
390
662
  --
@@ -398,16 +670,16 @@ CREATE INDEX idx_nodes_content_trgm ON public.nodes USING gin (content public.gi
398
670
  CREATE INDEX idx_nodes_created_at ON public.nodes USING btree (created_at);
399
671
 
400
672
  --
401
- -- Name: idx_nodes_embedding; Type: INDEX; Schema: public; Owner: -
673
+ -- Name: idx_nodes_deleted_at; Type: INDEX; Schema: public; Owner: -
402
674
  --
403
675
 
404
- CREATE INDEX idx_nodes_embedding ON public.nodes USING hnsw (embedding public.vector_cosine_ops) WITH (m='16', ef_construction='64');
676
+ CREATE INDEX idx_nodes_deleted_at ON public.nodes USING btree (deleted_at);
405
677
 
406
678
  --
407
- -- Name: idx_nodes_in_working_memory; Type: INDEX; Schema: public; Owner: -
679
+ -- Name: idx_nodes_embedding; Type: INDEX; Schema: public; Owner: -
408
680
  --
409
681
 
410
- CREATE INDEX idx_nodes_in_working_memory ON public.nodes USING btree (in_working_memory);
682
+ CREATE INDEX idx_nodes_embedding ON public.nodes USING hnsw (embedding public.vector_cosine_ops) WITH (m='16', ef_construction='64');
411
683
 
412
684
  --
413
685
  -- Name: idx_nodes_last_accessed; Type: INDEX; Schema: public; Owner: -
@@ -416,16 +688,28 @@ CREATE INDEX idx_nodes_in_working_memory ON public.nodes USING btree (in_working
416
688
  CREATE INDEX idx_nodes_last_accessed ON public.nodes USING btree (last_accessed);
417
689
 
418
690
  --
419
- -- Name: idx_nodes_robot_id; Type: INDEX; Schema: public; Owner: -
691
+ -- Name: idx_nodes_metadata; Type: INDEX; Schema: public; Owner: -
692
+ --
693
+
694
+ CREATE INDEX idx_nodes_metadata ON public.nodes USING gin (metadata);
695
+
696
+ --
697
+ -- Name: idx_nodes_not_deleted_created_at; Type: INDEX; Schema: public; Owner: -
420
698
  --
421
699
 
422
- CREATE INDEX idx_nodes_robot_id ON public.nodes USING btree (robot_id);
700
+ CREATE INDEX idx_nodes_not_deleted_created_at ON public.nodes USING btree (created_at) WHERE (deleted_at IS NULL);
423
701
 
424
702
  --
425
- -- Name: idx_nodes_source; Type: INDEX; Schema: public; Owner: -
703
+ -- Name: idx_nodes_source_chunk_position; Type: INDEX; Schema: public; Owner: -
426
704
  --
427
705
 
428
- CREATE INDEX idx_nodes_source ON public.nodes USING btree (source);
706
+ CREATE INDEX idx_nodes_source_chunk_position ON public.nodes USING btree (source_id, chunk_position);
707
+
708
+ --
709
+ -- Name: idx_nodes_source_id; Type: INDEX; Schema: public; Owner: -
710
+ --
711
+
712
+ CREATE INDEX idx_nodes_source_id ON public.nodes USING btree (source_id);
429
713
 
430
714
  --
431
715
  -- Name: idx_nodes_updated_at; Type: INDEX; Schema: public; Owner: -
@@ -433,6 +717,30 @@ CREATE INDEX idx_nodes_source ON public.nodes USING btree (source);
433
717
 
434
718
  CREATE INDEX idx_nodes_updated_at ON public.nodes USING btree (updated_at);
435
719
 
720
+ --
721
+ -- Name: idx_robot_nodes_last_remembered_at; Type: INDEX; Schema: public; Owner: -
722
+ --
723
+
724
+ CREATE INDEX idx_robot_nodes_last_remembered_at ON public.robot_nodes USING btree (last_remembered_at);
725
+
726
+ --
727
+ -- Name: idx_robot_nodes_node_id; Type: INDEX; Schema: public; Owner: -
728
+ --
729
+
730
+ CREATE INDEX idx_robot_nodes_node_id ON public.robot_nodes USING btree (node_id);
731
+
732
+ --
733
+ -- Name: idx_robot_nodes_robot_id; Type: INDEX; Schema: public; Owner: -
734
+ --
735
+
736
+ CREATE INDEX idx_robot_nodes_robot_id ON public.robot_nodes USING btree (robot_id);
737
+
738
+ --
739
+ -- Name: idx_robot_nodes_unique; Type: INDEX; Schema: public; Owner: -
740
+ --
741
+
742
+ CREATE UNIQUE INDEX idx_robot_nodes_unique ON public.robot_nodes USING btree (robot_id, node_id);
743
+
436
744
  --
437
745
  -- Name: idx_tags_name_pattern; Type: INDEX; Schema: public; Owner: -
438
746
  --
@@ -446,11 +754,50 @@ CREATE INDEX idx_tags_name_pattern ON public.tags USING btree (name text_pattern
446
754
  CREATE UNIQUE INDEX idx_tags_name_unique ON public.tags USING btree (name);
447
755
 
448
756
  --
449
- -- Name: nodes fk_rails_60162e9d3a; Type: FK CONSTRAINT; Schema: public; Owner: -
757
+ -- Name: idx_working_memories_node_id; Type: INDEX; Schema: public; Owner: -
758
+ --
759
+
760
+ CREATE INDEX idx_working_memories_node_id ON public.working_memories USING btree (node_id);
761
+
762
+ --
763
+ -- Name: idx_working_memories_robot_id; Type: INDEX; Schema: public; Owner: -
764
+ --
765
+
766
+ CREATE INDEX idx_working_memories_robot_id ON public.working_memories USING btree (robot_id);
767
+
768
+ --
769
+ -- Name: idx_working_memories_unique; Type: INDEX; Schema: public; Owner: -
770
+ --
771
+
772
+ CREATE UNIQUE INDEX idx_working_memories_unique ON public.working_memories USING btree (robot_id, node_id);
773
+
774
+ --
775
+ -- Name: working_memories fk_rails_2c1d8b383c; Type: FK CONSTRAINT; Schema: public; Owner: -
776
+ --
777
+
778
+ ALTER TABLE ONLY public.working_memories
779
+ ADD CONSTRAINT fk_rails_2c1d8b383c FOREIGN KEY (node_id) REFERENCES public.nodes(id) ON DELETE CASCADE;
780
+
781
+ --
782
+ -- Name: working_memories fk_rails_4b7c3eb07b; Type: FK CONSTRAINT; Schema: public; Owner: -
783
+ --
784
+
785
+ ALTER TABLE ONLY public.working_memories
786
+ ADD CONSTRAINT fk_rails_4b7c3eb07b FOREIGN KEY (robot_id) REFERENCES public.robots(id) ON DELETE CASCADE;
787
+
788
+ --
789
+ -- Name: nodes fk_rails_920ad16d08; Type: FK CONSTRAINT; Schema: public; Owner: -
450
790
  --
451
791
 
452
792
  ALTER TABLE ONLY public.nodes
453
- ADD CONSTRAINT fk_rails_60162e9d3a FOREIGN KEY (robot_id) REFERENCES public.robots(id) ON DELETE CASCADE;
793
+ ADD CONSTRAINT fk_rails_920ad16d08 FOREIGN KEY (source_id) REFERENCES public.file_sources(id) ON DELETE SET NULL;
794
+
795
+ --
796
+ -- Name: robot_nodes fk_rails_9b003078a8; Type: FK CONSTRAINT; Schema: public; Owner: -
797
+ --
798
+
799
+ ALTER TABLE ONLY public.robot_nodes
800
+ ADD CONSTRAINT fk_rails_9b003078a8 FOREIGN KEY (robot_id) REFERENCES public.robots(id) ON DELETE CASCADE;
454
801
 
455
802
  --
456
803
  -- Name: node_tags fk_rails_b51cdcc57f; Type: FK CONSTRAINT; Schema: public; Owner: -
@@ -466,8 +813,15 @@ ALTER TABLE ONLY public.node_tags
466
813
  ALTER TABLE ONLY public.node_tags
467
814
  ADD CONSTRAINT fk_rails_ebc9aafd9f FOREIGN KEY (node_id) REFERENCES public.nodes(id) ON DELETE CASCADE;
468
815
 
816
+ --
817
+ -- Name: robot_nodes fk_rails_f2fc98d49e; Type: FK CONSTRAINT; Schema: public; Owner: -
818
+ --
819
+
820
+ ALTER TABLE ONLY public.robot_nodes
821
+ ADD CONSTRAINT fk_rails_f2fc98d49e FOREIGN KEY (node_id) REFERENCES public.nodes(id) ON DELETE CASCADE;
822
+
469
823
  --
470
824
  -- PostgreSQL database dump complete
471
825
  --
472
826
 
473
- \unrestrict f5a75Zsnuw7NUeDmu1kxeQ3pRMbaORhrsWHJyDdXV4wbRfzQweTumJBXu85kf1z
827
+ \unrestrict DUrF24Zrve4qSBwlDrJ4qAzzZhvhX5s2S57oHYVJ0ZPbaDC4ItMZ29Pv9oI3Q9d