hindsight-api 0.2.1__py3-none-any.whl → 0.4.0__py3-none-any.whl

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 (88) hide show
  1. hindsight_api/admin/__init__.py +1 -0
  2. hindsight_api/admin/cli.py +311 -0
  3. hindsight_api/alembic/versions/f1a2b3c4d5e6_add_memory_links_composite_index.py +44 -0
  4. hindsight_api/alembic/versions/g2a3b4c5d6e7_add_tags_column.py +48 -0
  5. hindsight_api/alembic/versions/h3c4d5e6f7g8_mental_models_v4.py +112 -0
  6. hindsight_api/alembic/versions/i4d5e6f7g8h9_delete_opinions.py +41 -0
  7. hindsight_api/alembic/versions/j5e6f7g8h9i0_mental_model_versions.py +95 -0
  8. hindsight_api/alembic/versions/k6f7g8h9i0j1_add_directive_subtype.py +58 -0
  9. hindsight_api/alembic/versions/l7g8h9i0j1k2_add_worker_columns.py +109 -0
  10. hindsight_api/alembic/versions/m8h9i0j1k2l3_mental_model_id_to_text.py +41 -0
  11. hindsight_api/alembic/versions/n9i0j1k2l3m4_learnings_and_pinned_reflections.py +134 -0
  12. hindsight_api/alembic/versions/o0j1k2l3m4n5_migrate_mental_models_data.py +113 -0
  13. hindsight_api/alembic/versions/p1k2l3m4n5o6_new_knowledge_architecture.py +194 -0
  14. hindsight_api/alembic/versions/q2l3m4n5o6p7_fix_mental_model_fact_type.py +50 -0
  15. hindsight_api/alembic/versions/r3m4n5o6p7q8_add_reflect_response_to_reflections.py +47 -0
  16. hindsight_api/alembic/versions/s4n5o6p7q8r9_add_consolidated_at_to_memory_units.py +53 -0
  17. hindsight_api/alembic/versions/t5o6p7q8r9s0_rename_mental_models_to_observations.py +134 -0
  18. hindsight_api/alembic/versions/u6p7q8r9s0t1_mental_models_text_id.py +41 -0
  19. hindsight_api/alembic/versions/v7q8r9s0t1u2_add_max_tokens_to_mental_models.py +50 -0
  20. hindsight_api/api/http.py +1406 -118
  21. hindsight_api/api/mcp.py +11 -196
  22. hindsight_api/config.py +359 -27
  23. hindsight_api/engine/consolidation/__init__.py +5 -0
  24. hindsight_api/engine/consolidation/consolidator.py +859 -0
  25. hindsight_api/engine/consolidation/prompts.py +69 -0
  26. hindsight_api/engine/cross_encoder.py +706 -88
  27. hindsight_api/engine/db_budget.py +284 -0
  28. hindsight_api/engine/db_utils.py +11 -0
  29. hindsight_api/engine/directives/__init__.py +5 -0
  30. hindsight_api/engine/directives/models.py +37 -0
  31. hindsight_api/engine/embeddings.py +553 -29
  32. hindsight_api/engine/entity_resolver.py +8 -5
  33. hindsight_api/engine/interface.py +40 -17
  34. hindsight_api/engine/llm_wrapper.py +744 -68
  35. hindsight_api/engine/memory_engine.py +2505 -1017
  36. hindsight_api/engine/mental_models/__init__.py +14 -0
  37. hindsight_api/engine/mental_models/models.py +53 -0
  38. hindsight_api/engine/query_analyzer.py +4 -3
  39. hindsight_api/engine/reflect/__init__.py +18 -0
  40. hindsight_api/engine/reflect/agent.py +933 -0
  41. hindsight_api/engine/reflect/models.py +109 -0
  42. hindsight_api/engine/reflect/observations.py +186 -0
  43. hindsight_api/engine/reflect/prompts.py +483 -0
  44. hindsight_api/engine/reflect/tools.py +437 -0
  45. hindsight_api/engine/reflect/tools_schema.py +250 -0
  46. hindsight_api/engine/response_models.py +168 -4
  47. hindsight_api/engine/retain/bank_utils.py +79 -201
  48. hindsight_api/engine/retain/fact_extraction.py +424 -195
  49. hindsight_api/engine/retain/fact_storage.py +35 -12
  50. hindsight_api/engine/retain/link_utils.py +29 -24
  51. hindsight_api/engine/retain/orchestrator.py +24 -43
  52. hindsight_api/engine/retain/types.py +11 -2
  53. hindsight_api/engine/search/graph_retrieval.py +43 -14
  54. hindsight_api/engine/search/link_expansion_retrieval.py +391 -0
  55. hindsight_api/engine/search/mpfp_retrieval.py +362 -117
  56. hindsight_api/engine/search/reranking.py +2 -2
  57. hindsight_api/engine/search/retrieval.py +848 -201
  58. hindsight_api/engine/search/tags.py +172 -0
  59. hindsight_api/engine/search/think_utils.py +42 -141
  60. hindsight_api/engine/search/trace.py +12 -1
  61. hindsight_api/engine/search/tracer.py +26 -6
  62. hindsight_api/engine/search/types.py +21 -3
  63. hindsight_api/engine/task_backend.py +113 -106
  64. hindsight_api/engine/utils.py +1 -152
  65. hindsight_api/extensions/__init__.py +10 -1
  66. hindsight_api/extensions/builtin/tenant.py +5 -1
  67. hindsight_api/extensions/context.py +10 -1
  68. hindsight_api/extensions/operation_validator.py +81 -4
  69. hindsight_api/extensions/tenant.py +26 -0
  70. hindsight_api/main.py +69 -6
  71. hindsight_api/mcp_local.py +12 -53
  72. hindsight_api/mcp_tools.py +494 -0
  73. hindsight_api/metrics.py +433 -48
  74. hindsight_api/migrations.py +141 -1
  75. hindsight_api/models.py +3 -3
  76. hindsight_api/pg0.py +53 -0
  77. hindsight_api/server.py +39 -2
  78. hindsight_api/worker/__init__.py +11 -0
  79. hindsight_api/worker/main.py +296 -0
  80. hindsight_api/worker/poller.py +486 -0
  81. {hindsight_api-0.2.1.dist-info → hindsight_api-0.4.0.dist-info}/METADATA +16 -6
  82. hindsight_api-0.4.0.dist-info/RECORD +112 -0
  83. {hindsight_api-0.2.1.dist-info → hindsight_api-0.4.0.dist-info}/entry_points.txt +2 -0
  84. hindsight_api/engine/retain/observation_regeneration.py +0 -254
  85. hindsight_api/engine/search/observation_utils.py +0 -125
  86. hindsight_api/engine/search/scoring.py +0 -159
  87. hindsight_api-0.2.1.dist-info/RECORD +0 -75
  88. {hindsight_api-0.2.1.dist-info → hindsight_api-0.4.0.dist-info}/WHEEL +0 -0
