algo-cli-runtime 0.14.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 (237) hide show
  1. algo_cli/__init__.py +3 -0
  2. algo_cli/__main__.py +7 -0
  3. algo_cli/_internal/__init__.py +12 -0
  4. algo_cli/_internal/policy_chain.py +259 -0
  5. algo_cli/action_registry.py +1047 -0
  6. algo_cli/agent_blocks.py +550 -0
  7. algo_cli/agent_pipeline.py +1457 -0
  8. algo_cli/agent_threads.py +308 -0
  9. algo_cli/animations.py +316 -0
  10. algo_cli/cache_admission.py +209 -0
  11. algo_cli/capability_mask.py +66 -0
  12. algo_cli/chat_protocol.py +116 -0
  13. algo_cli/chatgpt_auth.py +510 -0
  14. algo_cli/chatgpt_client.py +657 -0
  15. algo_cli/code_rag.py +479 -0
  16. algo_cli/config.py +651 -0
  17. algo_cli/context_budget.py +679 -0
  18. algo_cli/credential_helpers.py +315 -0
  19. algo_cli/deliberation.py +29 -0
  20. algo_cli/display.py +1470 -0
  21. algo_cli/evals/__init__.py +21 -0
  22. algo_cli/evals/algorithm_effectiveness.py +560 -0
  23. algo_cli/evals/competitive_harness_rating.py +702 -0
  24. algo_cli/evals/cot_quality.py +220 -0
  25. algo_cli/evals/harness_retrieval_benchmark.py +401 -0
  26. algo_cli/evals/performance_regression.py +136 -0
  27. algo_cli/evals/scorecard_grading.py +308 -0
  28. algo_cli/evals/session_distribution.py +84 -0
  29. algo_cli/execution_guardrails.py +806 -0
  30. algo_cli/extensions_manifest.py +84 -0
  31. algo_cli/git_evidence.py +227 -0
  32. algo_cli/google_workspace.py +407 -0
  33. algo_cli/google_workspace_auth.py +523 -0
  34. algo_cli/harness.py +2587 -0
  35. algo_cli/identity.py +557 -0
  36. algo_cli/index_compute_lab.py +228 -0
  37. algo_cli/inference_harness.py +70 -0
  38. algo_cli/intelligence/__init__.py +1103 -0
  39. algo_cli/intelligence/acrobat_config.py +307 -0
  40. algo_cli/intelligence/acrobat_manifests.py +338 -0
  41. algo_cli/intelligence/acrobat_models.py +195 -0
  42. algo_cli/intelligence/acrobat_pipeline.py +295 -0
  43. algo_cli/intelligence/acrobat_runtime.py +302 -0
  44. algo_cli/intelligence/acrobat_security.py +261 -0
  45. algo_cli/intelligence/acrobat_workflows.py +226 -0
  46. algo_cli/intelligence/actionability.py +165 -0
  47. algo_cli/intelligence/adversarial_audit.py +136 -0
  48. algo_cli/intelligence/agent_arena.py +92 -0
  49. algo_cli/intelligence/agent_benchmark.py +236 -0
  50. algo_cli/intelligence/agent_runtime.py +171 -0
  51. algo_cli/intelligence/agents_as_tools.py +70 -0
  52. algo_cli/intelligence/artifact_binding.py +80 -0
  53. algo_cli/intelligence/autonomous_engineer.py +1976 -0
  54. algo_cli/intelligence/backpressure.py +99 -0
  55. algo_cli/intelligence/bloom_filter.py +186 -0
  56. algo_cli/intelligence/bonferroni.py +66 -0
  57. algo_cli/intelligence/boundary_compaction.py +98 -0
  58. algo_cli/intelligence/catalog_verifier.py +172 -0
  59. algo_cli/intelligence/cavecrew.py +118 -0
  60. algo_cli/intelligence/changelog.py +176 -0
  61. algo_cli/intelligence/checkpoint_resume.py +92 -0
  62. algo_cli/intelligence/circuit_breaker.py +88 -0
  63. algo_cli/intelligence/clarification_gate.py +101 -0
  64. algo_cli/intelligence/code_graph.py +180 -0
  65. algo_cli/intelligence/coderank.py +97 -0
  66. algo_cli/intelligence/consistent_hash.py +150 -0
  67. algo_cli/intelligence/consortium_synthesis.py +139 -0
  68. algo_cli/intelligence/construction/__init__.py +241 -0
  69. algo_cli/intelligence/construction/common.py +273 -0
  70. algo_cli/intelligence/construction/documents.py +496 -0
  71. algo_cli/intelligence/construction/labor_units.py +1395 -0
  72. algo_cli/intelligence/construction/payments.py +470 -0
  73. algo_cli/intelligence/construction/risk.py +784 -0
  74. algo_cli/intelligence/content_extractor.py +132 -0
  75. algo_cli/intelligence/context_adaptive.py +102 -0
  76. algo_cli/intelligence/context_ops.py +95 -0
  77. algo_cli/intelligence/count_min.py +145 -0
  78. algo_cli/intelligence/cow_state.py +103 -0
  79. algo_cli/intelligence/critic_loop.py +119 -0
  80. algo_cli/intelligence/cross_source.py +113 -0
  81. algo_cli/intelligence/daemon_mode.py +99 -0
  82. algo_cli/intelligence/dag_orchestration.py +151 -0
  83. algo_cli/intelligence/deep_research.py +155 -0
  84. algo_cli/intelligence/degenerate_detector.py +78 -0
  85. algo_cli/intelligence/delta_report.py +92 -0
  86. algo_cli/intelligence/discovery_event_log.py +92 -0
  87. algo_cli/intelligence/document_ingest.py +298 -0
  88. algo_cli/intelligence/dual_layer_validate.py +151 -0
  89. algo_cli/intelligence/echo_fidelity.py +73 -0
  90. algo_cli/intelligence/ema_tuning.py +104 -0
  91. algo_cli/intelligence/event_log.py +92 -0
  92. algo_cli/intelligence/evidence_graph.py +114 -0
  93. algo_cli/intelligence/extension_host.py +162 -0
  94. algo_cli/intelligence/extension_manifest.py +115 -0
  95. algo_cli/intelligence/falsification_suite.py +178 -0
  96. algo_cli/intelligence/finance/__init__.py +169 -0
  97. algo_cli/intelligence/finance/anomalies.py +135 -0
  98. algo_cli/intelligence/finance/ap_ar.py +351 -0
  99. algo_cli/intelligence/finance/cash.py +162 -0
  100. algo_cli/intelligence/finance/close.py +332 -0
  101. algo_cli/intelligence/finance/common.py +244 -0
  102. algo_cli/intelligence/finance/construction.py +135 -0
  103. algo_cli/intelligence/finance/controls.py +172 -0
  104. algo_cli/intelligence/finance/evidence.py +119 -0
  105. algo_cli/intelligence/finance/exceptions.py +157 -0
  106. algo_cli/intelligence/finance/reconciliations.py +254 -0
  107. algo_cli/intelligence/finance/revenue.py +109 -0
  108. algo_cli/intelligence/finance/tax.py +74 -0
  109. algo_cli/intelligence/finance/workpapers.py +111 -0
  110. algo_cli/intelligence/finding_record.py +120 -0
  111. algo_cli/intelligence/flow_dag.py +267 -0
  112. algo_cli/intelligence/gatherer.py +223 -0
  113. algo_cli/intelligence/golden_master.py +98 -0
  114. algo_cli/intelligence/graph_rag.py +195 -0
  115. algo_cli/intelligence/group_chat.py +143 -0
  116. algo_cli/intelligence/hash_dedup.py +145 -0
  117. algo_cli/intelligence/hyperloglog.py +128 -0
  118. algo_cli/intelligence/incremental_index.py +316 -0
  119. algo_cli/intelligence/index_store.py +16 -0
  120. algo_cli/intelligence/iteration_plan.py +133 -0
  121. algo_cli/intelligence/kernel_plugins.py +167 -0
  122. algo_cli/intelligence/lesson_catalog.py +135 -0
  123. algo_cli/intelligence/llm_fallback.py +169 -0
  124. algo_cli/intelligence/log2_histogram.py +267 -0
  125. algo_cli/intelligence/lsp_integration.py +147 -0
  126. algo_cli/intelligence/memory_evolution.py +117 -0
  127. algo_cli/intelligence/minhash_lsh.py +182 -0
  128. algo_cli/intelligence/multi_model_score.py +174 -0
  129. algo_cli/intelligence/multi_tier_grade.py +211 -0
  130. algo_cli/intelligence/negative_controls.py +113 -0
  131. algo_cli/intelligence/numeric_clamp.py +63 -0
  132. algo_cli/intelligence/occ_editor.py +66 -0
  133. algo_cli/intelligence/output_normalize.py +112 -0
  134. algo_cli/intelligence/parallel_delegation.py +98 -0
  135. algo_cli/intelligence/parallel_fanout.py +104 -0
  136. algo_cli/intelligence/permission_modes.py +105 -0
  137. algo_cli/intelligence/pre_push_gate.py +68 -0
  138. algo_cli/intelligence/prefetch.py +171 -0
  139. algo_cli/intelligence/process_framework.py +217 -0
  140. algo_cli/intelligence/project_graph.py +387 -0
  141. algo_cli/intelligence/query_expansion.py +146 -0
  142. algo_cli/intelligence/ralph_loop.py +117 -0
  143. algo_cli/intelligence/rate_limiter.py +153 -0
  144. algo_cli/intelligence/refactor_transaction.py +94 -0
  145. algo_cli/intelligence/research_workspace.py +108 -0
  146. algo_cli/intelligence/retraction_ledger.py +72 -0
  147. algo_cli/intelligence/saga_pattern.py +88 -0
  148. algo_cli/intelligence/session_fork.py +100 -0
  149. algo_cli/intelligence/shadow_editor.py +67 -0
  150. algo_cli/intelligence/shell_session.py +213 -0
  151. algo_cli/intelligence/source_registry.py +143 -0
  152. algo_cli/intelligence/spawn_scales.py +99 -0
  153. algo_cli/intelligence/stat_stability.py +104 -0
  154. algo_cli/intelligence/structural_validator.py +148 -0
  155. algo_cli/intelligence/subagent_spawner.py +111 -0
  156. algo_cli/intelligence/symmetric_verify.py +70 -0
  157. algo_cli/intelligence/task_classifier.py +129 -0
  158. algo_cli/intelligence/team_execution.py +122 -0
  159. algo_cli/intelligence/tiered_access.py +121 -0
  160. algo_cli/intelligence/utility_registry.py +159 -0
  161. algo_cli/intuition_engine.py +560 -0
  162. algo_cli/intuition_injector.py +82 -0
  163. algo_cli/kernels/__init__.py +5 -0
  164. algo_cli/kernels/manifest.py +763 -0
  165. algo_cli/main.py +3903 -0
  166. algo_cli/memory_candidates.py +541 -0
  167. algo_cli/memory_echo_veil.py +394 -0
  168. algo_cli/memory_runtime.py +112 -0
  169. algo_cli/model_info.py +548 -0
  170. algo_cli/model_profile.py +160 -0
  171. algo_cli/model_routing.py +74 -0
  172. algo_cli/oneshot.py +331 -0
  173. algo_cli/perf_telemetry.py +389 -0
  174. algo_cli/plugins.py +245 -0
  175. algo_cli/private_event_store.py +654 -0
  176. algo_cli/quantization/__init__.py +24 -0
  177. algo_cli/quantization/lloyd_max.py +98 -0
  178. algo_cli/quantization/turbo_quant.py +308 -0
  179. algo_cli/reasoning/__init__.py +46 -0
  180. algo_cli/reasoning/combinatorial.py +356 -0
  181. algo_cli/reasoning/graph_of_thought.py +297 -0
  182. algo_cli/reasoning/mcts.py +220 -0
  183. algo_cli/reasoning/neuro_symbolic.py +250 -0
  184. algo_cli/reasoning/react.py +246 -0
  185. algo_cli/reasoning/reflexion.py +225 -0
  186. algo_cli/reasoning/tree_of_thought.py +241 -0
  187. algo_cli/reasoning_bridge.py +150 -0
  188. algo_cli/reconciliation.py +284 -0
  189. algo_cli/reflex.py +385 -0
  190. algo_cli/resources/docs/ALGO.md +13958 -0
  191. algo_cli/resources/docs/algo-cli-algorithm-evidence-contract.md +60 -0
  192. algo_cli/resources/docs/algo-cli-execution-verification-contract.md +59 -0
  193. algo_cli/resources/docs/algo-cli-memory-lifecycle-contract.md +72 -0
  194. algo_cli/resources/docs/harness-extension-cleanup-recommendation.md +41 -0
  195. algo_cli/resources/docs/index-compute-lab-integration.md +32 -0
  196. algo_cli/resources/docs/inference-harness-loop-blueprint-2026-06.md +55 -0
  197. algo_cli/resources/docs/main-split-map.md +35 -0
  198. algo_cli/resources/docs/privacy-and-context.md +48 -0
  199. algo_cli/resources/docs/reflex-loop-v0.2.md +354 -0
  200. algo_cli/resources/skills/README.md +26 -0
  201. algo_cli/resources/skills/algo-cli.md +59 -0
  202. algo_cli/resources/skills/edit-file-precision.md +49 -0
  203. algo_cli/resources/skills/harness-search-first.md +47 -0
  204. algo_cli/resources/skills/memory-recall-ritual.md +51 -0
  205. algo_cli/resources/skills/qol-algorithms.md +224 -0
  206. algo_cli/resources/skills/smart-error-recovery.md +56 -0
  207. algo_cli/resources/skills/tool-selection-cheatsheet.md +65 -0
  208. algo_cli/retrieval_algorithms.py +127 -0
  209. algo_cli/runtime_qos.py +236 -0
  210. algo_cli/runtime_services.py +320 -0
  211. algo_cli/session_commands.py +95 -0
  212. algo_cli/session_mode.py +113 -0
  213. algo_cli/skills.py +430 -0
  214. algo_cli/slash_dispatch.py +1265 -0
  215. algo_cli/small_context.py +206 -0
  216. algo_cli/spawn_budget.py +89 -0
  217. algo_cli/task_ledger.py +84 -0
  218. algo_cli/task_router.py +197 -0
  219. algo_cli/tool_context.py +94 -0
  220. algo_cli/tool_contract.py +99 -0
  221. algo_cli/tool_policy.py +357 -0
  222. algo_cli/tool_runtime.py +647 -0
  223. algo_cli/tools.py +3056 -0
  224. algo_cli/url_scheme.py +174 -0
  225. algo_cli/verify.py +154 -0
  226. algo_cli/version_manifest.py +178 -0
  227. algo_cli/vision_screenshot_verify.py +76 -0
  228. algo_cli/workspace_resolver.py +68 -0
  229. algo_cli/x_account.py +209 -0
  230. algo_cli/xai_auth.py +374 -0
  231. algo_cli/xai_client.py +600 -0
  232. algo_cli_runtime-0.14.0.dist-info/METADATA +369 -0
  233. algo_cli_runtime-0.14.0.dist-info/RECORD +237 -0
  234. algo_cli_runtime-0.14.0.dist-info/WHEEL +4 -0
  235. algo_cli_runtime-0.14.0.dist-info/entry_points.txt +3 -0
  236. algo_cli_runtime-0.14.0.dist-info/licenses/LICENSE +21 -0
  237. ollama_cli/__init__.py +67 -0
