smartmemory-core 0.5.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 (405) hide show
  1. scripts/add_license_headers.py +122 -0
  2. smartmemory/__init__.py +29 -0
  3. smartmemory/__version__.py +50 -0
  4. smartmemory/background/__init__.py +0 -0
  5. smartmemory/background/extraction_worker.py +186 -0
  6. smartmemory/background/id_resolver.py +72 -0
  7. smartmemory/clear_all.py +130 -0
  8. smartmemory/cli.py +164 -0
  9. smartmemory/clustering/__init__.py +37 -0
  10. smartmemory/clustering/deduplicator.py +148 -0
  11. smartmemory/clustering/embedding.py +148 -0
  12. smartmemory/clustering/global_cluster.py +305 -0
  13. smartmemory/clustering/graph_aggregator.py +186 -0
  14. smartmemory/clustering/llm.py +265 -0
  15. smartmemory/code/__init__.py +16 -0
  16. smartmemory/code/indexer.py +482 -0
  17. smartmemory/code/models.py +126 -0
  18. smartmemory/code/parser.py +404 -0
  19. smartmemory/code/search.py +145 -0
  20. smartmemory/code/ts_parser.py +708 -0
  21. smartmemory/configuration/__init__.py +288 -0
  22. smartmemory/configuration/environment.py +99 -0
  23. smartmemory/configuration/loader.py +135 -0
  24. smartmemory/configuration/manager.py +239 -0
  25. smartmemory/configuration/models.py +154 -0
  26. smartmemory/configuration/validator.py +383 -0
  27. smartmemory/conversation/__init__.py +8 -0
  28. smartmemory/conversation/context.py +81 -0
  29. smartmemory/conversation/manager.py +98 -0
  30. smartmemory/conversation/session.py +37 -0
  31. smartmemory/decisions/__init__.py +6 -0
  32. smartmemory/decisions/manager.py +337 -0
  33. smartmemory/decisions/queries.py +255 -0
  34. smartmemory/drift_detector.py +135 -0
  35. smartmemory/evolution/__init__.py +49 -0
  36. smartmemory/evolution/cycle.py +35 -0
  37. smartmemory/evolution/diff_engine.py +212 -0
  38. smartmemory/evolution/flow.py +75 -0
  39. smartmemory/evolution/models.py +244 -0
  40. smartmemory/evolution/registry.py +198 -0
  41. smartmemory/evolution/store.py +323 -0
  42. smartmemory/evolution/tracker.py +353 -0
  43. smartmemory/evolution/utilities.py +315 -0
  44. smartmemory/extraction/__init__.py +0 -0
  45. smartmemory/extraction/extractor.py +499 -0
  46. smartmemory/extraction/models.py +87 -0
  47. smartmemory/feedback/__init__.py +1 -0
  48. smartmemory/feedback/agentic_improvement.py +79 -0
  49. smartmemory/feedback/agentic_routines.py +204 -0
  50. smartmemory/feedback/cli.py +7 -0
  51. smartmemory/feedback/manager.py +27 -0
  52. smartmemory/feedback/slack.py +65 -0
  53. smartmemory/graph/__init__.py +0 -0
  54. smartmemory/graph/analytics/__init__.py +0 -0
  55. smartmemory/graph/analytics/edge.py +17 -0
  56. smartmemory/graph/analytics/episodes.py +28 -0
  57. smartmemory/graph/analytics/export.py +28 -0
  58. smartmemory/graph/analytics/prune.py +52 -0
  59. smartmemory/graph/analytics/temporal.py +30 -0
  60. smartmemory/graph/backends/__init__.py +11 -0
  61. smartmemory/graph/backends/async_backend.py +102 -0
  62. smartmemory/graph/backends/async_falkordb.py +619 -0
  63. smartmemory/graph/backends/backend.py +96 -0
  64. smartmemory/graph/backends/falkordb.py +1173 -0
  65. smartmemory/graph/backends/queries.py +149 -0
  66. smartmemory/graph/backends/sqlite.py +464 -0
  67. smartmemory/graph/base.py +138 -0
  68. smartmemory/graph/core/__init__.py +0 -0
  69. smartmemory/graph/core/edges.py +252 -0
  70. smartmemory/graph/core/memory_path.py +274 -0
  71. smartmemory/graph/core/nodes.py +374 -0
  72. smartmemory/graph/core/search.py +399 -0
  73. smartmemory/graph/indexes.py +26 -0
  74. smartmemory/graph/models/__init__.py +0 -0
  75. smartmemory/graph/models/canonical_types.py +213 -0
  76. smartmemory/graph/models/node_types.py +305 -0
  77. smartmemory/graph/models/schema_validator.py +828 -0
  78. smartmemory/graph/ontology_graph.py +477 -0
  79. smartmemory/graph/smartgraph.py +565 -0
  80. smartmemory/graph/types/__init__.py +0 -0
  81. smartmemory/graph/types/episodic.py +345 -0
  82. smartmemory/graph/types/interfaces.py +165 -0
  83. smartmemory/graph/types/procedural.py +224 -0
  84. smartmemory/graph/types/semantic.py +342 -0
  85. smartmemory/graph/types/zettel.py +187 -0
  86. smartmemory/grounding/__init__.py +15 -0
  87. smartmemory/grounding/executors.py +40 -0
  88. smartmemory/grounding/registry.py +24 -0
  89. smartmemory/grounding/schemas.py +41 -0
  90. smartmemory/inference/__init__.py +6 -0
  91. smartmemory/inference/engine.py +131 -0
  92. smartmemory/inference/rules.py +82 -0
  93. smartmemory/integration/__init__.py +0 -0
  94. smartmemory/integration/archive/archive_provider.py +59 -0
  95. smartmemory/integration/chat/__init__.py +0 -0
  96. smartmemory/integration/chat/hitl.py +507 -0
  97. smartmemory/integration/chat/integration.py +274 -0
  98. smartmemory/integration/llm/__init__.py +0 -0
  99. smartmemory/integration/llm/llm_client.py +461 -0
  100. smartmemory/integration/llm/prompts/__init__.py +0 -0
  101. smartmemory/integration/llm/prompts/prompt_manager.py +275 -0
  102. smartmemory/integration/llm/prompts/prompt_provider.py +184 -0
  103. smartmemory/integration/llm/prompts/prompts.json +43 -0
  104. smartmemory/integration/llm/prompts/prompts_loader.py +204 -0
  105. smartmemory/integration/llm/providers.py +373 -0
  106. smartmemory/integration/llm/response_parser.py +258 -0
  107. smartmemory/integration/wikipedia_client.py +139 -0
  108. smartmemory/interfaces.py +43 -0
  109. smartmemory/managers/__init__.py +13 -0
  110. smartmemory/managers/debug.py +169 -0
  111. smartmemory/managers/enrichment.py +38 -0
  112. smartmemory/managers/evolution.py +30 -0
  113. smartmemory/managers/monitoring.py +40 -0
  114. smartmemory/memory/__init__.py +0 -0
  115. smartmemory/memory/base.py +302 -0
  116. smartmemory/memory/canonical_store.py +67 -0
  117. smartmemory/memory/context_types.py +14 -0
  118. smartmemory/memory/ingestion/__init__.py +0 -0
  119. smartmemory/memory/ingestion/enrichment.py +122 -0
  120. smartmemory/memory/ingestion/extraction.py +268 -0
  121. smartmemory/memory/ingestion/flow.py +486 -0
  122. smartmemory/memory/ingestion/grounding.py +30 -0
  123. smartmemory/memory/ingestion/observer.py +260 -0
  124. smartmemory/memory/ingestion/registry.py +250 -0
  125. smartmemory/memory/ingestion/storage.py +234 -0
  126. smartmemory/memory/ingestion/utils.py +231 -0
  127. smartmemory/memory/memory_factory.py +228 -0
  128. smartmemory/memory/migrate.py +127 -0
  129. smartmemory/memory/mixins.py +335 -0
  130. smartmemory/memory/models/__init__.py +0 -0
  131. smartmemory/memory/models/memory_item.py +64 -0
  132. smartmemory/memory/pipeline/__init__.py +0 -0
  133. smartmemory/memory/pipeline/classification.py +176 -0
  134. smartmemory/memory/pipeline/components.py +534 -0
  135. smartmemory/memory/pipeline/config.py +249 -0
  136. smartmemory/memory/pipeline/enrichment.py +295 -0
  137. smartmemory/memory/pipeline/extractor.py +511 -0
  138. smartmemory/memory/pipeline/grounding.py +194 -0
  139. smartmemory/memory/pipeline/input_adapter.py +166 -0
  140. smartmemory/memory/pipeline/linking.py +394 -0
  141. smartmemory/memory/pipeline/plugin_base.py +70 -0
  142. smartmemory/memory/pipeline/stages/__init__.py +7 -0
  143. smartmemory/memory/pipeline/stages/analytics.py +641 -0
  144. smartmemory/memory/pipeline/stages/clustering.py +139 -0
  145. smartmemory/memory/pipeline/stages/coreference.py +303 -0
  146. smartmemory/memory/pipeline/stages/crud.py +372 -0
  147. smartmemory/memory/pipeline/stages/enrichment.py +130 -0
  148. smartmemory/memory/pipeline/stages/evolution.py +272 -0
  149. smartmemory/memory/pipeline/stages/graph_operations.py +97 -0
  150. smartmemory/memory/pipeline/stages/grounding.py +95 -0
  151. smartmemory/memory/pipeline/stages/linking.py +69 -0
  152. smartmemory/memory/pipeline/stages/monitoring.py +118 -0
  153. smartmemory/memory/pipeline/stages/personalization.py +29 -0
  154. smartmemory/memory/pipeline/stages/search.py +208 -0
  155. smartmemory/memory/pipeline/stages/validation.py +204 -0
  156. smartmemory/memory/pipeline/state.py +147 -0
  157. smartmemory/memory/pipeline/storage.py +372 -0
  158. smartmemory/memory/pipeline/transactions/__init__.py +0 -0
  159. smartmemory/memory/pipeline/transactions/change_set.py +70 -0
  160. smartmemory/memory/pipeline/transactions/ops.py +324 -0
  161. smartmemory/memory/pipeline/transactions/transaction.py +87 -0
  162. smartmemory/memory/types/__init__.py +0 -0
  163. smartmemory/memory/types/episodic_memory.py +197 -0
  164. smartmemory/memory/types/factory_memory_creator.py +268 -0
  165. smartmemory/memory/types/procedural_memory.py +192 -0
  166. smartmemory/memory/types/semantic_memory.py +156 -0
  167. smartmemory/memory/types/wikilink_parser.py +352 -0
  168. smartmemory/memory/types/working_memory.py +179 -0
  169. smartmemory/memory/types/zettel_extensions.py +873 -0
  170. smartmemory/memory/types/zettel_memory.py +460 -0
  171. smartmemory/memory/utils.py +16 -0
  172. smartmemory/metrics/__init__.py +5 -0
  173. smartmemory/metrics/graph_health.py +134 -0
  174. smartmemory/models/__init__.py +51 -0
  175. smartmemory/models/base.py +81 -0
  176. smartmemory/models/compat/__init__.py +0 -0
  177. smartmemory/models/compat/boundary_converter.py +172 -0
  178. smartmemory/models/compat/dataclass_model.py +300 -0
  179. smartmemory/models/compat/simple_boundary.py +62 -0
  180. smartmemory/models/concept.py +39 -0
  181. smartmemory/models/conditional_step.py +31 -0
  182. smartmemory/models/corpus.py +9 -0
  183. smartmemory/models/decision.py +277 -0
  184. smartmemory/models/drift_event.py +111 -0
  185. smartmemory/models/entity.py +37 -0
  186. smartmemory/models/entity_types.py +70 -0
  187. smartmemory/models/library.py +41 -0
  188. smartmemory/models/link_types.py +15 -0
  189. smartmemory/models/memory_item.py +365 -0
  190. smartmemory/models/note.py +31 -0
  191. smartmemory/models/ontology.py +456 -0
  192. smartmemory/models/opinion.py +228 -0
  193. smartmemory/models/procedure.py +34 -0
  194. smartmemory/models/reasoning.py +222 -0
  195. smartmemory/models/schema_snapshot.py +97 -0
  196. smartmemory/models/status.py +46 -0
  197. smartmemory/models/step.py +33 -0
  198. smartmemory/models/tag.py +36 -0
  199. smartmemory/models/user_model.py +74 -0
  200. smartmemory/observability/__init__.py +10 -0
  201. smartmemory/observability/events.py +587 -0
  202. smartmemory/observability/instrumentation.py +446 -0
  203. smartmemory/observability/json_formatter.py +38 -0
  204. smartmemory/observability/logging_filter.py +117 -0
  205. smartmemory/observability/retrieval_tracking.py +210 -0
  206. smartmemory/observability/tracing.py +263 -0
  207. smartmemory/ontology/__init__.py +0 -0
  208. smartmemory/ontology/entity_pair_cache.py +94 -0
  209. smartmemory/ontology/governance.py +499 -0
  210. smartmemory/ontology/governance_manager.py +125 -0
  211. smartmemory/ontology/hitl/__init__.py +0 -0
  212. smartmemory/ontology/hitl/hitl_interface.py +453 -0
  213. smartmemory/ontology/inference/__init__.py +0 -0
  214. smartmemory/ontology/inference/inference.py +486 -0
  215. smartmemory/ontology/inference/ontogpt.py +509 -0
  216. smartmemory/ontology/ir_models.py +277 -0
  217. smartmemory/ontology/layered.py +210 -0
  218. smartmemory/ontology/llm_manager.py +515 -0
  219. smartmemory/ontology/manager.py +197 -0
  220. smartmemory/ontology/models.py +354 -0
  221. smartmemory/ontology/pattern_manager.py +170 -0
  222. smartmemory/ontology/promotion.py +324 -0
  223. smartmemory/ontology/reasoning_validator.py +182 -0
  224. smartmemory/ontology/registry.py +528 -0
  225. smartmemory/ontology/template_service.py +239 -0
  226. smartmemory/ontology/templates/_manifest.json +29 -0
  227. smartmemory/ontology/templates/business.json +312 -0
  228. smartmemory/ontology/templates/general.json +275 -0
  229. smartmemory/ontology/templates/software.json +337 -0
  230. smartmemory/pipeline/__init__.py +24 -0
  231. smartmemory/pipeline/config.py +355 -0
  232. smartmemory/pipeline/metrics_consumer.py +369 -0
  233. smartmemory/pipeline/protocol.py +38 -0
  234. smartmemory/pipeline/runner.py +259 -0
  235. smartmemory/pipeline/stages/__init__.py +31 -0
  236. smartmemory/pipeline/stages/classify.py +75 -0
  237. smartmemory/pipeline/stages/coreference.py +61 -0
  238. smartmemory/pipeline/stages/enrich.py +93 -0
  239. smartmemory/pipeline/stages/entity_ruler.py +178 -0
  240. smartmemory/pipeline/stages/evolve.py +53 -0
  241. smartmemory/pipeline/stages/ground.py +119 -0
  242. smartmemory/pipeline/stages/link.py +54 -0
  243. smartmemory/pipeline/stages/llm_extract.py +162 -0
  244. smartmemory/pipeline/stages/ontology_constrain.py +392 -0
  245. smartmemory/pipeline/stages/reasoning_detect.py +63 -0
  246. smartmemory/pipeline/stages/simplify.py +149 -0
  247. smartmemory/pipeline/stages/store.py +212 -0
  248. smartmemory/pipeline/state.py +138 -0
  249. smartmemory/pipeline/token_tracker.py +185 -0
  250. smartmemory/pipeline/transport/__init__.py +30 -0
  251. smartmemory/pipeline/transport/event_bus.py +364 -0
  252. smartmemory/plugins/__init__.py +51 -0
  253. smartmemory/plugins/base.py +445 -0
  254. smartmemory/plugins/embedding.py +232 -0
  255. smartmemory/plugins/enrichers/__init__.py +16 -0
  256. smartmemory/plugins/enrichers/basic.py +76 -0
  257. smartmemory/plugins/enrichers/link_expansion.py +540 -0
  258. smartmemory/plugins/enrichers/sentiment.py +157 -0
  259. smartmemory/plugins/enrichers/skills_tools.py +70 -0
  260. smartmemory/plugins/enrichers/temporal.py +97 -0
  261. smartmemory/plugins/enrichers/topic.py +137 -0
  262. smartmemory/plugins/enrichers/usage_tracking.py +122 -0
  263. smartmemory/plugins/evolvers/__init__.py +59 -0
  264. smartmemory/plugins/evolvers/base.py +11 -0
  265. smartmemory/plugins/evolvers/decision_confidence.py +322 -0
  266. smartmemory/plugins/evolvers/enhanced/__init__.py +71 -0
  267. smartmemory/plugins/evolvers/enhanced/exponential_decay.py +129 -0
  268. smartmemory/plugins/evolvers/enhanced/hebbian_co_retrieval.py +128 -0
  269. smartmemory/plugins/evolvers/enhanced/interference_based_consolidation.py +173 -0
  270. smartmemory/plugins/evolvers/enhanced/retrieval_based_strengthening.py +215 -0
  271. smartmemory/plugins/evolvers/enhanced/working_to_episodic.py +193 -0
  272. smartmemory/plugins/evolvers/episodic_decay.py +53 -0
  273. smartmemory/plugins/evolvers/episodic_to_semantic.py +57 -0
  274. smartmemory/plugins/evolvers/episodic_to_zettel.py +54 -0
  275. smartmemory/plugins/evolvers/observation_synthesis.py +333 -0
  276. smartmemory/plugins/evolvers/opinion_reinforcement.py +270 -0
  277. smartmemory/plugins/evolvers/opinion_synthesis.py +282 -0
  278. smartmemory/plugins/evolvers/semantic_decay.py +53 -0
  279. smartmemory/plugins/evolvers/working_to_episodic.py +65 -0
  280. smartmemory/plugins/evolvers/working_to_procedural.py +328 -0
  281. smartmemory/plugins/evolvers/zettel_prune.py +113 -0
  282. smartmemory/plugins/executor.py +150 -0
  283. smartmemory/plugins/extractors/__init__.py +13 -0
  284. smartmemory/plugins/extractors/conversation_aware_llm.py +546 -0
  285. smartmemory/plugins/extractors/decision.py +192 -0
  286. smartmemory/plugins/extractors/llm.py +319 -0
  287. smartmemory/plugins/extractors/llm_single.py +521 -0
  288. smartmemory/plugins/extractors/reasoning.py +440 -0
  289. smartmemory/plugins/extractors/spacy.py +216 -0
  290. smartmemory/plugins/grounders/__init__.py +5 -0
  291. smartmemory/plugins/grounders/wikipedia.py +126 -0
  292. smartmemory/plugins/manager.py +615 -0
  293. smartmemory/plugins/registry.py +499 -0
  294. smartmemory/plugins/resolvers/__init__.py +0 -0
  295. smartmemory/plugins/resolvers/external_resolver.py +57 -0
  296. smartmemory/plugins/security.py +391 -0
  297. smartmemory/procedure_matcher.py +188 -0
  298. smartmemory/procedures/__init__.py +45 -0
  299. smartmemory/procedures/candidate_namer.py +354 -0
  300. smartmemory/procedures/candidate_scorer.py +239 -0
  301. smartmemory/procedures/models.py +104 -0
  302. smartmemory/procedures/pattern_detector.py +273 -0
  303. smartmemory/py.typed +0 -0
  304. smartmemory/reasoning/__init__.py +37 -0
  305. smartmemory/reasoning/challenger.py +421 -0
  306. smartmemory/reasoning/confidence.py +104 -0
  307. smartmemory/reasoning/detection/__init__.py +18 -0
  308. smartmemory/reasoning/detection/base.py +31 -0
  309. smartmemory/reasoning/detection/cascade.py +25 -0
  310. smartmemory/reasoning/detection/embedding.py +71 -0
  311. smartmemory/reasoning/detection/graph.py +86 -0
  312. smartmemory/reasoning/detection/heuristic.py +97 -0
  313. smartmemory/reasoning/detection/llm.py +71 -0
  314. smartmemory/reasoning/fuzzy_confidence.py +119 -0
  315. smartmemory/reasoning/models.py +84 -0
  316. smartmemory/reasoning/proof_tree.py +154 -0
  317. smartmemory/reasoning/query_router.py +138 -0
  318. smartmemory/reasoning/reasoner.py +50 -0
  319. smartmemory/reasoning/residuation.py +147 -0
  320. smartmemory/reasoning/resolution/__init__.py +17 -0
  321. smartmemory/reasoning/resolution/base.py +19 -0
  322. smartmemory/reasoning/resolution/cascade.py +24 -0
  323. smartmemory/reasoning/resolution/grounding.py +51 -0
  324. smartmemory/reasoning/resolution/llm.py +75 -0
  325. smartmemory/reasoning/resolution/recency.py +41 -0
  326. smartmemory/reasoning/resolution/wikipedia.py +101 -0
  327. smartmemory/retrieval/__init__.py +14 -0
  328. smartmemory/retrieval/ssg_traversal.py +595 -0
  329. smartmemory/schema_diff.py +355 -0
  330. smartmemory/schema_providers.py +95 -0
  331. smartmemory/scope_provider.py +70 -0
  332. smartmemory/similarity/__init__.py +0 -0
  333. smartmemory/similarity/enhanced_metrics.py +849 -0
  334. smartmemory/similarity/framework.py +448 -0
  335. smartmemory/smart_memory.py +1539 -0
  336. smartmemory/stores/__init__.py +1 -0
  337. smartmemory/stores/base.py +228 -0
  338. smartmemory/stores/converters/__init__.py +0 -0
  339. smartmemory/stores/converters/episodic_converter.py +350 -0
  340. smartmemory/stores/converters/procedural_converter.py +440 -0
  341. smartmemory/stores/converters/semantic_converter.py +290 -0
  342. smartmemory/stores/converters/zettel_converter.py +341 -0
  343. smartmemory/stores/corpus/__init__.py +0 -0
  344. smartmemory/stores/corpus/store.py +76 -0
  345. smartmemory/stores/example_memory_handler.py +235 -0
  346. smartmemory/stores/external/__init__.py +0 -0
  347. smartmemory/stores/external/file_handler.py +180 -0
  348. smartmemory/stores/external/mcp_handler.py +143 -0
  349. smartmemory/stores/external/s3_handler.py +101 -0
  350. smartmemory/stores/external/web_handler.py +75 -0
  351. smartmemory/stores/factory.py +265 -0
  352. smartmemory/stores/json_store.py +363 -0
  353. smartmemory/stores/mixins.py +354 -0
  354. smartmemory/stores/ontology/__init__.py +94 -0
  355. smartmemory/stores/ontology/falkordb.py +360 -0
  356. smartmemory/stores/ontology/redis_service.py +336 -0
  357. smartmemory/stores/persistence/__init__.py +20 -0
  358. smartmemory/stores/persistence/base.py +56 -0
  359. smartmemory/stores/persistence/entity_handler.py +21 -0
  360. smartmemory/stores/persistence/json.py +125 -0
  361. smartmemory/stores/persistence/model.py +131 -0
  362. smartmemory/stores/persistence/ontology_handlers.py +175 -0
  363. smartmemory/stores/registrations.py +6 -0
  364. smartmemory/stores/registry.py +34 -0
  365. smartmemory/stores/vector/__init__.py +0 -0
  366. smartmemory/stores/vector/backends/__init__.py +7 -0
  367. smartmemory/stores/vector/backends/base.py +72 -0
  368. smartmemory/stores/vector/backends/falkor.py +219 -0
  369. smartmemory/stores/vector/backends/usearch.py +239 -0
  370. smartmemory/stores/vector/vector_store.py +390 -0
  371. smartmemory/streams/__init__.py +1 -0
  372. smartmemory/streams/pipeline_producer.py +110 -0
  373. smartmemory/temporal/__init__.py +41 -0
  374. smartmemory/temporal/context.py +84 -0
  375. smartmemory/temporal/performance.py +429 -0
  376. smartmemory/temporal/queries.py +746 -0
  377. smartmemory/temporal/relationships.py +538 -0
  378. smartmemory/temporal/version_tracker.py +478 -0
  379. smartmemory/tools/__init__.py +1 -0
  380. smartmemory/tools/factory.py +120 -0
  381. smartmemory/tools/markdown_writer.py +44 -0
  382. smartmemory/utils/__init__.py +120 -0
  383. smartmemory/utils/cache.py +286 -0
  384. smartmemory/utils/chunking.py +648 -0
  385. smartmemory/utils/context.py +47 -0
  386. smartmemory/utils/deduplication.py +427 -0
  387. smartmemory/utils/hybrid_retrieval.py +323 -0
  388. smartmemory/utils/llm.py +203 -0
  389. smartmemory/utils/llm_client/dspy.py +283 -0
  390. smartmemory/utils/llm_client/litellm.py +91 -0
  391. smartmemory/utils/llm_client/openai.py +76 -0
  392. smartmemory/utils/pipeline_utils.py +67 -0
  393. smartmemory/utils/serialization.py +188 -0
  394. smartmemory/utils/token_tracking.py +287 -0
  395. smartmemory/validation/__init__.py +6 -0
  396. smartmemory/validation/edge_validator.py +135 -0
  397. smartmemory/validation/memory_validator.py +148 -0
  398. smartmemory_core-0.5.0.dist-info/METADATA +768 -0
  399. smartmemory_core-0.5.0.dist-info/RECORD +405 -0
  400. smartmemory_core-0.5.0.dist-info/WHEEL +5 -0
  401. smartmemory_core-0.5.0.dist-info/entry_points.txt +2 -0
  402. smartmemory_core-0.5.0.dist-info/licenses/LICENSE +31 -0
  403. smartmemory_core-0.5.0.dist-info/licenses/LICENSE.agpl-v3 +661 -0
  404. smartmemory_core-0.5.0.dist-info/licenses/LICENSE.header +18 -0
  405. smartmemory_core-0.5.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to add AGPL v3 license headers with dual licensing notice to all Python files.