@@ -209,7 +209,7 @@ class EntityResolver:
209
209
  # This handles duplicates via ON CONFLICT and returns all IDs
210
210
  if entities_to_create:
211
211
  # Group entities by canonical name (lowercase) to handle duplicates within batch
212
- # For duplicates, we only insert once and reuse the ID
212
+ # For duplicates, we only insert once and reuse the ID, but track the count
213
213
  unique_entities = {} # lowercase_name -> (entity_data, event_date, [indices])
214
214
  for idx, entity_data, event_date in entities_to_create:
215
215
  name_lower = entity_data["text"].lower()
@@ -223,29 +223,32 @@ class EntityResolver:
223
223
  # Use a single query with unnest for speed
224
224
  entity_names = []
225
225
  entity_dates = []
226
+ entity_counts = [] # Track how many times each entity appears in this batch
226
227
  indices_map = [] # Maps result index -> list of original indices
227
228
 
228
229
  for name_lower, (entity_data, event_date, indices) in unique_entities.items():
229
230
  entity_names.append(entity_data["text"])
230
231
  entity_dates.append(event_date)
232
+ entity_counts.append(len(indices)) # Count of occurrences in this batch
231
233
  indices_map.append(indices)
232
234
 
233
235
  # Batch INSERT ... ON CONFLICT with RETURNING
234
- # This is much faster than individual inserts
236
+ # Uses the batch count for mention_count instead of always 1
235
237
  rows = await conn.fetch(
236
238
  f"""
237
239
  INSERT INTO {fq_table("entities")} (bank_id, canonical_name, first_seen, last_seen, mention_count)
238
- SELECT $1, name, event_date, event_date, 1
239
- FROM unnest($2::text[], $3::timestamptz[]) AS t(name, event_date)
240
+ SELECT $1, name, event_date, event_date, cnt
241
+ FROM unnest($2::text[], $3::timestamptz[], $4::int[]) AS t(name, event_date, cnt)
240
242
  ON CONFLICT (bank_id, LOWER(canonical_name))
241
243
  DO UPDATE SET
242
- mention_count = {fq_table("entities")}.mention_count + 1,
244
+ mention_count = {fq_table("entities")}.mention_count + EXCLUDED.mention_count,
243
245
  last_seen = EXCLUDED.last_seen
244
246
  RETURNING id
245
247
  """,
246
248
  bank_id,
247
249
  entity_names,
248
250
  entity_dates,
251
+ entity_counts,
249
252
  )
250
253
 
251
254
  # Map returned IDs back to original indices
@@ -160,14 +160,14 @@ class MemoryEngineInterface(ABC):
160
160
  request_context: "RequestContext",
161
161
  ) -> dict[str, Any]:
