superlocalmemory 3.5.8 → 3.6.0

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 (72) hide show
  1. package/ATTRIBUTION.md +24 -0
  2. package/CHANGELOG.md +35 -0
  3. package/README.md +142 -35
  4. package/package.json +1 -1
  5. package/pyproject.toml +2 -1
  6. package/src/superlocalmemory/__init__.py +1 -1
  7. package/src/superlocalmemory/cli/cache_cmd.py +198 -0
  8. package/src/superlocalmemory/cli/commands.py +80 -2
  9. package/src/superlocalmemory/cli/compress_cmd.py +179 -0
  10. package/src/superlocalmemory/cli/help_cmd.py +197 -0
  11. package/src/superlocalmemory/cli/main.py +122 -0
  12. package/src/superlocalmemory/cli/optimize_cmd.py +175 -0
  13. package/src/superlocalmemory/cli/optimize_constants.py +31 -0
  14. package/src/superlocalmemory/cli/proxy_cmd.py +95 -0
  15. package/src/superlocalmemory/core/config.py +5 -0
  16. package/src/superlocalmemory/core/engine.py +23 -0
  17. package/src/superlocalmemory/core/mcp_embedder_proxy.py +89 -0
  18. package/src/superlocalmemory/llm/backbone.py +10 -4
  19. package/src/superlocalmemory/mcp/server.py +34 -0
  20. package/src/superlocalmemory/mcp/tools_v3.py +6 -2
  21. package/src/superlocalmemory/optimize/NOTICE +11 -0
  22. package/src/superlocalmemory/optimize/__init__.py +0 -0
  23. package/src/superlocalmemory/optimize/adapters/__init__.py +68 -0
  24. package/src/superlocalmemory/optimize/adapters/_agent_registry.py +120 -0
  25. package/src/superlocalmemory/optimize/adapters/anthropic_adapter.py +115 -0
  26. package/src/superlocalmemory/optimize/adapters/openai_adapter.py +125 -0
  27. package/src/superlocalmemory/optimize/adapters/wrap.py +188 -0
  28. package/src/superlocalmemory/optimize/cache/__init__.py +31 -0
  29. package/src/superlocalmemory/optimize/cache/boundary_store.py +455 -0
  30. package/src/superlocalmemory/optimize/cache/centroid_store.py +158 -0
  31. package/src/superlocalmemory/optimize/cache/context_key.py +67 -0
  32. package/src/superlocalmemory/optimize/cache/exact.py +85 -0
  33. package/src/superlocalmemory/optimize/cache/invalidation.py +36 -0
  34. package/src/superlocalmemory/optimize/cache/key_builder.py +98 -0
  35. package/src/superlocalmemory/optimize/cache/manager.py +452 -0
  36. package/src/superlocalmemory/optimize/cache/semantic.py +568 -0
  37. package/src/superlocalmemory/optimize/cache/stampede.py +50 -0
  38. package/src/superlocalmemory/optimize/compress/__init__.py +17 -0
  39. package/src/superlocalmemory/optimize/compress/align.py +153 -0
  40. package/src/superlocalmemory/optimize/compress/ccr.py +157 -0
  41. package/src/superlocalmemory/optimize/compress/extractive_code.py +311 -0
  42. package/src/superlocalmemory/optimize/compress/extractive_json.py +72 -0
  43. package/src/superlocalmemory/optimize/compress/prose_llmlingua.py +77 -0
  44. package/src/superlocalmemory/optimize/compress/router.py +548 -0
  45. package/src/superlocalmemory/optimize/config/__init__.py +35 -0
  46. package/src/superlocalmemory/optimize/config/defaults.py +48 -0
  47. package/src/superlocalmemory/optimize/config/schema.py +255 -0
  48. package/src/superlocalmemory/optimize/config/store.py +209 -0
  49. package/src/superlocalmemory/optimize/metrics/__init__.py +8 -0
  50. package/src/superlocalmemory/optimize/metrics/counters.py +138 -0
  51. package/src/superlocalmemory/optimize/metrics/estimator.py +90 -0
  52. package/src/superlocalmemory/optimize/metrics/exporters.py +77 -0
  53. package/src/superlocalmemory/optimize/metrics/persistence.py +115 -0
  54. package/src/superlocalmemory/optimize/proxy/__init__.py +28 -0
  55. package/src/superlocalmemory/optimize/proxy/_helpers.py +257 -0
  56. package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +171 -0
  57. package/src/superlocalmemory/optimize/proxy/gemini_surface.py +121 -0
  58. package/src/superlocalmemory/optimize/proxy/lifecycle.py +126 -0
  59. package/src/superlocalmemory/optimize/proxy/openai_surface.py +125 -0
  60. package/src/superlocalmemory/optimize/proxy/server.py +151 -0
  61. package/src/superlocalmemory/optimize/storage/__init__.py +0 -0
  62. package/src/superlocalmemory/optimize/storage/db.py +1016 -0
  63. package/src/superlocalmemory/optimize/storage/schema.py +184 -0
  64. package/src/superlocalmemory/server/routes/optimize.py +166 -0
  65. package/src/superlocalmemory/server/routes/v3_api.py +63 -1
  66. package/src/superlocalmemory/server/unified_daemon.py +105 -0
  67. package/src/superlocalmemory/ui/index.html +98 -0
  68. package/src/superlocalmemory/ui/js/ng-shell.js +2 -1
  69. package/src/superlocalmemory/ui/js/optimize.js +173 -0
  70. package/src/superlocalmemory.egg-info/PKG-INFO +2 -1
  71. package/src/superlocalmemory.egg-info/SOURCES.txt +51 -0
  72. package/src/superlocalmemory.egg-info/requires.txt +1 -0
