superlocalmemory 3.6.23 → 3.7.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.
Files changed (285) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +271 -71
  3. package/bin/slm-npm +43 -89
  4. package/ide/configs/antigravity-mcp.json +2 -2
  5. package/ide/configs/chatgpt-desktop-mcp.json +1 -1
  6. package/ide/configs/claude-desktop-mcp.json +2 -2
  7. package/ide/configs/windsurf-mcp.json +2 -2
  8. package/ide/hooks/context-hook.js +6 -2
  9. package/ide/hooks/post-recall-hook.js +7 -3
  10. package/ide/hooks/tool-event-hook.sh +2 -1
  11. package/package.json +17 -9
  12. package/plugin/.claude-plugin/plugin.json +1 -1
  13. package/plugin/_GENERATED.md +1 -1
  14. package/plugin/agents/slm-memory-advisor.md +1 -1
  15. package/plugin/requirements.txt +1 -1
  16. package/plugin/skills/slm-session/SKILL.md +1 -1
  17. package/plugin-src/agents/slm-memory-advisor.md +1 -1
  18. package/plugin-src/manifest.json +1 -1
  19. package/plugin-src/requirements.txt +1 -1
  20. package/plugin-src/rules/AGENTS.md +1 -1
  21. package/plugin-src/skills/slm-session/SKILL.md +1 -1
  22. package/pyproject.toml +40 -8
  23. package/scripts/postinstall-interactive.js +17 -94
  24. package/scripts/postinstall.js +185 -258
  25. package/scripts/preuninstall.js +9 -50
  26. package/src/superlocalmemory/__init__.py +2 -2
  27. package/src/superlocalmemory/attribution/mathematical_dna.py +1 -1
  28. package/src/superlocalmemory/attribution/signer.py +34 -19
  29. package/src/superlocalmemory/attribution/watermark.py +1 -1
  30. package/src/superlocalmemory/cli/_lazy_init.py +7 -7
  31. package/src/superlocalmemory/cli/commands.py +453 -191
  32. package/src/superlocalmemory/cli/context_commands.py +5 -4
  33. package/src/superlocalmemory/cli/daemon.py +282 -187
  34. package/src/superlocalmemory/cli/db_migrate.py +3 -1
  35. package/src/superlocalmemory/cli/diagnostics_cmd.py +28 -0
  36. package/src/superlocalmemory/cli/evidence_cmd.py +103 -0
  37. package/src/superlocalmemory/cli/ingest_cmd.py +7 -3
  38. package/src/superlocalmemory/cli/main.py +128 -31
  39. package/src/superlocalmemory/cli/pending_store.py +54 -38
  40. package/src/superlocalmemory/cli/scale_engine_cmd.py +37 -0
  41. package/src/superlocalmemory/cli/service_installer.py +57 -52
  42. package/src/superlocalmemory/cli/setup_wizard.py +142 -88
  43. package/src/superlocalmemory/cli/version_banner.py +2 -1
  44. package/src/superlocalmemory/code_graph/config.py +3 -1
  45. package/src/superlocalmemory/core/backend_orchestrator.py +81 -21
  46. package/src/superlocalmemory/core/config.py +65 -20
  47. package/src/superlocalmemory/core/consolidation_engine.py +9 -7
  48. package/src/superlocalmemory/core/context_cache.py +56 -8
  49. package/src/superlocalmemory/core/derivation_lineage.py +246 -0
  50. package/src/superlocalmemory/core/embedding_worker.py +32 -20
  51. package/src/superlocalmemory/core/embeddings.py +54 -18
  52. package/src/superlocalmemory/core/engine.py +150 -104
  53. package/src/superlocalmemory/core/engine_ingestion.py +513 -0
  54. package/src/superlocalmemory/core/engine_wiring.py +32 -23
  55. package/src/superlocalmemory/core/evidence_bundle.py +526 -0
  56. package/src/superlocalmemory/core/fact_consolidator.py +5 -11
  57. package/src/superlocalmemory/core/graph_analyzer.py +2 -2
  58. package/src/superlocalmemory/core/health_monitor.py +4 -2
  59. package/src/superlocalmemory/core/ingestion_command.py +636 -0
  60. package/src/superlocalmemory/core/injection.py +69 -18
  61. package/src/superlocalmemory/core/lifecycle_state.py +153 -0
  62. package/src/superlocalmemory/core/maintenance.py +1 -1
  63. package/src/superlocalmemory/core/maintenance_scheduler.py +51 -35
  64. package/src/superlocalmemory/core/mutations.py +143 -0
  65. package/src/superlocalmemory/core/platform_utils.py +7 -4
  66. package/src/superlocalmemory/core/ram_lock.py +16 -5
  67. package/src/superlocalmemory/core/rate_limit.py +1 -1
  68. package/src/superlocalmemory/core/recall_pipeline.py +60 -101
  69. package/src/superlocalmemory/core/recall_worker.py +76 -59
  70. package/src/superlocalmemory/core/registry.py +1 -1
  71. package/src/superlocalmemory/core/scale_engine.py +293 -0
  72. package/src/superlocalmemory/core/score_contract.py +62 -0
  73. package/src/superlocalmemory/core/security_primitives.py +3 -1
  74. package/src/superlocalmemory/core/slm_disabled.py +3 -5
  75. package/src/superlocalmemory/core/store_pipeline.py +172 -40
  76. package/src/superlocalmemory/core/tier_manager.py +32 -20
  77. package/src/superlocalmemory/core/worker_pool.py +13 -4
  78. package/src/superlocalmemory/dynamics/activation_guided_quantization.py +1 -1
  79. package/src/superlocalmemory/dynamics/eap_scheduler.py +10 -3
  80. package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +1 -1
  81. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +1 -1
  82. package/src/superlocalmemory/encoding/auto_linker.py +1 -1
  83. package/src/superlocalmemory/encoding/cognitive_consolidator.py +7 -16
  84. package/src/superlocalmemory/encoding/consolidator.py +22 -5
  85. package/src/superlocalmemory/encoding/fact_extractor.py +1 -1
  86. package/src/superlocalmemory/encoding/foresight.py +2 -0
  87. package/src/superlocalmemory/encoding/graph_builder.py +1 -1
  88. package/src/superlocalmemory/encoding/temporal_parser.py +2 -0
  89. package/src/superlocalmemory/evaluation/__init__.py +13 -0
  90. package/src/superlocalmemory/evaluation/calibration.py +308 -0
  91. package/src/superlocalmemory/evolution/skill_evolver.py +2 -1
  92. package/src/superlocalmemory/graph/cozo_backend.py +256 -23
  93. package/src/superlocalmemory/hooks/_outcome_common.py +21 -11
  94. package/src/superlocalmemory/hooks/antigravity_adapter.py +10 -31
  95. package/src/superlocalmemory/hooks/auto_invoker.py +25 -27
  96. package/src/superlocalmemory/hooks/auto_recall.py +31 -6
  97. package/src/superlocalmemory/hooks/auto_recall_hook.py +13 -33
  98. package/src/superlocalmemory/hooks/before_web_hook.py +9 -7
  99. package/src/superlocalmemory/hooks/claude_code_hooks.py +123 -35
  100. package/src/superlocalmemory/hooks/codex_assets.py +59 -0
  101. package/src/superlocalmemory/hooks/codex_hooks.py +186 -0
  102. package/src/superlocalmemory/hooks/context_payload.py +1 -1
  103. package/src/superlocalmemory/hooks/copilot_adapter.py +9 -24
  104. package/src/superlocalmemory/hooks/cursor_adapter.py +10 -32
  105. package/src/superlocalmemory/hooks/hook_daemon.py +4 -2
  106. package/src/superlocalmemory/hooks/hook_handlers.py +219 -32
  107. package/src/superlocalmemory/hooks/memory_protocol.py +5 -3
  108. package/src/superlocalmemory/hooks/post_tool_async_hook.py +4 -2
  109. package/src/superlocalmemory/hooks/session_registry.py +15 -8
  110. package/src/superlocalmemory/hooks/stop_outcome_hook.py +10 -6
  111. package/src/superlocalmemory/hooks/topic_shift_hook.py +42 -12
  112. package/src/superlocalmemory/hooks/user_prompt_hook.py +9 -14
  113. package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +19 -11
  114. package/src/superlocalmemory/infra/auth_middleware.py +38 -5
  115. package/src/superlocalmemory/infra/backup.py +7 -5
  116. package/src/superlocalmemory/infra/cloud_backup.py +18 -8
  117. package/src/superlocalmemory/infra/daemon_identity.py +248 -0
  118. package/src/superlocalmemory/infra/data_root.py +199 -0
  119. package/src/superlocalmemory/infra/event_bus.py +3 -1
  120. package/src/superlocalmemory/infra/local_diagnostics.py +327 -0
  121. package/src/superlocalmemory/infra/process_reaper.py +23 -0
  122. package/src/superlocalmemory/ingestion/adapter_manager.py +27 -9
  123. package/src/superlocalmemory/ingestion/base_adapter.py +25 -31
  124. package/src/superlocalmemory/ingestion/calendar_adapter.py +13 -4
  125. package/src/superlocalmemory/ingestion/credentials.py +14 -7
  126. package/src/superlocalmemory/ingestion/gmail_adapter.py +13 -4
  127. package/src/superlocalmemory/ingestion/transcript_adapter.py +7 -2
  128. package/src/superlocalmemory/learning/consolidation_quantization_worker.py +1 -1
  129. package/src/superlocalmemory/learning/ensemble.py +11 -0
  130. package/src/superlocalmemory/learning/entity_compiler.py +1 -1
  131. package/src/superlocalmemory/learning/feedback.py +1 -1
  132. package/src/superlocalmemory/learning/forgetting_scheduler.py +12 -7
  133. package/src/superlocalmemory/learning/quantization_scheduler.py +1 -1
  134. package/src/superlocalmemory/learning/ranker.py +4 -1
  135. package/src/superlocalmemory/learning/source_quality.py +1 -1
  136. package/src/superlocalmemory/learning/trigram_index.py +3 -2
  137. package/src/superlocalmemory/llm/backbone.py +1 -1
  138. package/src/superlocalmemory/math/ebbinghaus.py +1 -1
  139. package/src/superlocalmemory/math/fisher.py +1 -1
  140. package/src/superlocalmemory/math/fisher_quantized.py +1 -1
  141. package/src/superlocalmemory/math/hopfield.py +1 -1
  142. package/src/superlocalmemory/math/langevin.py +1 -1
  143. package/src/superlocalmemory/math/polar_quant.py +3 -4
  144. package/src/superlocalmemory/math/qjl.py +1 -1
  145. package/src/superlocalmemory/math/sheaf.py +1 -1
  146. package/src/superlocalmemory/math/turbo_quant.py +3 -2
  147. package/src/superlocalmemory/mcp/_daemon_proxy.py +12 -11
  148. package/src/superlocalmemory/mcp/_pool_adapter.py +27 -0
  149. package/src/superlocalmemory/mcp/http_transport.py +53 -0
  150. package/src/superlocalmemory/mcp/server.py +39 -13
  151. package/src/superlocalmemory/mcp/shared.py +69 -3
  152. package/src/superlocalmemory/mcp/tools_active.py +141 -31
  153. package/src/superlocalmemory/mcp/tools_core.py +130 -31
  154. package/src/superlocalmemory/mcp/tools_evolution.py +5 -7
  155. package/src/superlocalmemory/mcp/tools_learning.py +42 -2
  156. package/src/superlocalmemory/mcp/tools_mesh.py +7 -23
  157. package/src/superlocalmemory/mcp/tools_optimize.py +8 -1
  158. package/src/superlocalmemory/mcp/tools_v28.py +23 -2
  159. package/src/superlocalmemory/mcp/tools_v3.py +26 -1
  160. package/src/superlocalmemory/mcp/tools_v33.py +56 -17
  161. package/src/superlocalmemory/mesh/broker.py +2 -0
  162. package/src/superlocalmemory/mesh/remote_sync.py +50 -12
  163. package/src/superlocalmemory/optimize/cache/manager.py +77 -1
  164. package/src/superlocalmemory/optimize/cache/semantic.py +23 -3
  165. package/src/superlocalmemory/optimize/compress/ccr.py +4 -0
  166. package/src/superlocalmemory/optimize/compress/router.py +6 -1
  167. package/src/superlocalmemory/optimize/config/__init__.py +5 -0
  168. package/src/superlocalmemory/optimize/config/store.py +6 -4
  169. package/src/superlocalmemory/optimize/proxy/_helpers.py +15 -5
  170. package/src/superlocalmemory/optimize/proxy/capture.py +3 -2
  171. package/src/superlocalmemory/optimize/proxy/server.py +2 -2
  172. package/src/superlocalmemory/optimize/storage/db.py +12 -12
  173. package/src/superlocalmemory/retrieval/agentic.py +1 -1
  174. package/src/superlocalmemory/retrieval/ann_index.py +1 -1
  175. package/src/superlocalmemory/retrieval/bm25_channel.py +35 -11
  176. package/src/superlocalmemory/retrieval/bridge_discovery.py +73 -8
  177. package/src/superlocalmemory/retrieval/engine.py +169 -79
  178. package/src/superlocalmemory/retrieval/entity_channel.py +289 -67
  179. package/src/superlocalmemory/retrieval/forgetting_filter.py +1 -1
  180. package/src/superlocalmemory/retrieval/fusion.py +1 -1
  181. package/src/superlocalmemory/retrieval/hopfield_channel.py +118 -30
  182. package/src/superlocalmemory/retrieval/profile_channel.py +1 -1
  183. package/src/superlocalmemory/retrieval/quantization_aware_search.py +16 -10
  184. package/src/superlocalmemory/retrieval/reranker.py +56 -20
  185. package/src/superlocalmemory/retrieval/scope_policy.py +85 -0
  186. package/src/superlocalmemory/retrieval/semantic_channel.py +122 -14
  187. package/src/superlocalmemory/retrieval/spreading_activation.py +141 -25
  188. package/src/superlocalmemory/retrieval/strategy.py +1 -1
  189. package/src/superlocalmemory/retrieval/temporal_channel.py +30 -15
  190. package/src/superlocalmemory/retrieval/vector_store.py +1 -1
  191. package/src/superlocalmemory/server/api.py +10 -7
  192. package/src/superlocalmemory/server/bandit_loops.py +4 -2
  193. package/src/superlocalmemory/server/recall_serializer.py +24 -0
  194. package/src/superlocalmemory/server/route_mutations.py +84 -0
  195. package/src/superlocalmemory/server/routes/agents.py +8 -6
  196. package/src/superlocalmemory/server/routes/brain.py +14 -12
  197. package/src/superlocalmemory/server/routes/chat.py +29 -12
  198. package/src/superlocalmemory/server/routes/data_io.py +55 -24
  199. package/src/superlocalmemory/server/routes/helpers.py +8 -63
  200. package/src/superlocalmemory/server/routes/ingest.py +53 -36
  201. package/src/superlocalmemory/server/routes/memories.py +104 -43
  202. package/src/superlocalmemory/server/routes/mesh.py +31 -0
  203. package/src/superlocalmemory/server/routes/profiles.py +26 -4
  204. package/src/superlocalmemory/server/routes/tiers.py +43 -11
  205. package/src/superlocalmemory/server/routes/timeline.py +5 -1
  206. package/src/superlocalmemory/server/routes/v3_api.py +76 -21
  207. package/src/superlocalmemory/server/security_middleware.py +1 -1
  208. package/src/superlocalmemory/server/unified_daemon.py +680 -293
  209. package/src/superlocalmemory/server/write_identity.py +147 -0
  210. package/src/superlocalmemory/storage/access_log.py +4 -3
  211. package/src/superlocalmemory/storage/database.py +118 -25
  212. package/src/superlocalmemory/storage/migration_runner.py +84 -1
  213. package/src/superlocalmemory/storage/migration_v33.py +1 -1
  214. package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +6 -60
  215. package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +120 -0
  216. package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +54 -0
  217. package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +52 -0
  218. package/src/superlocalmemory/storage/migrations/__init__.py +5 -0
  219. package/src/superlocalmemory/storage/models.py +16 -0
  220. package/src/superlocalmemory/storage/quantized_store.py +20 -3
  221. package/src/superlocalmemory/storage/v2_migrator.py +5 -3
  222. package/src/superlocalmemory/ui/favicon.svg +5 -0
  223. package/src/superlocalmemory/ui/index.html +1 -0
  224. package/src/superlocalmemory/ui/js/compliance.js +1 -1
  225. package/src/superlocalmemory/ui/js/core.js +49 -8
  226. package/src/superlocalmemory/ui/js/dashboard.js +23 -2
  227. package/src/superlocalmemory/ui/js/feedback.js +1 -1
  228. package/src/superlocalmemory/ui/js/graph-filters.js +1 -1
  229. package/src/superlocalmemory/ui/js/graph-ui.js +1 -1
  230. package/src/superlocalmemory/ui/js/lifecycle.js +1 -1
  231. package/src/superlocalmemory/ui/js/ng-mesh.js +15 -49
  232. package/src/superlocalmemory/ui/js/settings.js +4 -2
  233. package/src/superlocalmemory/vector/lancedb_backend.py +57 -9
  234. package/bin/slm +0 -59
  235. package/bin/slm.bat +0 -77
  236. package/bin/slm.cmd +0 -5
  237. package/ide/integrations/langchain/README.md +0 -106
  238. package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +0 -9
  239. package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +0 -201
  240. package/ide/integrations/langchain/pyproject.toml +0 -38
  241. package/ide/integrations/langchain/tests/__init__.py +0 -3
  242. package/ide/integrations/langchain/tests/test_chat_message_history.py +0 -215
  243. package/ide/integrations/langchain/tests/test_security.py +0 -117
  244. package/ide/integrations/llamaindex/README.md +0 -81
  245. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +0 -9
  246. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +0 -316
  247. package/ide/integrations/llamaindex/pyproject.toml +0 -43
  248. package/ide/integrations/llamaindex/tests/__init__.py +0 -3
  249. package/ide/integrations/llamaindex/tests/test_chat_store.py +0 -294
  250. package/ide/integrations/llamaindex/tests/test_security.py +0 -241
  251. package/scripts/__tests__/build-plugin.test.mjs +0 -613
  252. package/scripts/_savings_math.py +0 -270
  253. package/scripts/build-dmg.sh +0 -417
  254. package/scripts/build-plugin.js +0 -742
  255. package/scripts/build-slm-hook.ps1 +0 -40
  256. package/scripts/build-slm-hook.sh +0 -45
  257. package/scripts/build_entry.py +0 -452
  258. package/scripts/ci/stage5b_gate.sh +0 -50
  259. package/scripts/dogfood_savings.py +0 -490
  260. package/scripts/generate-thumbnails.py +0 -218
  261. package/scripts/install-skills.ps1 +0 -4
  262. package/scripts/install-skills.sh +0 -5
  263. package/scripts/install.ps1 +0 -701
  264. package/scripts/install.sh +0 -1015
  265. package/scripts/postinstall_binary.js +0 -287
  266. package/scripts/prepack.js +0 -33
  267. package/scripts/release_manifest.py +0 -273
  268. package/scripts/slm-hook.spec +0 -56
  269. package/scripts/start-dashboard.ps1 +0 -52
  270. package/scripts/start-dashboard.sh +0 -41
  271. package/scripts/sync-wiki.ps1 +0 -127
  272. package/scripts/sync-wiki.sh +0 -82
  273. package/scripts/test-dmg.sh +0 -161
  274. package/scripts/test-npm-package.ps1 +0 -252
  275. package/scripts/test-npm-package.sh +0 -207
  276. package/scripts/verify-install.ps1 +0 -294
  277. package/scripts/verify-install.sh +0 -266
  278. package/scripts/verify-v27.ps1 +0 -301
  279. package/scripts/verify-v27.sh +0 -233
  280. package/src/superlocalmemory.egg-info/PKG-INFO +0 -516
  281. package/src/superlocalmemory.egg-info/SOURCES.txt +0 -529
  282. package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
  283. package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
  284. package/src/superlocalmemory.egg-info/requires.txt +0 -71
  285. package/src/superlocalmemory.egg-info/top_level.txt +0 -1
