adaptive-memory-multi-model-router 1.2.2 → 1.3.1
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.
- package/LICENSE +21 -0
- package/README.md +146 -66
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/airtable.js +20 -0
- package/dist/integrations/discord.js +18 -0
- package/dist/integrations/github.js +23 -0
- package/dist/integrations/gmail.js +19 -0
- package/dist/integrations/google-calendar.js +18 -0
- package/dist/integrations/index.js +61 -0
- package/dist/integrations/jira.js +21 -0
- package/dist/integrations/linear.js +19 -0
- package/dist/integrations/notion.js +19 -0
- package/dist/integrations/slack.js +18 -0
- package/dist/integrations/telegram.js +19 -0
- package/dist/providers/registry.js +7 -3
- package/docs/ARCHITECTURAL-IMPROVEMENTS-2025.md +1391 -0
- package/docs/ARCHITECTURAL-IMPROVEMENTS-REVISED-2025.md +1051 -0
- package/docs/CONFIGURATION.md +476 -0
- package/docs/COUNCIL_DECISION.json +308 -0
- package/docs/COUNCIL_SUMMARY.md +265 -0
- package/docs/COUNCIL_V2.2_DECISION.md +416 -0
- package/docs/IMPROVEMENT_ROADMAP.md +515 -0
- package/docs/LLM_COUNCIL_DECISION.md +508 -0
- package/docs/QUICK_START_VISIBILITY.md +782 -0
- package/docs/REDDIT_GAP_ANALYSIS.md +299 -0
- package/docs/RESEARCH_BACKED_IMPROVEMENTS.md +1180 -0
- package/docs/TMLPD_QNA.md +751 -0
- package/docs/TMLPD_V2.1_COMPLETE.md +763 -0
- package/docs/TMLPD_V2.2_RESEARCH_ROADMAP.md +754 -0
- package/docs/V2.2_IMPLEMENTATION_COMPLETE.md +446 -0
- package/docs/V2_IMPLEMENTATION_GUIDE.md +388 -0
- package/docs/VISIBILITY_ADOPTION_PLAN.md +1005 -0
- package/docs/launch-content/LAUNCH_EXECUTION_CHECKLIST.md +421 -0
- package/docs/launch-content/README.md +457 -0
- package/docs/launch-content/assets/cost_comparison_100_tasks.png +0 -0
- package/docs/launch-content/assets/cumulative_savings.png +0 -0
- package/docs/launch-content/assets/parallel_speedup.png +0 -0
- package/docs/launch-content/assets/provider_pricing_comparison.png +0 -0
- package/docs/launch-content/assets/task_breakdown_comparison.png +0 -0
- package/docs/launch-content/generate_charts.py +313 -0
- package/docs/launch-content/hn_show_post.md +139 -0
- package/docs/launch-content/partner_outreach_templates.md +745 -0
- package/docs/launch-content/reddit_posts.md +467 -0
- package/docs/launch-content/twitter_thread.txt +460 -0
- package/examples/QUICKSTART.md +1 -1
- package/openclaw-alexa-bridge/ALL_REMAINING_FIXES_PLAN.md +313 -0
- package/openclaw-alexa-bridge/REMAINING_FIXES_SUMMARY.md +277 -0
- package/openclaw-alexa-bridge/src/alexa_handler_no_tmlpd.js +1234 -0
- package/openclaw-alexa-bridge/test_fixes.js +77 -0
- package/package.json +120 -29
- package/package.json.tmp +0 -0
- package/qna/TMLPD_QNA.md +3 -3
- package/skill/SKILL.md +2 -2
- package/src/__tests__/integration/tmpld_integration.test.py +540 -0
- package/src/agents/skill_enhanced_agent.py +318 -0
- package/src/memory/__init__.py +15 -0
- package/src/memory/agentic_memory.py +353 -0
- package/src/memory/semantic_memory.py +444 -0
- package/src/memory/simple_memory.py +466 -0
- package/src/memory/working_memory.py +447 -0
- package/src/orchestration/__init__.py +52 -0
- package/src/orchestration/execution_engine.py +353 -0
- package/src/orchestration/halo_orchestrator.py +367 -0
- package/src/orchestration/mcts_workflow.py +498 -0
- package/src/orchestration/role_assigner.py +473 -0
- package/src/orchestration/task_planner.py +522 -0
- package/src/providers/__init__.py +67 -0
- package/src/providers/anthropic.py +304 -0
- package/src/providers/base.py +241 -0
- package/src/providers/cerebras.py +373 -0
- package/src/providers/registry.py +476 -0
- package/src/routing/__init__.py +30 -0
- package/src/routing/universal_router.py +621 -0
- package/src/skills/TMLPD-QUICKREF.md +210 -0
- package/src/skills/TMLPD-SETUP-SUMMARY.md +157 -0
- package/src/skills/TMLPD.md +540 -0
- package/src/skills/__tests__/skill_manager.test.ts +328 -0
- package/src/skills/skill_manager.py +385 -0
- package/src/skills/test-tmlpd.sh +108 -0
- package/src/skills/tmlpd-category.yaml +67 -0
- package/src/skills/tmlpd-monitoring.yaml +188 -0
- package/src/skills/tmlpd-phase.yaml +132 -0
- package/src/state/__init__.py +17 -0
- package/src/state/simple_checkpoint.py +508 -0
- package/src/tmlpd_agent.py +464 -0
- package/src/tmpld_v2.py +427 -0
- package/src/workflows/__init__.py +18 -0
- package/src/workflows/advanced_difficulty_classifier.py +377 -0
- package/src/workflows/chaining_executor.py +417 -0
- package/src/workflows/difficulty_integration.py +209 -0
- package/src/workflows/orchestrator.py +469 -0
- package/src/workflows/orchestrator_executor.py +456 -0
- package/src/workflows/parallelization_executor.py +382 -0
- package/src/workflows/router.py +311 -0
- package/test_integration_simple.py +86 -0
- package/test_mcts_workflow.py +150 -0
- package/test_templd_integration.py +262 -0
- package/test_universal_router.py +275 -0
- package/tmlpd-pi-extension/README.md +36 -0
- package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts +114 -0
- package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/cache/prefixCache.js +285 -0
- package/tmlpd-pi-extension/dist/cache/prefixCache.js.map +1 -0
- package/tmlpd-pi-extension/dist/cache/responseCache.d.ts +58 -0
- package/tmlpd-pi-extension/dist/cache/responseCache.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/cache/responseCache.js +153 -0
- package/tmlpd-pi-extension/dist/cache/responseCache.js.map +1 -0
- package/tmlpd-pi-extension/dist/cli.js +59 -0
- package/tmlpd-pi-extension/dist/cost/costTracker.d.ts +95 -0
- package/tmlpd-pi-extension/dist/cost/costTracker.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/cost/costTracker.js +240 -0
- package/tmlpd-pi-extension/dist/cost/costTracker.js.map +1 -0
- package/tmlpd-pi-extension/dist/index.d.ts +723 -0
- package/tmlpd-pi-extension/dist/index.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/index.js +239 -0
- package/tmlpd-pi-extension/dist/index.js.map +1 -0
- package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts +82 -0
- package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/memory/episodicMemory.js +145 -0
- package/tmlpd-pi-extension/dist/memory/episodicMemory.js.map +1 -0
- package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts +102 -0
- package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js +207 -0
- package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js.map +1 -0
- package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts +85 -0
- package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js +210 -0
- package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js.map +1 -0
- package/tmlpd-pi-extension/dist/providers/localProvider.d.ts +102 -0
- package/tmlpd-pi-extension/dist/providers/localProvider.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/providers/localProvider.js +338 -0
- package/tmlpd-pi-extension/dist/providers/localProvider.js.map +1 -0
- package/tmlpd-pi-extension/dist/providers/registry.d.ts +55 -0
- package/tmlpd-pi-extension/dist/providers/registry.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/providers/registry.js +138 -0
- package/tmlpd-pi-extension/dist/providers/registry.js.map +1 -0
- package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts +68 -0
- package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/routing/advancedRouter.js +332 -0
- package/tmlpd-pi-extension/dist/routing/advancedRouter.js.map +1 -0
- package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts +101 -0
- package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/tools/tmlpdTools.js +368 -0
- package/tmlpd-pi-extension/dist/tools/tmlpdTools.js.map +1 -0
- package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts +96 -0
- package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/utils/batchProcessor.js +170 -0
- package/tmlpd-pi-extension/dist/utils/batchProcessor.js.map +1 -0
- package/tmlpd-pi-extension/dist/utils/compression.d.ts +61 -0
- package/tmlpd-pi-extension/dist/utils/compression.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/utils/compression.js +281 -0
- package/tmlpd-pi-extension/dist/utils/compression.js.map +1 -0
- package/tmlpd-pi-extension/dist/utils/reliability.d.ts +74 -0
- package/tmlpd-pi-extension/dist/utils/reliability.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/utils/reliability.js +177 -0
- package/tmlpd-pi-extension/dist/utils/reliability.js.map +1 -0
- package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts +117 -0
- package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js +246 -0
- package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js.map +1 -0
- package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts +50 -0
- package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts.map +1 -0
- package/tmlpd-pi-extension/dist/utils/tokenUtils.js +124 -0
- package/tmlpd-pi-extension/dist/utils/tokenUtils.js.map +1 -0
- package/tmlpd-pi-extension/examples/QUICKSTART.md +183 -0
- package/tmlpd-pi-extension/package-lock.json +75 -0
- package/tmlpd-pi-extension/package.json +172 -0
- package/tmlpd-pi-extension/python/examples.py +53 -0
- package/tmlpd-pi-extension/python/integrations.py +330 -0
- package/tmlpd-pi-extension/python/setup.py +28 -0
- package/tmlpd-pi-extension/python/tmlpd.py +369 -0
- package/tmlpd-pi-extension/qna/REDDIT_GAP_ANALYSIS.md +299 -0
- package/tmlpd-pi-extension/qna/TMLPD_QNA.md +751 -0
- package/tmlpd-pi-extension/skill/SKILL.md +238 -0
- package/{src → tmlpd-pi-extension/src}/index.ts +1 -1
- package/tmlpd-pi-extension/tsconfig.json +18 -0
- package/demo/research-demo.js +0 -266
- package/notebooks/quickstart.ipynb +0 -157
- package/rust/tmlpd.h +0 -268
- package/src/cache/prefixCache.ts +0 -365
- package/src/routing/advancedRouter.ts +0 -406
- package/src/utils/speculativeDecoding.ts +0 -344
- /package/{src → tmlpd-pi-extension/src}/cache/responseCache.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/cost/costTracker.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/memory/episodicMemory.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/orchestration/haloOrchestrator.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/orchestration/mctsWorkflow.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/providers/localProvider.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/providers/registry.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/tools/tmlpdTools.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/utils/batchProcessor.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/utils/compression.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/utils/reliability.ts +0 -0
- /package/{src → tmlpd-pi-extension/src}/utils/tokenUtils.ts +0 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Phase 3c: Working Memory Cache
|
|
3
|
+
|
|
4
|
+
In-memory cache for active session context and frequently accessed data.
|
|
5
|
+
Based on Memoria framework (arXiv:2512.12686) working memory component.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import time
|
|
9
|
+
from typing import Dict, List, Any, Optional
|
|
10
|
+
from datetime import datetime, timedelta
|
|
11
|
+
from collections import OrderedDict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WorkingMemoryCache:
|
|
15
|
+
"""
|
|
16
|
+
Working memory: Fast in-memory cache for active session context.
|
|
17
|
+
|
|
18
|
+
Based on Memoria framework (arXiv:2512.12686)
|
|
19
|
+
|
|
20
|
+
Features:
|
|
21
|
+
- LRU (Least Recently Used) eviction policy
|
|
22
|
+
- TTL (Time To Live) for automatic expiration
|
|
23
|
+
- Session-based context tracking
|
|
24
|
+
- Fast lookups (< 1ms)
|
|
25
|
+
- Persistent across operations in a session
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
max_size: int = 1000,
|
|
31
|
+
default_ttl_seconds: int = 3600
|
|
32
|
+
):
|
|
33
|
+
"""
|
|
34
|
+
Initialize working memory cache.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
max_size: Maximum number of items to store
|
|
38
|
+
default_ttl_seconds: Default time-to-live for cache entries
|
|
39
|
+
"""
|
|
40
|
+
self.max_size = max_size
|
|
41
|
+
self.default_ttl = default_ttl_seconds
|
|
42
|
+
|
|
43
|
+
# Main cache (OrderedDict for LRU)
|
|
44
|
+
self.cache: OrderedDict[str, Dict[str, Any]] = OrderedDict()
|
|
45
|
+
|
|
46
|
+
# Session context
|
|
47
|
+
self.session_context: Dict[str, Any] = {
|
|
48
|
+
"session_start": datetime.now().isoformat(),
|
|
49
|
+
"operations_count": 0,
|
|
50
|
+
"cache_hits": 0,
|
|
51
|
+
"cache_misses": 0
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Indexes for faster queries
|
|
55
|
+
self.tag_index: Dict[str, set] = {} # tag -> set of keys
|
|
56
|
+
self.category_index: Dict[str, set] = {} # category -> set of keys
|
|
57
|
+
|
|
58
|
+
def set(
|
|
59
|
+
self,
|
|
60
|
+
key: str,
|
|
61
|
+
value: Any,
|
|
62
|
+
ttl: Optional[int] = None,
|
|
63
|
+
tags: Optional[List[str]] = None,
|
|
64
|
+
category: Optional[str] = None,
|
|
65
|
+
metadata: Optional[Dict] = None
|
|
66
|
+
):
|
|
67
|
+
"""
|
|
68
|
+
Store value in cache.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
key: Cache key
|
|
72
|
+
value: Value to store (must be JSON-serializable)
|
|
73
|
+
ttl: Time-to-live in seconds (uses default if not specified)
|
|
74
|
+
tags: Optional tags for categorization
|
|
75
|
+
category: Optional category
|
|
76
|
+
metadata: Optional metadata
|
|
77
|
+
"""
|
|
78
|
+
# Check if we need to evict
|
|
79
|
+
if len(self.cache) >= self.max_size and key not in self.cache:
|
|
80
|
+
self._evict_lru()
|
|
81
|
+
|
|
82
|
+
# Calculate expiration
|
|
83
|
+
ttl = ttl if ttl is not None else self.default_ttl
|
|
84
|
+
expires_at = datetime.now() + timedelta(seconds=ttl)
|
|
85
|
+
|
|
86
|
+
# Create cache entry
|
|
87
|
+
entry = {
|
|
88
|
+
"value": value,
|
|
89
|
+
"created_at": datetime.now().isoformat(),
|
|
90
|
+
"expires_at": expires_at.isoformat(),
|
|
91
|
+
"accessed_at": datetime.now().isoformat(),
|
|
92
|
+
"access_count": 0,
|
|
93
|
+
"tags": tags or [],
|
|
94
|
+
"category": category,
|
|
95
|
+
"metadata": metadata or {},
|
|
96
|
+
"size_bytes": len(str(value)) # Approximate size
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Remove from indexes if updating existing key
|
|
100
|
+
if key in self.cache:
|
|
101
|
+
self._remove_from_indexes(key)
|
|
102
|
+
|
|
103
|
+
# Add to cache
|
|
104
|
+
self.cache[key] = entry
|
|
105
|
+
|
|
106
|
+
# Move to end (most recently used)
|
|
107
|
+
self.cache.move_to_end(key)
|
|
108
|
+
|
|
109
|
+
# Update indexes
|
|
110
|
+
self._add_to_indexes(key, entry)
|
|
111
|
+
|
|
112
|
+
def get(self, key: str) -> Optional[Any]:
|
|
113
|
+
"""
|
|
114
|
+
Get value from cache.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
key: Cache key
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Cached value or None if not found/expired
|
|
121
|
+
"""
|
|
122
|
+
# Check if key exists
|
|
123
|
+
if key not in self.cache:
|
|
124
|
+
self.session_context["cache_misses"] += 1
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
entry = self.cache[key]
|
|
128
|
+
|
|
129
|
+
# Check if expired
|
|
130
|
+
if self._is_expired(entry):
|
|
131
|
+
# Remove expired entry
|
|
132
|
+
del self.cache[key]
|
|
133
|
+
self._remove_from_indexes(key)
|
|
134
|
+
self.session_context["cache_misses"] += 1
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
# Update access statistics
|
|
138
|
+
entry["accessed_at"] = datetime.now().isoformat()
|
|
139
|
+
entry["access_count"] += 1
|
|
140
|
+
|
|
141
|
+
# Move to end (most recently used)
|
|
142
|
+
self.cache.move_to_end(key)
|
|
143
|
+
|
|
144
|
+
self.session_context["cache_hits"] += 1
|
|
145
|
+
|
|
146
|
+
return entry["value"]
|
|
147
|
+
|
|
148
|
+
def get_many(self, keys: List[str]) -> Dict[str, Any]:
|
|
149
|
+
"""
|
|
150
|
+
Get multiple values from cache.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
keys: List of cache keys
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Dict of key -> value (only for found keys)
|
|
157
|
+
"""
|
|
158
|
+
result = {}
|
|
159
|
+
|
|
160
|
+
for key in keys:
|
|
161
|
+
value = self.get(key)
|
|
162
|
+
if value is not None:
|
|
163
|
+
result[key] = value
|
|
164
|
+
|
|
165
|
+
return result
|
|
166
|
+
|
|
167
|
+
def set_many(self, items: Dict[str, Any], **kwargs):
|
|
168
|
+
"""
|
|
169
|
+
Store multiple values in cache.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
items: Dict of key -> value
|
|
173
|
+
**kwargs: Additional arguments passed to set()
|
|
174
|
+
"""
|
|
175
|
+
for key, value in items.items():
|
|
176
|
+
self.set(key, value, **kwargs)
|
|
177
|
+
|
|
178
|
+
def delete(self, key: str) -> bool:
|
|
179
|
+
"""
|
|
180
|
+
Delete entry from cache.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
key: Cache key
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
True if deleted, False if not found
|
|
187
|
+
"""
|
|
188
|
+
if key in self.cache:
|
|
189
|
+
del self.cache[key]
|
|
190
|
+
self._remove_from_indexes(key)
|
|
191
|
+
return True
|
|
192
|
+
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
def clear(self):
|
|
196
|
+
"""Clear all cache entries"""
|
|
197
|
+
self.cache.clear()
|
|
198
|
+
self.tag_index.clear()
|
|
199
|
+
self.category_index.clear()
|
|
200
|
+
|
|
201
|
+
def get_by_tag(self, tag: str) -> List[Any]:
|
|
202
|
+
"""
|
|
203
|
+
Get all entries with a specific tag.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
tag: Tag to search for
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
List of values with that tag
|
|
210
|
+
"""
|
|
211
|
+
if tag not in self.tag_index:
|
|
212
|
+
return []
|
|
213
|
+
|
|
214
|
+
values = []
|
|
215
|
+
keys_to_remove = []
|
|
216
|
+
|
|
217
|
+
for key in self.tag_index[tag]:
|
|
218
|
+
value = self.get(key)
|
|
219
|
+
if value is not None:
|
|
220
|
+
values.append(value)
|
|
221
|
+
else:
|
|
222
|
+
keys_to_remove.append(key)
|
|
223
|
+
|
|
224
|
+
# Clean up expired keys from index
|
|
225
|
+
for key in keys_to_remove:
|
|
226
|
+
self.tag_index[tag].discard(key)
|
|
227
|
+
|
|
228
|
+
return values
|
|
229
|
+
|
|
230
|
+
def get_by_category(self, category: str) -> List[Any]:
|
|
231
|
+
"""
|
|
232
|
+
Get all entries in a specific category.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
category: Category to search for
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
List of values in that category
|
|
239
|
+
"""
|
|
240
|
+
if category not in self.category_index:
|
|
241
|
+
return []
|
|
242
|
+
|
|
243
|
+
values = []
|
|
244
|
+
keys_to_remove = []
|
|
245
|
+
|
|
246
|
+
for key in self.category_index[category]:
|
|
247
|
+
value = self.get(key)
|
|
248
|
+
if value is not None:
|
|
249
|
+
values.append(value)
|
|
250
|
+
else:
|
|
251
|
+
keys_to_remove.append(key)
|
|
252
|
+
|
|
253
|
+
# Clean up expired keys from index
|
|
254
|
+
for key in keys_to_remove:
|
|
255
|
+
self.category_index[category].discard(key)
|
|
256
|
+
|
|
257
|
+
return values
|
|
258
|
+
|
|
259
|
+
def search(
|
|
260
|
+
self,
|
|
261
|
+
query: str,
|
|
262
|
+
search_values: bool = True,
|
|
263
|
+
search_keys: bool = False,
|
|
264
|
+
search_metadata: bool = False
|
|
265
|
+
) -> List[Dict[str, Any]]:
|
|
266
|
+
"""
|
|
267
|
+
Search cache for entries matching query.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
query: Search query (simple string matching)
|
|
271
|
+
search_values: Search in values
|
|
272
|
+
search_keys: Search in keys
|
|
273
|
+
search_metadata: Search in metadata
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
List of matching entries with keys
|
|
277
|
+
"""
|
|
278
|
+
results = []
|
|
279
|
+
query_lower = query.lower()
|
|
280
|
+
|
|
281
|
+
for key, entry in self.cache.items():
|
|
282
|
+
# Skip expired
|
|
283
|
+
if self._is_expired(entry):
|
|
284
|
+
continue
|
|
285
|
+
|
|
286
|
+
# Search key
|
|
287
|
+
if search_keys and query_lower in key.lower():
|
|
288
|
+
results.append({"key": key, "value": entry["value"]})
|
|
289
|
+
continue
|
|
290
|
+
|
|
291
|
+
# Search value
|
|
292
|
+
if search_values and query_lower in str(entry["value"]).lower():
|
|
293
|
+
results.append({"key": key, "value": entry["value"]})
|
|
294
|
+
continue
|
|
295
|
+
|
|
296
|
+
# Search metadata
|
|
297
|
+
if search_metadata:
|
|
298
|
+
metadata_str = str(entry["metadata"])
|
|
299
|
+
if query_lower in metadata_str.lower():
|
|
300
|
+
results.append({"key": key, "value": entry["value"]})
|
|
301
|
+
continue
|
|
302
|
+
|
|
303
|
+
return results
|
|
304
|
+
|
|
305
|
+
def cleanup_expired(self):
|
|
306
|
+
"""Remove all expired entries"""
|
|
307
|
+
keys_to_remove = []
|
|
308
|
+
|
|
309
|
+
for key, entry in self.cache.items():
|
|
310
|
+
if self._is_expired(entry):
|
|
311
|
+
keys_to_remove.append(key)
|
|
312
|
+
|
|
313
|
+
for key in keys_to_remove:
|
|
314
|
+
del self.cache[key]
|
|
315
|
+
self._remove_from_indexes(key)
|
|
316
|
+
|
|
317
|
+
return len(keys_to_remove)
|
|
318
|
+
|
|
319
|
+
def _evict_lru(self):
|
|
320
|
+
"""Evict least recently used entry"""
|
|
321
|
+
if self.cache:
|
|
322
|
+
# First item is least recently used
|
|
323
|
+
lru_key = next(iter(self.cache))
|
|
324
|
+
del self.cache[lru_key]
|
|
325
|
+
self._remove_from_indexes(lru_key)
|
|
326
|
+
|
|
327
|
+
def _is_expired(self, entry: Dict[str, Any]) -> bool:
|
|
328
|
+
"""Check if entry is expired"""
|
|
329
|
+
expires_at = datetime.fromisoformat(entry["expires_at"])
|
|
330
|
+
return datetime.now() > expires_at
|
|
331
|
+
|
|
332
|
+
def _add_to_indexes(self, key: str, entry: Dict[str, Any]):
|
|
333
|
+
"""Add entry to tag and category indexes"""
|
|
334
|
+
# Tag index
|
|
335
|
+
for tag in entry.get("tags", []):
|
|
336
|
+
if tag not in self.tag_index:
|
|
337
|
+
self.tag_index[tag] = set()
|
|
338
|
+
self.tag_index[tag].add(key)
|
|
339
|
+
|
|
340
|
+
# Category index
|
|
341
|
+
category = entry.get("category")
|
|
342
|
+
if category:
|
|
343
|
+
if category not in self.category_index:
|
|
344
|
+
self.category_index[category] = set()
|
|
345
|
+
self.category_index[category].add(key)
|
|
346
|
+
|
|
347
|
+
def _remove_from_indexes(self, key: str):
|
|
348
|
+
"""Remove entry from tag and category indexes"""
|
|
349
|
+
# Tag index
|
|
350
|
+
for tag_set in self.tag_index.values():
|
|
351
|
+
tag_set.discard(key)
|
|
352
|
+
|
|
353
|
+
# Category index
|
|
354
|
+
for category_set in self.category_index.values():
|
|
355
|
+
category_set.discard(key)
|
|
356
|
+
|
|
357
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
358
|
+
"""Get cache statistics"""
|
|
359
|
+
# Calculate total size
|
|
360
|
+
total_size_bytes = sum(
|
|
361
|
+
entry["size_bytes"] for entry in self.cache.values()
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
# Calculate hit rate
|
|
365
|
+
total_requests = (
|
|
366
|
+
self.session_context["cache_hits"] +
|
|
367
|
+
self.session_context["cache_misses"]
|
|
368
|
+
)
|
|
369
|
+
hit_rate = (
|
|
370
|
+
self.session_context["cache_hits"] / total_requests
|
|
371
|
+
if total_requests > 0 else 0
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
# Calculate avg access count
|
|
375
|
+
if self.cache:
|
|
376
|
+
avg_access_count = sum(
|
|
377
|
+
entry["access_count"] for entry in self.cache.values()
|
|
378
|
+
) / len(self.cache)
|
|
379
|
+
else:
|
|
380
|
+
avg_access_count = 0
|
|
381
|
+
|
|
382
|
+
# Session duration
|
|
383
|
+
session_start = datetime.fromisoformat(self.session_context["session_start"])
|
|
384
|
+
session_duration = (datetime.now() - session_start).total_seconds()
|
|
385
|
+
|
|
386
|
+
return {
|
|
387
|
+
"cache_size": len(self.cache),
|
|
388
|
+
"max_size": self.max_size,
|
|
389
|
+
"total_size_bytes": total_size_bytes,
|
|
390
|
+
"total_size_mb": total_size_bytes / (1024 * 1024),
|
|
391
|
+
"hit_rate": hit_rate,
|
|
392
|
+
"cache_hits": self.session_context["cache_hits"],
|
|
393
|
+
"cache_misses": self.session_context["cache_misses"],
|
|
394
|
+
"avg_access_count": avg_access_count,
|
|
395
|
+
"tags_count": len(self.tag_index),
|
|
396
|
+
"categories_count": len(self.category_index),
|
|
397
|
+
"session_duration_seconds": session_duration,
|
|
398
|
+
"operations_count": self.session_context["operations_count"]
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
def export_cache(self, include_expired: bool = False) -> List[Dict[str, Any]]:
|
|
402
|
+
"""
|
|
403
|
+
Export cache entries as list.
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
include_expired: Whether to include expired entries
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
List of cache entries
|
|
410
|
+
"""
|
|
411
|
+
entries = []
|
|
412
|
+
|
|
413
|
+
for key, entry in self.cache.items():
|
|
414
|
+
# Skip expired if requested
|
|
415
|
+
if not include_expired and self._is_expired(entry):
|
|
416
|
+
continue
|
|
417
|
+
|
|
418
|
+
entry_copy = entry.copy()
|
|
419
|
+
entry_copy["key"] = key
|
|
420
|
+
entries.append(entry_copy)
|
|
421
|
+
|
|
422
|
+
return entries
|
|
423
|
+
|
|
424
|
+
def import_cache(self, entries: List[Dict[str, Any]]):
|
|
425
|
+
"""
|
|
426
|
+
Import cache entries from list.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
entries: List of cache entries (from export_cache)
|
|
430
|
+
"""
|
|
431
|
+
for entry in entries:
|
|
432
|
+
key = entry.pop("key")
|
|
433
|
+
value = entry.pop("value")
|
|
434
|
+
|
|
435
|
+
self.set(key, value, **entry)
|
|
436
|
+
|
|
437
|
+
def __len__(self):
|
|
438
|
+
"""Get cache size"""
|
|
439
|
+
return len(self.cache)
|
|
440
|
+
|
|
441
|
+
def __contains__(self, key: str):
|
|
442
|
+
"""Check if key exists in cache"""
|
|
443
|
+
return key in self.cache and not self._is_expired(self.cache[key])
|
|
444
|
+
|
|
445
|
+
def __repr__(self):
|
|
446
|
+
"""String representation"""
|
|
447
|
+
return f"WorkingMemoryCache(size={len(self.cache)}, max_size={self.max_size})"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HALO Orchestration Module
|
|
3
|
+
|
|
4
|
+
Hierarchical Autonomous Logic-Oriented Orchestration for TMLPD v2.2
|
|
5
|
+
|
|
6
|
+
Based on:
|
|
7
|
+
- arXiv:2505.13516 (HALO - 3-tier hierarchical planning)
|
|
8
|
+
- arXiv:2506.12508v3 (AgentOrchestra)
|
|
9
|
+
|
|
10
|
+
Components:
|
|
11
|
+
- TaskPlanner: High-level task decomposition
|
|
12
|
+
- RoleAssigner: Specialized agent assignment
|
|
13
|
+
- ExecutionEngine: Parallel execution with verification
|
|
14
|
+
- HALOOrchestrator: Main coordinator (3-tier system)
|
|
15
|
+
- MCTSWorkflowSearch: MCTS-based workflow optimization
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from .task_planner import TaskPlanner, TaskDecomposition, SubTask, TaskType
|
|
19
|
+
from .role_assigner import RoleAssigner, AgentAssignment, AgentConfig, AgentRole
|
|
20
|
+
from .execution_engine import ExecutionEngine, ExecutionResult, ExecutionSummary
|
|
21
|
+
from .halo_orchestrator import HALOOrchestrator, HALOOrchestrationResult
|
|
22
|
+
from .mcts_workflow import MCTSWorkflowSearch, WorkflowNode, WorkflowStrategy
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
# Task Planning
|
|
26
|
+
"TaskPlanner",
|
|
27
|
+
"TaskDecomposition",
|
|
28
|
+
"SubTask",
|
|
29
|
+
"TaskType",
|
|
30
|
+
|
|
31
|
+
# Role Assignment
|
|
32
|
+
"RoleAssigner",
|
|
33
|
+
"AgentAssignment",
|
|
34
|
+
"AgentConfig",
|
|
35
|
+
"AgentRole",
|
|
36
|
+
|
|
37
|
+
# Execution
|
|
38
|
+
"ExecutionEngine",
|
|
39
|
+
"ExecutionResult",
|
|
40
|
+
"ExecutionSummary",
|
|
41
|
+
|
|
42
|
+
# Main Orchestrator
|
|
43
|
+
"HALOOrchestrator",
|
|
44
|
+
"HALOOrchestrationResult",
|
|
45
|
+
|
|
46
|
+
# Workflow Optimization
|
|
47
|
+
"MCTSWorkflowSearch",
|
|
48
|
+
"WorkflowNode",
|
|
49
|
+
"WorkflowStrategy"
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
__version__ = "2.2.0-alpha"
|