mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
838 lines
24 KiB
Python
838 lines
24 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Manifold Surface API Server
|
|
Provides REST API for manifold navigation interface
|
|
"""
|
|
|
|
from fastapi import FastAPI, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from pydantic import BaseModel
|
|
from typing import List, Optional
|
|
import sqlite3
|
|
import json
|
|
import numpy as np
|
|
import sys
|
|
import os
|
|
|
|
# Add parent directory to path
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
|
|
from projection_engine import ProjectionEngine, ConceptVector14, ProjectionMethod
|
|
from soliton_search import SolitonSearchEngine
|
|
from collapse_editor import CollapseEditor, StateType
|
|
from particle_interaction import ParticleInteractionEngine, ParticleType
|
|
from self_typing_engine import SelfTypingEngine, InteractionType
|
|
from relativity_adapter import RelativityAdapter, CognitiveLoadLevel
|
|
from substrate_bridge import SubstrateBridge
|
|
|
|
app = FastAPI(title="Manifold Surface API")
|
|
|
|
# CORS middleware
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Database path
|
|
DB_PATH = "/home/allaun/Documents/Research Stack/data/substrate_index.db"
|
|
|
|
# Global projection engine
|
|
projection_engine = None
|
|
soliton_engine = None
|
|
collapse_editor = CollapseEditor()
|
|
particle_engine = ParticleInteractionEngine()
|
|
self_typing_engine = SelfTypingEngine()
|
|
relativity_adapter = RelativityAdapter()
|
|
substrate_bridge = SubstrateBridge(DB_PATH)
|
|
|
|
|
|
class VectorData(BaseModel):
|
|
vectors: List[List[float]]
|
|
archive_ids: List[str]
|
|
|
|
|
|
class ProjectionRequest(BaseModel):
|
|
vectors: List[List[float]]
|
|
archive_ids: List[str]
|
|
method: str = "PCA"
|
|
slice_axis_x: int = 3
|
|
slice_axis_y: int = 4
|
|
|
|
|
|
class ProjectionResponse(BaseModel):
|
|
points: List[dict]
|
|
projection_matrix: List[List[float]]
|
|
mean_vector: List[float]
|
|
|
|
|
|
def get_db_connection():
|
|
"""Get database connection"""
|
|
conn = sqlite3.connect(DB_PATH)
|
|
conn.row_factory = sqlite3.Row
|
|
return conn
|
|
|
|
|
|
def load_concept_vectors_from_ene() -> List[ConceptVector14]:
|
|
"""Load concept vectors from ENE database"""
|
|
vectors = []
|
|
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
# Query concept vectors from packages table
|
|
cursor.execute("""
|
|
SELECT archive_id, concept_vector_14
|
|
FROM packages
|
|
WHERE concept_vector_14 IS NOT NULL
|
|
""")
|
|
|
|
for row in cursor.fetchall():
|
|
archive_id = row['archive_id']
|
|
vector_str = row['concept_vector_14']
|
|
|
|
try:
|
|
# Parse vector string (assuming JSON format)
|
|
vector_data = json.loads(vector_str)
|
|
vector = np.array(vector_data, dtype=np.float32)
|
|
|
|
if len(vector) != 14:
|
|
continue # Skip invalid vectors
|
|
|
|
vectors.append(ConceptVector14(vector=vector, archive_id=archive_id))
|
|
except (json.JSONDecodeError, ValueError) as e:
|
|
print(f"Error parsing vector for {archive_id}: {e}")
|
|
continue
|
|
|
|
conn.close()
|
|
|
|
except Exception as e:
|
|
print(f"Error loading concept vectors: {e}")
|
|
|
|
return vectors
|
|
|
|
|
|
@app.get("/health")
|
|
def health_check():
|
|
"""Health check endpoint"""
|
|
return {"status": "ok", "service": "manifold-surface-api"}
|
|
|
|
|
|
@app.get("/api/load-concept-vectors")
|
|
def load_concept_vectors():
|
|
"""Load concept vectors from ENE database"""
|
|
global projection_engine
|
|
|
|
try:
|
|
vectors = load_concept_vectors_from_ene()
|
|
|
|
if not vectors:
|
|
return {"vectors": [], "count": 0}
|
|
|
|
# Initialize projection engine
|
|
projection_engine = ProjectionEngine(method=ProjectionMethod.PCA)
|
|
|
|
# Fit and transform
|
|
projected = projection_engine.fit_transform(vectors)
|
|
|
|
# Convert to response format
|
|
vector_data = [v.vector.tolist() for v in vectors]
|
|
archive_ids = [v.archive_id for v in vectors]
|
|
|
|
return {
|
|
"vectors": vector_data,
|
|
"archive_ids": archive_ids,
|
|
"count": len(vectors),
|
|
"projection_matrix": projection_engine._projection_matrix.tolist() if projection_engine._projection_matrix is not None else [],
|
|
"mean_vector": projection_engine._mean.tolist() if projection_engine._mean is not None else []
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/project")
|
|
def project_vectors(request: ProjectionRequest):
|
|
"""Project vectors using specified method"""
|
|
global projection_engine
|
|
|
|
try:
|
|
# Convert to ConceptVector14 objects
|
|
vectors = [
|
|
ConceptVector14(vector=np.array(v, dtype=np.float32), archive_id=aid)
|
|
for v, aid in zip(request.vectors, request.archive_ids)
|
|
]
|
|
|
|
# Create projection engine with specified method
|
|
method_map = {
|
|
"PCA": ProjectionMethod.PCA,
|
|
"tSNE": ProjectionMethod.T_SNE,
|
|
"UMAP": ProjectionMethod.UMAP,
|
|
"ManifoldChart": ProjectionMethod.MANIFOLD_CHART
|
|
}
|
|
|
|
method = method_map.get(request.method, ProjectionMethod.PCA)
|
|
projection_engine = ProjectionEngine(method=method)
|
|
|
|
# Fit and transform
|
|
projected = projection_engine.fit_transform(vectors)
|
|
|
|
# Convert to response format
|
|
points = [p.to_dict() for p in projected]
|
|
|
|
return {
|
|
"points": points,
|
|
"projection_matrix": projection_engine._projection_matrix.tolist() if projection_engine._projection_matrix is not None else [],
|
|
"mean_vector": projection_engine._mean.tolist() if projection_engine._mean is not None else []
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
class SolitonSearchRequest(BaseModel):
|
|
query_vector: List[float]
|
|
max_results: int = 10
|
|
|
|
|
|
class CreateSuperpositionRequest(BaseModel):
|
|
initial_content: str
|
|
state_type: str = "text"
|
|
|
|
|
|
class AddStateRequest(BaseModel):
|
|
superposition_id: str
|
|
branch_id: str
|
|
content: str
|
|
state_type: str = "text"
|
|
|
|
|
|
class CreateBranchRequest(BaseModel):
|
|
superposition_id: str
|
|
parent_branch_id: Optional[str] = None
|
|
content: str = ""
|
|
state_type: str = "text"
|
|
|
|
|
|
class CollapseRequest(BaseModel):
|
|
superposition_id: str
|
|
branch_id: str
|
|
|
|
|
|
class CreateParticleRequest(BaseModel):
|
|
particle_type: str
|
|
position: Tuple[float, float]
|
|
velocity: Tuple[float, float] = (0.0, 0.0)
|
|
|
|
|
|
class EmitPhotonRequest(BaseModel):
|
|
from_particle_id: str
|
|
to_particle_id: str
|
|
|
|
|
|
class AbsorbPhotonRequest(BaseModel):
|
|
photon_id: str
|
|
target_particle_id: str
|
|
|
|
|
|
class RecordInteractionRequest(BaseModel):
|
|
interaction_type: str
|
|
source_layer: str
|
|
target_layer: str
|
|
context: Optional[Dict[str, str]] = None
|
|
|
|
|
|
class InferMetatypeRequest(BaseModel):
|
|
context: Dict[str, str]
|
|
|
|
|
|
class MeasureCognitiveLoadRequest(BaseModel):
|
|
information_density: float
|
|
complexity: float
|
|
novelty: float
|
|
uncertainty: float
|
|
|
|
|
|
class TransformRequest(BaseModel):
|
|
input_vector: List[float]
|
|
from_topology: Optional[str] = None
|
|
to_topology: Optional[str] = None
|
|
|
|
|
|
@app.post("/api/soliton-search")
|
|
def soliton_search(request: SolitonSearchRequest):
|
|
"""Search using soliton propagation with AVMR O(√N) indexing"""
|
|
global soliton_engine
|
|
|
|
try:
|
|
# Load vectors if not already loaded
|
|
if soliton_engine is None:
|
|
vectors = load_concept_vectors_from_ene()
|
|
if not vectors:
|
|
return {"results": [], "count": 0}
|
|
|
|
vector_data = [v.vector.tolist() for v in vectors]
|
|
archive_ids = [v.archive_id for v in vectors]
|
|
|
|
soliton_engine = SolitonSearchEngine(vector_data, archive_ids)
|
|
|
|
# Perform search
|
|
query = np.array(request.query_vector, dtype=np.float32)
|
|
results = soliton_engine.search(query, max_results=request.max_results)
|
|
|
|
return {
|
|
"results": [{"archive_id": aid, "confidence": conf} for aid, conf in results],
|
|
"count": len(results)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/superposition/create")
|
|
def create_superposition(request: CreateSuperpositionRequest):
|
|
"""Create new superposition with single branch"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
state_type = StateType[request.state_type.upper()]
|
|
superposition = collapse_editor.create_superposition(request.initial_content, state_type)
|
|
|
|
return {
|
|
"superposition_id": superposition.superposition_id,
|
|
"current_branch_id": superposition.current_branch_id,
|
|
"branches": len(superposition.branches)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/superposition/add-state")
|
|
def add_state_to_branch(request: AddStateRequest):
|
|
"""Add new state to existing branch"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
state_type = StateType[request.state_type.upper()]
|
|
collapse_editor.add_state_to_branch(
|
|
request.superposition_id,
|
|
request.branch_id,
|
|
request.content,
|
|
state_type
|
|
)
|
|
|
|
return {"status": "ok"}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/superposition/create-branch")
|
|
def create_branch(request: CreateBranchRequest):
|
|
"""Create new branch in superposition"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
state_type = StateType[request.state_type.upper()]
|
|
branch = collapse_editor.create_branch(
|
|
request.superposition_id,
|
|
request.parent_branch_id,
|
|
request.content,
|
|
state_type
|
|
)
|
|
|
|
return {
|
|
"branch_id": branch.branch_id,
|
|
"amplitude": branch.amplitude,
|
|
"states": len(branch.states)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/superposition/collapse")
|
|
def collapse_superposition(request: CollapseRequest):
|
|
"""Collapse superposition to observable state"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
observable = collapse_editor.collapse(request.superposition_id, request.branch_id)
|
|
|
|
return {
|
|
"archive_id": observable.archive_id,
|
|
"witness_hash": observable.witness_hash,
|
|
"collapsed_at": observable.collapsed_at.isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/superposition/{superposition_id}/branches")
|
|
def get_superposition_branches(superposition_id: str):
|
|
"""Get all branches for superposition"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
branches = collapse_editor.get_branches(superposition_id)
|
|
|
|
return {
|
|
"branches": [
|
|
{
|
|
"branch_id": b.branch_id,
|
|
"amplitude": b.amplitude,
|
|
"states": len(b.states),
|
|
"parent_branch_id": b.parent_branch_id
|
|
}
|
|
for b in branches
|
|
]
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/superposition/{superposition_id}/tree")
|
|
def get_branch_tree(superposition_id: str):
|
|
"""Get branch tree structure for visualization"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
tree = collapse_editor.get_branch_tree(superposition_id)
|
|
return {"tree": tree}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/collapse-editor/undo")
|
|
def undo_collapse():
|
|
"""Revert to previous observable state"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
previous_state = collapse_editor.undo()
|
|
|
|
if previous_state is None:
|
|
return {"status": "no_undo_available"}
|
|
|
|
return {
|
|
"archive_id": previous_state.archive_id,
|
|
"witness_hash": previous_state.witness_hash
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/collapse-editor/witnesses")
|
|
def get_witness_history():
|
|
"""Get all witness records"""
|
|
global collapse_editor
|
|
|
|
try:
|
|
witnesses = collapse_editor.get_witness_history()
|
|
|
|
return {
|
|
"witnesses": [
|
|
{
|
|
"witness_hash": w.witness_hash,
|
|
"superposition_id": w.superposition_id,
|
|
"collapsed_branch_id": w.collapsed_branch_id,
|
|
"timestamp": w.timestamp.isoformat()
|
|
}
|
|
for w in witnesses
|
|
],
|
|
"count": len(witnesses)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/particle/create")
|
|
def create_particle(request: CreateParticleRequest):
|
|
"""Create new particle"""
|
|
global particle_engine
|
|
|
|
try:
|
|
particle_type = ParticleType[request.particle_type.upper()]
|
|
particle = particle_engine.create_particle(
|
|
particle_type,
|
|
request.position,
|
|
request.velocity
|
|
)
|
|
|
|
return particle.to_dict()
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/particle/emit-photon")
|
|
def emit_photon(request: EmitPhotonRequest):
|
|
"""Emit photon from one particle to another"""
|
|
global particle_engine
|
|
|
|
try:
|
|
interaction = particle_engine.emit_photon(request.from_particle_id, request.to_particle_id)
|
|
|
|
return {
|
|
"interaction_id": len(particle_engine.interactions),
|
|
"from_particle_id": interaction.from_particle_id,
|
|
"to_particle_id": interaction.to_particle_id,
|
|
"interaction_type": interaction.interaction_type,
|
|
"energy_transfer": interaction.energy_transfer
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/particle/absorb-photon")
|
|
def absorb_photon(request: AbsorbPhotonRequest):
|
|
"""Absorb photon by target particle"""
|
|
global particle_engine
|
|
|
|
try:
|
|
interaction = particle_engine.absorb_photon(request.photon_id, request.target_particle_id)
|
|
|
|
return {
|
|
"interaction_id": len(particle_engine.interactions),
|
|
"from_particle_id": interaction.from_particle_id,
|
|
"to_particle_id": interaction.to_particle_id,
|
|
"interaction_type": interaction.interaction_type,
|
|
"energy_transfer": interaction.energy_transfer
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/particle/detect-neutrino/{particle_id}")
|
|
def detect_neutrino(particle_id: str):
|
|
"""Attempt to detect neutrino (weakly-interacting inference)"""
|
|
global particle_engine
|
|
|
|
try:
|
|
detected = particle_engine.detect_neutrino(particle_id)
|
|
|
|
return {"detected": detected}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/particle/update")
|
|
def update_particles():
|
|
"""Update particle positions and velocities"""
|
|
global particle_engine
|
|
|
|
try:
|
|
particle_engine.update()
|
|
|
|
return {"time": particle_engine.time}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/particle/conservation")
|
|
def check_conservation():
|
|
"""Check all conservation laws"""
|
|
global particle_engine
|
|
|
|
try:
|
|
conservation = particle_engine.check_conservation()
|
|
return conservation
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/particle/graph")
|
|
def get_interaction_graph():
|
|
"""Get interaction graph for visualization"""
|
|
global particle_engine
|
|
|
|
try:
|
|
graph = particle_engine.get_interaction_graph()
|
|
return graph
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/particle/type/{particle_type}")
|
|
def get_particles_by_type(particle_type: str):
|
|
"""Get all particles of specific type"""
|
|
global particle_engine
|
|
|
|
try:
|
|
ptype = ParticleType[particle_type.upper()]
|
|
particles = particle_engine.get_particles_by_type(ptype)
|
|
|
|
return {
|
|
"particles": [p.to_dict() for p in particles],
|
|
"count": len(particles)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/self-typing/record-interaction")
|
|
def record_interaction(request: RecordInteractionRequest):
|
|
"""Record interaction between layers"""
|
|
global self_typing_engine
|
|
|
|
try:
|
|
interaction_type = InteractionType[request.interaction_type.upper()]
|
|
interaction = self_typing_engine.record_interaction(
|
|
interaction_type,
|
|
request.source_layer,
|
|
request.target_layer,
|
|
request.context
|
|
)
|
|
|
|
return {
|
|
"interaction_id": interaction.interaction_id,
|
|
"interaction_type": interaction.interaction_type.value,
|
|
"source_layer": interaction.source_layer,
|
|
"target_layer": interaction.target_layer,
|
|
"timestamp": interaction.timestamp.isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/self-typing/infer-metatype")
|
|
def infer_metatype(request: InferMetatypeRequest):
|
|
"""Infer metatype from interaction patterns"""
|
|
global self_typing_engine
|
|
|
|
try:
|
|
metatype = self_typing_engine.infer_metatype(request.context)
|
|
|
|
return {
|
|
"metatype_id": metatype.metatype_id,
|
|
"type_signature": metatype.type_signature,
|
|
"confidence": metatype.confidence,
|
|
"suggestions": metatype.suggestions,
|
|
"created_at": metatype.created_at.isoformat()
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/self-typing/interactions")
|
|
def get_interaction_history(limit: int = 100):
|
|
"""Get recent interaction history"""
|
|
global self_typing_engine
|
|
|
|
try:
|
|
interactions = self_typing_engine.get_interaction_history(limit)
|
|
|
|
return {
|
|
"interactions": [
|
|
{
|
|
"interaction_id": i.interaction_id,
|
|
"interaction_type": i.interaction_type.value,
|
|
"source_layer": i.source_layer,
|
|
"target_layer": i.target_layer,
|
|
"timestamp": i.timestamp.isoformat()
|
|
}
|
|
for i in interactions
|
|
],
|
|
"count": len(interactions)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/self-typing/statistics")
|
|
def get_type_statistics():
|
|
"""Get statistics about type inference"""
|
|
global self_typing_engine
|
|
|
|
try:
|
|
stats = self_typing_engine.get_type_statistics()
|
|
return stats
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/relativity/measure-cognitive-load")
|
|
def measure_cognitive_load(request: MeasureCognitiveLoadRequest):
|
|
"""Measure cognitive load"""
|
|
global relativity_adapter
|
|
|
|
try:
|
|
load_vector = relativity_adapter.measure_cognitive_load(
|
|
request.information_density,
|
|
request.complexity,
|
|
request.novelty,
|
|
request.uncertainty
|
|
)
|
|
|
|
return {
|
|
"level": load_vector.get_level().value,
|
|
"information_density": load_vector.information_density,
|
|
"complexity": load_vector.complexity,
|
|
"novelty": load_vector.novelty,
|
|
"uncertainty": load_vector.uncertainty,
|
|
"timestamp": load_vector.timestamp
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/relativity/adapt-topology")
|
|
def adapt_topology(request: MeasureCognitiveLoadRequest):
|
|
"""Adapt topology based on cognitive load"""
|
|
global relativity_adapter
|
|
|
|
try:
|
|
load_vector = relativity_adapter.measure_cognitive_load(
|
|
request.information_density,
|
|
request.complexity,
|
|
request.novelty,
|
|
request.uncertainty
|
|
)
|
|
|
|
topology = relativity_adapter.adapt_topology(load_vector)
|
|
|
|
return {
|
|
"topology_id": topology.topology_id,
|
|
"distance_metric": topology.distance_metric,
|
|
"cognitive_load_level": topology.cognitive_load_level.value
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/relativity/transform")
|
|
def transform_coordinates(request: TransformRequest):
|
|
"""Transform coordinates between topologies"""
|
|
global relativity_adapter
|
|
|
|
try:
|
|
input_vector = np.array(request.input_vector, dtype=np.float32)
|
|
transformed = relativity_adapter.transform(
|
|
input_vector,
|
|
request.from_topology,
|
|
request.to_topology
|
|
)
|
|
|
|
return {
|
|
"transformed_vector": transformed.tolist(),
|
|
"from_topology": request.from_topology,
|
|
"to_topology": request.to_topology
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.post("/api/relativity/enable-dolphin-mode")
|
|
def enable_dolphin_mode():
|
|
"""Enable dolphin mode (non-Euclidean visualization)"""
|
|
global relativity_adapter
|
|
|
|
try:
|
|
relativity_adapter.enable_dolphin_mode()
|
|
|
|
return {
|
|
"status": "dolphin_mode_enabled",
|
|
"current_topology": relativity_adapter.current_topology.topology_id if relativity_adapter.current_topology else None
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/relativity/cognitive-load-history")
|
|
def get_cognitive_load_history(limit: int = 100):
|
|
"""Get cognitive load history"""
|
|
global relativity_adapter
|
|
|
|
try:
|
|
history = relativity_adapter.get_cognitive_load_history(limit)
|
|
|
|
return {
|
|
"history": [
|
|
{
|
|
"level": h.get_level().value,
|
|
"information_density": h.information_density,
|
|
"complexity": h.complexity,
|
|
"novelty": h.novelty,
|
|
"uncertainty": h.uncertainty,
|
|
"timestamp": h.timestamp
|
|
}
|
|
for h in history
|
|
],
|
|
"count": len(history)
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/relativity/statistics")
|
|
def get_topology_statistics():
|
|
"""Get topology statistics"""
|
|
global relativity_adapter
|
|
|
|
try:
|
|
stats = relativity_adapter.get_topology_statistics()
|
|
return stats
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@app.get("/api/stats")
|
|
def get_stats():
|
|
"""Get database statistics"""
|
|
try:
|
|
conn = get_db_connection()
|
|
cursor = conn.cursor()
|
|
|
|
# Count total packages
|
|
cursor.execute("SELECT COUNT(*) as count FROM packages")
|
|
total_count = cursor.fetchone()['count']
|
|
|
|
# Count packages with concept vectors
|
|
cursor.execute("SELECT COUNT(*) as count FROM packages WHERE concept_vector_14 IS NOT NULL")
|
|
vector_count = cursor.fetchone()['count']
|
|
|
|
conn.close()
|
|
|
|
return {
|
|
"total_packages": total_count,
|
|
"packages_with_vectors": vector_count,
|
|
"coverage": vector_count / total_count if total_count > 0 else 0
|
|
}
|
|
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
|
|
print("Starting Manifold Surface API Server...")
|
|
print(f"Database: {DB_PATH}")
|
|
|
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|