alma-memory 0.4.0__py3-none-any.whl → 0.5.1__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 (94) hide show
  1. alma/__init__.py +121 -45
  2. alma/confidence/__init__.py +1 -1
  3. alma/confidence/engine.py +92 -58
  4. alma/confidence/types.py +34 -14
  5. alma/config/loader.py +3 -2
  6. alma/consolidation/__init__.py +23 -0
  7. alma/consolidation/engine.py +678 -0
  8. alma/consolidation/prompts.py +84 -0
  9. alma/core.py +136 -28
  10. alma/domains/__init__.py +6 -6
  11. alma/domains/factory.py +12 -9
  12. alma/domains/schemas.py +17 -3
  13. alma/domains/types.py +8 -4
  14. alma/events/__init__.py +75 -0
  15. alma/events/emitter.py +284 -0
  16. alma/events/storage_mixin.py +246 -0
  17. alma/events/types.py +126 -0
  18. alma/events/webhook.py +425 -0
  19. alma/exceptions.py +49 -0
  20. alma/extraction/__init__.py +31 -0
  21. alma/extraction/auto_learner.py +265 -0
  22. alma/extraction/extractor.py +420 -0
  23. alma/graph/__init__.py +106 -0
  24. alma/graph/backends/__init__.py +32 -0
  25. alma/graph/backends/kuzu.py +624 -0
  26. alma/graph/backends/memgraph.py +432 -0
  27. alma/graph/backends/memory.py +236 -0
  28. alma/graph/backends/neo4j.py +417 -0
  29. alma/graph/base.py +159 -0
  30. alma/graph/extraction.py +198 -0
  31. alma/graph/store.py +860 -0
  32. alma/harness/__init__.py +4 -4
  33. alma/harness/base.py +18 -9
  34. alma/harness/domains.py +27 -11
  35. alma/initializer/__init__.py +1 -1
  36. alma/initializer/initializer.py +51 -43
  37. alma/initializer/types.py +25 -17
  38. alma/integration/__init__.py +9 -9
  39. alma/integration/claude_agents.py +32 -20
  40. alma/integration/helena.py +32 -22
  41. alma/integration/victor.py +57 -33
  42. alma/learning/__init__.py +27 -27
  43. alma/learning/forgetting.py +198 -148
  44. alma/learning/heuristic_extractor.py +40 -24
  45. alma/learning/protocols.py +65 -17
  46. alma/learning/validation.py +7 -2
  47. alma/mcp/__init__.py +4 -4
  48. alma/mcp/__main__.py +2 -1
  49. alma/mcp/resources.py +17 -16
  50. alma/mcp/server.py +102 -44
  51. alma/mcp/tools.py +180 -45
  52. alma/observability/__init__.py +84 -0
  53. alma/observability/config.py +302 -0
  54. alma/observability/logging.py +424 -0
  55. alma/observability/metrics.py +583 -0
  56. alma/observability/tracing.py +440 -0
  57. alma/progress/__init__.py +3 -3
  58. alma/progress/tracker.py +26 -20
  59. alma/progress/types.py +8 -12
  60. alma/py.typed +0 -0
  61. alma/retrieval/__init__.py +11 -11
  62. alma/retrieval/cache.py +20 -21
  63. alma/retrieval/embeddings.py +4 -4
  64. alma/retrieval/engine.py +179 -39
  65. alma/retrieval/scoring.py +73 -63
  66. alma/session/__init__.py +2 -2
  67. alma/session/manager.py +5 -5
  68. alma/session/types.py +5 -4
  69. alma/storage/__init__.py +70 -0
  70. alma/storage/azure_cosmos.py +414 -133
  71. alma/storage/base.py +215 -4
  72. alma/storage/chroma.py +1443 -0
  73. alma/storage/constants.py +103 -0
  74. alma/storage/file_based.py +59 -28
  75. alma/storage/migrations/__init__.py +21 -0
  76. alma/storage/migrations/base.py +321 -0
  77. alma/storage/migrations/runner.py +323 -0
  78. alma/storage/migrations/version_stores.py +337 -0
  79. alma/storage/migrations/versions/__init__.py +11 -0
  80. alma/storage/migrations/versions/v1_0_0.py +373 -0
  81. alma/storage/pinecone.py +1080 -0
  82. alma/storage/postgresql.py +1559 -0
  83. alma/storage/qdrant.py +1306 -0
  84. alma/storage/sqlite_local.py +504 -60
  85. alma/testing/__init__.py +46 -0
  86. alma/testing/factories.py +301 -0
  87. alma/testing/mocks.py +389 -0
  88. alma/types.py +62 -14
  89. alma_memory-0.5.1.dist-info/METADATA +939 -0
  90. alma_memory-0.5.1.dist-info/RECORD +93 -0
  91. {alma_memory-0.4.0.dist-info → alma_memory-0.5.1.dist-info}/WHEEL +1 -1
  92. alma_memory-0.4.0.dist-info/METADATA +0 -488
  93. alma_memory-0.4.0.dist-info/RECORD +0 -52
  94. {alma_memory-0.4.0.dist-info → alma_memory-0.5.1.dist-info}/top_level.txt +0 -0