@@ -0,0 +1,153 @@
1
+ # compress/align.py
2
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
3
+ # Licensed under AGPL-3.0-or-later
4
+ #
5
+ # Volatile-detection algorithm adapted from:
6
+ # headroom/transforms/cache_aligner.py (Apache-2.0, Headroom contributors)
7
+ # Specifically: _is_uuid(), _is_iso8601(), _is_jwt_shape(), _is_hex_hash(),
8
+ # _classify_token(), _split_tokens(), detect_volatile_content()
9
+ # Lines: cache_aligner.py:76-200
10
+ # Attribution: See ATTRIBUTION.md.
11
+
12
+ """CacheAligner — volatile-token detector for system prompt prefix stability.
13
+
14
+ Phase 2: Detection only. No mutation of the system prompt.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import base64
20
+ import binascii
21
+ import logging
22
+ import uuid as _uuid
23
+ from dataclasses import dataclass, field
24
+ from datetime import datetime
25
+
26
+ logger = logging.getLogger("slm.optimize.compress.align")
27
+
28
+ _HEX_HASH_LENGTHS = frozenset({32, 40, 64})
29
+ _UUID_CANONICAL_LEN = 36 # L-02: 36 chars INCLUDING 4 dashes (RFC 4122 canonical form: 8-4-4-4-12)
30
+ _JWT_SEGMENT_COUNT = 3
31
+ _JWT_MIN_SEGMENT_BYTES = 4
32
+
33
+ _LABEL_UUID = "uuid"
34
+ _LABEL_ISO8601 = "iso8601"
35
+ _LABEL_JWT = "jwt"
36
+ _LABEL_HEX_HASH = "hex_hash"
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class VolatileFinding:
41
+ label: str
42
+ sample: str
43
+
44
+
45
+ @dataclass
46
+ class AlignResult:
47
+ prefix_stable: bool = True
48
+ stability_score: float = 1.0
49
+ findings: list[VolatileFinding] = field(default_factory=list)
50
+ total_tokens_scanned: int = 0
51
+
52
+
53
+ class CacheAligner:
54
+ """Detects volatile tokens in system prompts. No mutation. Thread-safe."""
55
+
56
+ def detect(self, system_prompt: str) -> AlignResult:
57
+ try:
58
+ return _detect(system_prompt)
59
+ except Exception as exc:
60
+ logger.debug("CacheAligner.detect failed (non-fatal): %s", exc)
61
+ return AlignResult()
62
+
63
+
64
+ def _detect(text: str) -> AlignResult:
65
+ tokens = _split_tokens(text)
66
+ findings: list[VolatileFinding] = []
67
+ volatile_count = 0
68
+
69
+ for token in tokens:
70
+ label = _classify_token(token)
71
+ if label is not None:
72
+ volatile_count += 1
73
+ if len(findings) < 20:
74
+ findings.append(VolatileFinding(label=label, sample=token[:20]))
75
+
76
+ total = len(tokens)
77
+ score = 1.0 - (volatile_count / total) if total > 0 else 1.0
78
+
79
+ return AlignResult(
80
+ prefix_stable=(volatile_count == 0),
81
+ stability_score=round(score, 4),
82
+ findings=findings,
83
+ total_tokens_scanned=total,
84
+ )
85
+
86
+
87
+ def _split_tokens(content: str) -> list[str]:
88
+ if not content:
89
+ return []
90
+ tokens: list[str] = []
91
+ for raw in content.split():
92
+ cleaned = raw.strip(".,;:!?\"'()[]{}<>`|\\")
93
+ if cleaned:
94
+ tokens.append(cleaned)
95
+ return tokens
96
+
97
+
98
+ def _classify_token(token: str) -> str | None:
99
+ if _is_uuid(token):
100
+ return _LABEL_UUID
101
+ if "." in token and _is_jwt_shape(token):
102
+ return _LABEL_JWT
103
+ if _is_iso8601(token):
104
+ return _LABEL_ISO8601
105
+ if _is_hex_hash(token):
106
+ return _LABEL_HEX_HASH
107
+ return None
108
+
109
+
110
+ def _is_uuid(token: str) -> bool:
111
+ if len(token) != _UUID_CANONICAL_LEN or token.count("-") != 4:
112
+ return False
113
+ try:
114
+ _uuid.UUID(token)
115
+ except (ValueError, AttributeError):
116
+ return False
117
+ return True
118
+
119
+
120
+ def _is_iso8601(token: str) -> bool:
121
+ if len(token) < 8 or ("T" not in token and "-" not in token):
122
+ return False
123
+ candidate = token[:-1] + "+00:00" if token.endswith("Z") else token
124
+ try:
125
+ datetime.fromisoformat(candidate)
126
+ except (ValueError, TypeError):
127
+ return False
128
+ return True
129
+
130
+
131
+ def _is_jwt_shape(token: str) -> bool:
132
+ if token.count(".") != _JWT_SEGMENT_COUNT - 1:
133
+ return False
134
+ segments = token.split(".")
135
+ for seg in segments:
136
+ if len(seg) < _JWT_MIN_SEGMENT_BYTES:
137
+ return False
138
+ padded = seg + "=" * (-len(seg) % 4)
139
+ try:
140
+ base64.urlsafe_b64decode(padded.encode("ascii"))
141
+ except (binascii.Error, ValueError, UnicodeEncodeError):
142
+ return False
143
+ return True
144
+
145
+
146
+ def _is_hex_hash(token: str) -> bool:
147
+ if len(token) not in _HEX_HASH_LENGTHS:
148
+ return False
149
+ try:
150
+ int(token, 16)
151
+ except ValueError:
152
+ return False
153
+ return True
@@ -0,0 +1,157 @@
1
+ # compress/ccr.py
2
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
3
+ # Licensed under AGPL-3.0-or-later
4
+ #
5
+ # CCR (Compressed Context Retrieval) concept and pattern:
6
+ # headroom/ccr/ package (Apache-2.0, Headroom contributors)
7
+ # Specifically: batch_store.py (BatchContext dataclass, TTL pattern),
8
+ # tool_injection.py (MCP tool injection pattern)
9
+ # Attribution: See ATTRIBUTION.md.
10
+ # Storage: llmcache_ccr table defined in INTERFACE-CONTRACT §1.
11
+ # Database access: CacheDB.ccr_put() and CacheDB.ccr_get() per INTERFACE-CONTRACT §1.
12
+
13
+ """CCRStore — stores pre-compression originals, provides retrieval tool."""
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import re
19
+ import threading
20
+
21
+ logger = logging.getLogger("slm.optimize.compress.ccr")
22
+
23
+ # SEC-C-04: UUID4 format validator — only ^UUID4^ values pass
24
+ _UUID4_RE = re.compile(
25
+ r'^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
26
+ )
27
+
28
+
29
+ class CCRStore:
30
+ """Stores compression originals and retrieves them by ccr_id.
31
+
32
+ Thread-safe. Singleton per daemon instance.
33
+ """
34
+
35
+ _instance: "CCRStore | None" = None
36
+ _lock: threading.Lock = threading.Lock()
37
+
38
+ @classmethod
39
+ def get_instance(cls) -> "CCRStore":
40
+ if cls._instance is None:
41
+ with cls._lock:
42
+ if cls._instance is None:
43
+ cls._instance = cls()
44
+ return cls._instance
45
+
46
+ def __init__(self) -> None:
47
+ self._db: "CacheDB | None" = None
48
+
49
+ def store(
50
+ self,
51
+ original: bytes,
52
+ model: str = "",
53
+ tenant_id: str = "default",
54
+ ttl_seconds: int | None = None,
55
+ ) -> str:
56
+ """Store a pre-compression original. Returns ccr_id (UUID4) or '' on failure.
57
+
58
+ B-03: Called BEFORE compression runs.
59
+ RB-05: Only original bytes accepted; compressed bytes stored via update_compressed().
60
+ """
61
+ try:
62
+ import uuid as _uuid_mod
63
+ import time as _time_mod
64
+ ccr_id = str(_uuid_mod.uuid4())
65
+ db = self._get_db()
66
+ ttl_expires = (
67
+ _time_mod.time() + ttl_seconds
68
+ if ttl_seconds is not None
69
+ else None
70
+ )
71
+ db.ccr_put(ccr_id, original, ttl_expires=ttl_expires)
72
+ logger.debug("CCR stored ccr_id=%s orig_bytes=%d", ccr_id, len(original))
73
+ return ccr_id
74
+ except Exception as exc:
75
+ logger.warning("CCRStore.store failed (fail-open): %s", exc)
76
+ return ""
77
+
78
+ def update_compressed(self, ccr_id: str, compressed_bytes: bytes) -> None:
79
+ """Update the compressed_hash for an existing CCR row. Non-fatal if fails."""
80
+ try:
81
+ db = self._get_db()
82
+ if hasattr(db, "ccr_update_compressed"):
83
+ db.ccr_update_compressed(ccr_id, compressed_bytes)
84
+ except Exception as exc:
85
+ logger.debug("CCRStore.update_compressed failed (non-fatal): %s", exc)
86
+
87
+ def retrieve(self, ccr_id: str) -> bytes | None:
88
+ """Retrieve a CCR original by ccr_id. Returns None if not found or TTL expired."""
89
+ try:
90
+ db = self._get_db()
91
+ return db.ccr_get(ccr_id)
92
+ except Exception as exc:
93
+ logger.warning("CCRStore.retrieve failed (ccr_id=%s): %s", ccr_id, exc)
94
+ return None
95
+
96
+ def get_mcp_tool_definition(self) -> dict:
97
+ return {
98
+ "name": "headroom_retrieve",
99
+ "description": (
100
+ "Retrieve the original (pre-compression) text for a compressed content block. "
101
+ "Use this when you need the full, uncompressed version of content that was "
102
+ "compressed by SLM. Provide the ccr_id from the compression stub comment."
103
+ ),
104
+ "inputSchema": {
105
+ "type": "object",
106
+ "properties": {
107
+ "ccr_id": {
108
+ "type": "string",
109
+ "description": "The ccr_id from the compression stub comment.",
110
+ }
111
+ },
112
+ "required": ["ccr_id"],
113
+ },
114
+ }
115
+
116
+ async def handle_mcp_call(self, arguments: dict) -> dict:
117
+ ccr_id = arguments.get("ccr_id", "")
118
+ if not ccr_id:
119
+ return {
120
+ "isError": True,
121
+ "content": [{"type": "text", "text": "ccr_id is required"}],
122
+ }
123
+ if not _UUID4_RE.match(ccr_id):
124
+ return {
125
+ "isError": True,
126
+ "content": [{
127
+ "type": "text",
128
+ "text": f"ccr_id must be a UUID4, got {ccr_id!r}",
129
+ }],
130
+ }
131
+ original = self.retrieve(ccr_id)
132
+ if original is None:
133
+ return {
134
+ "isError": True,
135
+ "content": [{
136
+ "type": "text",
137
+ "text": (
138
+ f"CCR original not found for ccr_id={ccr_id!r}. "
139
+ "Possible causes: entry expired, never stored, or ccr_id incorrect."
140
+ ),
141
+ }],
142
+ }
143
+ try:
144
+ text = original.decode("utf-8")
145
+ except UnicodeDecodeError:
146
+ logger.warning(
147
+ "CCR ccr_id=%s: original bytes not valid UTF-8; falling back to latin-1",
148
+ ccr_id,
149
+ )
150
+ text = original.decode("latin-1")
151
+ return {"content": [{"type": "text", "text": text}]}
152
+
153
+ def _get_db(self) -> "CacheDB":
154
+ if self._db is None:
155
+ from superlocalmemory.optimize.storage.db import CacheDB
156
+ self._db = CacheDB()
157
+ return self._db
@@ -0,0 +1,311 @@
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
@@ -0,0 +1,72 @@
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