Replace getSimulationHistory (simulation API) with listProjects (graph API)
and adapt all template references from simulation_id/report_id fields to
project_id/graph_id fields matching the new project data model.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8 tests covering list, get, create, delete, and reset endpoints via
Flask test client with in-memory SQLite and mocked storage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert all project.attribute accesses to project["key"]/project.get("key"),
use save_project({...}) dict calls, and wire save_graph_record/complete_graph_record
helpers for proper graph persistence.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace .to_dict() calls and attribute access with direct dict usage,
add get_storage() import for delete_project, and rewrite reset_project
to use save_project() with a partial dict instead of mutating an ORM object.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove unused `import io`
- Avoid double-encoding in save_extracted_text by caching encoded bytes
- Delegate _to_dict queries to get_ontology/get_latest_graph_external_id
- Add comment to save_ontology noting full versioning is planned for F2-3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `from ..config import Config` import
- Convert `_to_dict` from @staticmethod to @classmethod; it now opens a
fresh session to populate `ontology` and `graph_id` from OntologyModel
and GraphModel respectively
- Use `db.expunge(proj)` before closing sessions in create_project,
get_project and list_projects so `_to_dict` can open its own session
without nesting conflicts (SQLite StaticPool safe)
- Add five new classmethods: save_ontology, get_ontology,
save_graph_record, get_latest_graph_external_id, complete_graph_record
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace conftest.py with two autouse fixtures: reset_graph_factory_singleton
and reset_task_manager_singleton, plus in_memory_db fixture for tests
requiring a real DB
- Rewrite test_project_task_recovery.py to use ProjectManager + SQLite in-memory
DB instead of the removed Project dataclass (same guarantee: active_task_id
persists and defaults to None)
- Fix db.py init_db() to import db_models before Base.metadata.create_all() so
all ORM tables are registered and created on first startup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace file-based JSON persistence with SQLAlchemy DB (ProjectModel/ProjectFileModel)
and StorageService for file content; remove Project dataclass; add 7 passing tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace in-memory dict-based TaskManager with a SQLAlchemy-backed implementation
using TaskModel. Tasks now survive process restarts. 6 new tests added and passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Initializes the database (via init_db) and registers the StorageService
instance in app.extensions['storage'] inside create_app(). Adds get_storage()
helper for convenient access from any Flask context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Initializes Alembic with autogenerated migration covering all 11 tables
(tasks, users, projects, project_files, ontologies, graphs, simulations,
reports, system_config, invitation_tokens, password_reset_tokens).
Adds *.db to .gitignore to exclude local SQLite dev database.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin és també user: accés a tots els projectes + admin en pantalles separades
- Documentar auth provisional (DEMO_PASSWORD) a eliminar
- Afegir flux forgot-password amb resposta genèrica (no revela validesa email)
- Principi de seguretat: cap endpoint d'auth revela si un email existeix
- Look & feel: Sistema de Disseny Gencat, consistent amb AgentCAT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds ?format=md|pdf query param to GET /api/report/<id>/download.
PDF is generated from Markdown via fitz.Story (PyMuPDF). Also fixes
create_app() to support dict config and skip JWT auth in TESTING mode.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
graphiti-core 0.28.2 has _extract_entity_attributes required by the
monkey-patch in GraphitiBackend. Override neo4j to resolve conflict
with camel-oasis==0.2.5 which pins neo4j==5.23.0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All variables now flow from config.sh through 2-build-deploy.sh to the
container env, so GRAPH_BACKEND=graphiti is honoured at runtime.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract parse_azure_url from graphiti_backend into utils/llm_client so all
services (oasis_profile_generator, simulation_config_generator, graphiti_backend,
LLMClient) strip the /chat/completions suffix and api-version before passing
base_url to the OpenAI SDK, fixing 404 errors when the full Azure endpoint URL
is set in LLM_BASE_URL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous fix applied _flatten_attributes too broadly, breaking graphiti's
internal ExtractedEntities validation (lists were converted to strings).
Instead, monkey-patch only _extract_entity_attributes — the exact function
that returns entity attribute dicts to node.attributes before Neo4j write.
Lists of primitives are preserved; only dict-valued attributes are flattened.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Graphiti's attribute extraction LLM sometimes returns values wrapped in
nested dicts ({"value": "CTTI"}) instead of plain strings. Neo4j rejects
these with TypeError: "Property values can only be of primitive types".
Fix: after _AzureGenericClient gets the LLM response, validate it through
the Pydantic response_model and call _flatten_attributes() so every value
reaching Neo4j is a scalar. Also add _flatten_attributes() helper.
UI: exclude 'summary' from the Properties section of the node detail panel
since it already appears in the dedicated Summary section below.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Revert default limits back to 10 edges and 12 entities (10 specific + 2
fallback), matching Zep Cloud's maximum. Expose ONTOLOGY_MAX_ENTITY_TYPES
and ONTOLOGY_MAX_EDGE_TYPES in Config so operators can override without
touching code. Prompts now inject the live values at request time.
Also replace Chinese comments in .env.example with English equivalents.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>