alma/storage/base.py CHANGED
@@ -5,16 +5,15 @@ Abstract base class that all storage backends must implement.
5
5
  """
6
6
 
7
7
  from abc import ABC, abstractmethod
8
- from typing import Optional, List, Dict, Any
9
8
  from datetime import datetime
9
+ from typing import Any, Dict, List, Optional
10
10
 
11
11
  from alma.types import (
12
+ AntiPattern,
13
+ DomainKnowledge,
12
14
  Heuristic,
13
15
  Outcome,
14
16
  UserPreference,
15
- DomainKnowledge,
16
- AntiPattern,
17
- MemoryType,
18
17
  )
19
18
 
20
19
 
@@ -55,6 +54,22 @@ class StorageBackend(ABC):
55
54
  """Save an anti-pattern, return its ID."""
56
55
  pass
57
56
 
57
+ # ==================== BATCH WRITE OPERATIONS ====================
58
+
59
+ def save_heuristics(self, heuristics: List[Heuristic]) -> List[str]:
60
+ """Save multiple heuristics in a batch. Default implementation calls save_heuristic in a loop."""
61
+ return [self.save_heuristic(h) for h in heuristics]
62
+
63
+ def save_outcomes(self, outcomes: List[Outcome]) -> List[str]:
64
+ """Save multiple outcomes in a batch. Default implementation calls save_outcome in a loop."""
65
+ return [self.save_outcome(o) for o in outcomes]
66
+
67
+ def save_domain_knowledge_batch(
68
+ self, knowledge_items: List[DomainKnowledge]
69
+ ) -> List[str]:
70
+ """Save multiple domain knowledge items in a batch. Default implementation calls save_domain_knowledge in a loop."""
71
+ return [self.save_domain_knowledge(k) for k in knowledge_items]
72
+
58
73
  # ==================== READ OPERATIONS ====================
59
74
 
60
75
  @abstractmethod
@@ -339,6 +354,144 @@ class StorageBackend(ABC):
339
354
  """
340
355
  pass
341
356
 