162
162
  """
163
- Get bank profile including disposition and background.
163
+ Get bank profile including disposition and mission.
164
164
 
165
165
  Args:
166
166
  bank_id: The memory bank ID.
167
167
  request_context: Request context for authentication.
168
168
 
169
169
  Returns:
170
- Bank profile dict.
170
+ Bank profile dict with bank_id, name, disposition, and mission.
171
171
  """
172
172
  ...
173
173
 
@@ -190,25 +190,44 @@ class MemoryEngineInterface(ABC):
190
190
  ...
191
191
 
192
192
  @abstractmethod
193
- async def merge_bank_background(
193
+ async def merge_bank_mission(
194
194
  self,
195
195
  bank_id: str,
196
196
  new_info: str,
197
197
  *,
198
- update_disposition: bool = True,
199
198
  request_context: "RequestContext",
200
199
  ) -> dict[str, Any]:
201
200
  """
202
- Merge new background information into bank profile.
201
+ Merge new mission information into bank profile.
203
202
 
204
203
  Args:
205
204
  bank_id: The memory bank ID.
206
- new_info: New background information to merge.
207
- update_disposition: Whether to infer disposition from background.
205
+ new_info: New mission information to merge.
208
206
  request_context: Request context for authentication.
209
207
 
210
208
  Returns:
211
- Updated background info.
209
+ Updated mission info.
210
+ """
211
+ ...
212
+
213
+ @abstractmethod
214
+ async def set_bank_mission(
215
+ self,
216
+ bank_id: str,
217
+ mission: str,
218
+ *,
219
+ request_context: "RequestContext",
220
+ ) -> dict[str, Any]:
221
+ """
222
+ Set the bank's mission (replaces existing).
223
+
224
+ Args:
225
+ bank_id: The memory bank ID.
226
+ mission: The mission text.
227
+ request_context: Request context for authentication.
228
+
229
+ Returns:
230
+ Dict with bank_id and mission.
212
231
  """
213
232
  ...
214
233
 
@@ -289,6 +308,7 @@ class MemoryEngineInterface(ABC):
289
308
  bank_id: str,
290
309
  *,
291
310
  fact_type: str | None = None,
311
+ limit: int = 1000,
292
312
  request_context: "RequestContext",
293
313
  ) -> dict[str, Any]:
294
314
  """
@@ -297,10 +317,11 @@ class MemoryEngineInterface(ABC):
297
317
  Args:
298
318
  bank_id: The memory bank ID.
299
319
  fact_type: Filter by fact type.
320
+ limit: Maximum number of items to return (default: 1000).
300
321
  request_context: Request context for authentication.
301
322
 
302
323
  Returns:
303
- Dict with nodes, edges, table_rows, total_units.
324
+ Dict with nodes, edges, table_rows, total_units, limit.
304
325
  """
305
326
  ...
306
327
 
@@ -404,18 +425,20 @@ class MemoryEngineInterface(ABC):
404
425
  bank_id: str,
405
426
  *,
406
427
  limit: int = 100,
428
+ offset: int = 0,
407
429
  request_context: "RequestContext",
408
- ) -> list[dict[str, Any]]:
430
+ ) -> dict[str, Any]:
409
431
  """
410
- List entities for a bank.
432
+ List entities for a bank with pagination.
411
433
 
412
434
  Args:
413
435
  bank_id: The memory bank ID.
414
436
  limit: Maximum results.
437
+ offset: Offset for pagination.
415
438
  request_context: Request context for authentication.
416
439
 
417
440
  Returns:
418
- List of entity dicts.
441
+ Dict with items, total, limit, offset.
419
442
  """
420
443
  ...
421
444
 
@@ -514,7 +537,7 @@ class MemoryEngineInterface(ABC):
514
537
  bank_id: str,
515
538
  *,
516
539
  request_context: "RequestContext",
517
- ) -> list[dict[str, Any]]:
540
+ ) -> dict[str, Any]:
518
541
  """
519
542
  List async operations for a bank.
520
543
 
@@ -523,7 +546,7 @@ class MemoryEngineInterface(ABC):
523
546
  request_context: Request context for authentication.
524
547
 
525
548
  Returns:
526
- List of operation dicts with id, task_type, status, etc.
549
+ Dict with 'total' (int) and 'operations' (list of operation dicts).
527
550
  """
528
551
  ...
529
552
 
@@ -557,16 +580,16 @@ class MemoryEngineInterface(ABC):
557
580
  bank_id: str,
558
581
  *,
559
582
  name: str | None = None,
560
- background: str | None = None,
583
+ mission: str | None = None,
561
584
  request_context: "RequestContext",
562
585
  ) -> dict[str, Any]:
563
586
  """
564
- Update bank name and/or background.
587
+ Update bank name and/or mission.
565
588
 
566
589
  Args:
567
590
  bank_id: The memory bank ID.
568
591
  name: New bank name (optional).
569
- background: New background text (optional, replaces existing).
592
+ mission: New mission text (optional, replaces existing).
570
593
  request_context: Request context for authentication.
571
594
 
572
595
  Returns: