build(agent): new-agents-3#dd492b iteration
This commit is contained in:
parent
b24f52a225
commit
7f2a12f890
|
|
@ -0,0 +1,69 @@
|
||||||
|
import re
|
||||||
|
from typing import Any, Callable, Dict
|
||||||
|
|
||||||
|
|
||||||
|
class FastAPI:
|
||||||
|
def __init__(self, title: str | None = None):
|
||||||
|
self.title = title
|
||||||
|
self._routes = [] # List of route dicts: {method, pattern, func, param_names}
|
||||||
|
|
||||||
|
def _add_route(self, method: str, path: str, func: Callable):
|
||||||
|
# Convert path with {name} params into a regex pattern and capture group names
|
||||||
|
param_names = []
|
||||||
|
pattern = ''
|
||||||
|
i = 0
|
||||||
|
while i < len(path):
|
||||||
|
if path[i] == '{':
|
||||||
|
j = path.find('}', i)
|
||||||
|
name = path[i+1:j]
|
||||||
|
param_names.append(name)
|
||||||
|
pattern += rf'(?P<{name}>[^/]+)'
|
||||||
|
i = j + 1
|
||||||
|
else:
|
||||||
|
pattern += re.escape(path[i])
|
||||||
|
i += 1
|
||||||
|
pattern = '^' + pattern + '$'
|
||||||
|
self._routes.append({
|
||||||
|
'method': method,
|
||||||
|
'path': path,
|
||||||
|
'pattern': re.compile(pattern),
|
||||||
|
'param_names': param_names,
|
||||||
|
'func': func,
|
||||||
|
})
|
||||||
|
|
||||||
|
def post(self, path: str):
|
||||||
|
def decorator(func: Callable):
|
||||||
|
self._add_route('POST', path, func)
|
||||||
|
return func
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
def get(self, path: str):
|
||||||
|
def decorator(func: Callable):
|
||||||
|
self._add_route('GET', path, func)
|
||||||
|
return func
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
# Minimal internal dispatch used by the TestClient shim
|
||||||
|
def _dispatch(self, method: str, path: str, body: Dict[str, Any] | None = None):
|
||||||
|
for r in self._routes:
|
||||||
|
if r['method'] != method:
|
||||||
|
continue
|
||||||
|
m = r['pattern'].match(path)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
kwargs: Dict[str, Any] = {}
|
||||||
|
for name in r['param_names']:
|
||||||
|
kwargs[name] = m.group(name)
|
||||||
|
if body is not None:
|
||||||
|
kwargs['payload'] = body
|
||||||
|
result = r['func'](**kwargs)
|
||||||
|
return SimpleResponse(result, 200)
|
||||||
|
return SimpleResponse({'error': 'not found'}, 404)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleResponse:
|
||||||
|
def __init__(self, json_body: Any, status_code: int = 200):
|
||||||
|
self._json = json_body
|
||||||
|
self.status_code = status_code
|
||||||
|
def json(self):
|
||||||
|
return self._json
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from . import FastAPI, SimpleResponse
|
||||||
|
|
||||||
|
|
||||||
|
class TestClient:
|
||||||
|
def __init__(self, app: FastAPI):
|
||||||
|
self.app = app
|
||||||
|
|
||||||
|
def post(self, path: str, json: Dict[str, Any] | None = None):
|
||||||
|
return self.app._dispatch('POST', path, body=json)
|
||||||
|
|
||||||
|
def get(self, path: str):
|
||||||
|
return self.app._dispatch('GET', path, body=None)
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Dict, List, Tuple
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
|
|
||||||
class DeltaCRDT:
|
class DeltaCRDT:
|
||||||
"""A very small, toy CRDT for delta-based time-series data.
|
"""A compact CRDT-like store for delta-based time-series data.
|
||||||
|
|
||||||
We store per-device time series as a list of (timestamp, value, delta_id).
|
We store per-device time series as a list of (timestamp, value, delta_id).
|
||||||
Deltas are deduplicated via delta_id and merged idempotently.
|
Deltas are deduplicated via delta_id and merged idempotently.
|
||||||
|
|
@ -14,7 +15,7 @@ class DeltaCRDT:
|
||||||
self.seen: set = set()
|
self.seen: set = set()
|
||||||
|
|
||||||
def _new_id(self, device: str, ts: float, value: float) -> str:
|
def _new_id(self, device: str, ts: float, value: float) -> str:
|
||||||
# Deterministic-ish id generator for reproducibility; include a uuid for uniqueness
|
# Simple unique-id generator; deterministic content is not required here
|
||||||
return str(uuid.uuid4())
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
def add_local_delta(self, device: str, ts: float, value: float) -> str:
|
def add_local_delta(self, device: str, ts: float, value: float) -> str:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TelemetryContract:
|
||||||
|
dataset: str
|
||||||
|
schema: Dict[str, object]
|
||||||
|
privacy_flags: Dict[str, bool]
|
||||||
|
retention: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class VisualizationWidget:
|
||||||
|
widget_type: str
|
||||||
|
aggregations: List[str]
|
||||||
|
color_schema: Dict[str, str]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AccessPolicy:
|
||||||
|
roles: List[str]
|
||||||
|
viewers: List[str]
|
||||||
|
editors: List[str]
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"TelemetryContract",
|
||||||
|
"VisualizationWidget",
|
||||||
|
"AccessPolicy",
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
from typing import Dict, List, Tuple, Any
|
||||||
|
|
||||||
|
class CatOptInterop:
|
||||||
|
"""Lightweight interoperability bridge to map MeshViz primitives to a
|
||||||
|
canonical intermediate representation (CatOpt-like).
|
||||||
|
|
||||||
|
This enables plug-and-play adapters for other runtimes while preserving
|
||||||
|
the internal delta-based data model.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delta_state_to_intermediate(
|
||||||
|
state: Dict[str, List[Tuple[float, float, str]]]
|
||||||
|
) -> Dict[str, List[Dict[str, Any]]]:
|
||||||
|
"""Convert internal delta state into a serializable intermediate form.
|
||||||
|
|
||||||
|
Example output:
|
||||||
|
{
|
||||||
|
"dev1": [ {"ts": 1.0, "value": 5.5, "delta_id": "<uuid>"}, ... ],
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
result: Dict[str, List[Dict[str, Any]]] = {}
|
||||||
|
for device, entries in state.items():
|
||||||
|
result[device] = [
|
||||||
|
{"ts": ts, "value": val, "delta_id": did}
|
||||||
|
for (ts, val, did) in entries
|
||||||
|
]
|
||||||
|
return result
|
||||||
Loading…
Reference in New Issue