neo-cortex2-mcp 6.1.0__tar.gz
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.
- neo_cortex2_mcp-6.1.0/.gitignore +20 -0
- neo_cortex2_mcp-6.1.0/PKG-INFO +24 -0
- neo_cortex2_mcp-6.1.0/mbel.md +59 -0
- neo_cortex2_mcp-6.1.0/pyproject.toml +74 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/assets/__init__.py +10 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/assets/default-gitignore +6 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/assets/default-models.json +28 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/assets/docker-compose.yml +37 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/__init__.py +1 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/dashboard_v2.py +78 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/import_logs.py +175 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/init.py +77 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/mcp_server_v2.py +252 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/rebuild_cli.py +262 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/status.py +94 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/stop_hook.py +51 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cli/timeline_v2.py +228 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/__init__.py +7 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/bundle.py +196 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/config/__init__.py +27 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/config/project_discovery.py +112 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/config/schema.py +360 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/doctor/__init__.py +1 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/doctor/service.py +142 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/embedder/__init__.py +4 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/embedder/jina.py +101 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/hooks.py +69 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/integrity/__init__.py +2 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/integrity/scanner.py +73 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/__init__.py +11 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/executor.py +171 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/factory.py +134 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/providers/__init__.py +4 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/providers/anthropic.py +200 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/providers/groq.py +117 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/providers/openrouter.py +131 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/transport_retry.py +78 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/llm/validators.py +41 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/logging/__init__.py +24 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/logging/context.py +37 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/logging/setup.py +139 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/__init__.py +4 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/article_prompt.py +99 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/article_validator.py +175 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/articulator_v2.py +154 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/compress_mbel.py +31 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/dtos.py +40 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/manual_path.py +73 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/persist_articulation.py +69 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompt_helpers.py +24 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/__init__.py +10 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/_versions/README.md +18 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/_versions/relatore_BASE.md +115 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/_versions/relatore_v1_delta_seconds.md +118 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/_versions/relatore_v2_precomputed_deltas.md +118 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/_versions/relatore_v3_strict_artifact.md +121 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/articulator.md +312 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/prompts/relatore.md +121 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/relate_jobs.py +202 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/relate_validator.py +96 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/relate_worker.py +156 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/relatore.py +306 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/retry.py +153 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/stop_hook.py +134 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/synth_lifecycle.py +126 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/transcript_cleanup.py +41 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/validators/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/pipeline/validators/identity_validator.py +57 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/__init__.py +8 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/drill.py +269 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/identity_review.py +162 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/ingest.py +124 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/projects.py +84 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/resume.py +251 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/search.py +404 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/primitives/timeline.py +89 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/setup.py +143 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/source/__init__.py +11 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/source/mongo.py +115 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/source/protocol.py +37 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/__init__.py +141 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/assertions.py +128 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/entities.py +214 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/protocols.py +294 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/__init__.py +11 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/_occ.py +36 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/_rid.py +54 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/article_store.py +376 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/build_jobs.py +101 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/concept_index.py +261 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/factory.py +130 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/integrity_probe.py +104 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/manual_log.py +47 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/pool.py +173 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/relate_queue.py +217 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/relation_graph.py +357 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/schema.py +462 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/synth_boundary.py +316 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/turn_log.py +164 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/surrealdb/worker_state.py +168 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/storage/utils.py +18 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/workers/__init__.py +13 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/workers/articulator_phase.py +106 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/workers/orchestrator.py +176 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/workers/phase_a.py +113 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/workers/relator_phase.py +83 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/core/workers/turn_ingest.py +150 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_cli/__init__.py +6 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_cli/__main__.py +182 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_mcp/__init__.py +6 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_mcp/tools.py +354 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_web/__init__.py +6 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_web/dashboard.py +234 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/cortex2_web/static/index.html +1097 -0
- neo_cortex2_mcp-6.1.0/src/neo_cortex/mbel.md +59 -0
- neo_cortex2_mcp-6.1.0/tests/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/_article_factory.py +41 -0
- neo_cortex2_mcp-6.1.0/tests/_surreal_instance.py +74 -0
- neo_cortex2_mcp-6.1.0/tests/conftest.py +176 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/conftest.py +278 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_cli.py +848 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_crash_recovery.py +306 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_edge_cases.py +253 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_fixture.py +94 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_full_pipeline_flow.py +146 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_llm_errors.py +638 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_maintenance_lifecycle.py +168 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_mcp_tools.py +994 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_pipeline_atomics.py +336 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_rebuild_cycle.py +219 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_stress.py +231 -0
- neo_cortex2_mcp-6.1.0/tests/e2e/test_worker_phases.py +269 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/conversation_log_snapshot.db +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_db_snapshot/5844946a-6106-4ad5-8726-20afd3d66c9e/data_level0.bin +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_db_snapshot/5844946a-6106-4ad5-8726-20afd3d66c9e/header.bin +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_db_snapshot/5844946a-6106-4ad5-8726-20afd3d66c9e/index_metadata.pickle +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_db_snapshot/5844946a-6106-4ad5-8726-20afd3d66c9e/length.bin +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_db_snapshot/5844946a-6106-4ad5-8726-20afd3d66c9e/link_lists.bin +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_db_snapshot/chroma.sqlite3 +0 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/cortex_projects_with_descriptions.json +34 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/poc_synth_ids.txt +12 -0
- neo_cortex2_mcp-6.1.0/tests/fixtures/regression_articles.json +186 -0
- neo_cortex2_mcp-6.1.0/tests/integration/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/algo/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/algo/test_primitives_v3.py +96 -0
- neo_cortex2_mcp-6.1.0/tests/integration/cli/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/cli/test_import_logs.py +173 -0
- neo_cortex2_mcp-6.1.0/tests/integration/cli/test_init_status.py +121 -0
- neo_cortex2_mcp-6.1.0/tests/integration/cli/test_stop_hook_v2.py +30 -0
- neo_cortex2_mcp-6.1.0/tests/integration/conftest.py +45 -0
- neo_cortex2_mcp-6.1.0/tests/integration/e2e/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/e2e/test_e2e_v3.py +147 -0
- neo_cortex2_mcp-6.1.0/tests/integration/integrity/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/integrity/test_integrity_scan.py +106 -0
- neo_cortex2_mcp-6.1.0/tests/integration/pipeline/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/pipeline/test_stop_hook.py +207 -0
- neo_cortex2_mcp-6.1.0/tests/integration/pipeline/test_synth_lifecycle.py +119 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/test_cortex_drill.py +144 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/test_cortex_ingest.py +201 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/test_cortex_projects.py +194 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/test_cortex_resume.py +94 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/test_cortex_search.py +215 -0
- neo_cortex2_mcp-6.1.0/tests/integration/primitives/test_cortex_timeline.py +149 -0
- neo_cortex2_mcp-6.1.0/tests/integration/rebuild/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/rebuild/test_rebuild_v3.py +107 -0
- neo_cortex2_mcp-6.1.0/tests/integration/scripts/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/scripts/test_scripts_pool.py +55 -0
- neo_cortex2_mcp-6.1.0/tests/integration/smoke/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/smoke/test_mcp_dashboard_v3.py +46 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_article_store_query_fix.py +135 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_article_store_v3.py +69 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_assertions.py +147 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_boot_v3.py +67 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_build_jobs.py +97 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_clear_for_project.py +122 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_concept_index_v3.py +64 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_concurrency_production.py +245 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_factory_boot_pool.py +180 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_lock_race.py +84 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_manual_log.py +74 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_persist_conflict_robustness.py +182 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_pool_ws_concurrency.py +69 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_pool_ws_robustness.py +126 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_post_write_assertions.py +135 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_provider_consolidation.py +12 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_queue_claim_atomic.py +87 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_relation_graph_v3.py +79 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_return_before_bulk.py +149 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_schema_apply_concurrent.py +79 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_schema_on_pool.py +125 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_schema_v3.py +106 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_search_lean_projection.py +134 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_storage_backend_surrealdb_e2e.py +116 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_article_store.py +327 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_concept_index.py +297 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_pool.py +137 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_relate_queue.py +159 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_relation_graph.py +401 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_schema.py +1034 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_synth_boundary.py +181 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_turn_log.py +112 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_surreal_worker_state.py +105 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_synth_claim_articulating.py +119 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_synth_extend_atomic.py +95 -0
- neo_cortex2_mcp-6.1.0/tests/integration/storage/test_worker_state_upsert_atomic.py +126 -0
- neo_cortex2_mcp-6.1.0/tests/integration/test_orphan_guard.py +88 -0
- neo_cortex2_mcp-6.1.0/tests/integration/test_prompt_quality.py +431 -0
- neo_cortex2_mcp-6.1.0/tests/integration/test_surreal_test_instance.py +97 -0
- neo_cortex2_mcp-6.1.0/tests/integration/test_validator_regression.py +101 -0
- neo_cortex2_mcp-6.1.0/tests/integration/web/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/web/test_dashboard_smoke.py +255 -0
- neo_cortex2_mcp-6.1.0/tests/integration/workers/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/integration/workers/test_orchestrator_integration.py +139 -0
- neo_cortex2_mcp-6.1.0/tests/integration/workers/test_workers_v3.py +73 -0
- neo_cortex2_mcp-6.1.0/tests/unit/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_connection_removed.py +76 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_no_db_access_without_pool.py +123 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_no_handrolled_pool_in_tests.py +50 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_no_warning_suppression.py +95 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_prod_safety_guard.py +41 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_single_pool_provider.py +44 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_storage_isolation.py +143 -0
- neo_cortex2_mcp-6.1.0/tests/unit/architecture/test_test_groups.py +108 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_dashboard_v2.py +83 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_mcp_server_surrealdb_check.py +23 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_mcp_server_v2.py +179 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_rebuild_cli.py +196 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_rebuild_cli_protocol.py +28 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_stop_hook_signal.py +56 -0
- neo_cortex2_mcp-6.1.0/tests/unit/cli/test_timeline_v2.py +163 -0
- neo_cortex2_mcp-6.1.0/tests/unit/config/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/config/test_project_discovery.py +142 -0
- neo_cortex2_mcp-6.1.0/tests/unit/config/test_projects_config_with_description.py +62 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/llm/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/llm/test_executor.py +230 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/llm/test_openrouter_session.py +117 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/llm/test_validators_protocol.py +51 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/source/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/source/test_mongo.py +168 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/source/test_protocol.py +49 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_auto_setup.py +136 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_bundle.py +203 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_config_workers.py +44 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_cortex_config.py +265 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_hooks.py +68 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_llm_factory.py +79 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_logging.py +164 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_logging_no_warning.py +57 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_logging_quiet_loggers.py +42 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_setup_logging_defaults.py +19 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/test_storage_factory.py +188 -0
- neo_cortex2_mcp-6.1.0/tests/unit/core/workers/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/mcp/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_apply_turn_to_synth.py +156 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_article_schema_no_length_constraints.py +43 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_article_validator.py +276 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_articulator_template_no_examples.py +61 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_articulator_v2.py +181 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_manual_path.py +135 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_prompt_helpers.py +74 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_relate_jobs.py +376 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_relate_validator.py +91 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_relatore.py +208 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_retry.py +188 -0
- neo_cortex2_mcp-6.1.0/tests/unit/pipeline/test_transcript_cleanup.py +67 -0
- neo_cortex2_mcp-6.1.0/tests/unit/primitives/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/primitives/test_cortex_identity_review.py +183 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_entity_article_strict.py +81 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_entity_relate_queue.py +83 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_pool_lockless.py +26 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_pool_url_guard.py +35 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_protocols.py +230 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_rid_helpers.py +74 -0
- neo_cortex2_mcp-6.1.0/tests/unit/storage/test_schema_v3_guards.py +72 -0
- neo_cortex2_mcp-6.1.0/tests/unit/test_no_silent_exceptions.py +37 -0
- neo_cortex2_mcp-6.1.0/tests/unit/web/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/web/test_dashboard.py +270 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/__init__.py +0 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_articulator_exactly_once.py +173 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_guard_maintenance.py +129 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_mcp_integration.py +115 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_orchestrator.py +130 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_phase_a.py +169 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_phases.py +179 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_rebuild_tool_complete.py +115 -0
- neo_cortex2_mcp-6.1.0/tests/unit/workers/test_turn_ingest.py +168 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
.venv/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
logs/
|
|
9
|
+
neo-cortex.log
|
|
10
|
+
cortex_db/
|
|
11
|
+
neo-cortex.log.1
|
|
12
|
+
*.log.1
|
|
13
|
+
.lsai/
|
|
14
|
+
|
|
15
|
+
# Postgres dev volume
|
|
16
|
+
pgdata/
|
|
17
|
+
.env
|
|
18
|
+
|
|
19
|
+
# Throwaway forensic probes / experiments (never committed)
|
|
20
|
+
tmp/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: neo-cortex2-mcp
|
|
3
|
+
Version: 6.1.0
|
|
4
|
+
Summary: Neo Memory Cortex — Standalone Memory Server
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: fastapi>=0.115.0
|
|
7
|
+
Requires-Dist: fastmcp>=2.14.0
|
|
8
|
+
Requires-Dist: httpx>=0.28.0
|
|
9
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
10
|
+
Requires-Dist: pydantic>=2.10.0
|
|
11
|
+
Requires-Dist: structlog>=24.0.0
|
|
12
|
+
Requires-Dist: surrealdb>=2.0.0
|
|
13
|
+
Requires-Dist: uvicorn>=0.34.0
|
|
14
|
+
Requires-Dist: watchfiles>=1.0.0
|
|
15
|
+
Provides-Extra: anthropic
|
|
16
|
+
Requires-Dist: anthropic>=0.40.0; extra == 'anthropic'
|
|
17
|
+
Provides-Extra: claude
|
|
18
|
+
Requires-Dist: claude-code-sdk>=0.0.1; extra == 'claude'
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pyright>=1.1.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest-asyncio>=0.25.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest-httpx>=0.35.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pyyaml>=6.0; extra == 'dev'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# MBEL v5 Grammar [IMMUTABLE]
|
|
2
|
+
|
|
3
|
+
§MBEL:5.0
|
|
4
|
+
@purpose::AIMemoryEncoding{compression%75,fidelity%100}
|
|
5
|
+
|
|
6
|
+
## Operators [IMMUTABLE]
|
|
7
|
+
|
|
8
|
+
### Core Set (27)
|
|
9
|
+
```
|
|
10
|
+
[Temporal:4]
|
|
11
|
+
> past/did/changed/was
|
|
12
|
+
@ present/current/now/is
|
|
13
|
+
? future/todo/will/planned
|
|
14
|
+
≈ around/circa/approximate/roughly
|
|
15
|
+
|
|
16
|
+
[State:4]
|
|
17
|
+
✓ complete/done/success/working
|
|
18
|
+
✗ failed/broken/error/bug
|
|
19
|
+
! critical/important/priority/alert
|
|
20
|
+
⚡ active/urgent/in-progress/hot
|
|
21
|
+
|
|
22
|
+
[Relation:6]
|
|
23
|
+
:: is/defines/equals/becomes
|
|
24
|
+
→ leads_to/causes/then/produces
|
|
25
|
+
← comes_from/because/source/from
|
|
26
|
+
↔ mutual/bidirectional/syncs/relates
|
|
27
|
+
+ and/with/combines/includes
|
|
28
|
+
- remove/delete/without/except
|
|
29
|
+
|
|
30
|
+
[Structure:5]
|
|
31
|
+
[] section/category/namespace/group
|
|
32
|
+
{} metadata/attributes/properties/details
|
|
33
|
+
() note/comment/aside/remark
|
|
34
|
+
| or/alternative/choice/option
|
|
35
|
+
<> variant/template/placeholder/variable
|
|
36
|
+
|
|
37
|
+
[Quantification:3]
|
|
38
|
+
# number/count/quantity/amount
|
|
39
|
+
% percentage/ratio/proportion/part
|
|
40
|
+
~ approximately/range/between/around
|
|
41
|
+
|
|
42
|
+
[Logic:3]
|
|
43
|
+
& AND/requires/must-have/with
|
|
44
|
+
|| OR/either/can-be/allows
|
|
45
|
+
¬ NOT/exclude/prevent/disable
|
|
46
|
+
|
|
47
|
+
[Meta:2]
|
|
48
|
+
© source/origin/author/credit
|
|
49
|
+
§ version/revision/protocol/schema
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Grammar Rules [IMMUTABLE]
|
|
53
|
+
1. NoArticles(a/the/an)
|
|
54
|
+
2. CamelCase→MultiWord
|
|
55
|
+
3. ImplicitSubject{contextClear}
|
|
56
|
+
4. OperatorsOnly¬Punctuation
|
|
57
|
+
5. Newline::StatementSeparator
|
|
58
|
+
6. LatestOverridesPrevious
|
|
59
|
+
7. LeftToRight→Composition
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "neo-cortex2-mcp"
|
|
7
|
+
version = "6.1.0"
|
|
8
|
+
description = "Neo Memory Cortex — Standalone Memory Server"
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"fastapi>=0.115.0",
|
|
12
|
+
"uvicorn>=0.34.0",
|
|
13
|
+
"httpx>=0.28.0",
|
|
14
|
+
"pydantic>=2.10.0",
|
|
15
|
+
"fastmcp>=2.14.0",
|
|
16
|
+
"structlog>=24.0.0",
|
|
17
|
+
"pydantic-settings>=2.0.0",
|
|
18
|
+
"surrealdb>=2.0.0",
|
|
19
|
+
"watchfiles>=1.0.0",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
neo-cortex2-stop-hook = "neo_cortex.cli.stop_hook:cli"
|
|
24
|
+
neo-cortex2-mcp = "neo_cortex.cli.mcp_server_v2:cli"
|
|
25
|
+
neo-cortex2-dashboard = "neo_cortex.cli.dashboard_v2:cli"
|
|
26
|
+
neo-cortex2-import = "neo_cortex.cli.import_logs:cli"
|
|
27
|
+
neo-cortex2-rebuild = "neo_cortex.cli.rebuild_cli:cli"
|
|
28
|
+
neo-cortex2-timeline = "neo_cortex.cli.timeline_v2:cli"
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
claude = ["claude-code-sdk>=0.0.1"]
|
|
32
|
+
anthropic = ["anthropic>=0.40.0"]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=8.0.0",
|
|
35
|
+
"pytest-asyncio>=0.25.0",
|
|
36
|
+
"pytest-httpx>=0.35.0",
|
|
37
|
+
"pyright>=1.1.0",
|
|
38
|
+
"pyyaml>=6.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/neo_cortex"]
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel.shared-data]
|
|
45
|
+
"src/neo_cortex/core/pipeline/prompts" = "neo_cortex/core/pipeline/prompts"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.sdist]
|
|
48
|
+
include = ["src/neo_cortex/**", "mbel.md", "tests/**", "pyproject.toml"]
|
|
49
|
+
|
|
50
|
+
[tool.pytest.ini_options]
|
|
51
|
+
asyncio_mode = "auto"
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
markers = [
|
|
54
|
+
"unit: fast in-process unit test, no external dependencies",
|
|
55
|
+
"integration: requires external service (SurrealDB, etc.)",
|
|
56
|
+
"slow: long-running test, opt-in via -m slow",
|
|
57
|
+
"live_llm: hits a live LLM provider (OpenRouter); gated by RUN_LIVE_LLM_TESTS=1",
|
|
58
|
+
"e2e: end-to-end test with real SurrealDB, fake LLM/embedder",
|
|
59
|
+
]
|
|
60
|
+
filterwarnings = [
|
|
61
|
+
"error",
|
|
62
|
+
# CAUSA B — finalizzazione GC dell'async-generator `Connection.__aiter__` di websockets
|
|
63
|
+
# (v15.0.1, asyncio API), iterato in `_recv_task` del SDK surrealdb-py
|
|
64
|
+
# (`connections/async_ws.py:59` `async for data in self.socket`), finalizzato dal GC DOPO
|
|
65
|
+
# la chiusura del loop per-test di pytest-asyncio. NON è un leak nostro:
|
|
66
|
+
# misurato 1164 connessioni aperte = 1164 `close()` chiamate (0 non chiuse). Upstream, benigna.
|
|
67
|
+
# Pattern scoped al repr esatto dell'async-gen; il `.*` copre il prefisso "Exception ignored in:"
|
|
68
|
+
# (evita il `:` come separatore di campo). Verificato: matcha solo questo async-gen, non altri.
|
|
69
|
+
"ignore:.*async_generator object Connection\\.__aiter__:pytest.PytestUnraisableExceptionWarning",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.pyright]
|
|
73
|
+
typeCheckingMode = "strict"
|
|
74
|
+
pythonVersion = "3.12"
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Bundled assets for auto-setup (compose, model profiles, gitignore)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import importlib.resources
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_asset(name: str) -> Path:
|
|
9
|
+
"""Return the filesystem path to a bundled asset file."""
|
|
10
|
+
return importlib.resources.files(__package__) / name
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"active": "openrouter_default",
|
|
3
|
+
"profiles": {
|
|
4
|
+
"openrouter_default": {
|
|
5
|
+
"name": "DeepSeek v4 Flash via OpenRouter",
|
|
6
|
+
"description": "Default profile. Fast, cheap, high quality articulation.",
|
|
7
|
+
"provider": "openrouter",
|
|
8
|
+
"model": "deepseek/deepseek-v4-flash",
|
|
9
|
+
"reasoning_effort": "high",
|
|
10
|
+
"max_tokens": 300000
|
|
11
|
+
},
|
|
12
|
+
"gemini": {
|
|
13
|
+
"name": "Gemini 2.5 Flash",
|
|
14
|
+
"description": "Google Gemini via OpenRouter. Good quality, very cheap.",
|
|
15
|
+
"provider": "openrouter",
|
|
16
|
+
"model": "google/gemini-2.5-flash",
|
|
17
|
+
"reasoning_effort": "high",
|
|
18
|
+
"max_tokens": 65000
|
|
19
|
+
},
|
|
20
|
+
"groq": {
|
|
21
|
+
"name": "Llama 4 Scout via Groq",
|
|
22
|
+
"description": "Fastest inference. Groq direct API, no OpenRouter.",
|
|
23
|
+
"provider": "groq",
|
|
24
|
+
"model": "meta-llama/llama-4-scout-17b-16e-instruct",
|
|
25
|
+
"max_tokens": 8192
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: cortex2
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
surrealdb:
|
|
5
|
+
image: surrealdb/surrealdb:v3.0.5
|
|
6
|
+
container_name: cortex-surrealdb
|
|
7
|
+
user: "0:0"
|
|
8
|
+
command: start --user ${SURREAL_USER:-root} --pass ${SURREAL_PASS:-root} rocksdb:/data/srdb
|
|
9
|
+
ports:
|
|
10
|
+
- "${SURREAL_PORT:-8000}:8000"
|
|
11
|
+
volumes:
|
|
12
|
+
- surreal-data:/data
|
|
13
|
+
healthcheck:
|
|
14
|
+
test: ["CMD", "/surreal", "is-ready"]
|
|
15
|
+
interval: 5s
|
|
16
|
+
timeout: 3s
|
|
17
|
+
retries: 10
|
|
18
|
+
restart: unless-stopped
|
|
19
|
+
|
|
20
|
+
dashboard:
|
|
21
|
+
image: ghcr.io/astral-sh/uv:python3.12-bookworm-slim
|
|
22
|
+
container_name: cortex-dashboard
|
|
23
|
+
command: uvx --from neo-cortex-mcp neo-cortex2-dashboard
|
|
24
|
+
ports:
|
|
25
|
+
- "${DASHBOARD_PORT:-5075}:5075"
|
|
26
|
+
env_file: .env
|
|
27
|
+
environment:
|
|
28
|
+
UV_PRERELEASE: allow
|
|
29
|
+
CORTEX_STORAGE__SURREALDB_URL: http://surrealdb:8000
|
|
30
|
+
CORTEX2_DASHBOARD_HOST: "0.0.0.0"
|
|
31
|
+
depends_on:
|
|
32
|
+
surrealdb:
|
|
33
|
+
condition: service_healthy
|
|
34
|
+
restart: unless-stopped
|
|
35
|
+
|
|
36
|
+
volumes:
|
|
37
|
+
surreal-data:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Command-line entry points for cortex2."""
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""cortex2 dashboard entrypoint — read-only FastAPI on port 5075.
|
|
2
|
+
|
|
3
|
+
Boots `cortex2_web.dashboard.build_app(bundle)` against the same
|
|
4
|
+
storage bundle the MCP server uses. NO worker tasks (the dashboard is
|
|
5
|
+
read-only — it observes what the workers produce, never schedules work
|
|
6
|
+
itself).
|
|
7
|
+
|
|
8
|
+
Listens on port 5075 by default to coexist with the legacy dashboard on
|
|
9
|
+
5074. Override via CORTEX2_DASHBOARD_PORT / CORTEX2_DASHBOARD_HOST.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import asyncio
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
import structlog
|
|
19
|
+
import uvicorn
|
|
20
|
+
|
|
21
|
+
from neo_cortex.core.bundle import build_bundle, close_bundle
|
|
22
|
+
from neo_cortex.core.config.schema import CortexConfig
|
|
23
|
+
from neo_cortex.core.logging import configure_logging
|
|
24
|
+
from neo_cortex.cortex2_web.dashboard import build_app
|
|
25
|
+
|
|
26
|
+
log = structlog.get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _resolve_host() -> str:
|
|
30
|
+
return os.environ.get("CORTEX2_DASHBOARD_HOST", "127.0.0.1")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _resolve_port() -> int:
|
|
34
|
+
raw = os.environ.get("CORTEX2_DASHBOARD_PORT", "5075")
|
|
35
|
+
try:
|
|
36
|
+
return int(raw)
|
|
37
|
+
except ValueError:
|
|
38
|
+
return 5075
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def _build_app_async() -> tuple:
|
|
42
|
+
config = CortexConfig.load()
|
|
43
|
+
configure_logging(config.logging)
|
|
44
|
+
bundle = await build_bundle(config)
|
|
45
|
+
app = build_app(bundle)
|
|
46
|
+
return app, bundle
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def cli(argv: list[str] | None = None) -> int:
|
|
50
|
+
parser = argparse.ArgumentParser(
|
|
51
|
+
description="cortex2 dashboard — read-only FastAPI",
|
|
52
|
+
)
|
|
53
|
+
parser.add_argument("--host", default=None)
|
|
54
|
+
parser.add_argument("--port", type=int, default=None)
|
|
55
|
+
args = parser.parse_args(argv)
|
|
56
|
+
|
|
57
|
+
host = args.host or _resolve_host()
|
|
58
|
+
port = args.port or _resolve_port()
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
app, bundle = asyncio.run(_build_app_async())
|
|
62
|
+
except Exception as e: # noqa: BLE001
|
|
63
|
+
log.error("cortex2.dashboard.init_failed", error=str(e))
|
|
64
|
+
return 1
|
|
65
|
+
|
|
66
|
+
log.info("cortex2.dashboard.starting", host=host, port=port)
|
|
67
|
+
try:
|
|
68
|
+
uvicorn.run(app, host=host, port=port, log_level="info")
|
|
69
|
+
finally:
|
|
70
|
+
try:
|
|
71
|
+
asyncio.run(close_bundle(bundle))
|
|
72
|
+
except Exception: # noqa: BLE001
|
|
73
|
+
pass
|
|
74
|
+
return 0
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
raise SystemExit(cli())
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""cortex2 importer — drain a legacy ConversationLog into bundle.turn_log.
|
|
2
|
+
|
|
3
|
+
Source-agnostic: accepts any IConversationLogSource implementation.
|
|
4
|
+
Today: `--source mongo --uri ... --db ... --ws ...` builds a
|
|
5
|
+
MongoConversationLogSource. Tomorrow: `--source sqlite --path ...` will
|
|
6
|
+
build the SQLite adapter (Plan 35) without changing this CLI.
|
|
7
|
+
|
|
8
|
+
Idempotent: bundle.turn_log.append_if_new uses content_hash UNIQUE — a
|
|
9
|
+
re-run on the same source skips already-imported turns. `--since-ts`
|
|
10
|
+
acts as a coarse cursor for resume.
|
|
11
|
+
|
|
12
|
+
Progress: structlog event every PROGRESS_EVERY rows.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import asyncio
|
|
18
|
+
import sys
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
import structlog
|
|
22
|
+
|
|
23
|
+
from neo_cortex.core.bundle import build_bundle, close_bundle
|
|
24
|
+
from neo_cortex.core.config.schema import CortexConfig
|
|
25
|
+
from neo_cortex.core.logging import configure_logging
|
|
26
|
+
from neo_cortex.core.source import IConversationLogSource
|
|
27
|
+
from neo_cortex.core.storage.entities import Turn
|
|
28
|
+
from neo_cortex.core.storage.utils import compute_content_hash
|
|
29
|
+
|
|
30
|
+
log = structlog.get_logger(__name__)
|
|
31
|
+
|
|
32
|
+
PROGRESS_EVERY = 200
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
async def _drain(
|
|
36
|
+
source: IConversationLogSource,
|
|
37
|
+
bundle,
|
|
38
|
+
*,
|
|
39
|
+
session_id_filter: Optional[str],
|
|
40
|
+
since_ts: Optional[float],
|
|
41
|
+
limit: Optional[int],
|
|
42
|
+
) -> dict:
|
|
43
|
+
n_seen = 0
|
|
44
|
+
n_inserted = 0
|
|
45
|
+
n_skipped = 0
|
|
46
|
+
n_errors = 0
|
|
47
|
+
last_ts = since_ts or 0.0
|
|
48
|
+
|
|
49
|
+
async for turn in source.iter_entries(
|
|
50
|
+
session_id_filter=session_id_filter,
|
|
51
|
+
since_ts=since_ts,
|
|
52
|
+
limit=limit,
|
|
53
|
+
):
|
|
54
|
+
n_seen += 1
|
|
55
|
+
# Compute content_hash here so re-runs are idempotent regardless
|
|
56
|
+
# of whether the source provides the column.
|
|
57
|
+
if turn.content_hash is None:
|
|
58
|
+
turn = Turn(
|
|
59
|
+
session_id=turn.session_id,
|
|
60
|
+
ts=turn.ts,
|
|
61
|
+
role=turn.role,
|
|
62
|
+
content=turn.content,
|
|
63
|
+
content_hash=compute_content_hash(turn),
|
|
64
|
+
)
|
|
65
|
+
try:
|
|
66
|
+
if hasattr(bundle.turn_log, "append_if_new"):
|
|
67
|
+
inserted = await bundle.turn_log.append_if_new(turn)
|
|
68
|
+
if inserted:
|
|
69
|
+
n_inserted += 1
|
|
70
|
+
else:
|
|
71
|
+
n_skipped += 1
|
|
72
|
+
else:
|
|
73
|
+
await bundle.turn_log.append(turn)
|
|
74
|
+
n_inserted += 1
|
|
75
|
+
last_ts = max(last_ts, turn.ts)
|
|
76
|
+
except Exception as e: # noqa: BLE001 — keep draining on errors
|
|
77
|
+
n_errors += 1
|
|
78
|
+
log.warning(
|
|
79
|
+
"importer.row_failed",
|
|
80
|
+
ts=turn.ts, session=turn.session_id, error=str(e),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if n_seen % PROGRESS_EVERY == 0:
|
|
84
|
+
log.info(
|
|
85
|
+
"importer.progress",
|
|
86
|
+
seen=n_seen, inserted=n_inserted, skipped=n_skipped,
|
|
87
|
+
errors=n_errors, last_ts=last_ts,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
"seen": n_seen,
|
|
92
|
+
"inserted": n_inserted,
|
|
93
|
+
"skipped": n_skipped,
|
|
94
|
+
"errors": n_errors,
|
|
95
|
+
"last_ts": last_ts,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _build_source(args: argparse.Namespace) -> IConversationLogSource:
|
|
100
|
+
if args.source == "mongo":
|
|
101
|
+
if not args.mongo_uri or not args.mongo_db:
|
|
102
|
+
raise SystemExit(
|
|
103
|
+
"--source mongo requires --mongo-uri and --mongo-db"
|
|
104
|
+
)
|
|
105
|
+
from neo_cortex.core.source.mongo import (
|
|
106
|
+
MongoConversationLogSource,
|
|
107
|
+
)
|
|
108
|
+
return MongoConversationLogSource(
|
|
109
|
+
mongo_uri=args.mongo_uri,
|
|
110
|
+
db_name=args.mongo_db,
|
|
111
|
+
ws_name=args.ws,
|
|
112
|
+
)
|
|
113
|
+
raise SystemExit(f"unknown --source: {args.source}")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
async def _run(args: argparse.Namespace) -> int:
|
|
117
|
+
config = CortexConfig.load()
|
|
118
|
+
configure_logging(config.logging)
|
|
119
|
+
bundle = await build_bundle(config)
|
|
120
|
+
source = _build_source(args)
|
|
121
|
+
try:
|
|
122
|
+
stats = await _drain(
|
|
123
|
+
source, bundle,
|
|
124
|
+
session_id_filter=args.session_id,
|
|
125
|
+
since_ts=args.since_ts,
|
|
126
|
+
limit=args.limit,
|
|
127
|
+
)
|
|
128
|
+
log.info("importer.done", **stats)
|
|
129
|
+
print(
|
|
130
|
+
f"[importer] seen={stats['seen']} "
|
|
131
|
+
f"inserted={stats['inserted']} "
|
|
132
|
+
f"skipped(dup)={stats['skipped']} "
|
|
133
|
+
f"errors={stats['errors']} "
|
|
134
|
+
f"last_ts={stats['last_ts']}",
|
|
135
|
+
)
|
|
136
|
+
return 0 if stats["errors"] == 0 else 2
|
|
137
|
+
finally:
|
|
138
|
+
await source.close()
|
|
139
|
+
await close_bundle(bundle)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def cli(argv: list[str] | None = None) -> int:
|
|
143
|
+
parser = argparse.ArgumentParser(
|
|
144
|
+
description="cortex2 importer — drain legacy ConversationLog into "
|
|
145
|
+
"bundle.turn_log via storage Protocol",
|
|
146
|
+
)
|
|
147
|
+
parser.add_argument(
|
|
148
|
+
"--source", choices=["mongo"], required=True,
|
|
149
|
+
help="adapter selector (sqlite/jsonl coming in Plan 35)",
|
|
150
|
+
)
|
|
151
|
+
parser.add_argument("--ws", required=True, help="workspace name")
|
|
152
|
+
parser.add_argument("--mongo-uri", help="mongo connection URI")
|
|
153
|
+
parser.add_argument("--mongo-db", help="mongo database name")
|
|
154
|
+
parser.add_argument("--session-id", default=None, help="filter to one session")
|
|
155
|
+
parser.add_argument(
|
|
156
|
+
"--since-ts", type=float, default=None,
|
|
157
|
+
help="resume cursor — skip turns with ts <= value",
|
|
158
|
+
)
|
|
159
|
+
parser.add_argument(
|
|
160
|
+
"--limit", type=int, default=None,
|
|
161
|
+
help="cap on total imported turns (smoke runs)",
|
|
162
|
+
)
|
|
163
|
+
args = parser.parse_args(argv)
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
return asyncio.run(_run(args))
|
|
167
|
+
except KeyboardInterrupt:
|
|
168
|
+
return 130
|
|
169
|
+
except Exception as e: # noqa: BLE001
|
|
170
|
+
log.error("cortex2.import.fatal", error=str(e))
|
|
171
|
+
return 1
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
if __name__ == "__main__":
|
|
175
|
+
raise SystemExit(cli())
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""cortex init — atomic setup for a new ws + subscribed projects.
|
|
2
|
+
|
|
3
|
+
Applies the LOGS_DDL to cortex_logs/<ws_name> and the PROJECTS_DDL to
|
|
4
|
+
cortex_projects/<each subscribed project>. Idempotent — safe to run
|
|
5
|
+
multiple times. Optionally writes a default `.cortex.env` if missing.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import asyncio
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING, Optional
|
|
13
|
+
|
|
14
|
+
from neo_cortex.core.logging import get_logger
|
|
15
|
+
from neo_cortex.core.storage.surrealdb.schema import apply_schema
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from neo_cortex.core.storage.surrealdb.pool import SurrealPool
|
|
19
|
+
|
|
20
|
+
log = get_logger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
_DEFAULT_ENV = """\
|
|
24
|
+
# cortex2 environment
|
|
25
|
+
CORTEX_STORAGE__SURREALDB_URL=http://localhost:8000
|
|
26
|
+
CORTEX_STORAGE__SURREALDB_USER=root
|
|
27
|
+
CORTEX_STORAGE__SURREALDB_PASS=root
|
|
28
|
+
CORTEX_LLM__PROVIDER=openrouter
|
|
29
|
+
CORTEX_EMBEDDING__API_KEY=jina-key-here
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def cortex_init(
|
|
34
|
+
ws_name: str,
|
|
35
|
+
projects: list[str],
|
|
36
|
+
pool: "SurrealPool",
|
|
37
|
+
env_path: Optional[Path] = None,
|
|
38
|
+
*,
|
|
39
|
+
logs_ns: str = "cortex_logs",
|
|
40
|
+
projects_ns: str = "cortex_projects",
|
|
41
|
+
) -> int:
|
|
42
|
+
"""Returns 0 on success, non-zero on failure."""
|
|
43
|
+
await apply_schema(pool, logs_ns, ws_name)
|
|
44
|
+
for p in projects:
|
|
45
|
+
await apply_schema(pool, projects_ns, p)
|
|
46
|
+
|
|
47
|
+
if env_path is not None and not env_path.exists():
|
|
48
|
+
env_path.write_text(_DEFAULT_ENV)
|
|
49
|
+
log.info("cortex_init.env_written", path=str(env_path))
|
|
50
|
+
|
|
51
|
+
log.info(
|
|
52
|
+
"cortex_init.done",
|
|
53
|
+
ws=ws_name, n_projects=len(projects),
|
|
54
|
+
)
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main() -> int:
|
|
59
|
+
parser = argparse.ArgumentParser(description="cortex2 init")
|
|
60
|
+
parser.add_argument("--ws", required=True, help="workspace name")
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"--project", action="append", default=[],
|
|
63
|
+
help="subscribed project (repeatable)",
|
|
64
|
+
)
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
"--env", help="path to write .cortex.env if missing",
|
|
67
|
+
)
|
|
68
|
+
args = parser.parse_args()
|
|
69
|
+
print(
|
|
70
|
+
f"cortex init --ws {args.ws} "
|
|
71
|
+
f"--projects {args.project} --env {args.env}"
|
|
72
|
+
)
|
|
73
|
+
print(
|
|
74
|
+
"Live wiring requires a SurrealPool — invoke cortex_init() "
|
|
75
|
+
"from the service container."
|
|
76
|
+
)
|
|
77
|
+
return 0
|