superlocalmemory 3.6.9 → 3.6.11

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 (46) hide show
  1. package/CHANGELOG.md +112 -10
  2. package/README.md +67 -9
  3. package/package.json +1 -1
  4. package/pyproject.toml +6 -1
  5. package/skills/slm-optimize/README.md +55 -0
  6. package/skills/slm-optimize/SKILL.md +139 -0
  7. package/src/superlocalmemory/__init__.py +1 -1
  8. package/src/superlocalmemory/cli/compress_cmd.py +32 -70
  9. package/src/superlocalmemory/cli/optimize_cmd.py +1 -3
  10. package/src/superlocalmemory/cli/setup_wizard.py +49 -0
  11. package/src/superlocalmemory/mcp/agent_context.py +111 -0
  12. package/src/superlocalmemory/mcp/server.py +4 -0
  13. package/src/superlocalmemory/mcp/tools_active.py +7 -8
  14. package/src/superlocalmemory/mcp/tools_core.py +16 -0
  15. package/src/superlocalmemory/mcp/tools_optimize.py +304 -0
  16. package/src/superlocalmemory/optimize/cache/boundary_store.py +23 -9
  17. package/src/superlocalmemory/optimize/cache/exact.py +7 -4
  18. package/src/superlocalmemory/optimize/cache/key_builder.py +13 -0
  19. package/src/superlocalmemory/optimize/cache/manager.py +70 -8
  20. package/src/superlocalmemory/optimize/cache/semantic.py +10 -5
  21. package/src/superlocalmemory/optimize/compress/prose_llmlingua.py +1 -7
  22. package/src/superlocalmemory/optimize/compress/router.py +82 -87
  23. package/src/superlocalmemory/optimize/config/__init__.py +16 -0
  24. package/src/superlocalmemory/optimize/config/defaults.py +1 -6
  25. package/src/superlocalmemory/optimize/config/schema.py +2 -19
  26. package/src/superlocalmemory/optimize/config/store.py +15 -1
  27. package/src/superlocalmemory/optimize/metrics/counters.py +15 -7
  28. package/src/superlocalmemory/optimize/proxy/_helpers.py +100 -2
  29. package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +12 -0
  30. package/src/superlocalmemory/optimize/proxy/capture.py +243 -0
  31. package/src/superlocalmemory/optimize/proxy/gemini_surface.py +31 -0
  32. package/src/superlocalmemory/optimize/proxy/openai_surface.py +12 -0
  33. package/src/superlocalmemory/optimize/proxy/server.py +29 -0
  34. package/src/superlocalmemory/optimize/storage/db.py +102 -11
  35. package/src/superlocalmemory/optimize/storage/schema.py +11 -0
  36. package/src/superlocalmemory/server/routes/optimize.py +6 -8
  37. package/src/superlocalmemory/server/unified_daemon.py +26 -5
  38. package/src/superlocalmemory/ui/index.html +18 -14
  39. package/src/superlocalmemory/ui/js/auto-settings.js +3 -1
  40. package/src/superlocalmemory/ui/js/ng-shell.js +3 -0
  41. package/src/superlocalmemory/ui/js/optimize.js +9 -9
  42. package/src/superlocalmemory.egg-info/PKG-INFO +69 -10
  43. package/src/superlocalmemory.egg-info/SOURCES.txt +3 -2
  44. package/src/superlocalmemory.egg-info/requires.txt +1 -0
  45. package/src/superlocalmemory/optimize/compress/extractive_code.py +0 -311
  46. package/src/superlocalmemory/optimize/compress/extractive_json.py +0 -72
