semvec 0.1.0a2__cp310-abi3-win_amd64.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.
- semvec/__init__.py +82 -0
- semvec/_core.pyd +0 -0
- semvec/_core.pyi +415 -0
- semvec/api/__init__.py +26 -0
- semvec/api/app.py +127 -0
- semvec/api/auth.py +153 -0
- semvec/api/cli.py +55 -0
- semvec/api/cluster_manager.py +287 -0
- semvec/api/cluster_routes.py +221 -0
- semvec/api/database.py +55 -0
- semvec/api/event_bus.py +87 -0
- semvec/api/global_observer.py +398 -0
- semvec/api/literal_cache_routes.py +107 -0
- semvec/api/metrics_export.py +77 -0
- semvec/api/models.py +132 -0
- semvec/api/network_manager.py +189 -0
- semvec/api/network_routes.py +118 -0
- semvec/api/observer_routes.py +115 -0
- semvec/api/regional_manager.py +294 -0
- semvec/api/regional_routes.py +150 -0
- semvec/api/routes.py +284 -0
- semvec/api/schemas.py +453 -0
- semvec/api/session_delta_routes.py +241 -0
- semvec/api/session_manager.py +804 -0
- semvec/audit.py +163 -0
- semvec/benchmarks/__init__.py +6 -0
- semvec/benchmarks/longmemeval/__init__.py +42 -0
- semvec/benchmarks/longmemeval/__main__.py +6 -0
- semvec/benchmarks/longmemeval/call_counter.py +95 -0
- semvec/benchmarks/longmemeval/cli.py +299 -0
- semvec/benchmarks/longmemeval/evaluator.py +298 -0
- semvec/benchmarks/longmemeval/loader.py +112 -0
- semvec/benchmarks/longmemeval/runner.py +356 -0
- semvec/benchmarks/longmemeval/schema.py +103 -0
- semvec/coding/__init__.py +43 -0
- semvec/coding/engine.py +180 -0
- semvec/coding/hooks/__init__.py +22 -0
- semvec/coding/hooks/pre_compact.py +118 -0
- semvec/coding/hooks/session_start.py +108 -0
- semvec/coding/mcp_server.py +316 -0
- semvec/coding/persistence.py +94 -0
- semvec/coding/transcript_parser.py +186 -0
- semvec/cortex/__init__.py +98 -0
- semvec/cortex/service.py +203 -0
- semvec/literal_cache.py +35 -0
- semvec/metrics.py +12 -0
- semvec/py.typed +0 -0
- semvec/token_reduction/__init__.py +93 -0
- semvec/token_reduction/chat_proxy.py +253 -0
- semvec/token_reduction/llm_client.py +170 -0
- semvec/token_reduction/phase_prompts.py +43 -0
- semvec/token_reduction/serializer.py +117 -0
- semvec/token_reduction/token_counter.py +173 -0
- semvec-0.1.0a2.dist-info/METADATA +294 -0
- semvec-0.1.0a2.dist-info/RECORD +59 -0
- semvec-0.1.0a2.dist-info/WHEEL +4 -0
- semvec-0.1.0a2.dist-info/entry_points.txt +2 -0
- semvec-0.1.0a2.dist-info/licenses/LICENSE +6 -0
- semvec-0.1.0a2.dist-info/sboms/semvec.cyclonedx.json +4101 -0
semvec/__init__.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Semvec — patent-pending persistent semantic state engine.
|
|
2
|
+
|
|
3
|
+
The public surface is PEP-8 compliant PascalCase. Legacy PSS-prefixed
|
|
4
|
+
names (``PSS_State_V4``, ``PSSConfig``, ``PSSError``) remain importable
|
|
5
|
+
as deprecated aliases — accessing them raises :class:`DeprecationWarning`.
|
|
6
|
+
Aliases are scheduled for removal in semvec 0.2.0.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import warnings as _warnings
|
|
12
|
+
from typing import Any as _Any
|
|
13
|
+
|
|
14
|
+
from semvec._core import (
|
|
15
|
+
AdaptiveParameters,
|
|
16
|
+
CodeEntity,
|
|
17
|
+
ConfigurationError,
|
|
18
|
+
EmbeddingError,
|
|
19
|
+
EmbeddingService,
|
|
20
|
+
LicenseError,
|
|
21
|
+
LicenseExpiredError,
|
|
22
|
+
LiteralCache,
|
|
23
|
+
MemoryUnit,
|
|
24
|
+
MultiResolutionMemory,
|
|
25
|
+
PhaseDetector,
|
|
26
|
+
RateLimitError,
|
|
27
|
+
SemvecConfig,
|
|
28
|
+
SemvecError,
|
|
29
|
+
SemvecState,
|
|
30
|
+
StateCorruptionError,
|
|
31
|
+
safe_cosine_similarity,
|
|
32
|
+
)
|
|
33
|
+
from semvec.literal_cache import EntityKind
|
|
34
|
+
|
|
35
|
+
__version__ = "0.1.0a2"
|
|
36
|
+
__author__ = "Michael Neuberger"
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"AdaptiveParameters",
|
|
40
|
+
"CodeEntity",
|
|
41
|
+
"ConfigurationError",
|
|
42
|
+
"EmbeddingError",
|
|
43
|
+
"EmbeddingService",
|
|
44
|
+
"EntityKind",
|
|
45
|
+
"LicenseError",
|
|
46
|
+
"LicenseExpiredError",
|
|
47
|
+
"LiteralCache",
|
|
48
|
+
"MemoryUnit",
|
|
49
|
+
"MultiResolutionMemory",
|
|
50
|
+
"PhaseDetector",
|
|
51
|
+
"RateLimitError",
|
|
52
|
+
"SemvecConfig",
|
|
53
|
+
"SemvecError",
|
|
54
|
+
"SemvecState",
|
|
55
|
+
"StateCorruptionError",
|
|
56
|
+
"safe_cosine_similarity",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
61
|
+
# Deprecated aliases — emit a DeprecationWarning on access, resolve to the
|
|
62
|
+
# current PEP-8 names. Scheduled for removal in 0.2.0.
|
|
63
|
+
|
|
64
|
+
_DEPRECATED_ALIASES: dict[str, tuple[str, _Any]] = {
|
|
65
|
+
"PSS_State_V4": ("SemvecState", SemvecState),
|
|
66
|
+
"PSSConfig": ("SemvecConfig", SemvecConfig),
|
|
67
|
+
"PSSError": ("SemvecError", SemvecError),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def __getattr__(name: str) -> _Any:
|
|
72
|
+
alias = _DEPRECATED_ALIASES.get(name)
|
|
73
|
+
if alias is not None:
|
|
74
|
+
replacement_name, obj = alias
|
|
75
|
+
_warnings.warn(
|
|
76
|
+
f"{name} is deprecated and will be removed in semvec 0.2.0. "
|
|
77
|
+
f"Use {replacement_name} instead.",
|
|
78
|
+
DeprecationWarning,
|
|
79
|
+
stacklevel=2,
|
|
80
|
+
)
|
|
81
|
+
return obj
|
|
82
|
+
raise AttributeError(f"module 'semvec' has no attribute {name!r}")
|
semvec/_core.pyd
ADDED
|
Binary file
|
semvec/_core.pyi
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"""Type stubs for the Rust-backed `semvec._core` extension.
|
|
2
|
+
|
|
3
|
+
Covers the public surface used by typed consumers (mypy, pyright, IDE
|
|
4
|
+
auto-complete). Kept at the level of published shapes — implementation
|
|
5
|
+
details live in the Rust source.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Iterable, Mapping
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from numpy.typing import NDArray
|
|
14
|
+
|
|
15
|
+
# ---------------------------------------------------------------------------
|
|
16
|
+
# Core
|
|
17
|
+
|
|
18
|
+
class SemvecConfig:
|
|
19
|
+
dimension: int
|
|
20
|
+
short_term_size: int
|
|
21
|
+
medium_term_size: int
|
|
22
|
+
long_term_size: int
|
|
23
|
+
history_length: int
|
|
24
|
+
model_name: str
|
|
25
|
+
device: str
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
dimension: int = 384,
|
|
30
|
+
short_term_size: int = 20,
|
|
31
|
+
medium_term_size: int = 100,
|
|
32
|
+
long_term_size: int = 500,
|
|
33
|
+
history_length: int = 50,
|
|
34
|
+
model_name: str = ...,
|
|
35
|
+
device: str = "cpu",
|
|
36
|
+
**kwargs: Any,
|
|
37
|
+
) -> None: ...
|
|
38
|
+
|
|
39
|
+
class AdaptiveParameters:
|
|
40
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
|
41
|
+
|
|
42
|
+
class SemvecState:
|
|
43
|
+
semantic_state: NDArray[np.float64]
|
|
44
|
+
interaction_count: int
|
|
45
|
+
alpha_hit_count: int
|
|
46
|
+
timestamp: int
|
|
47
|
+
memory: "MultiResolutionMemory"
|
|
48
|
+
phase_detector: "PhaseDetector"
|
|
49
|
+
literal_cache: "LiteralCache"
|
|
50
|
+
similarity_history: list[float]
|
|
51
|
+
beta_history: list[float]
|
|
52
|
+
fsm_history: list[float]
|
|
53
|
+
phase_history: list[str]
|
|
54
|
+
|
|
55
|
+
def __init__(self, config: SemvecConfig | None = None) -> None: ...
|
|
56
|
+
def update(self, embedding: NDArray[np.float64], text: str) -> dict[str, Any]: ...
|
|
57
|
+
def to_dict(self) -> dict[str, Any]: ...
|
|
58
|
+
@staticmethod
|
|
59
|
+
def from_dict(data: Mapping[str, Any]) -> "SemvecState": ...
|
|
60
|
+
def set_retrieval_projection_weights(
|
|
61
|
+
self, matrix: list[list[float]] | NDArray[np.float64]
|
|
62
|
+
) -> None: ...
|
|
63
|
+
def get_retrieval_projection_weights(self) -> list[list[float]]: ...
|
|
64
|
+
def get_retrieval_projection_w_up(self) -> list[list[float]]: ...
|
|
65
|
+
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
# Memory
|
|
68
|
+
|
|
69
|
+
class MemoryUnit:
|
|
70
|
+
embedding: NDArray[np.float64]
|
|
71
|
+
text: str
|
|
72
|
+
importance: float
|
|
73
|
+
access_count: int
|
|
74
|
+
timestamp: float
|
|
75
|
+
semantic_hash: str
|
|
76
|
+
protection_score: float
|
|
77
|
+
|
|
78
|
+
def __init__(self, embedding: NDArray[np.float64], weight: float, promote: bool) -> None: ...
|
|
79
|
+
def to_dict(self) -> dict[str, Any]: ...
|
|
80
|
+
@staticmethod
|
|
81
|
+
def from_dict(data: Mapping[str, Any]) -> "MemoryUnit": ...
|
|
82
|
+
|
|
83
|
+
class MultiResolutionMemory:
|
|
84
|
+
short_term: list[MemoryUnit]
|
|
85
|
+
medium_term: list[MemoryUnit]
|
|
86
|
+
long_term: list[MemoryUnit]
|
|
87
|
+
|
|
88
|
+
def get_relevant_memories(
|
|
89
|
+
self, query: NDArray[np.float64], top_k: int = 10
|
|
90
|
+
) -> list[MemoryUnit]: ...
|
|
91
|
+
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
# Phase + attention + cache
|
|
94
|
+
|
|
95
|
+
class PhaseDetector:
|
|
96
|
+
current_phase: str
|
|
97
|
+
phase_transitions: list[dict[str, Any]]
|
|
98
|
+
|
|
99
|
+
def __init__(self, window_size: int, switch_cost: float, min_dwell: int) -> None: ...
|
|
100
|
+
def update(self, metrics: Mapping[str, float], timestamp: int) -> str | None: ...
|
|
101
|
+
def signal_topic_switch(self, magnitude: float) -> None: ...
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
# Literal cache
|
|
105
|
+
|
|
106
|
+
class CodeEntity:
|
|
107
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
|
108
|
+
|
|
109
|
+
class EntityKind:
|
|
110
|
+
FUNCTION: "EntityKind"
|
|
111
|
+
CLASS: "EntityKind"
|
|
112
|
+
METHOD: "EntityKind"
|
|
113
|
+
MODULE: "EntityKind"
|
|
114
|
+
|
|
115
|
+
class LiteralCache:
|
|
116
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
|
117
|
+
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
# Cortex — aggregation
|
|
120
|
+
|
|
121
|
+
class WeightedAverageAggregation:
|
|
122
|
+
def __init__(self, dimension: int = 384) -> None: ...
|
|
123
|
+
def aggregate(
|
|
124
|
+
self,
|
|
125
|
+
local_states: list[NDArray[np.float64]],
|
|
126
|
+
weights: NDArray[np.float64] | None = None,
|
|
127
|
+
) -> NDArray[np.float64]: ...
|
|
128
|
+
|
|
129
|
+
class AttentionAggregation:
|
|
130
|
+
def __init__(self, attention_dim: int = 64, dimension: int = 384) -> None: ...
|
|
131
|
+
def aggregate(
|
|
132
|
+
self,
|
|
133
|
+
local_states: list[NDArray[np.float64]],
|
|
134
|
+
weights: NDArray[np.float64] | None = None,
|
|
135
|
+
) -> NDArray[np.float64]: ...
|
|
136
|
+
|
|
137
|
+
# ---------------------------------------------------------------------------
|
|
138
|
+
# Cortex — consensus + packets
|
|
139
|
+
|
|
140
|
+
class ConsensusLevel:
|
|
141
|
+
SIMPLE_MAJORITY: "ConsensusLevel"
|
|
142
|
+
QUALIFIED_MAJORITY: "ConsensusLevel"
|
|
143
|
+
UNANIMOUS: "ConsensusLevel"
|
|
144
|
+
WEIGHTED_VOTE: "ConsensusLevel"
|
|
145
|
+
ADAPTIVE_THRESHOLD: "ConsensusLevel"
|
|
146
|
+
value: str
|
|
147
|
+
|
|
148
|
+
class TransferType:
|
|
149
|
+
FULL_STATE: "TransferType"
|
|
150
|
+
PARTIAL_STATE: "TransferType"
|
|
151
|
+
SEMANTIC_DELTA: "TransferType"
|
|
152
|
+
MEMORY_FRAGMENT: "TransferType"
|
|
153
|
+
COHERENCE_FIELD: "TransferType"
|
|
154
|
+
value: str
|
|
155
|
+
|
|
156
|
+
class StateVectorPacket:
|
|
157
|
+
packet_id: str
|
|
158
|
+
source_instance: str
|
|
159
|
+
target_instance: str
|
|
160
|
+
transfer_type: TransferType
|
|
161
|
+
state_vector: NDArray[np.float64]
|
|
162
|
+
metadata: dict[str, Any]
|
|
163
|
+
timestamp: float
|
|
164
|
+
size_bytes: int
|
|
165
|
+
checksum: str
|
|
166
|
+
|
|
167
|
+
def __init__(
|
|
168
|
+
self,
|
|
169
|
+
packet_id: str,
|
|
170
|
+
source_instance: str,
|
|
171
|
+
target_instance: str,
|
|
172
|
+
transfer_type: TransferType,
|
|
173
|
+
state_vector: NDArray[np.float64],
|
|
174
|
+
metadata: Mapping[str, Any] | None = None,
|
|
175
|
+
) -> None: ...
|
|
176
|
+
def verify_integrity(self) -> bool: ...
|
|
177
|
+
def serialize(self) -> bytes: ...
|
|
178
|
+
@classmethod
|
|
179
|
+
def deserialize(cls, data: bytes) -> "StateVectorPacket": ...
|
|
180
|
+
|
|
181
|
+
class ConsensusProposal:
|
|
182
|
+
proposal_id: str
|
|
183
|
+
proposer_instance: str
|
|
184
|
+
proposal_type: str
|
|
185
|
+
proposed_state: NDArray[np.float64]
|
|
186
|
+
rationale: str
|
|
187
|
+
consensus_level: str
|
|
188
|
+
voting_deadline: float
|
|
189
|
+
votes: dict[str, bool]
|
|
190
|
+
vote_weights: dict[str, float]
|
|
191
|
+
status: str
|
|
192
|
+
creation_time: float
|
|
193
|
+
|
|
194
|
+
def __init__(
|
|
195
|
+
self,
|
|
196
|
+
proposal_id: str,
|
|
197
|
+
proposer_instance: str,
|
|
198
|
+
proposal_type: str,
|
|
199
|
+
proposed_state: NDArray[np.float64],
|
|
200
|
+
rationale: str,
|
|
201
|
+
consensus_level: str = "simple_majority",
|
|
202
|
+
voting_deadline: float = 0.0,
|
|
203
|
+
) -> None: ...
|
|
204
|
+
def add_vote(self, instance_id: str, vote: bool, weight: float = 1.0) -> None: ...
|
|
205
|
+
def calculate_consensus(self) -> tuple[bool, float]: ...
|
|
206
|
+
def is_expired(self) -> bool: ...
|
|
207
|
+
|
|
208
|
+
class ConsensusEngine:
|
|
209
|
+
local_instance_id: str
|
|
210
|
+
network_id: str
|
|
211
|
+
consensus_id: str
|
|
212
|
+
|
|
213
|
+
def __init__(self, local_instance_id: str, network_id: str) -> None: ...
|
|
214
|
+
def register_instance(self, instance_id: str, weight: float = 1.0) -> None: ...
|
|
215
|
+
def create_proposal(
|
|
216
|
+
self,
|
|
217
|
+
proposal_type: str,
|
|
218
|
+
proposed_state: NDArray[np.float64],
|
|
219
|
+
rationale: str,
|
|
220
|
+
consensus_level: str = "simple_majority",
|
|
221
|
+
voting_timeout: float = 300.0,
|
|
222
|
+
) -> ConsensusProposal: ...
|
|
223
|
+
def vote_on_proposal(
|
|
224
|
+
self,
|
|
225
|
+
proposal_id: str,
|
|
226
|
+
vote: bool,
|
|
227
|
+
voting_instance: str | None = None,
|
|
228
|
+
) -> bool: ...
|
|
229
|
+
def check_expired_proposals(self) -> None: ...
|
|
230
|
+
def get_statistics(self) -> dict[str, Any]: ...
|
|
231
|
+
|
|
232
|
+
# ---------------------------------------------------------------------------
|
|
233
|
+
# Cortex — local/meta
|
|
234
|
+
|
|
235
|
+
class SemvecAgent:
|
|
236
|
+
instance_id: str
|
|
237
|
+
local_coherence: float
|
|
238
|
+
interaction_count: int
|
|
239
|
+
global_influence: float
|
|
240
|
+
last_update_time: float
|
|
241
|
+
min_coherence_threshold: float
|
|
242
|
+
pss_state: SemvecState
|
|
243
|
+
|
|
244
|
+
def __init__(
|
|
245
|
+
self,
|
|
246
|
+
instance_id: str,
|
|
247
|
+
embedder: object | None = None,
|
|
248
|
+
dimension: int = 384,
|
|
249
|
+
) -> None: ...
|
|
250
|
+
def process_input(
|
|
251
|
+
self,
|
|
252
|
+
text: str,
|
|
253
|
+
global_feedback: NDArray[np.float64] | None = None,
|
|
254
|
+
) -> dict[str, Any]: ...
|
|
255
|
+
def process_input_embedding(
|
|
256
|
+
self,
|
|
257
|
+
embedding: NDArray[np.float64] | list[float],
|
|
258
|
+
text: str,
|
|
259
|
+
global_feedback: NDArray[np.float64] | None = None,
|
|
260
|
+
) -> dict[str, Any]: ...
|
|
261
|
+
def get_state_vector(self) -> NDArray[np.float64]: ...
|
|
262
|
+
|
|
263
|
+
class SemvecCortexObserver:
|
|
264
|
+
global_state: list[float]
|
|
265
|
+
global_coherence: float
|
|
266
|
+
network_resonance: float
|
|
267
|
+
beta_global: float
|
|
268
|
+
update_count: int
|
|
269
|
+
|
|
270
|
+
def __init__(
|
|
271
|
+
self,
|
|
272
|
+
aggregation_strategy: WeightedAverageAggregation | AttentionAggregation | None = None,
|
|
273
|
+
dimension: int = 384,
|
|
274
|
+
) -> None: ...
|
|
275
|
+
def update_global_state(
|
|
276
|
+
self, local_instances: Iterable[LocalPSSInstance]
|
|
277
|
+
) -> dict[str, Any]: ...
|
|
278
|
+
def get_feedback_for_instance(self, instance_id: str) -> NDArray[np.float64] | None: ...
|
|
279
|
+
|
|
280
|
+
class SemvecAgentNetwork:
|
|
281
|
+
local_instances: dict[str, LocalPSSInstance]
|
|
282
|
+
meta_pss: MetaPSSInstance
|
|
283
|
+
enable_feedback: bool
|
|
284
|
+
feedback_strength: float
|
|
285
|
+
max_instances: int
|
|
286
|
+
|
|
287
|
+
def __init__(
|
|
288
|
+
self,
|
|
289
|
+
aggregation_strategy: WeightedAverageAggregation | AttentionAggregation | None = None,
|
|
290
|
+
enable_feedback: bool = True,
|
|
291
|
+
feedback_strength: float = 0.3,
|
|
292
|
+
max_instances: int = 100,
|
|
293
|
+
) -> None: ...
|
|
294
|
+
def add_instance(self, instance_id: str) -> bool: ...
|
|
295
|
+
def add_local_instance(self, instance_id: str) -> bool: ...
|
|
296
|
+
def remove_local_instance(self, instance_id: str) -> bool: ...
|
|
297
|
+
def process_input(self, instance_id: str, text: str) -> dict[str, Any]: ...
|
|
298
|
+
def get_network_state(self) -> dict[str, Any]: ...
|
|
299
|
+
|
|
300
|
+
# SemvecCortexService lives in semvec.cortex.service (Python layer).
|
|
301
|
+
|
|
302
|
+
# ---------------------------------------------------------------------------
|
|
303
|
+
# Coding primitives
|
|
304
|
+
|
|
305
|
+
class CodePointer:
|
|
306
|
+
intent_vector: NDArray[np.float64]
|
|
307
|
+
file_path: str
|
|
308
|
+
signature: str
|
|
309
|
+
importance: float
|
|
310
|
+
access_count: int
|
|
311
|
+
timestamp: float
|
|
312
|
+
semantic_hash: str
|
|
313
|
+
|
|
314
|
+
def __init__(
|
|
315
|
+
self,
|
|
316
|
+
intent_vector: NDArray[np.float64] | list[float],
|
|
317
|
+
file_path: str,
|
|
318
|
+
signature: str,
|
|
319
|
+
importance: float = 1.0,
|
|
320
|
+
access_count: int = 0,
|
|
321
|
+
timestamp: float | None = None,
|
|
322
|
+
semantic_hash: str = "",
|
|
323
|
+
) -> None: ...
|
|
324
|
+
def to_dict(self) -> dict[str, Any]: ...
|
|
325
|
+
@staticmethod
|
|
326
|
+
def from_dict(data: Mapping[str, Any]) -> "CodePointer": ...
|
|
327
|
+
|
|
328
|
+
class CodePointerIndex:
|
|
329
|
+
size: int
|
|
330
|
+
capacity: int
|
|
331
|
+
all_pointers: list[CodePointer]
|
|
332
|
+
|
|
333
|
+
def __init__(
|
|
334
|
+
self,
|
|
335
|
+
capacity: int = 100,
|
|
336
|
+
w_importance: float = 0.4,
|
|
337
|
+
w_recency: float = 0.35,
|
|
338
|
+
w_access: float = 0.25,
|
|
339
|
+
) -> None: ...
|
|
340
|
+
def register(self, pointer: CodePointer) -> None: ...
|
|
341
|
+
def retrieve(
|
|
342
|
+
self, query: NDArray[np.float64], top_k: int = 10
|
|
343
|
+
) -> list[CodePointer]: ...
|
|
344
|
+
def retention_score(self, pointer: CodePointer) -> float: ...
|
|
345
|
+
def to_dict(self) -> dict[str, Any]: ...
|
|
346
|
+
@staticmethod
|
|
347
|
+
def from_dict(data: Mapping[str, Any]) -> "CodePointerIndex": ...
|
|
348
|
+
|
|
349
|
+
class NegativeAttractor:
|
|
350
|
+
error_vector: NDArray[np.float64]
|
|
351
|
+
description: str
|
|
352
|
+
source: str
|
|
353
|
+
severity: float
|
|
354
|
+
created_at: float
|
|
355
|
+
|
|
356
|
+
def __init__(
|
|
357
|
+
self,
|
|
358
|
+
error_vector: NDArray[np.float64] | list[float],
|
|
359
|
+
description: str,
|
|
360
|
+
source: str,
|
|
361
|
+
severity: float = 1.0,
|
|
362
|
+
created_at: float | None = None,
|
|
363
|
+
) -> None: ...
|
|
364
|
+
|
|
365
|
+
class NegativeAttractorSet:
|
|
366
|
+
size: int
|
|
367
|
+
capacity: int
|
|
368
|
+
all_attractors: list[NegativeAttractor]
|
|
369
|
+
|
|
370
|
+
def __init__(self, capacity: int = 30, min_severity: float = 0.01) -> None: ...
|
|
371
|
+
def add(
|
|
372
|
+
self,
|
|
373
|
+
error_vector: NDArray[np.float64] | list[float],
|
|
374
|
+
description: str,
|
|
375
|
+
source: str,
|
|
376
|
+
severity: float = 1.0,
|
|
377
|
+
) -> None: ...
|
|
378
|
+
def check(
|
|
379
|
+
self, proposal: NDArray[np.float64], threshold: float = 0.7
|
|
380
|
+
) -> list[NegativeAttractor]: ...
|
|
381
|
+
def decay(self, factor: float = 0.95) -> None: ...
|
|
382
|
+
|
|
383
|
+
class PromptBuilder:
|
|
384
|
+
def __init__(self, budget: int = 6000) -> None: ...
|
|
385
|
+
def build(
|
|
386
|
+
self,
|
|
387
|
+
code_pointers: CodePointerIndex,
|
|
388
|
+
negative_attractors: NegativeAttractorSet,
|
|
389
|
+
task_vector: NDArray[np.float64],
|
|
390
|
+
*,
|
|
391
|
+
invariants: list[str] | None = None,
|
|
392
|
+
test_summary: str | None = None,
|
|
393
|
+
git_diff: str | None = None,
|
|
394
|
+
pss_memories: list[str] | None = None,
|
|
395
|
+
phase: str | None = None,
|
|
396
|
+
) -> str: ...
|
|
397
|
+
|
|
398
|
+
class CompactionEngine:
|
|
399
|
+
"""Placeholder for isinstance checks; the real orchestrator is `semvec.coding.CodingEngine`."""
|
|
400
|
+
|
|
401
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
|
402
|
+
|
|
403
|
+
# ---------------------------------------------------------------------------
|
|
404
|
+
# Misc
|
|
405
|
+
|
|
406
|
+
def safe_cosine_similarity(
|
|
407
|
+
a: NDArray[np.float64] | list[float],
|
|
408
|
+
b: NDArray[np.float64] | list[float],
|
|
409
|
+
eps: float = 1e-8,
|
|
410
|
+
) -> float: ...
|
|
411
|
+
|
|
412
|
+
class EmbeddingService:
|
|
413
|
+
"""Placeholder stub for isinstance compatibility with pss."""
|
|
414
|
+
|
|
415
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
semvec/api/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Semvec REST API — framework-agnostic HTTP access to the Rust core.
|
|
2
|
+
|
|
3
|
+
The API is auth-gated by the bundled Ed25519 JWT licensing system.
|
|
4
|
+
Clients send their license JWT via ``Authorization: Bearer <jwt>`` or
|
|
5
|
+
``X-API-Key: <jwt>``; the server verifies the signature, extracts the
|
|
6
|
+
tier (community/pro/enterprise), and enforces rate limits accordingly.
|
|
7
|
+
|
|
8
|
+
A SQLite database (``DATABASE_URL``, default ``sqlite:///semvec.db``)
|
|
9
|
+
stores session/cluster/member/audit metadata — no password store, no
|
|
10
|
+
separate API-key table. The license JWT is the single source of truth.
|
|
11
|
+
|
|
12
|
+
Start with::
|
|
13
|
+
|
|
14
|
+
semvec serve --host 0.0.0.0 --port 8080
|
|
15
|
+
|
|
16
|
+
or programmatically::
|
|
17
|
+
|
|
18
|
+
from semvec.api import create_app
|
|
19
|
+
app = create_app()
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from semvec.api.app import create_app
|
|
25
|
+
|
|
26
|
+
__all__ = ["create_app"]
|
semvec/api/app.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""FastAPI application factory for the Semvec REST API.
|
|
2
|
+
|
|
3
|
+
Wires auth + rate limiting + CORS + routers. CORS origins come from the
|
|
4
|
+
``CORS_ORIGINS`` env var (comma-separated); an empty value blocks
|
|
5
|
+
cross-origin requests by default.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from fastapi import Depends, FastAPI, Request
|
|
13
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
14
|
+
from fastapi.responses import JSONResponse, Response
|
|
15
|
+
from slowapi.errors import RateLimitExceeded
|
|
16
|
+
|
|
17
|
+
from semvec.api.auth import verify_basic_auth
|
|
18
|
+
from semvec.api.metrics_export import get_metrics_response, setup_metrics
|
|
19
|
+
|
|
20
|
+
from semvec.api.cluster_manager import ClusterManager
|
|
21
|
+
from semvec.api.cluster_routes import cluster_router, set_cluster_manager
|
|
22
|
+
from semvec.api.database import create_tables
|
|
23
|
+
from semvec.api.event_bus import DriftEventBus
|
|
24
|
+
from semvec.api.global_observer import ObserverManager
|
|
25
|
+
from semvec.api.literal_cache_routes import (
|
|
26
|
+
literal_router,
|
|
27
|
+
set_literal_session_manager,
|
|
28
|
+
)
|
|
29
|
+
from semvec.api.network_manager import NetworkManager
|
|
30
|
+
from semvec.api.network_routes import network_router, set_network_manager
|
|
31
|
+
from semvec.api.observer_routes import observer_router, set_observer_manager
|
|
32
|
+
from semvec.api.regional_manager import RegionalManager
|
|
33
|
+
from semvec.api.regional_routes import regional_router, set_regional_manager
|
|
34
|
+
from semvec.api.routes import (
|
|
35
|
+
limiter,
|
|
36
|
+
router as core_router,
|
|
37
|
+
set_layer3_managers,
|
|
38
|
+
set_session_manager,
|
|
39
|
+
)
|
|
40
|
+
from semvec.api.session_delta_routes import (
|
|
41
|
+
delta_router,
|
|
42
|
+
set_delta_session_manager,
|
|
43
|
+
)
|
|
44
|
+
from semvec.api.session_manager import SessionManager
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _get_cors_origins() -> list[str]:
|
|
48
|
+
raw = os.environ.get("CORS_ORIGINS", "")
|
|
49
|
+
if not raw.strip():
|
|
50
|
+
return []
|
|
51
|
+
return [origin.strip() for origin in raw.split(",") if origin.strip()]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def create_app() -> FastAPI:
|
|
55
|
+
"""Build and return the Semvec REST API FastAPI application."""
|
|
56
|
+
app = FastAPI(
|
|
57
|
+
title="Semvec REST API — Persistent Semantic State",
|
|
58
|
+
description=(
|
|
59
|
+
"Framework-agnostic semantic memory service. Feed text into "
|
|
60
|
+
"Semvec sessions and retrieve context-aware memories. Auth "
|
|
61
|
+
"via Ed25519-signed license JWTs (SEMVEC_LICENSE_KEY)."
|
|
62
|
+
),
|
|
63
|
+
version="1.0.0",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
app.state.limiter = limiter
|
|
67
|
+
|
|
68
|
+
def _rate_limit_handler(request: Request, exc: RateLimitExceeded) -> JSONResponse:
|
|
69
|
+
return JSONResponse(
|
|
70
|
+
status_code=429,
|
|
71
|
+
content={"detail": "Too many requests"},
|
|
72
|
+
headers={"Retry-After": "60"},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
app.add_exception_handler(RateLimitExceeded, _rate_limit_handler)
|
|
76
|
+
|
|
77
|
+
app.add_middleware(
|
|
78
|
+
CORSMiddleware,
|
|
79
|
+
allow_origins=_get_cors_origins(),
|
|
80
|
+
allow_methods=["GET", "POST", "PATCH", "DELETE", "PUT", "OPTIONS"],
|
|
81
|
+
allow_headers=["Content-Type", "Authorization", "X-API-Key"],
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
setup_metrics(app)
|
|
85
|
+
|
|
86
|
+
@app.get("/metrics")
|
|
87
|
+
def _metrics(_: bool = Depends(verify_basic_auth)) -> Response:
|
|
88
|
+
return get_metrics_response()
|
|
89
|
+
|
|
90
|
+
create_tables()
|
|
91
|
+
|
|
92
|
+
manager = SessionManager()
|
|
93
|
+
set_session_manager(manager)
|
|
94
|
+
set_delta_session_manager(manager)
|
|
95
|
+
set_literal_session_manager(manager)
|
|
96
|
+
app.state.session_manager = manager
|
|
97
|
+
|
|
98
|
+
cluster_manager = ClusterManager(manager)
|
|
99
|
+
set_cluster_manager(cluster_manager)
|
|
100
|
+
app.state.cluster_manager = cluster_manager
|
|
101
|
+
|
|
102
|
+
event_bus = DriftEventBus()
|
|
103
|
+
regional_manager = RegionalManager(manager, cluster_manager, event_bus)
|
|
104
|
+
set_regional_manager(regional_manager)
|
|
105
|
+
app.state.regional_manager = regional_manager
|
|
106
|
+
app.state.drift_event_bus = event_bus
|
|
107
|
+
|
|
108
|
+
# routes.run() publishes drift events through these managers.
|
|
109
|
+
set_layer3_managers(cluster_manager, regional_manager)
|
|
110
|
+
|
|
111
|
+
observer_manager = ObserverManager(cluster_manager, regional_manager, manager)
|
|
112
|
+
set_observer_manager(observer_manager)
|
|
113
|
+
app.state.observer_manager = observer_manager
|
|
114
|
+
|
|
115
|
+
network_manager = NetworkManager(manager)
|
|
116
|
+
set_network_manager(network_manager)
|
|
117
|
+
app.state.network_manager = network_manager
|
|
118
|
+
|
|
119
|
+
app.include_router(core_router)
|
|
120
|
+
app.include_router(delta_router)
|
|
121
|
+
app.include_router(literal_router)
|
|
122
|
+
app.include_router(cluster_router)
|
|
123
|
+
app.include_router(regional_router)
|
|
124
|
+
app.include_router(observer_router)
|
|
125
|
+
app.include_router(network_router)
|
|
126
|
+
|
|
127
|
+
return app
|