4
+ Run this from the project root directory.
5
+ """
6
+
7
+ import os
8
+ from typing import List
9
+
10
+ LICENSE_HEADER = '''# Copyright (C) 2025 SmartMemory
11
+ #
12
+ # This program is free software: you can redistribute it and/or modify
13
+ # it under the terms of the GNU Affero General Public License as published by
14
+ # the Free Software Foundation, either version 3 of the License, or
15
+ # (at your option) any later version.
16
+ #
17
+ # This program is distributed in the hope that it will be useful,
18
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ # GNU Affero General Public License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
24
+ #
25
+ # For commercial licensing options, please contact: help@smartmemory.ai
26
+ # Commercial licenses are available for organizations that wish to use
27
+ # this software in proprietary applications without the AGPL restrictions.
28
+
29
+ '''
30
+
31
+ def find_python_files(directory: str) -> List[str]:
32
+ """Find all Python files in directory and subdirectories."""
33
+ python_files = []
34
+ for root, dirs, files in os.walk(directory):
35
+ # Skip hidden directories and common build/cache directories
36
+ dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ['__pycache__', 'build', 'dist']]
37
+
38
+ for file in files:
39
+ if file.endswith('.py'):
40
+ python_files.append(os.path.join(root, file))
41
+
42
+ return python_files
43
+
44
+ def has_license_header(file_path: str) -> bool:
45
+ """Check if file already has a license header."""
46
+ try:
47
+ with open(file_path, 'r', encoding='utf-8') as f:
48
+ content = f.read(1000) # Check first 1000 characters
49
+ return 'Copyright (C) 2025 SmartMemory' in content or 'GNU Affero General Public License' in content
50
+ except Exception:
51
+ return False
52
+
53
+ def add_license_header(file_path: str) -> bool:
54
+ """Add license header to Python file."""
55
+ try:
56
+ with open(file_path, 'r', encoding='utf-8') as f:
57
+ original_content = f.read()
58
+
59
+ # Handle shebang line
60
+ lines = original_content.split('\n')
61
+ if lines and lines[0].startswith('#!'):
62
+ # Keep shebang, add license after it
63
+ shebang = lines[0] + '\n'
64
+ rest_content = '\n'.join(lines[1:])
65
+ new_content = shebang + LICENSE_HEADER + rest_content
66
+ else:
67
+ # Add license at the beginning
68
+ new_content = LICENSE_HEADER + original_content
69
+
70
+ # Write back the file
71
+ with open(file_path, 'w', encoding='utf-8') as f:
72
+ f.write(new_content)
73
+
74
+ return True
75
+ except Exception as e:
76
+ print(f"Error processing {file_path}: {e}")
77
+ return False
78
+
79
+ def main():
80
+ """Main function to process all Python files."""
81
+ project_root = os.path.dirname(os.path.abspath(__file__))
82
+
83
+ # Find all Python files
84
+ python_files = find_python_files(project_root)
85
+
86
+ # Filter out this script itself and other utility scripts you might not want to modify
87
+ exclude_files = [
88
+ os.path.join(project_root, 'add_license_headers.py'),
89
+ # Add other files to exclude here if needed
90
+ ]
91
+
92
+ python_files = [f for f in python_files if f not in exclude_files]
93
+
94
+ print(f"Found {len(python_files)} Python files")
95
+
96
+ processed = 0
97
+ skipped = 0
98
+ errors = 0
99
+
100
+ for file_path in python_files:
101
+ relative_path = os.path.relpath(file_path, project_root)
102
+
103
+ if has_license_header(file_path):
104
+ print(f"SKIP: {relative_path} (already has license header)")
105
+ skipped += 1
106
+ continue
107
+
108
+ if add_license_header(file_path):
109
+ print(f"ADD: {relative_path}")
110
+ processed += 1
111
+ else:
112
+ print(f"ERR: {relative_path}")
113
+ errors += 1
114
+
115
+ print("\nSummary:")
116
+ print(f" Processed: {processed}")
117
+ print(f" Skipped: {skipped}")
118
+ print(f" Errors: {errors}")
119
+ print(f" Total files: {len(python_files)}")
120
+
121
+ if __name__ == "__main__":
122
+ main()
@@ -0,0 +1,29 @@
1
+ """
2
+ SmartMemory: Multi-layered AI memory system with graph databases, vector stores, and
3
+ intelligent processing pipelines for context-aware AI applications. Provides semantic,
4
+ episodic, procedural, and working memory types with advanced relationship modeling and
5
+ storage and retrieval for AI applications.
6
+ """
7
+
8
+ from smartmemory.__version__ import __version__, __version_info__
9
+
10
+ __author__ = "SmartMemory Team"
11
+
12
+ __all__ = [
13
+ "SmartMemory",
14
+ "MemoryItem",
15
+ "__version__",
16
+ "__version_info__",
17
+ ]
18
+
19
+
20
+ def __getattr__(name: str):
21
+ """Lazy-load heavy top-level exports so submodule imports don't pull the
22
+ full ML stack (torch, numpy, etc.) unless SmartMemory itself is used."""
23
+ if name == "SmartMemory":
24
+ from smartmemory.smart_memory import SmartMemory
25
+ return SmartMemory
26
+ if name == "MemoryItem":
27
+ from smartmemory.models.memory_item import MemoryItem
28
+ return MemoryItem
29
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1,50 @@
1
+ """
2
+ SmartMemory version information.
3
+
4
+ Version is read dynamically from package metadata or VERSION file.
5
+ Single source of truth: VERSION file
6
+ """
7
+
8
+ from pathlib import Path
9
+
10
+ def _get_version() -> str:
11
+ """Get version from VERSION file or package metadata."""
12
+ try:
13
+ # For installed package, read from metadata
14
+ from importlib.metadata import version
15
+ return version("smartmemory-core")
16
+ except Exception:
17
+ # For development, read from VERSION file
18
+ try:
19
+ version_file = Path(__file__).parent.parent / "VERSION"
20
+ with open(version_file, "r", encoding="utf-8") as f:
21
+ return f.read().strip()
22
+ except FileNotFoundError:
23
+ # Fallback if VERSION file not found
24
+ return "unknown"
25
+
26
+ __version__ = _get_version()
27
+
28
+ # Parse version info
29
+ try:
30
+ __version_info__ = tuple(int(x) for x in __version__.split("."))
31
+ except Exception:
32
+ __version_info__ = (0, 1, 6)
33
+
34
+ # Version history:
35
+ # 0.3.0 - Decision Memory: Decision model, DecisionManager, DecisionQueries, DecisionExtractor, edge schemas (PRODUCED, DERIVED_FROM, SUPERSEDES, CONTRADICTS, INFLUENCES)
36
+ # 0.2.6 - SSG integration, user signature support, documentation updates, DRY version management (VERSION file as single source of truth)
37
+ # 0.1.14 - Tenant isolation bug fix
38
+ # 0.1.13 - Tenant isolation bug fix
39
+ # 0.1.12 - Tenant isolation improvements
40
+ # 0.1.11 - Version bump and maintenance
41
+ # 0.1.10 - Minor fix to grounder plugin, publish script improvements
42
+ # 0.1.9 - Add dspy to requirements
43
+ # 0.1.8 - README overhaul: fixed all code snippets to use public API, verified evolvers, added "In Progress" section, removed internal imports
44
+ # 0.1.7 - Updated README, removed ChromaDB references, fixed PyPI deployment
45
+ # 0.1.6 - Production PyPI deployment setup
46
+ # 0.1.5 - Complete bi-temporal implementation: version tracking, temporal search, relationship queries, bi-temporal joins, performance optimizations
47
+ # 0.1.4 - Bi-temporal queries: time-travel, audit trails, version history, rollback
48
+ # 0.1.3 - Zettelkasten system with wikilink support, documentation, examples, CLI
49
+ # 0.1.2 - ChromaDB optional, Python 3.10+ requirement, version externalized
50
+ # 0.1.1 - Plugin system with security
File without changes
@@ -0,0 +1,186 @@
1
+ """Tier 2 async extraction worker — runs LLM extraction on items stored by Tier 1.
2
+
3
+ Tier 1 (sync, ~4ms): spaCy + EntityRuler → stores memory, enqueues item_id.
4
+ Tier 2 (this module, ~740ms): loads item, runs LLMSingleExtractor, diffs against
5
+ ruler entities already stored, writes net-new entities + resolved relations,
6
+ then updates EntityPattern nodes for the self-learning EntityRuler loop.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from typing import Any, Dict, Optional, Set
12
+
13
+ from smartmemory.models.memory_item import MemoryItem
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ # Pre-write quality gates for entity pattern candidates
18
+ _MIN_CONFIDENCE = 0.8
19
+ _MIN_NAME_LENGTH = 3
20
+ _BLOCKLIST: Set[str] = {"it", "this", "that", "the", "a", "an", "he", "she", "they", "we"}
21
+
22
+
23
+ def process_extract_job(
24
+ memory: Any,
25
+ payload: Dict[str, Any],
26
+ redis_client: Optional[Any] = None,
27
+ ) -> Dict[str, Any]:
28
+ """Run Tier 2 LLM extraction on a stored memory item.
29
+
30
+ Args:
31
+ memory: A SmartMemory (or SecureSmartMemory) instance scoped to the workspace.
32
+ payload: Dict from the extract queue: {item_id, workspace_id, entity_ids}.
33
+ entity_ids is {name.lower(): graph_node_id} from Tier 1 StoreStage.
34
+ redis_client: Optional Redis connection for ruler hot-reload pub/sub.
35
+
36
+ Returns:
37
+ {"status": "ok"|"no_text"|"item_not_found"|"llm_failed",
38
+ "new_entities": int, "new_relations": int, "new_patterns": int}
39
+ """
40
+ item_id: Optional[str] = payload.get("item_id")
41
+ workspace_id: str = payload.get("workspace_id", "")
42
+ # ruler_entity_ids: {name.lower(): graph_node_id} populated by Tier 1 StoreStage
43
+ ruler_entity_ids: Dict[str, str] = payload.get("entity_ids") or {}
44
+ # Respect enable_ontology flag set by the enqueuing SmartMemory instance.
45
+ # When False, skip EntityPattern writes and ruler hot-reload entirely.
46
+ enable_ontology: bool = payload.get("enable_ontology", True)
47
+
48
+ # --- 1. Load stored item ---
49
+ item = memory.get(item_id)
50
+ if item is None:
51
+ logger.warning("Extract job: item_id=%s not found", item_id)
52
+ return {"status": "item_not_found", "new_entities": 0, "new_relations": 0, "new_patterns": 0}
53
+
54
+ content: str = ""
55
+ if isinstance(item, MemoryItem):
56
+ content = item.content or ""
57
+ elif isinstance(item, dict):
58
+ content = item.get("content", "") or ""
59
+
60
+ if not content.strip():
61
+ return {"status": "no_text", "new_entities": 0, "new_relations": 0, "new_patterns": 0}
62
+
63
+ # --- 2. Run LLM extraction ---
64
+ try:
65
+ from smartmemory.plugins.extractors.llm_single import LLMSingleExtractor
66
+
67
+ extractor = LLMSingleExtractor()
68
+ extraction = extractor.extract(content)
69
+ except Exception as exc:
70
+ logger.warning("Extract job: LLM extraction failed for item_id=%s: %s", item_id, exc)
71
+ return {"status": "llm_failed", "new_entities": 0, "new_relations": 0, "new_patterns": 0}
72
+
73
+ llm_entities: list[MemoryItem] = extraction.get("entities") or []
74
+ llm_relations: list[dict] = extraction.get("relations") or []
75
+
76
+ # --- 3. Build id remapping and filter valid relations ---
77
+ from smartmemory.background.id_resolver import build_sha256_to_stored, filter_valid_relations
78
+
79
+ sha256_to_stored = build_sha256_to_stored(llm_entities, ruler_entity_ids)
80
+
81
+ # --- 4. Write net-new entities (those NOT already in ruler_entity_ids) ---
82
+ net_new_ids: Set[str] = set()
83
+ new_entity_count = 0
84
+ ruler_names_lower = {n.lower() for n in ruler_entity_ids}
85
+
86
+ for entity in llm_entities:
87
+ name = (entity.metadata.get("name") or "").strip()
88
+ if not name or name.lower() in ruler_names_lower:
89
+ continue
90
+ # Net-new entity — write to graph via simple add()
91
+ try:
92
+ result = memory._crud.add(entity)
93
+ if isinstance(result, dict):
94
+ net_new_node_id = result.get("memory_node_id") or entity.item_id
95
+ else:
96
+ net_new_node_id = result or entity.item_id
97
+ if net_new_node_id:
98
+ net_new_ids.add(net_new_node_id)
99
+ # Update sha256→stored so relations can resolve this entity too
100
+ if entity.item_id:
101
+ sha256_to_stored[entity.item_id] = net_new_node_id
102
+ new_entity_count += 1
103
+ except Exception as exc:
104
+ logger.warning("Extract job: failed to write net-new entity '%s': %s", name, exc)
105
+
106
+ # --- 5. Write resolved relations ---
107
+ resolved_relations = filter_valid_relations(llm_relations, sha256_to_stored, net_new_ids)
108
+ new_relation_count = 0
109
+ for rel in resolved_relations:
110
+ try:
111
+ memory._graph.add_edge(
112
+ rel["source_id"],
113
+ rel["target_id"],
114
+ edge_type=rel["relation_type"],
115
+ properties={},
116
+ )
117
+ new_relation_count += 1
118
+ except Exception as exc:
119
+ logger.warning(
120
+ "Extract job: failed to write relation %s->%s (%s): %s",
121
+ rel["source_id"],
122
+ rel["target_id"],
123
+ rel["relation_type"],
124
+ exc,
125
+ )
126
+
127
+ # --- 6+7. Update EntityPattern nodes + notify ruler hot-reload ---
128
+ # Guarded by enable_ontology: when False (e.g. SmartMemory(enable_ontology=False)),
129
+ # skip all ontology graph writes and Redis pub/sub entirely.
130
+ new_pattern_count = 0
131
+ if enable_ontology:
132
+ try:
133
+ from smartmemory.graph.ontology_graph import OntologyGraph
134
+
135
+ ontology_graph = OntologyGraph(workspace_id=workspace_id)
136
+ for entity in llm_entities:
137
+ name = (entity.metadata.get("name") or "").strip()
138
+ entity_type = entity.metadata.get("entity_type") or entity.memory_type or "concept"
139
+ confidence = float(entity.metadata.get("confidence", 0.0))
140
+
141
+ # Pre-write quality gates (confidence, length, blocklist)
142
+ if not name or len(name) < _MIN_NAME_LENGTH:
143
+ continue
144
+ if name.lower() in _BLOCKLIST:
145
+ continue
146
+ if confidence < _MIN_CONFIDENCE:
147
+ continue
148
+
149
+ added = ontology_graph.add_entity_pattern(
150
+ name=name,
151
+ label=entity_type,
152
+ confidence=confidence,
153
+ workspace_id=workspace_id,
154
+ is_global=False,
155
+ source="llm_discovery",
156
+ )
157
+ if added:
158
+ new_pattern_count += 1
159
+ except Exception as exc:
160
+ logger.warning("Extract job: failed to update entity patterns for item_id=%s: %s", item_id, exc)
161
+
162
+ if new_pattern_count > 0 and redis_client is not None:
163
+ try:
164
+ from smartmemory.ontology.pattern_manager import PatternManager
165
+
166
+ channel = f"{PatternManager.RELOAD_CHANNEL_PREFIX}:{workspace_id}"
167
+ redis_client.publish(channel, "reload")
168
+ logger.debug("Extract job: published ruler reload on %s", channel)
169
+ except Exception as exc:
170
+ logger.warning("Extract job: failed to publish ruler reload: %s", exc)
171
+ else:
172
+ logger.debug("Extract job: ontology disabled; skipping EntityPattern writes for item_id=%s", item_id)
173
+
174
+ logger.info(
175
+ "Extract job ok: item_id=%s new_entities=%d new_relations=%d new_patterns=%d",
176
+ item_id,
177
+ new_entity_count,
178
+ new_relation_count,
179
+ new_pattern_count,
180
+ )
181
+ return {
182
+ "status": "ok",
183
+ "new_entities": new_entity_count,
184
+ "new_relations": new_relation_count,
185
+ "new_patterns": new_pattern_count,
186
+ }
@@ -0,0 +1,72 @@
1
+ """Id resolution between LLMSingleExtractor's SHA-256 id space and FalkorDB stored ids.
2
+
3
+ LLMSingleExtractor._process_entities() assigns SHA-256 item_ids (hashlib.sha256 of
4
+ "name|entity_type", first 16 chars) to MemoryItem objects. StoreStage._map_entity_ids()
5
+ assigns FalkorDB graph node ids, stored in PipelineState.entity_ids as {name -> graph_id}.
6
+
7
+ Relations from the LLM call reference SHA-256 ids which must be remapped to graph ids
8
+ before writing edges. Both id spaces are needed: sha256_to_stored for ruler entities
9
+ present in both spaces, net_new_ids for entities added only in this Tier 2 run.
10
+ """
11
+ from __future__ import annotations
12
+
13
+ from smartmemory.models.memory_item import MemoryItem
14
+
15
+
16
+ def build_sha256_to_stored(
17
+ llm_entities: list[MemoryItem],
18
+ ruler_entity_ids: dict[str, str],
19
+ ) -> dict[str, str]:
20
+ """Map SHA-256 ids (LLM extractor space) to stored FalkorDB ids (Tier 1 space).
21
+
22
+ Args:
23
+ llm_entities: List[MemoryItem] from LLMSingleExtractor.extract()["entities"].
24
+ Accessed via entity.item_id (SHA-256) and entity.metadata["name"].
25
+ ruler_entity_ids: state.entity_ids from the job payload — {name.lower(): graph_node_id}.
26
+ Populated by StoreStage._map_entity_ids() during Tier 1 ingest.
27
+
28
+ Returns:
29
+ {sha256_id: graph_node_id} for entities present in both id spaces.
30
+ """
31
+ remap: dict[str, str] = {}
32
+ for entity in llm_entities:
33
+ name = entity.metadata.get("name", "").lower()
34
+ sha256_id = entity.item_id
35
+ if name and sha256_id and name in ruler_entity_ids:
36
+ stored_id = ruler_entity_ids[name]
37
+ if stored_id:
38
+ remap[sha256_id] = stored_id
39
+ return remap
40
+
41
+
42
+ def filter_valid_relations(
43
+ llm_relations: list[dict],
44
+ sha256_to_stored: dict[str, str],
45
+ net_new_ids: set[str],
46
+ ) -> list[dict]:
47
+ """Return relations where both endpoints resolve to known graph nodes.
48
+
49
+ An endpoint is valid if it appears in sha256_to_stored (ruler entity remapped
50
+ to a stored id) or in net_new_ids (entity written in this Tier 2 run).
51
+
52
+ Args:
53
+ llm_relations: List of relation dicts from LLMSingleExtractor.extract()["relations"].
54
+ Each dict: {source_id: sha256, target_id: sha256, relation_type: str}.
55
+ sha256_to_stored: Output of build_sha256_to_stored().
56
+ net_new_ids: Set of item_ids for net-new entities written in this Tier 2 run.
57
+
58
+ Returns:
59
+ List of relation dicts with source_id/target_id remapped to graph node ids.
60
+ """
61
+ valid_ids = set(sha256_to_stored.values()) | net_new_ids
62
+ resolved = []
63
+ for rel in llm_relations:
64
+ source_id = sha256_to_stored.get(rel["source_id"], rel["source_id"])
65
+ target_id = sha256_to_stored.get(rel["target_id"], rel["target_id"])
66
+ if source_id in valid_ids and target_id in valid_ids:
67
+ resolved.append({
68
+ "source_id": source_id,
69
+ "target_id": target_id,
70
+ "relation_type": rel["relation_type"],
71
+ })
72
+ return resolved
@@ -0,0 +1,130 @@
1
+ """
2
+ Utility to clear SmartMemory state across caches and stores.
3
+
4
+ Actions:
5
+ - Clear SmartGraph (drops all nodes/edges, clears graph caches)
6
+ - Clear VectorStore (if supported by current backend)
7
+ - Clear Redis-backed extraction caches (best effort)
8
+
9
+ Usage:
10
+ python -m smartmemory.maintenance.clear_all --all
11
+ python -m smartmemory.maintenance.clear_all --graph
12
+ python -m smartmemory.maintenance.clear_all --vector
13
+ python -m smartmemory.maintenance.clear_all --cache
14
+
15
+ Notes:
16
+ - This is intended for local/dev use. Use with caution in shared environments.
17
+ - We do not swallow exceptions silently: failures are logged and surfaced.
18
+ """
19
+ from __future__ import annotations
20
+
21
+ import argparse
22
+ import logging
23
+ import os
24
+ from typing import Any
25
+
26
+
27
+ def _setup_logging(verbose: bool):
28
+ level = logging.DEBUG if verbose else logging.INFO
29
+ logging.basicConfig(level=level, format="[%(levelname)s] %(message)s")
30
+
31
+
32
+ def clear_graph() -> bool:
33
+ from smartmemory.graph.smartgraph import SmartGraph
34
+
35
+ logging.info("Clearing SmartGraph (nodes/edges/caches)...")
36
+ try:
37
+ g = SmartGraph()
38
+ ok = g.clear()
39
+ logging.info("SmartGraph cleared: %s", ok)
40
+ return bool(ok)
41
+ except Exception as e:
42
+ logging.error("Failed to clear SmartGraph: %s", e)
43
+ raise
44
+
45
+
46
+ def clear_vector_store() -> bool:
47
+ try:
48
+ from smartmemory.stores.vector.vector_store import VectorStore
49
+ except Exception as e:
50
+ logging.warning("VectorStore not available: %s", e)
51
+ return False
52
+
53
+ logging.info("Clearing VectorStore (if backend supports clear())...")
54
+ try:
55
+ vs = VectorStore()
56
+ ok = vs.clear()
57
+ logging.info("VectorStore cleared via clear(): %s", ok)
58
+ return bool(ok)
59
+ except Exception as e:
60
+ logging.error("Failed to clear VectorStore: %s", e)
61
+ raise
62
+
63
+
64
+ def clear_cache() -> bool:
65
+ try:
66
+ from smartmemory.utils.cache import get_cache
67
+ except Exception as e:
68
+ logging.warning("Cache utils not available: %s", e)
69
+ return False
70
+
71
+ logging.info("Clearing Redis-backed caches (best effort)...")
72
+ try:
73
+ cache = get_cache()
74
+ # Try to get redis client from cache object
75
+ client = getattr(cache, 'redis', None)
76
+ if client and hasattr(client, "flushdb"):
77
+ client.flushdb()
78
+ logging.info("Redis FLUSHDB successful")
79
+ return True
80
+ # Extract connection params if available
81
+ url = os.getenv("REDIS_URL") or os.getenv("REDIS_URI")
82
+ if url:
83
+ try:
84
+ import redis # type: ignore
85
+ r = redis.from_url(url)
86
+ r.flushdb()
87
+ logging.info("Redis FLUSHDB via REDIS_URL successful")
88
+ return True
89
+ except Exception as e:
90
+ logging.warning("Redis module/connection failed: %s", e)
91
+ logging.warning("Could not locate a Redis client to flush; skipped.")
92
+ return False
93
+ except Exception as e:
94
+ logging.error("Failed to clear caches: %s", e)
95
+ raise
96
+
97
+
98
+ def main():
99
+ parser = argparse.ArgumentParser(description="Clear SmartMemory state across caches and stores.")
100
+ parser.add_argument("--all", action="store_true", help="Clear graph, vector store, and caches")
101
+ parser.add_argument("--graph", action="store_true", help="Clear SmartGraph")
102
+ parser.add_argument("--vector", action="store_true", help="Clear VectorStore")
103
+ parser.add_argument("--cache", action="store_true", help="Clear Redis-backed caches")
104
+ parser.add_argument("-v", "--verbose", action="store_true", help="Verbose logging")
105
+ args = parser.parse_args()
106
+
107
+ _setup_logging(args.verbose)
108
+
109
+ if not any([args.all, args.graph, args.vector, args.cache]):
110
+ logging.info("No flags provided; defaulting to --all")
111
+ args.all = True
112
+
113
+ results: dict[str, Any] = {}
114
+
115
+ try:
116
+ if args.all or args.graph:
117
+ results["graph"] = clear_graph()
118
+ if args.all or args.vector:
119
+ results["vector"] = clear_vector_store()
120
+ if args.all or args.cache:
121
+ results["cache"] = clear_cache()
122
+ except Exception as e:
123
+ logging.error("One or more clear operations failed: %s", e)
124
+ raise
125
+
126
+ logging.info("Done. Summary: %s", results)
127
+
128
+
129
+ if __name__ == "__main__":
130
+ main()