@@ -1,311 +0,0 @@
1
- # compress/extractive_code.py
2
- # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
3
- # Licensed under AGPL-3.0-or-later
4
- #
5
- # AST structural patterns adapted from:
6
- # headroom/compression/handlers/code_handler.py:66-138 (Apache-2.0)
7
- # Specifically: _STRUCTURAL_NODE_TYPES per-language dict, CodeLanguage enum
8
- # headroom/compression/handlers/code_handler.py:141-150 — _SIGNATURE_PATTERNS regex fallback
9
- # Attribution: See ATTRIBUTION.md.
10
-
11
- """CodeCompressor — AST-aware extractive code compressor.
12
-
13
- Supported languages: Python, JavaScript, Go, Rust, Java, C++.
14
- Path A (tree-sitter): used if tree-sitter-language-pack installed.
15
- Path B (regex fallback): used otherwise. Tests pass on both paths.
16
- """
17
-
18
- from __future__ import annotations
19
-
20
- import logging
21
- import re
22
- from dataclasses import dataclass
23
- from enum import Enum
24
-
25
- logger = logging.getLogger("slm.optimize.compress.code")
26
-
27
- _BODY_STUB_BY_LANG: dict[str, str] = {
28
- "python": " # [slm: body compressed — retrieve with ccr_id={ccr_id}]",
29
- "javascript": " // [slm: body compressed — retrieve with ccr_id={ccr_id}]",
30
- "go": " // [slm: body compressed — retrieve with ccr_id={ccr_id}]",
31
- "rust": " // [slm: body compressed — retrieve with ccr_id={ccr_id}]",
32
- "java": " // [slm: body compressed — retrieve with ccr_id={ccr_id}]",
33
- "cpp": " // [slm: body compressed — retrieve with ccr_id={ccr_id}]",
34
- }
35
- _BODY_STUB_NO_CCR_BY_LANG: dict[str, str] = {
36
- "python": " # [slm: body compressed]",
37
- "javascript": " // [slm: body compressed]",
38
- "go": " // [slm: body compressed]",
39
- "rust": " // [slm: body compressed]",
40
- "java": " // [slm: body compressed]",
41
- "cpp": " // [slm: body compressed]",
42
- }
43
-
44
- _MIN_BODY_LINES: int = 4
45
-
46
-
47
- class CodeLanguage(Enum):
48
- PYTHON = "python"
49
- JAVASCRIPT = "javascript"
50
- GO = "go"
51
- RUST = "rust"
52
- JAVA = "java"
53
- CPP = "cpp"
54
-
55
-
56
- @dataclass(frozen=True)
57
- class CodeSpan:
58
- start_line: int
59
- end_line: int
60
- role: str # "import" | "signature" | "body" | "class_header" | "decorator"
61
- is_structural: bool
62
-
63
-
64
- # ── Signature patterns for regex path (Path B) ────────────────────────────────
65
-
66
- _SIGNATURE_PATTERNS: dict[str, list[str]] = {
67
- "python": [
68
- r"^\s*(async\s+)?def\s+\w+\s*\([^)]*\)\s*(->\s*[^:]+)?:",
69
- r"^\s*class\s+\w+(\([^)]*\))?:",
70
- r"^\s*import\s+",
71
- r"^\s*from\s+\w+\s+import",
72
- r"^\s*@\w+",
73
- ],
74
- "javascript": [
75
- r"^\s*(async\s+)?function\s+\w+\s*\([^)]*\)",
76
- r"^\s*class\s+\w+(\s+extends\s+\w+)?",
77
- r"^\s*import\s+",
78
- r"^\s*const\s+\w+\s*=\s*(async\s+)?\(",
79
- r"^\s*export\s+(default\s+|const\s+|class\s+|function\s+)",
80
- ],
81
- "go": [
82
- r"^\s*func\s+(\(\w+\s+\*?\w+\)\s*)?\w+\s*\(",
83
- r"^\s*import\s+",
84
- r"^\s*package\s+",
85
- r"^\s*type\s+\w+\s+(struct|interface)\s*\{",
86
- ],
87
- "rust": [
88
- r"^\s*(pub\s+)?(async\s+)?fn\s+\w+",
89
- r"^\s*use\s+",
90
- r"^\s*impl\s+",
91
- r"^\s*struct\s+",
92
- r"^\s*enum\s+",
93
- r"^\s*trait\s+",
94
- ],
95
- "java": [
96
- r"^\s*(public|private|protected)\s+(static\s+)?\w+\s+\w+\s*\(",
97
- r"^\s*import\s+",
98
- r"^\s*(public|private|protected)?\s*class\s+\w+",
99
- ],
100
- "cpp": [
101
- r"^\s*\w[\w\s\*&:<,>]*\s+\w+\s*\([^)]*\)\s*(const\s*)?\{",
102
- r"^\s*#include\s+",
103
- r"^\s*(class|struct)\s+\w+",
104
- ],
105
- }
106
-
107
-
108
- class CodeCompressor:
109
- """AST-aware extractive code compressor. Thread-safe (no mutable state)."""
110
-
111
- def compress(self, code: str, language: str, ccr_id: str = "") -> str:
112
- try:
113
- lang = CodeLanguage(language)
114
- except ValueError:
115
- logger.warning("CodeCompressor: unknown language %r — passthrough", language)
116
- return code
117
-
118
- try:
119
- if _tree_sitter_available():
120
- return self._compress_with_tree_sitter(code, lang, ccr_id)
121
- else:
122
- return self._compress_with_regex(code, lang, ccr_id)
123
- except Exception as exc:
124
- logger.warning("CodeCompressor.compress failed — passthrough: %s", exc)
125
- return code
126
-
127
- def _compress_with_tree_sitter(self, code: str, lang: CodeLanguage, ccr_id: str) -> str:
128
- from tree_sitter_language_pack import get_parser # type: ignore[import]
129
- parser = get_parser(lang.value)
130
- tree = parser.parse(code.encode())
131
- lines = code.split("\n")
132
- spans = _collect_spans_tree_sitter(tree.root_node, lang)
133
- return _apply_spans(lines, spans, ccr_id, lang.value)
134
-
135
- def _compress_with_regex(self, code: str, lang: CodeLanguage, ccr_id: str) -> str:
136
- lines = code.split("\n")
137
- spans = _collect_spans_regex(lines, lang)
138
- return _apply_spans(lines, spans, ccr_id, lang.value)
139
-
140
-
141
- # ── Span collection ───────────────────────────────────────────────────────────
142
-
143
- def _collect_spans_tree_sitter(root_node: object, lang: CodeLanguage) -> list[CodeSpan]:
144
- _STRUCTURAL_TYPES: dict[str, set[str]] = {
145
- "python": {"import_statement", "import_from_statement", "function_definition",
146
- "class_definition", "decorated_definition", "type_alias_statement"},
147
- "javascript": {"import_statement", "export_statement", "function_declaration",
148
- "class_declaration", "method_definition", "arrow_function"},
149
- "go": {"import_declaration", "function_declaration", "method_declaration",
150
- "type_declaration", "interface_type"},
151
- "rust": {"use_declaration", "function_item", "impl_item", "struct_item",
152
- "enum_item", "trait_item"},
153
- "java": {"import_declaration", "class_declaration", "method_declaration",
154
- "interface_declaration", "annotation"},
155
- "cpp": {"function_definition", "preproc_include", "class_specifier"},
156
- }
157
- structural = _STRUCTURAL_TYPES.get(lang.value, set())
158
- spans: list[CodeSpan] = []
159
-
160
- def _walk(node: object, depth: int = 0) -> None:
161
- start_row: int = getattr(node, "start_point", (0, 0))[0]
162
- end_row: int = getattr(node, "end_point", (0, 0))[0]
163
- node_type: str = getattr(node, "type", "")
164
- is_struct = node_type in structural
165
-
166
- if is_struct and node_type in {
167
- "function_definition", "method_definition", "function_declaration",
168
- "function_item", "method_declaration",
169
- }:
170
- body_node = _find_child(node, "block") or _find_child(node, "body")
171
- if body_node is not None:
172
- body_start = getattr(body_node, "start_point", (0, 0))[0]
173
- sig_end = body_start - 1
174
- if sig_end > start_row:
175
- spans.append(CodeSpan(start_row, sig_end, "signature", True))
176
- spans.append(CodeSpan(body_start, end_row, "body", False))
177
- else:
178
- spans.append(CodeSpan(start_row, end_row, "signature", True))
179
- elif is_struct and node_type in {"decorated_definition"}:
180
- def_node = _find_child(node, "function_definition") or _find_child(node, "class_definition")
181
- if def_node is not None:
182
- def_start = getattr(def_node, "start_point", (0, 0))[0]
183
- spans.append(CodeSpan(start_row, def_start - 1, "decorator", True))
184
- _walk(def_node, depth + 1)
185
- else:
186
- spans.append(CodeSpan(start_row, end_row, node_type, True))
187
- elif is_struct:
188
- spans.append(CodeSpan(start_row, end_row, "signature", True))
189
- else:
190
- children = getattr(node, "children", None)
191
- if children is not None:
192
- has_named = False
193
- for child in children:
194
- if getattr(child, "is_named", False):
195
- has_named = True
196
- _walk(child, depth + 1)
197
- if not has_named:
198
- spans.append(CodeSpan(start_row, end_row, "body", False))
199
-
200
- _walk(root_node)
201
- return spans
202
-
203
-
204
- def _find_child(node: object, child_type: str) -> object | None:
205
- children = getattr(node, "children", None)
206
- if children is None:
207
- return None
208
- for child in children:
209
- if hasattr(child, "type") and child.type == child_type:
210
- return child
211
- return None
212
-
213
-
214
- def _collect_spans_regex(lines: list[str], lang: CodeLanguage) -> list[CodeSpan]:
215
- patterns = _SIGNATURE_PATTERNS.get(lang.value, [])
216
- spans: list[CodeSpan] = []
217
- i = 0
218
- n = len(lines)
219
-
220
- while i < n:
221
- line = lines[i]
222
- matched = False
223
- for pat in patterns:
224
- if re.search(pat, line):
225
- body_start = i + 1
226
- body_end = body_start
227
- while body_end < n and (
228
- lines[body_end].startswith((" ", "\t", "", "#", "//", "/*", "*/", "{"))
229
- or re.match(r"^\s*$", lines[body_end])
230
- ):
231
- if re.match(r"^\s*($|#|//|/\*|\*/|\*|}|\)|\])", lines[body_end]):
232
- body_end += 1
233
- else:
234
- break
235
- body_len = body_end - body_start
236
- if body_len >= _MIN_BODY_LINES and _looks_like_body(lines, body_start, body_end):
237
- spans.append(CodeSpan(i, i, "signature", True))
238
- spans.append(CodeSpan(body_start, body_end, "body", False))
239
- i = body_end
240
- matched = True
241
- break
242
- else:
243
- body_start = body_end
244
- # else: pattern didn't match
245
- if not matched:
246
- i += 1
247
- return spans
248
-
249
-
250
- def _looks_like_body(lines: list[str], start: int, end: int) -> bool:
251
- body_lines = [l for l in lines[start:end] if l.strip() and not l.strip().startswith(("#", "//"))]
252
- return len(body_lines) >= _MIN_BODY_LINES
253
-
254
-
255
- def _apply_spans(
256
- lines: list[str],
257
- spans: list[CodeSpan],
258
- ccr_id: str,
259
- lang: str = "python",
260
- ) -> str:
261
- if not spans:
262
- return "\n".join(lines)
263
-
264
- stub_tmpl = _BODY_STUB_BY_LANG.get(lang, _BODY_STUB_BY_LANG["python"])
265
- stub_no_ccr = _BODY_STUB_NO_CCR_BY_LANG.get(lang, _BODY_STUB_NO_CCR_BY_LANG["python"])
266
- stub = stub_tmpl.format(ccr_id=ccr_id) if ccr_id else stub_no_ccr
267
-
268
- sorted_spans = sorted(spans, key=lambda s: s.start_line)
269
- start_set = set()
270
- deduped: list[CodeSpan] = []
271
- for s in sorted_spans:
272
- if s.start_line not in start_set:
273
- deduped.append(s)
274
- start_set.add(s.start_line)
275
-
276
- span_by_start: dict[int, CodeSpan] = {s.start_line: s for s in deduped}
277
-
278
- result_lines: list[str] = []
279
- i = 0
280
- n = len(lines)
281
-
282
- while i < n:
283
- span = span_by_start.get(i)
284
- if span is not None and not span.is_structural:
285
- end = min(span.end_line, n - 1)
286
- body_len = end - i + 1
287
- if body_len >= _MIN_BODY_LINES:
288
- result_lines.append(stub)
289
- i = end + 1
290
- else:
291
- for j in range(i, end + 1):
292
- result_lines.append(lines[j])
293
- i = end + 1
294
- elif span is not None and span.is_structural:
295
- end = min(span.end_line, n - 1)
296
- for j in range(i, end + 1):
297
- result_lines.append(lines[j])
298
- i = end + 1
299
- else:
300
- result_lines.append(lines[i])
301
- i += 1
302
-
303
- return "\n".join(result_lines)
304
-
305
-
306
- def _tree_sitter_available() -> bool:
307
- try:
308
- import tree_sitter_language_pack # noqa: F401
309
- return True
310
- except ImportError:
311
- return False
@@ -1,72 +0,0 @@
1
- # compress/extractive_json.py
2
- # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
3
- # Licensed under AGPL-3.0-or-later
4
- #
5
- # Structural masking pattern adapted from:
6
- # headroom/compression/handlers/json_handler.py (Apache-2.0, Headroom contributors)
7
- # Specifically: JSONStructureHandler._extract_mask(), JSONToken, JSONTokenType
8
- # Attribution: See ATTRIBUTION.md.
9
- #
10
- # HARD RULE: This compressor MUST NEVER prune or reorder JSON keys.
11
- # Keys pruned = structured semantics corrupted non-recoverably. Not configurable.
12
-
13
- """JSONCompressor — lossless-ish extractive JSON compressor."""
14
-
15
- from __future__ import annotations
16
-
17
- import json
18
- import logging
19
- from typing import Any
20
-
21
- logger = logging.getLogger("slm.optimize.compress.json")
22
-
23
- VALUE_TRUNCATE_CHARS: int = 120
24
- VALUE_TRUNCATE_SUFFIX: str = "\u2026" # ellipsis
25
- MAX_ARRAY_ITEMS_SHOWN: int = 5
26
- ARRAY_REMAINDER_KEY: str = "__slm_omitted__"
27
- MIN_VALUE_LEN_TO_TRUNCATE: int = 40
28
-
29
-
30
- class JSONCompressor:
31
- """Lossless-ish JSON compressor. Thread-safe (no mutable state)."""
32
-
33
- def compress(self, parsed: Any) -> str:
34
- try:
35
- masked = self._mask(parsed, depth=0)
36
- return json.dumps(masked, ensure_ascii=False, separators=(",", ":"))
37
- except Exception as exc:
38
- logger.warning("JSONCompressor.compress failed — returning original: %s", exc)
39
- return json.dumps(parsed, ensure_ascii=False, separators=(",", ":"))
40
-
41
- def _mask(self, obj: Any, depth: int) -> Any:
42
- if isinstance(obj, dict):
43
- return {k: self._mask(v, depth + 1) for k, v in obj.items()}
44
- if isinstance(obj, list):
45
- return self._mask_array(obj, depth)
46
- if isinstance(obj, str):
47
- return self._mask_string(obj)
48
- return obj
49
-
50
- def _mask_array(self, arr: list, depth: int) -> list:
51
- if len(arr) <= MAX_ARRAY_ITEMS_SHOWN:
52
- return [self._mask(item, depth + 1) for item in arr]
53
- shown = [self._mask(item, depth + 1) for item in arr[:MAX_ARRAY_ITEMS_SHOWN]]
54
- collision = any(
55
- isinstance(item, dict) and ARRAY_REMAINDER_KEY in item
56
- for item in arr
57
- )
58
- if collision:
59
- logger.warning(
60
- "JSONCompressor: input contains reserved key %r — skipping array sentinel",
61
- ARRAY_REMAINDER_KEY,
62
- )
63
- else:
64
- shown.append({ARRAY_REMAINDER_KEY: len(arr) - MAX_ARRAY_ITEMS_SHOWN})
65
- return shown
66
-
67
- def _mask_string(self, s: str) -> str:
68
- if len(s) < MIN_VALUE_LEN_TO_TRUNCATE:
69
- return s
70
- if len(s) <= VALUE_TRUNCATE_CHARS:
71
- return s
72
- return s[:VALUE_TRUNCATE_CHARS] + VALUE_TRUNCATE_SUFFIX