357
+ # ==================== MULTI-AGENT MEMORY SHARING ====================
358
+
359
+ def get_heuristics_for_agents(
360
+ self,
361
+ project_id: str,
362
+ agents: List[str],
363
+ embedding: Optional[List[float]] = None,
364
+ top_k: int = 5,
365
+ min_confidence: float = 0.0,
366
+ ) -> List[Heuristic]:
367
+ """
368
+ Get heuristics from multiple agents in one call.
369
+
370
+ This enables multi-agent memory sharing where an agent can
371
+ read memories from agents it inherits from.
372
+
373
+ Args:
374
+ project_id: Project to query
375
+ agents: List of agent names to query
376
+ embedding: Query embedding for semantic search
377
+ top_k: Max results to return per agent
378
+ min_confidence: Minimum confidence threshold
379
+
380
+ Returns:
381
+ List of matching heuristics from all specified agents
382
+ """
383
+ # Default implementation: query each agent individually
384
+ results = []
385
+ for agent in agents:
386
+ agent_heuristics = self.get_heuristics(
387
+ project_id=project_id,
388
+ agent=agent,
389
+ embedding=embedding,
390
+ top_k=top_k,
391
+ min_confidence=min_confidence,
392
+ )
393
+ results.extend(agent_heuristics)
394
+ return results
395
+
396
+ def get_outcomes_for_agents(
397
+ self,
398
+ project_id: str,
399
+ agents: List[str],
400
+ task_type: Optional[str] = None,
401
+ embedding: Optional[List[float]] = None,
402
+ top_k: int = 5,
403
+ success_only: bool = False,
404
+ ) -> List[Outcome]:
405
+ """
406
+ Get outcomes from multiple agents in one call.
407
+
408
+ Args:
409
+ project_id: Project to query
410
+ agents: List of agent names to query
411
+ task_type: Filter by task type
412
+ embedding: Query embedding for semantic search
413
+ top_k: Max results to return per agent
414
+ success_only: Only return successful outcomes
415
+
416
+ Returns:
417
+ List of matching outcomes from all specified agents
418
+ """
419
+ results = []
420
+ for agent in agents:
421
+ agent_outcomes = self.get_outcomes(
422
+ project_id=project_id,
423
+ agent=agent,
424
+ task_type=task_type,
425
+ embedding=embedding,
426
+ top_k=top_k,
427
+ success_only=success_only,
428
+ )
429
+ results.extend(agent_outcomes)
430
+ return results
431
+
432
+ def get_domain_knowledge_for_agents(
433
+ self,
434
+ project_id: str,
435
+ agents: List[str],
436
+ domain: Optional[str] = None,
437
+ embedding: Optional[List[float]] = None,
438
+ top_k: int = 5,
439
+ ) -> List[DomainKnowledge]:
440
+ """
441
+ Get domain knowledge from multiple agents in one call.
442
+
443
+ Args:
444
+ project_id: Project to query
445
+ agents: List of agent names to query
446
+ domain: Filter by domain
447
+ embedding: Query embedding for semantic search
448
+ top_k: Max results to return per agent
449
+
450
+ Returns:
451
+ List of matching domain knowledge from all specified agents
452
+ """
453
+ results = []
454
+ for agent in agents:
455
+ agent_knowledge = self.get_domain_knowledge(
456
+ project_id=project_id,
457
+ agent=agent,
458
+ domain=domain,
459
+ embedding=embedding,
460
+ top_k=top_k,
461
+ )
462
+ results.extend(agent_knowledge)
463
+ return results
464
+
465
+ def get_anti_patterns_for_agents(
466
+ self,
467
+ project_id: str,
468
+ agents: List[str],
469
+ embedding: Optional[List[float]] = None,
470
+ top_k: int = 5,
471
+ ) -> List[AntiPattern]:
472
+ """
473
+ Get anti-patterns from multiple agents in one call.
474
+
475
+ Args:
476
+ project_id: Project to query
477
+ agents: List of agent names to query
478
+ embedding: Query embedding for semantic search
479
+ top_k: Max results to return per agent
480
+
481
+ Returns:
482
+ List of matching anti-patterns from all specified agents
483
+ """
484
+ results = []
485
+ for agent in agents:
486
+ agent_patterns = self.get_anti_patterns(
487
+ project_id=project_id,
488
+ agent=agent,
489
+ embedding=embedding,
490
+ top_k=top_k,
491
+ )
492
+ results.extend(agent_patterns)
493
+ return results
494
+
342
495
  # ==================== STATS ====================
343
496
 
344
497
  @abstractmethod
@@ -355,6 +508,64 @@ class StorageBackend(ABC):
355
508
  """
356
509
  pass
357
510
 
511
+ # ==================== MIGRATION SUPPORT ====================
512
+
513
+ def get_schema_version(self) -> Optional[str]:
514
+ """
515
+ Get the current schema version.
516
+
517
+ Returns:
518
+ Current schema version string, or None if not tracked
519
+ """
520
+ # Default implementation returns None (no version tracking)
521
+ return None
522
+
523
+ def get_migration_status(self) -> Dict[str, Any]:
524
+ """
525
+ Get migration status information.
526
+
527
+ Returns:
528
+ Dict with current version, pending migrations, etc.
529
+ """
530
+ return {
531
+ "current_version": self.get_schema_version(),
532
+ "target_version": None,
533
+ "pending_count": 0,
534
+ "pending_versions": [],
535
+ "needs_migration": False,
536
+ "migration_supported": False,
537
+ }
538
+
539
+ def migrate(
540
+ self, target_version: Optional[str] = None, dry_run: bool = False
541
+ ) -> List[str]:
542
+ """
543
+ Apply pending schema migrations.
544
+
545
+ Args:
546
+ target_version: Optional target version (applies all if not specified)
547
+ dry_run: If True, show what would be done without making changes
548
+
549
+ Returns:
550
+ List of applied migration versions
551
+ """
552
+ # Default implementation does nothing
553
+ return []
554
+
555
+ def rollback(self, target_version: str, dry_run: bool = False) -> List[str]:
556
+ """
557
+ Roll back schema to a previous version.
558
+
559
+ Args:
560
+ target_version: Version to roll back to
561
+ dry_run: If True, show what would be done without making changes
562
+
563
+ Returns:
564
+ List of rolled back migration versions
565
+ """
566
+ # Default implementation does nothing
567
+ return []
568
+
358
569
  # ==================== UTILITY ====================
359
570
 
360
571
  @classmethod