@@ -0,0 +1,654 @@
1
+ """Bounded, private JSONL persistence for local runtime events.
2
+
3
+ The store deliberately has a small contract:
4
+
5
+ * callers append JSON objects;
6
+ * the store owns the timestamp and on-disk envelope;
7
+ * readers receive only valid, non-expired records;
8
+ * maintenance keeps the newest suffix that satisfies record and byte limits;
9
+ * readiness exposes aggregate metadata, never event content.
10
+
11
+ The implementation uses an advisory sidecar lock so cooperating processes do
12
+ not interleave appends or race an atomic compaction. A completed append is not
13
+ rolled back if the following compaction fails: the new line remains durable and
14
+ the aggregate result reports that maintenance is still required. A later
15
+ append or explicit ``compact`` call can repair the file.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import math
22
+ import os
23
+ import stat
24
+ import tempfile
25
+ import time
26
+ from collections import deque
27
+ from contextlib import contextmanager
28
+ from dataclasses import dataclass
29
+ from pathlib import Path
30
+ from typing import Any, Callable, Iterator, Mapping
31
+
32
+
33
+ STORE_SCHEMA_VERSION = 1
34
+ DEFAULT_MAX_RECORDS = 1_000
35
+ DEFAULT_MAX_BYTES = 4 * 1024 * 1024
36
+ DEFAULT_MAX_AGE_SECONDS = 30 * 24 * 60 * 60
37
+
38
+ _DIRECTORY_MODE = 0o700
39
+ _FILE_MODE = 0o600
40
+ _LOCK_RETRY_SECONDS = 0.025
41
+
42
+
43
+ class PrivateEventStoreError(RuntimeError):
44
+ """Base error for private event-store operations."""
45
+
46
+
47
+ class UnsafeStorePathError(PrivateEventStoreError):
48
+ """Raised when a store or lock path is not a regular file."""
49
+
50
+
51
+ class EventTooLargeError(ValueError):
52
+ """Raised before writing an event that cannot fit the byte limit."""
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class RetentionPolicy:
57
+ """Mandatory record, byte, and age bounds for a private event store."""
58
+
59
+ max_records: int = DEFAULT_MAX_RECORDS
60
+ max_bytes: int = DEFAULT_MAX_BYTES
61
+ max_age_seconds: float = DEFAULT_MAX_AGE_SECONDS
62
+
63
+ def __post_init__(self) -> None:
64
+ if not isinstance(self.max_records, int) or isinstance(self.max_records, bool) or self.max_records < 1:
65
+ raise ValueError("max_records must be a positive integer")
66
+ if not isinstance(self.max_bytes, int) or isinstance(self.max_bytes, bool) or self.max_bytes < 1:
67
+ raise ValueError("max_bytes must be a positive integer")
68
+ if (
69
+ not isinstance(self.max_age_seconds, (int, float))
70
+ or isinstance(self.max_age_seconds, bool)
71
+ or not math.isfinite(float(self.max_age_seconds))
72
+ or self.max_age_seconds <= 0
73
+ ):
74
+ raise ValueError("max_age_seconds must be a positive finite number")
75
+
76
+
77
+ @dataclass(frozen=True)
78
+ class StoredEvent:
79
+ """One decoded event plus its store-controlled admission timestamp."""
80
+
81
+ stored_at: float
82
+ event: dict[str, Any]
83
+
84
+
85
+ @dataclass(frozen=True)
86
+ class MaintenanceResult:
87
+ """Content-free aggregate result from append or compaction maintenance."""
88
+
89
+ stored: bool
90
+ compacted: bool
91
+ retained_records: int
92
+ retained_bytes: int
93
+ file_bytes: int
94
+ dropped_records: int
95
+ malformed_records: int
96
+ retention_satisfied: bool
97
+ error_type: str | None = None
98
+
99
+
100
+ @dataclass
101
+ class _ScanResult:
102
+ retained: deque[tuple[StoredEvent, bytes]]
103
+ file_bytes: int = 0
104
+ valid_records: int = 0
105
+ malformed_records: int = 0
106
+ expired_records: int = 0
107
+ dropped_for_bounds: int = 0
108
+ retained_bytes: int = 0
109
+
110
+ @property
111
+ def dropped_records(self) -> int:
112
+ return self.expired_records + self.dropped_for_bounds
113
+
114
+ @property
115
+ def compaction_needed(self) -> bool:
116
+ return (
117
+ self.malformed_records > 0
118
+ or self.dropped_records > 0
119
+ or self.file_bytes != self.retained_bytes
120
+ )
121
+
122
+
123
+ def _mode_is(path: Path, expected: int) -> bool | None:
124
+ """Return exact POSIX mode equality, or ``None`` where it is not meaningful."""
125
+ if os.name != "posix":
126
+ return None
127
+ try:
128
+ return stat.S_IMODE(path.stat().st_mode) == expected
129
+ except OSError:
130
+ return False
131
+
132
+
133
+ def _ensure_regular_file(path: Path) -> None:
134
+ """Reject symlinks and special files before following them for private I/O."""
135
+ try:
136
+ info = path.lstat()
137
+ except FileNotFoundError:
138
+ return
139
+ if stat.S_ISLNK(info.st_mode) or not stat.S_ISREG(info.st_mode):
140
+ raise UnsafeStorePathError("private store paths must be regular files")
141
+
142
+
143
+ def _secure_open_flags(flags: int) -> int:
144
+ flags |= getattr(os, "O_CLOEXEC", 0)
145
+ flags |= getattr(os, "O_NOFOLLOW", 0)
146
+ if os.name == "nt":
147
+ flags |= getattr(os, "O_BINARY", 0)
148
+ return flags
149
+
150
+
151
+ def _fsync_directory(path: Path) -> None:
152
+ """Best-effort directory sync after atomic publication."""
153
+ if os.name != "posix":
154
+ return
155
+ flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0)
156
+ try:
157
+ descriptor = os.open(path, flags)
158
+ except OSError:
159
+ return
160
+ try:
161
+ os.fsync(descriptor)
162
+ except OSError:
163
+ # Some otherwise valid filesystems do not support directory fsync.
164
+ pass
165
+ finally:
166
+ try:
167
+ os.close(descriptor)
168
+ except OSError:
169
+ pass
170
+
171
+
172
+ class PrivateEventStore:
173
+ """A cross-platform, lock-safe, retention-bounded private JSONL store."""
174
+
175
+ def __init__(
176
+ self,
177
+ path: Path | str,
178
+ *,
179
+ policy: RetentionPolicy | None = None,
180
+ lock_timeout_seconds: float = 10.0,
181
+ clock: Callable[[], float] = time.time,
182
+ ) -> None:
183
+ self.path = Path(path)
184
+ self.policy = policy or RetentionPolicy()
185
+ if (
186
+ isinstance(lock_timeout_seconds, bool)
187
+ or not math.isfinite(float(lock_timeout_seconds))
188
+ or lock_timeout_seconds <= 0
189
+ ):
190
+ raise ValueError("lock_timeout_seconds must be a positive finite number")
191
+ self.lock_timeout_seconds = float(lock_timeout_seconds)
192
+ self._clock = clock
193
+
194
+ @property
195
+ def lock_path(self) -> Path:
196
+ return self.path.with_suffix(self.path.suffix + ".lock")
197
+
198
+ def _ensure_private_directory(self, *, repair_permissions: bool = True) -> None:
199
+ parent = self.path.parent
200
+ parent.mkdir(mode=_DIRECTORY_MODE, parents=True, exist_ok=True)
201
+ if not parent.is_dir():
202
+ raise UnsafeStorePathError("private store parent must be a directory")
203
+ if repair_permissions and os.name == "posix":
204
+ os.chmod(parent, _DIRECTORY_MODE)
205
+
206
+ def _repair_file_mode(self, path: Path) -> None:
207
+ _ensure_regular_file(path)
208
+ if os.name == "posix" and path.exists():
209
+ os.chmod(path, _FILE_MODE)
210
+
211
+ @contextmanager
212
+ def _locked(self, *, repair_permissions: bool = True) -> Iterator[None]:
213
+ """Take an advisory lock without growing the sidecar on each use."""
214
+ self._ensure_private_directory(repair_permissions=repair_permissions)
215
+ _ensure_regular_file(self.lock_path)
216
+ descriptor = os.open(
217
+ self.lock_path,
218
+ _secure_open_flags(os.O_RDWR | os.O_CREAT),
219
+ _FILE_MODE,
220
+ )
221
+ try:
222
+ if repair_permissions and os.name == "posix":
223
+ os.fchmod(descriptor, _FILE_MODE)
224
+ # msvcrt locks a byte range and needs at least one byte to exist.
225
+ if os.fstat(descriptor).st_size == 0:
226
+ os.write(descriptor, b"\0")
227
+ os.fsync(descriptor)
228
+
229
+ deadline = time.monotonic() + self.lock_timeout_seconds
230
+ if os.name == "nt":
231
+ import msvcrt
232
+
233
+ lock_region = getattr(msvcrt, "locking")
234
+ lock_nonblocking = getattr(msvcrt, "LK_NBLCK")
235
+ unlock = getattr(msvcrt, "LK_UNLCK")
236
+ while True:
237
+ try:
238
+ os.lseek(descriptor, 0, os.SEEK_SET)
239
+ lock_region(descriptor, lock_nonblocking, 1)
240
+ break
241
+ except OSError:
242
+ if time.monotonic() >= deadline:
243
+ raise TimeoutError("timed out waiting for private event-store lock")
244
+ time.sleep(_LOCK_RETRY_SECONDS)
245
+ try:
246
+ if os.fstat(descriptor).st_size != 1:
247
+ os.ftruncate(descriptor, 1)
248
+ os.fsync(descriptor)
249
+ yield
250
+ finally:
251
+ os.lseek(descriptor, 0, os.SEEK_SET)
252
+ lock_region(descriptor, unlock, 1)
253
+ else:
254
+ import fcntl
255
+
256
+ while True:
257
+ try:
258
+ fcntl.flock(descriptor, fcntl.LOCK_EX | fcntl.LOCK_NB)
259
+ break
260
+ except BlockingIOError:
261
+ if time.monotonic() >= deadline:
262
+ raise TimeoutError("timed out waiting for private event-store lock")
263
+ time.sleep(_LOCK_RETRY_SECONDS)
264
+ try:
265
+ if os.fstat(descriptor).st_size != 1:
266
+ os.ftruncate(descriptor, 1)
267
+ os.fsync(descriptor)
268
+ yield
269
+ finally:
270
+ fcntl.flock(descriptor, fcntl.LOCK_UN)
271
+ finally:
272
+ os.close(descriptor)
273
+
274
+ def initialize(self) -> None:
275
+ """Create an empty private store and repair its directory/file modes."""
276
+ with self._locked():
277
+ self._repair_file_mode(self.path)
278
+ created = not self.path.exists()
279
+ descriptor = os.open(
280
+ self.path,
281
+ _secure_open_flags(os.O_WRONLY | os.O_APPEND | os.O_CREAT),
282
+ _FILE_MODE,
283
+ )
284
+ try:
285
+ if os.name == "posix":
286
+ os.fchmod(descriptor, _FILE_MODE)
287
+ os.fsync(descriptor)
288
+ finally:
289
+ os.close(descriptor)
290
+ if created:
291
+ _fsync_directory(self.path.parent)
292
+
293
+ def repair_permissions(self) -> None:
294
+ """Repair the store directory, data file, and lock file when present."""
295
+ with self._locked():
296
+ self._repair_file_mode(self.path)
297
+ self._repair_file_mode(self.lock_path)
298
+
299
+ @staticmethod
300
+ def _encode_event(event: Mapping[str, Any], stored_at: float) -> bytes:
301
+ envelope = {
302
+ "version": STORE_SCHEMA_VERSION,
303
+ "stored_at": stored_at,
304
+ "event": dict(event),
305
+ }
306
+ try:
307
+ text = json.dumps(
308
+ envelope,
309
+ ensure_ascii=False,
310
+ allow_nan=False,
311
+ separators=(",", ":"),
312
+ sort_keys=True,
313
+ )
314
+ except (TypeError, ValueError) as exc:
315
+ raise ValueError("event must be a finite JSON object") from exc
316
+ return text.encode("utf-8") + b"\n"
317
+
318
+ @staticmethod
319
+ def _decode_line(raw: bytes) -> StoredEvent | None:
320
+ try:
321
+ item = json.loads(raw.decode("utf-8"))
322
+ except (UnicodeDecodeError, json.JSONDecodeError):
323
+ return None
324
+ if not isinstance(item, dict) or item.get("version") != STORE_SCHEMA_VERSION:
325
+ return None
326
+ stored_at = item.get("stored_at")
327
+ event = item.get("event")
328
+ if (
329
+ isinstance(stored_at, bool)
330
+ or not isinstance(stored_at, (int, float))
331
+ or not math.isfinite(float(stored_at))
332
+ or float(stored_at) < 0
333
+ or not isinstance(event, dict)
334
+ ):
335
+ return None
336
+ return StoredEvent(stored_at=float(stored_at), event=event)
337
+
338
+ @classmethod
339
+ def _encode_stored(cls, stored: StoredEvent) -> bytes:
340
+ return cls._encode_event(stored.event, stored.stored_at)
341
+
342
+ def _scan(self, *, now: float) -> _ScanResult:
343
+ result = _ScanResult(retained=deque())
344
+ _ensure_regular_file(self.path)
345
+ try:
346
+ result.file_bytes = self.path.stat().st_size
347
+ except FileNotFoundError:
348
+ return result
349
+
350
+ cutoff = now - float(self.policy.max_age_seconds)
351
+ retained_bytes = 0
352
+ with self.path.open("rb") as handle:
353
+ for raw in handle:
354
+ if not raw.strip():
355
+ # Empty separators can safely delimit a previously torn tail.
356
+ continue
357
+ stored = self._decode_line(raw)
358
+ if stored is None:
359
+ result.malformed_records += 1
360
+ continue
361
+ result.valid_records += 1
362
+ try:
363
+ # Python's decoder accepts non-standard NaN/Infinity
364
+ # tokens. Requiring canonical finite JSON here keeps such
365
+ # externally injected lines in the malformed bucket.
366
+ encoded = self._encode_stored(stored)
367
+ except (TypeError, ValueError, RecursionError):
368
+ result.valid_records -= 1
369
+ result.malformed_records += 1
370
+ continue
371
+ if stored.stored_at < cutoff:
372
+ result.expired_records += 1
373
+ continue
374
+
375
+ result.retained.append((stored, encoded))
376
+ retained_bytes += len(encoded)
377
+ while (
378
+ len(result.retained) > self.policy.max_records
379
+ or retained_bytes > self.policy.max_bytes
380
+ ):
381
+ _discarded, discarded_bytes = result.retained.popleft()
382
+ retained_bytes -= len(discarded_bytes)
383
+ result.dropped_for_bounds += 1
384
+
385
+ result.retained_bytes = retained_bytes
386
+ return result
387
+
388
+ def _append_bytes(self, payload: bytes) -> None:
389
+ """Append all bytes and fsync; a torn failure is tolerated on next use."""
390
+ self._repair_file_mode(self.path)
391
+ created = not self.path.exists()
392
+ descriptor = os.open(
393
+ self.path,
394
+ _secure_open_flags(os.O_WRONLY | os.O_APPEND | os.O_CREAT),
395
+ _FILE_MODE,
396
+ )
397
+ try:
398
+ if os.name == "posix":
399
+ os.fchmod(descriptor, _FILE_MODE)
400
+ view = memoryview(payload)
401
+ while view:
402
+ written = os.write(descriptor, view)
403
+ if written <= 0:
404
+ raise OSError("private event-store append made no progress")
405
+ view = view[written:]
406
+ os.fsync(descriptor)
407
+ finally:
408
+ os.close(descriptor)
409
+ if created:
410
+ _fsync_directory(self.path.parent)
411
+
412
+ def _needs_separator(self) -> bool:
413
+ try:
414
+ size = self.path.stat().st_size
415
+ except FileNotFoundError:
416
+ return False
417
+ if size == 0:
418
+ return False
419
+ with self.path.open("rb") as handle:
420
+ handle.seek(-1, os.SEEK_END)
421
+ # JSONL records are LF-delimited. A lone CR may be the first half
422
+ # of a torn CRLF, so prefix LF to close it before the new record.
423
+ return handle.read(1) != b"\n"
424
+
425
+ def _atomic_replace(self, lines: Iterator[bytes]) -> None:
426
+ """Publish compacted JSONL without exposing a partially written file."""
427
+ self._ensure_private_directory()
428
+ descriptor, temporary_name = tempfile.mkstemp(
429
+ prefix=f".{self.path.name}.",
430
+ suffix=".tmp",
431
+ dir=str(self.path.parent),
432
+ )
433
+ temporary = Path(temporary_name)
434
+ try:
435
+ if os.name == "posix":
436
+ os.fchmod(descriptor, _FILE_MODE)
437
+ with os.fdopen(descriptor, "wb") as handle:
438
+ for line in lines:
439
+ handle.write(line)
440
+ handle.flush()
441
+ os.fsync(handle.fileno())
442
+ os.replace(temporary, self.path)
443
+ # The temporary inode already has the final private mode. Keep
444
+ # publication as the last fallible state transition so an error
445
+ # before replace always leaves the old file intact.
446
+ _fsync_directory(self.path.parent)
447
+ except BaseException:
448
+ try:
449
+ os.close(descriptor)
450
+ except OSError:
451
+ pass
452
+ try:
453
+ temporary.unlink()
454
+ except OSError:
455
+ pass
456
+ raise
457
+
458
+ def _maintenance_result(
459
+ self,
460
+ scan: _ScanResult,
461
+ *,
462
+ stored: bool,
463
+ compacted: bool,
464
+ error_type: str | None = None,
465
+ ) -> MaintenanceResult:
466
+ if compacted:
467
+ file_bytes = scan.retained_bytes
468
+ else:
469
+ try:
470
+ file_bytes = self.path.stat().st_size
471
+ except OSError:
472
+ file_bytes = scan.file_bytes
473
+ retention_satisfied = (
474
+ error_type is None
475
+ and len(scan.retained) <= self.policy.max_records
476
+ and scan.retained_bytes <= self.policy.max_bytes
477
+ and (compacted or not scan.compaction_needed)
478
+ )
479
+ return MaintenanceResult(
480
+ stored=stored,
481
+ compacted=compacted,
482
+ retained_records=len(scan.retained),
483
+ retained_bytes=scan.retained_bytes,
484
+ file_bytes=file_bytes,
485
+ dropped_records=scan.dropped_records,
486
+ malformed_records=scan.malformed_records,
487
+ retention_satisfied=retention_satisfied,
488
+ error_type=error_type,
489
+ )
490
+
491
+ def append(self, event: Mapping[str, Any]) -> MaintenanceResult:
492
+ """Durably append one event, then atomically enforce retention.
493
+
494
+ Serialization and single-record size validation happen before touching
495
+ the file. If append succeeds but compaction raises an ``OSError``, the
496
+ append is kept and the returned result names only the exception type.
497
+ """
498
+ if not isinstance(event, Mapping):
499
+ raise TypeError("event must be a mapping")
500
+ now = float(self._clock())
501
+ if not math.isfinite(now) or now < 0:
502
+ raise ValueError("clock must return a finite non-negative timestamp")
503
+ encoded = self._encode_event(event, now)
504
+ if len(encoded) > self.policy.max_bytes:
505
+ raise EventTooLargeError("encoded event exceeds private store max_bytes")
506
+
507
+ with self._locked():
508
+ # Delimit an old torn tail so this complete event remains recoverable.
509
+ payload = (b"\n" if self._needs_separator() else b"") + encoded
510
+ self._append_bytes(payload)
511
+ scan = self._scan(now=now)
512
+ if not scan.compaction_needed:
513
+ return self._maintenance_result(scan, stored=True, compacted=False)
514
+ try:
515
+ self._atomic_replace(line for _stored, line in scan.retained)
516
+ except Exception as exc:
517
+ # Do not report append failure after its fsync: that invites a
518
+ # retry and duplicate. Surface bounded, content-free state.
519
+ return self._maintenance_result(
520
+ scan,
521
+ stored=True,
522
+ compacted=False,
523
+ error_type=type(exc).__name__,
524
+ )
525
+ return self._maintenance_result(scan, stored=True, compacted=True)
526
+
527
+ def compact(self) -> MaintenanceResult:
528
+ """Atomically remove malformed, expired, and out-of-bound records."""
529
+ now = float(self._clock())
530
+ if not math.isfinite(now) or now < 0:
531
+ raise ValueError("clock must return a finite non-negative timestamp")
532
+ with self._locked():
533
+ self._repair_file_mode(self.path)
534
+ scan = self._scan(now=now)
535
+ if not scan.compaction_needed:
536
+ return self._maintenance_result(scan, stored=False, compacted=False)
537
+ self._atomic_replace(line for _stored, line in scan.retained)
538
+ return self._maintenance_result(scan, stored=False, compacted=True)
539
+
540
+ def read_records(self, *, limit: int | None = None) -> list[StoredEvent]:
541
+ """Read the valid retained suffix without returning malformed content."""
542
+ if limit is not None and (
543
+ not isinstance(limit, int) or isinstance(limit, bool) or limit < 0
544
+ ):
545
+ raise ValueError("limit must be a non-negative integer or None")
546
+ if limit == 0:
547
+ return []
548
+ now = float(self._clock())
549
+ if not math.isfinite(now) or now < 0:
550
+ raise ValueError("clock must return a finite non-negative timestamp")
551
+ with self._locked():
552
+ self._repair_file_mode(self.path)
553
+ scan = self._scan(now=now)
554
+ records = [stored for stored, _line in scan.retained]
555
+ if limit is not None:
556
+ return records[-limit:]
557
+ return records
558
+
559
+ def read_events(self, *, limit: int | None = None) -> list[dict[str, Any]]:
560
+ """Convenience view returning event objects without store metadata."""
561
+ return [record.event for record in self.read_records(limit=limit)]
562
+
563
+ def readiness(self, *, repair_permissions: bool = True) -> dict[str, Any]:
564
+ """Return content-free aggregate health and retention metadata.
565
+
566
+ Permission repair is enabled by default because broad permissions on a
567
+ private store are a live safety defect. No data file is created merely
568
+ by checking readiness; the private directory and lock sidecar may be.
569
+ """
570
+ base: dict[str, Any] = {
571
+ "schema_version": STORE_SCHEMA_VERSION,
572
+ "initialized": False,
573
+ "records": 0,
574
+ "retained_records": 0,
575
+ "file_bytes": 0,
576
+ "retained_bytes": 0,
577
+ "malformed_records": 0,
578
+ "expired_records": 0,
579
+ "dropped_for_bounds": 0,
580
+ "compaction_needed": False,
581
+ "permissions_enforced": os.name == "posix",
582
+ "directory_private": None,
583
+ "file_private": None,
584
+ "lock_private": None,
585
+ "limits": {
586
+ "max_records": self.policy.max_records,
587
+ "max_bytes": self.policy.max_bytes,
588
+ "max_age_seconds": self.policy.max_age_seconds,
589
+ },
590
+ "error_type": None,
591
+ }
592
+ try:
593
+ if repair_permissions:
594
+ self._ensure_private_directory()
595
+ elif not self.path.parent.exists():
596
+ return {**base, "status": "empty"}
597
+
598
+ with self._locked(repair_permissions=repair_permissions):
599
+ if repair_permissions:
600
+ self._repair_file_mode(self.path)
601
+ self._repair_file_mode(self.lock_path)
602
+ now = float(self._clock())
603
+ if not math.isfinite(now) or now < 0:
604
+ raise ValueError("clock must return a finite non-negative timestamp")
605
+ scan = self._scan(now=now)
606
+
607
+ initialized = self.path.exists()
608
+ directory_private = _mode_is(self.path.parent, _DIRECTORY_MODE)
609
+ file_private = _mode_is(self.path, _FILE_MODE) if initialized else None
610
+ lock_private = _mode_is(self.lock_path, _FILE_MODE)
611
+ permission_problem = os.name == "posix" and (
612
+ directory_private is not True
613
+ or lock_private is not True
614
+ or (initialized and file_private is not True)
615
+ )
616
+ degraded = scan.compaction_needed or permission_problem
617
+ status = "degraded" if degraded else ("ready" if initialized else "empty")
618
+ return {
619
+ **base,
620
+ "status": status,
621
+ "initialized": initialized,
622
+ "records": scan.valid_records,
623
+ "retained_records": len(scan.retained),
624
+ "file_bytes": scan.file_bytes,
625
+ "retained_bytes": scan.retained_bytes,
626
+ "malformed_records": scan.malformed_records,
627
+ "expired_records": scan.expired_records,
628
+ "dropped_for_bounds": scan.dropped_for_bounds,
629
+ "compaction_needed": scan.compaction_needed,
630
+ "directory_private": directory_private,
631
+ "file_private": file_private,
632
+ "lock_private": lock_private,
633
+ }
634
+ except Exception as exc:
635
+ return {
636
+ **base,
637
+ "status": "error",
638
+ "error_type": type(exc).__name__,
639
+ }
640
+
641
+
642
+ __all__ = [
643
+ "DEFAULT_MAX_AGE_SECONDS",
644
+ "DEFAULT_MAX_BYTES",
645
+ "DEFAULT_MAX_RECORDS",
646
+ "EventTooLargeError",
647
+ "MaintenanceResult",
648
+ "PrivateEventStore",
649
+ "PrivateEventStoreError",
650
+ "RetentionPolicy",
651
+ "STORE_SCHEMA_VERSION",
652
+ "StoredEvent",
653
+ "UnsafeStorePathError",
654
+ ]
@@ -0,0 +1,24 @@
1
+ """TurboQuant-inspired vector quantization for agent memory and RAG compression.
2
+
3
+ Implements PolarQuant/TurboQuant-MSE (random rotation + optimal scalar quantization)
4
+ and QJL residual correction for inner-product preservation, based on arXiv:2504.19874.
5
+
6
+ Local-first: uses NumPy for all operations. No external ML frameworks required.
7
+ TurboVec (Rust-accelerated) is used when available for production throughput.
8
+ """
9
+
10
+ from .turbo_quant import TurboQuantMSE, TurboQuantIP
11
+ from .lloyd_max import precompute_codebook, beta_distribution_pdf
12
+
13
+ # High-level API
14
+ from .turbo_quant import create_vector_index, compress_embeddings, decompress_embeddings
15
+
16
+ __all__ = [
17
+ "TurboQuantMSE",
18
+ "TurboQuantIP",
19
+ "precompute_codebook",
20
+ "beta_distribution_pdf",
21
+ "create_vector_index",
22
+ "compress_embeddings",
23
+ "decompress_embeddings",
24
+ ]