@@ -1,270 +0,0 @@
1
- # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
- # Licensed under AGPL-3.0-or-later - see LICENSE file
3
- # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
-
5
- """_savings_math.py — PURE math module for WP-14 metered-pipeline $-savings dogfood.
6
-
7
- Zero I/O. No network. No side effects.
8
-
9
- Prices used here come from R6 (2026-06-16):
10
- Anthropic Sonnet 4.6: $3.00/MTok input, $15.00/MTok output — VERIFIED
11
- Anthropic Opus 4.8: $5.00/MTok input, $25.00/MTok output — VERIFIED
12
- Anthropic Haiku 4.5: $1.00/MTok input, $5.00/MTok output — VERIFIED
13
- Cache-read multiplier: 0.10x (90% off cached portion) — VERIFIED
14
- Source: https://platform.claude.com/docs/en/about-claude/pricing (fetched 2026-06-16)
15
-
16
- OpenAI prices: UNVERIFIED-OFFICIAL (openai.com/api/pricing unreachable at fetch time;
17
- data from aipricing.guru aggregator). Do not cite as authoritative.
18
-
19
- CRIT notes (from LLD §9):
20
- 1. Blended input-price is a conservative lower-bound (output tokens cost more).
21
- 2. tokens_saved_compress is a word-count proxy (not a real tokenizer).
22
- 3. chars//4 is used in sim for input tokens (char-exact by construction).
23
- """
24
-
25
- from __future__ import annotations
26
-
27
- import dataclasses
28
- import json
29
- from datetime import datetime, timezone
30
- from typing import Any
31
-
32
- # ---------------------------------------------------------------------------
33
- # Public types
34
- # ---------------------------------------------------------------------------
35
-
36
-
37
- @dataclasses.dataclass(frozen=False)
38
- class MetricsDelta:
39
- """Difference between two MetricsSnapshots, clamped to ≥0.
40
-
41
- Negative values indicate the DB was reset or shared between runs —
42
- clamped to 0 (conservative, never overclaim).
43
- """
44
-
45
- hits: int
46
- misses: int
47
- tokens_saved_input: int
48
- tokens_saved_output: int
49
- tokens_saved_compress: int
50
-
51
- def __post_init__(self) -> None:
52
- # Clamp all fields to ≥ 0 (immutable-safe: assign back to self)
53
- self.hits = max(0, self.hits)
54
- self.misses = max(0, self.misses)
55
- self.tokens_saved_input = max(0, self.tokens_saved_input)
56
- self.tokens_saved_output = max(0, self.tokens_saved_output)
57
- self.tokens_saved_compress = max(0, self.tokens_saved_compress)
58
-
59
- @property
60
- def total_tokens_saved(self) -> int:
61
- return (
62
- self.tokens_saved_input
63
- + self.tokens_saved_output
64
- + self.tokens_saved_compress
65
- )
66
-
67
- @property
68
- def hit_rate(self) -> float:
69
- total = self.hits + self.misses
70
- return self.hits / total if total > 0 else 0.0
71
-
72
-
73
- @dataclasses.dataclass(frozen=True)
74
- class Report:
75
- """Immutable dogfood savings report."""
76
-
77
- mode: str # "sim" or "live"
78
- provider: str
79
- prompts: int
80
- repeat: int
81
- delta: MetricsDelta
82
- price_per_1m: float
83
- price_source: str # e.g. "DEFAULT_COST_PER_MILLION_INPUT_TOKENS[anthropic], 2026-06-07 (R6)"
84
- savings_usd: float
85
- savings_inr: float
86
- inr_rate: float
87
-
88
- def to_json(self) -> str:
89
- """Serialize to raw JSON ledger format per LLD §5."""
90
- d = self.delta
91
- formula_str = (
92
- f"({d.tokens_saved_input} + {d.tokens_saved_output} + "
93
- f"{d.tokens_saved_compress}) / 1_000_000 * {self.price_per_1m}"
94
- )
95
- payload: dict[str, Any] = {
96
- "mode": self.mode,
97
- "provider": self.provider,
98
- "workload": {
99
- "prompts": self.prompts,
100
- "repeat": self.repeat,
101
- "total_requests": self.prompts * (1 + self.repeat),
102
- },
103
- "delta": {
104
- "hits": d.hits,
105
- "misses": d.misses,
106
- "tokens_saved_input": d.tokens_saved_input,
107
- "tokens_saved_output": d.tokens_saved_output,
108
- "tokens_saved_compress": d.tokens_saved_compress,
109
- "total_tokens_saved": d.total_tokens_saved,
110
- "hit_rate": round(d.hit_rate, 4),
111
- },
112
- "pricing": {
113
- "price_per_1m": self.price_per_1m,
114
- "source": self.price_source,
115
- "date": "2026-06-07",
116
- "inr_rate": self.inr_rate,
117
- },
118
- "computed": {
119
- "savings_usd": round(self.savings_usd, 6),
120
- "savings_inr": round(self.savings_inr, 4),
121
- "formula": formula_str,
122
- },
123
- "generated_at": datetime.now(timezone.utc).isoformat(),
124
- }
125
- return json.dumps(payload, indent=2)
126
-
127
- def to_markdown(self) -> str:
128
- """Render human-readable Markdown report per LLD §5 / AC3."""
129
- d = self.delta
130
- mode_label = "simulated" if self.mode == "sim" else "live"
131
- openai_note = (
132
- "\n> **UNVERIFIED-OFFICIAL:** OpenAI prices sourced from third-party "
133
- "aggregator (openai.com/api/pricing was unreachable). Do not cite externally."
134
- if self.provider.lower() == "openai"
135
- else ""
136
- )
137
-
138
- return f"""# SLM Optimize — Metered-Pipeline $-Savings Report ({mode_label.upper()})
139
-
140
- > Generated by `scripts/dogfood_savings.py` — WP-14 evidence artifact.
141
- > Mode: **{self.mode}** | Provider: **{self.provider}** | Date: {datetime.now(timezone.utc).strftime("%Y-%m-%d")}
142
-
143
- ## Workload
144
-
145
- | Parameter | Value |
146
- |-----------|-------|
147
- | Prompts (N) | {self.prompts} |
148
- | Repeats per prompt (R) | {self.repeat} |
149
- | Total requests | {self.prompts * (1 + self.repeat)} |
150
- | Hit rate | {d.hit_rate * 100:.1f}% (R/{1 + self.repeat} = {self.repeat}/{1 + self.repeat}) |
151
-
152
- ## Token Savings (delta from MetricsSnapshot)
153
-
154
- | Component | Tokens saved |
155
- |-----------|-------------|
156
- | Input (cache hit) | {d.tokens_saved_input:,} |
157
- | Output (cache hit) | {d.tokens_saved_output:,} |
158
- | Compress (word-count proxy) | {d.tokens_saved_compress:,} |
159
- | **Total** | **{d.total_tokens_saved:,}** |
160
-
161
- > Tokens saved: produced by SHIPPED CacheManager.on_hit recovery (M-01/M-02), not invented.
162
-
163
- ## Pricing
164
-
165
- | Field | Value |
166
- |-------|-------|
167
- | Price per 1M tokens | ${self.price_per_1m:.2f} (blended input, conservative lower bound) |
168
- | Source | {self.price_source} |
169
- | USD→INR rate | {self.inr_rate} |
170
- {openai_note}
171
-
172
- ## Computed Savings
173
-
174
- **Formula:** `total_tokens_saved / 1_000_000 × price_per_1m`
175
-
176
- | Metric | Value |
177
- |--------|-------|
178
- | Savings (USD) | **${self.savings_usd:.4f}** |
179
- | Savings (INR) | **₹{self.savings_inr:.2f}** |
180
-
181
- > Formula: `({d.tokens_saved_input} + {d.tokens_saved_output} + {d.tokens_saved_compress}) / 1_000_000 × {self.price_per_1m} = {self.savings_usd:.6f} USD`
182
-
183
- ## Methodology & Caveats
184
-
185
- 1. **Simulated workload (this run):** synthetic prompts with char-exact content (chars//4 = exact tokens by construction). No API key or network required.
186
- 2. **Savings metric is REAL:** tokens_saved_* fields come from `CacheManager.on_hit` M-01/M-02 recovery in the SHIPPED proxy — not a hardcoded percentage.
187
- 3. **Blended input price is a conservative lower bound:** output tokens cost 5× more ($15/MTok for Sonnet 4.6 output vs $3 input). This report uses input price only → understates true savings.
188
- 4. **Hit rate is workload-dependent:** this run simulates R={self.repeat} repeats per prompt → hit_rate = R/(1+R) = {self.repeat/(1+self.repeat)*100:.1f}%. Real workloads vary.
189
- 5. **tokens_saved_compress is a word-count proxy** (not a real tokenizer). Field name "bytes" in DB schema is legacy; unit is word count.
190
- 6. **Pricing is a point-in-time snapshot** (source date: 2026-06-07). Verify before citing externally.
191
- 7. **Local/self-hosted usage = $0 savings** (no metered API). Savings apply only to metered API workloads (Anthropic, OpenAI, Gemini).
192
- 8. **Live mode:** `--mode live --i-will-spend-money + SLM_DOGFOOD_API_KEY` routes real HTTP through proxy at 127.0.0.1:8765. ~$0.05–$0.20 per run. Never run in CI.
193
-
194
- ## Verification
195
-
196
- Cross-check with: `slm optimize savings --provider {self.provider} --json`
197
- (same formula as `optimize_cmd.py:145-155`; numbers should agree within rounding).
198
- """
199
-
200
-
201
- # ---------------------------------------------------------------------------
202
- # Pure functions
203
- # ---------------------------------------------------------------------------
204
-
205
-
206
- def compute_savings_usd(
207
- tokens_saved_input: int,
208
- tokens_saved_output: int,
209
- tokens_saved_compress: int,
210
- *,
211
- price_per_1m: float,
212
- ) -> float:
213
- """Compute estimated USD savings from token counts.
214
-
215
- Contract-twin of optimize_cmd.py:145-155:
216
- tokens_saved = ti + to + tc
217
- estimated_savings_usd = tokens_saved / 1_000_000 * rate
218
-
219
- CRIT-1: This uses the blended input price — a conservative lower bound.
220
- Output tokens cost 5× more than input (e.g. $15 vs $3/MTok for Sonnet 4.6).
221
- """
222
- total = tokens_saved_input + tokens_saved_output + tokens_saved_compress
223
- return total / 1_000_000 * price_per_1m
224
-
225
-
226
- def resolve_price(
227
- provider: str,
228
- default_table: dict[str, float],
229
- overrides: dict[str, Any],
230
- ) -> tuple[float, str]:
231
- """Resolve price per 1M tokens for a provider.
232
-
233
- Priority: overrides[provider].input_per_1m_usd > default_table[provider] > default_table["default"].
234
-
235
- Returns (price, source_description).
236
- """
237
- # 1. Check config overrides
238
- if provider in overrides:
239
- override_val = overrides[provider]
240
- if isinstance(override_val, dict) and "input_per_1m_usd" in override_val:
241
- price = float(override_val["input_per_1m_usd"])
242
- return price, f"pricing_override[{provider}].input_per_1m_usd"
243
-
244
- # 2. Default table lookup
245
- if provider in default_table:
246
- price = float(default_table[provider])
247
- return price, f"default_table[{provider}]"
248
-
249
- # 3. Fallback to "default"
250
- price = float(default_table.get("default", 3.00))
251
- return price, "default_table[default]"
252
-
253
-
254
- def to_inr(usd: float, rate: float) -> float:
255
- """Convert USD to INR at the given exchange rate."""
256
- return usd * rate
257
-
258
-
259
- def metrics_delta(before: Any, after: Any) -> MetricsDelta:
260
- """Compute the delta between two MetricsSnapshots, clamping to ≥0.
261
-
262
- Uses attribute access (compatible with MetricsSnapshot dataclass).
263
- """
264
- return MetricsDelta(
265
- hits=after.hits - before.hits,
266
- misses=after.misses - before.misses,
267
- tokens_saved_input=after.tokens_saved_input - before.tokens_saved_input,
268
- tokens_saved_output=after.tokens_saved_output - before.tokens_saved_output,
269
- tokens_saved_compress=after.tokens_saved_compress - before.tokens_saved_compress,
270
- )
@@ -1,417 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # SuperLocalMemory V2 - DMG Installer Build Script
4
- #
5
- # Copyright (c) 2026 Varun Pratap Bhardwaj
6
- # Solution Architect & Original Creator
7
- #
8
- # Licensed under MIT License (see LICENSE file)
9
- # Repository: https://github.com/qualixar/superlocalmemory
10
- #
11
- # ATTRIBUTION REQUIRED: This notice must be preserved in all copies.
12
- #
13
-
14
- set -e # Exit on any error
15
-
16
- # ============================================================================
17
- # CONFIGURATION
18
- # ============================================================================
19
-
20
- VERSION="2.7.4"
21
- APP_NAME="SuperLocalMemory"
22
- DMG_NAME="SuperLocalMemory-v${VERSION}-macos"
23
- BUILD_DIR="build/dmg"
24
- INSTALLER_DIR="${BUILD_DIR}/${APP_NAME}"
25
- TEMP_DMG="${BUILD_DIR}/temp.dmg"
26
- FINAL_DMG="${DMG_NAME}.dmg"
27
-
28
- # Colors for output
29
- RED='\033[0;31m'
30
- GREEN='\033[0;32m'
31
- YELLOW='\033[1;33m'
32
- BLUE='\033[0;34m'
33
- NC='\033[0m' # No Color
34
-
35
- # ============================================================================
36
- # FUNCTIONS
37
- # ============================================================================
38
-
39
- log_info() {
40
- echo -e "${BLUE}[INFO]${NC} $1"
41
- }
42
-
43
- log_success() {
44
- echo -e "${GREEN}[SUCCESS]${NC} $1"
45
- }
46
-
47
- log_warning() {
48
- echo -e "${YELLOW}[WARNING]${NC} $1"
49
- }
50
-
51
- log_error() {
52
- echo -e "${RED}[ERROR]${NC} $1"
53
- }
54
-
55
- cleanup_build() {
56
- log_info "Cleaning up previous build artifacts..."
57
- rm -rf "${BUILD_DIR}"
58
- rm -f "${FINAL_DMG}"
59
- }
60
-
61
- create_directory_structure() {
62
- log_info "Creating directory structure..."
63
- mkdir -p "${INSTALLER_DIR}"
64
- }
65
-
66
- copy_installer_files() {
67
- log_info "Copying installer files..."
68
-
69
- # Core installation script
70
- cp install.sh "${INSTALLER_DIR}/"
71
-
72
- # Source files
73
- log_info " → Copying src/ directory..."
74
- cp -r src "${INSTALLER_DIR}/"
75
-
76
- # Binary files
77
- log_info " → Copying bin/ directory..."
78
- cp -r bin "${INSTALLER_DIR}/"
79
-
80
- # MCP configurations
81
- log_info " → Copying configs/ directory..."
82
- cp -r configs "${INSTALLER_DIR}/"
83
-
84
- # Universal skills
85
- log_info " → Copying skills/ directory..."
86
- cp -r skills "${INSTALLER_DIR}/"
87
-
88
- # MCP server
89
- log_info " → Copying mcp_server.py..."
90
- cp mcp_server.py "${INSTALLER_DIR}/"
91
-
92
- # Skills installer
93
- log_info " → Copying install-skills.sh..."
94
- cp install-skills.sh "${INSTALLER_DIR}/"
95
-
96
- # Requirements files
97
- log_info " → Copying requirements files..."
98
- cp requirements.txt "${INSTALLER_DIR}/"
99
- cp requirements-core.txt "${INSTALLER_DIR}/"
100
- cp requirements-full.txt "${INSTALLER_DIR}/"
101
- cp requirements-search.txt "${INSTALLER_DIR}/"
102
- cp requirements-ui.txt "${INSTALLER_DIR}/"
103
- cp requirements-learning.txt "${INSTALLER_DIR}/" 2>/dev/null || true
104
-
105
- # UI server
106
- log_info " → Copying ui_server.py..."
107
- cp ui_server.py "${INSTALLER_DIR}/"
108
-
109
- # Start scripts
110
- log_info " → Copying start scripts..."
111
- cp start-dashboard.sh "${INSTALLER_DIR}/"
112
-
113
- # Verification script
114
- log_info " → Copying verify-install.sh..."
115
- cp verify-install.sh "${INSTALLER_DIR}/"
116
-
117
- # Documentation
118
- log_info " → Copying documentation..."
119
- cp README.md "${INSTALLER_DIR}/" 2>/dev/null || true
120
- cp LICENSE "${INSTALLER_DIR}/" 2>/dev/null || true
121
- cp ATTRIBUTION.md "${INSTALLER_DIR}/" 2>/dev/null || true
122
- cp CHANGELOG.md "${INSTALLER_DIR}/" 2>/dev/null || true
123
- if [ -d "docs" ]; then
124
- cp -r docs "${INSTALLER_DIR}/"
125
- fi
126
-
127
- # Shell completions
128
- if [ -d "completions" ]; then
129
- log_info " → Copying shell completions..."
130
- cp -r completions "${INSTALLER_DIR}/"
131
- fi
132
- }
133
-
134
- create_readme() {
135
- log_info "Creating README-INSTALLATION.txt..."
136
-
137
- cat > "${INSTALLER_DIR}/README-INSTALLATION.txt" << 'READMEEOF'
138
- ================================================================================
139
- SuperLocalMemory V2.7.0 - macOS Installation
140
- ================================================================================
141
-
142
- Thank you for downloading SuperLocalMemory V2!
143
-
144
- QUICK START (2 minutes):
145
- ------------------------
146
-
147
- 1. Open Terminal (Applications → Utilities → Terminal)
148
-
149
- 2. Navigate to this folder:
150
- cd /Volumes/SuperLocalMemory
151
-
152
- 3. Run the installer:
153
- ./install.sh
154
-
155
- 4. Follow the on-screen prompts
156
-
157
- 5. Restart your AI tools (Claude Desktop, Cursor, etc.)
158
-
159
- WHAT GETS INSTALLED:
160
- -------------------
161
- • Core memory system → ~/.superlocalmemory/
162
- • MCP server auto-configured for 11+ IDEs
163
- • 6 universal skills (Claude Code, Continue.dev, Cody, etc.)
164
- • CLI command: slm
165
- • Dashboard server: start-dashboard.sh
166
-
167
- VERIFICATION:
168
- ------------
169
- After installation, verify by running:
170
- slm status
171
-
172
- NEED HELP?
173
- ---------
174
- • Documentation: README.md
175
- • Quick Start: docs/CLI-COMMANDS-REFERENCE.md
176
- • GitHub Wiki: https://github.com/qualixar/superlocalmemory/wiki
177
- • Issues: https://github.com/qualixar/superlocalmemory/issues
178
-
179
- UNINSTALL:
180
- ---------
181
- To uninstall:
182
- rm -rf ~/.superlocalmemory
183
- rm -f /usr/local/bin/slm
184
-
185
- ================================================================================
186
- Created by: Varun Pratap Bhardwaj
187
- License: MIT (Attribution Required)
188
- Repository: https://github.com/qualixar/superlocalmemory
189
- ================================================================================
190
- READMEEOF
191
- }
192
-
193
- create_installer_wrapper() {
194
- log_info "Creating installer wrapper script..."
195
-
196
- cat > "${INSTALLER_DIR}/INSTALL" << 'WRAPPEREOF'
197
- #!/usr/bin/env bash
198
- #
199
- # SuperLocalMemory V2 - Installer Wrapper
200
- # Double-click this file to install, or run from Terminal
201
- #
202
-
203
- # Detect if running from Finder (double-click)
204
- if [ -t 0 ]; then
205
- # Running in terminal
206
- TERMINAL_MODE=true
207
- else
208
- # Running from Finder
209
- TERMINAL_MODE=false
210
- # Open Terminal and run installer
211
- osascript <<APPLESCRIPT
212
- tell application "Terminal"
213
- activate
214
- do script "cd \"$(dirname \"$0\")\" && ./install.sh && echo '\\n\\nPress Enter to close...' && read"
215
- end tell
216
- APPLESCRIPT
217
- exit 0
218
- fi
219
-
220
- # If in terminal mode, just run installer
221
- cd "$(dirname "$0")"
222
- ./install.sh
223
-
224
- echo ""
225
- echo "Installation complete!"
226
- echo "Press Enter to close..."
227
- read
228
- WRAPPEREOF
229
-
230
- chmod +x "${INSTALLER_DIR}/INSTALL"
231
- }
232
-
233
- create_dmg_background() {
234
- log_info "Creating DMG background image..."
235
-
236
- # Create a simple background with instructions
237
- # (This uses ImageMagick if available, otherwise creates a simple text file)
238
-
239
- if command -v convert &> /dev/null; then
240
- log_info " → Using ImageMagick to create background..."
241
- convert -size 640x480 xc:white \
242
- -font Helvetica -pointsize 20 \
243
- -fill black -gravity north \
244
- -annotate +0+50 "SuperLocalMemory" \
245
- -pointsize 14 -gravity center \
246
- -annotate +0+0 "Drag to Applications folder\nor double-click INSTALL to begin" \
247
- "${BUILD_DIR}/.background.png" 2>/dev/null || true
248
- else
249
- log_warning " → ImageMagick not found, skipping background image"
250
- fi
251
- }
252
-
253
- create_symlink() {
254
- log_info "Creating Applications folder symlink..."
255
- ln -s /Applications "${BUILD_DIR}/Applications"
256
- }
257
-
258
- create_dmg() {
259
- log_info "Creating temporary DMG..."
260
-
261
- # Calculate size needed (add 50MB buffer)
262
- SIZE=$(du -sm "${INSTALLER_DIR}" | awk '{print $1}')
263
- SIZE=$((SIZE + 50))
264
-
265
- log_info " → Allocating ${SIZE}MB for DMG..."
266
-
267
- # Create writable DMG
268
- hdiutil create \
269
- -volname "${APP_NAME}" \
270
- -srcfolder "${BUILD_DIR}" \
271
- -ov \
272
- -format UDRW \
273
- -size ${SIZE}m \
274
- "${TEMP_DMG}"
275
-
276
- log_info "Mounting temporary DMG..."
277
- DEVICE=$(hdiutil attach -readwrite -noverify -noautoopen "${TEMP_DMG}" | \
278
- grep -E '^/dev/' | sed 1q | awk '{print $1}')
279
-
280
- log_info " → Mounted at: ${DEVICE}"
281
-
282
- # Wait for mount
283
- sleep 2
284
-
285
- MOUNT_POINT="/Volumes/${APP_NAME}"
286
-
287
- # Set custom icon positions (if possible)
288
- log_info "Configuring Finder view settings..."
289
-
290
- osascript <<APPLESCRIPT || log_warning "Could not set Finder view settings"
291
- tell application "Finder"
292
- tell disk "${APP_NAME}"
293
- open
294
- set current view of container window to icon view
295
- set toolbar visible of container window to false
296
- set statusbar visible of container window to false
297
- set the bounds of container window to {100, 100, 740, 580}
298
- set theViewOptions to the icon view options of container window
299
- set arrangement of theViewOptions to not arranged
300
- set icon size of theViewOptions to 128
301
- set background picture of theViewOptions to file ".background.png"
302
-
303
- -- Position installer folder
304
- set position of item "${APP_NAME}" of container window to {160, 240}
305
-
306
- -- Position Applications symlink
307
- set position of item "Applications" of container window to {480, 240}
308
-
309
- -- Position README
310
- if exists item "README-INSTALLATION.txt" then
311
- set position of item "README-INSTALLATION.txt" of container window to {320, 400}
312
- end if
313
-
314
- update without registering applications
315
- delay 2
316
- close
317
- end tell
318
- end tell
319
- APPLESCRIPT
320
-
321
- # Ensure everything is written
322
- sync
323
- sleep 2
324
-
325
- log_info "Unmounting temporary DMG..."
326
- hdiutil detach "${DEVICE}" -quiet || {
327
- log_warning "Normal unmount failed, forcing..."
328
- hdiutil detach "${DEVICE}" -force -quiet
329
- }
330
-
331
- log_info "Converting to compressed read-only DMG..."
332
- hdiutil convert "${TEMP_DMG}" \
333
- -format UDZO \
334
- -imagekey zlib-level=9 \
335
- -o "${FINAL_DMG}"
336
-
337
- # Clean up temp DMG
338
- rm -f "${TEMP_DMG}"
339
- }
340
-
341
- verify_dmg() {
342
- log_info "Verifying DMG..."
343
-
344
- if [ ! -f "${FINAL_DMG}" ]; then
345
- log_error "DMG file not found: ${FINAL_DMG}"
346
- return 1
347
- fi
348
-
349
- # Check DMG integrity
350
- hdiutil verify "${FINAL_DMG}" && log_success "DMG verification passed"
351
-
352
- # Show file size
353
- SIZE=$(du -h "${FINAL_DMG}" | awk '{print $1}')
354
- log_info "DMG size: ${SIZE}"
355
- }
356
-
357
- show_summary() {
358
- echo ""
359
- echo "============================================================================"
360
- log_success "DMG BUILD COMPLETE!"
361
- echo "============================================================================"
362
- echo ""
363
- echo " Output file: ${FINAL_DMG}"
364
- echo " Size: $(du -h "${FINAL_DMG}" | awk '{print $1}')"
365
- echo ""
366
- echo "NEXT STEPS:"
367
- echo " 1. Test the DMG:"
368
- echo " open ${FINAL_DMG}"
369
- echo ""
370
- echo " 2. Upload to GitHub Releases:"
371
- echo " gh release create v${VERSION} ${FINAL_DMG} \\"
372
- echo " --title \"SuperLocalMemory v${VERSION}\" \\"
373
- echo " --notes \"See CHANGELOG.md for details\""
374
- echo ""
375
- echo " 3. Or upload manually:"
376
- echo " https://github.com/qualixar/superlocalmemory/releases/new"
377
- echo ""
378
- echo "============================================================================"
379
- }
380
-
381
- # ============================================================================
382
- # MAIN EXECUTION
383
- # ============================================================================
384
-
385
- main() {
386
- log_info "Starting DMG build for SuperLocalMemory v${VERSION}..."
387
- echo ""
388
-
389
- # Check we're in the right directory
390
- if [ ! -f "install.sh" ]; then
391
- log_error "Must run from superlocalmemory repository root"
392
- exit 1
393
- fi
394
-
395
- # Check required tools
396
- if ! command -v hdiutil &> /dev/null; then
397
- log_error "hdiutil not found (required for macOS DMG creation)"
398
- exit 1
399
- fi
400
-
401
- # Build process
402
- cleanup_build
403
- create_directory_structure
404
- copy_installer_files
405
- create_readme
406
- create_installer_wrapper
407
- create_dmg_background
408
- create_symlink
409
- create_dmg
410
- verify_dmg
411
- show_summary
412
-
413
- log_success "Build complete!"
414
- }
415
-
416
- # Run main function
417
- main "$@"