ciris-agent 1.7.7__py3-none-any.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.
- ciris_adapters/README.md +113 -0
- ciris_adapters/__init__.py +30 -0
- ciris_adapters/ciris_covenant_metrics/README.md +144 -0
- ciris_adapters/ciris_covenant_metrics/__init__.py +36 -0
- ciris_adapters/ciris_covenant_metrics/adapter.py +249 -0
- ciris_adapters/ciris_covenant_metrics/manifest.json +152 -0
- ciris_adapters/ciris_covenant_metrics/services.py +403 -0
- ciris_adapters/ciris_hosted_tools/__init__.py +24 -0
- ciris_adapters/ciris_hosted_tools/adapter.py +169 -0
- ciris_adapters/ciris_hosted_tools/manifest.json +94 -0
- ciris_adapters/ciris_hosted_tools/services.py +744 -0
- ciris_adapters/external_data_sql/README.md +559 -0
- ciris_adapters/external_data_sql/__init__.py +43 -0
- ciris_adapters/external_data_sql/adapter.py +144 -0
- ciris_adapters/external_data_sql/configurable.py +315 -0
- ciris_adapters/external_data_sql/dialects/__init__.py +37 -0
- ciris_adapters/external_data_sql/dialects/base.py +133 -0
- ciris_adapters/external_data_sql/dialects/mysql.py +63 -0
- ciris_adapters/external_data_sql/dialects/postgresql.py +59 -0
- ciris_adapters/external_data_sql/dialects/sqlite.py +62 -0
- ciris_adapters/external_data_sql/example_config.json +88 -0
- ciris_adapters/external_data_sql/example_privacy_schema.yaml +127 -0
- ciris_adapters/external_data_sql/manifest.json +195 -0
- ciris_adapters/external_data_sql/privacy_schema_loader.py +189 -0
- ciris_adapters/external_data_sql/protocol.py +101 -0
- ciris_adapters/external_data_sql/schemas.py +146 -0
- ciris_adapters/external_data_sql/service.py +1547 -0
- ciris_adapters/external_data_sql/service_old.py +492 -0
- ciris_adapters/home_assistant/__init__.py +63 -0
- ciris_adapters/home_assistant/adapter.py +201 -0
- ciris_adapters/home_assistant/communication_service.py +347 -0
- ciris_adapters/home_assistant/configurable.py +667 -0
- ciris_adapters/home_assistant/manifest.json +203 -0
- ciris_adapters/home_assistant/schemas.py +129 -0
- ciris_adapters/home_assistant/service.py +751 -0
- ciris_adapters/home_assistant/tool_service.py +441 -0
- ciris_adapters/mcp_client/__init__.py +82 -0
- ciris_adapters/mcp_client/adapter.py +847 -0
- ciris_adapters/mcp_client/config.py +280 -0
- ciris_adapters/mcp_client/configurable.py +422 -0
- ciris_adapters/mcp_client/manifest.json +185 -0
- ciris_adapters/mcp_client/mcp_communication_service.py +393 -0
- ciris_adapters/mcp_client/mcp_tool_service.py +463 -0
- ciris_adapters/mcp_client/mcp_wise_service.py +394 -0
- ciris_adapters/mcp_client/schemas.py +149 -0
- ciris_adapters/mcp_client/security.py +592 -0
- ciris_adapters/mcp_common/__init__.py +44 -0
- ciris_adapters/mcp_common/manifest.json +25 -0
- ciris_adapters/mcp_common/protocol.py +315 -0
- ciris_adapters/mcp_common/schemas.py +225 -0
- ciris_adapters/mcp_server/__init__.py +47 -0
- ciris_adapters/mcp_server/adapter.py +581 -0
- ciris_adapters/mcp_server/config.py +260 -0
- ciris_adapters/mcp_server/configurable.py +393 -0
- ciris_adapters/mcp_server/handlers.py +663 -0
- ciris_adapters/mcp_server/manifest.json +211 -0
- ciris_adapters/mcp_server/security.py +500 -0
- ciris_adapters/mock_llm/README.md +117 -0
- ciris_adapters/mock_llm/__init__.py +21 -0
- ciris_adapters/mock_llm/adapter.py +131 -0
- ciris_adapters/mock_llm/configurable.py +237 -0
- ciris_adapters/mock_llm/manifest.json +106 -0
- ciris_adapters/mock_llm/protocol.py +37 -0
- ciris_adapters/mock_llm/responses.py +520 -0
- ciris_adapters/mock_llm/responses_action_selection.py +1041 -0
- ciris_adapters/mock_llm/responses_epistemic.py +17 -0
- ciris_adapters/mock_llm/responses_feedback.py +27 -0
- ciris_adapters/mock_llm/schemas.py +35 -0
- ciris_adapters/mock_llm/service.py +294 -0
- ciris_adapters/navigation/__init__.py +21 -0
- ciris_adapters/navigation/adapter.py +129 -0
- ciris_adapters/navigation/configurable.py +239 -0
- ciris_adapters/navigation/manifest.json +104 -0
- ciris_adapters/navigation/service.py +487 -0
- ciris_adapters/reddit/README.md +132 -0
- ciris_adapters/reddit/REDDIT_ADAPTER_ANALYSIS.md +715 -0
- ciris_adapters/reddit/REDDIT_ADAPTER_SUMMARY.txt +278 -0
- ciris_adapters/reddit/REDDIT_ANALYSIS_INDEX.md +307 -0
- ciris_adapters/reddit/REDDIT_PRODUCTION_READINESS_PLAN.md +518 -0
- ciris_adapters/reddit/__init__.py +15 -0
- ciris_adapters/reddit/adapter.py +189 -0
- ciris_adapters/reddit/configurable.py +274 -0
- ciris_adapters/reddit/error_handler.py +307 -0
- ciris_adapters/reddit/manifest.json +218 -0
- ciris_adapters/reddit/observer.py +532 -0
- ciris_adapters/reddit/protocol.py +34 -0
- ciris_adapters/reddit/schemas.py +433 -0
- ciris_adapters/reddit/service.py +1471 -0
- ciris_adapters/sample_adapter/README.md +474 -0
- ciris_adapters/sample_adapter/__init__.py +45 -0
- ciris_adapters/sample_adapter/adapter.py +208 -0
- ciris_adapters/sample_adapter/configurable.py +469 -0
- ciris_adapters/sample_adapter/manifest.json +247 -0
- ciris_adapters/sample_adapter/services.py +486 -0
- ciris_adapters/weather/__init__.py +16 -0
- ciris_adapters/weather/adapter.py +130 -0
- ciris_adapters/weather/configurable.py +240 -0
- ciris_adapters/weather/manifest.json +156 -0
- ciris_adapters/weather/service.py +600 -0
- ciris_agent-1.7.7.dist-info/METADATA +284 -0
- ciris_agent-1.7.7.dist-info/RECORD +986 -0
- ciris_agent-1.7.7.dist-info/WHEEL +5 -0
- ciris_agent-1.7.7.dist-info/entry_points.txt +15 -0
- ciris_agent-1.7.7.dist-info/licenses/LICENSE +205 -0
- ciris_agent-1.7.7.dist-info/licenses/NOTICE +82 -0
- ciris_agent-1.7.7.dist-info/top_level.txt +4 -0
- ciris_engine/__init__.py +15 -0
- ciris_engine/ciris_templates/ally.yaml +632 -0
- ciris_engine/ciris_templates/default.yaml +411 -0
- ciris_engine/ciris_templates/echo-core.yaml +629 -0
- ciris_engine/ciris_templates/echo-speculative.yaml +764 -0
- ciris_engine/ciris_templates/echo.yaml +647 -0
- ciris_engine/ciris_templates/sage.yaml +332 -0
- ciris_engine/ciris_templates/scout.yaml +338 -0
- ciris_engine/ciris_templates/test.yaml +168 -0
- ciris_engine/cli.py +42 -0
- ciris_engine/config/CIRIS_SERVICES.json +19 -0
- ciris_engine/config/MODEL_CAPABILITIES.json +419 -0
- ciris_engine/config/PRICING_DATA.json +179 -0
- ciris_engine/config/__init__.py +50 -0
- ciris_engine/config/ciris_services.py +113 -0
- ciris_engine/config/model_capabilities.py +388 -0
- ciris_engine/config/pricing_models.py +276 -0
- ciris_engine/constants.py +35 -0
- ciris_engine/data/__init__.py +1 -0
- ciris_engine/data/covenant_1.0b.txt +978 -0
- ciris_engine/gui_static/11steps.svg +107 -0
- ciris_engine/gui_static/2x-schematics.png +0 -0
- ciris_engine/gui_static/404/index.html +1 -0
- ciris_engine/gui_static/404.html +1 -0
- ciris_engine/gui_static/_next/static/0edhkwDxd5UccTsCmtaBi/_buildManifest.js +1 -0
- ciris_engine/gui_static/_next/static/0edhkwDxd5UccTsCmtaBi/_ssgManifest.js +1 -0
- ciris_engine/gui_static/_next/static/U-3xTQao7hc2wnAi-Uekm/_buildManifest.js +1 -0
- ciris_engine/gui_static/_next/static/U-3xTQao7hc2wnAi-Uekm/_ssgManifest.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/3297-60e86ba0f8a7b040.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/3835-2aad4b7f5f8e4643.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4499-99a0bc47de0b8975.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4534-af88cd4ba6e99bff.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4541-84b455f9e0dc4cfe.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4789-61412711484754bb.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/6539-c6398bc9d7018430.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/704-8e827b26cc8c2d32.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/704-fb45d630f3192c6f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8072-de4952a2e6d2b33f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8315-b91d03a3949db0af.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8386-f93a83ccbd789bd9.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/87c73c54-781a7f35148d5433.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8903-fefea3339a02d41b.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/9090-e66485adf8d9d990.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/_not-found/page-a67d9808462c23b1.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/api-keys/page-2d7ee1583bbbd02e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/api-keys/page-6a3c2bae6fe92b7b.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/consent/page-2ed3a035136bc4e8.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/consent/page-b2f5c91844a32422.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/page-25b90f89af3ea58c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/page-b65d16c94ecaf69c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/privacy/page-675b6d05c8f9184f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/privacy/page-cbee2e1c8ab52145.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/settings/page-0f44da06697cf9f0.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/settings/page-563420253577edbf.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/adapters/page-1854631018bc32be.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/agents/page-8353752c176a7c70.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/agents/page-f61a529f110a6040.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/api-demo/page-7f19b9d20d39be28.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/api-demo/page-d1063938f249b8bd.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/audit/page-321b6728b8fff0bb.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/audit/page-ebac35ca961a1277.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/billing/page-6f3dc3bd02924f8e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/billing/page-fa4a469f814c821a.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/comms/page-0d4f734269addd8f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/comms/page-79227d426050089c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/config/page-018d21d683b6e5bc.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/config/page-2aa5a5363ca2a371.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/consent/page-198373205fd316e2.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/consent/page-f2ca39e7713b13f8.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/dashboard/page-1dd5a196f643c60d.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/dashboard/page-530a04d3abbb8cda.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/docs/page-3193b06d094ab654.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/docs/page-330e996dedb87aba.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/layout-0a70f5fc460298b1.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/layout-21f2f99dd5b336e9.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/login/page-33240e6c6034a49d.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/login/page-68ffab6d54a7fdcd.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/logs/page-8a6167aecc4a475c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/memory/page-9ca8c5d0056de3ff.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/memory/page-e961226941c18f81.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/page-6fdb065a787a4974.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/page-89f87d431be6064a.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/runtime/page-2e728b9c43aa164d.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/runtime/page-c7dd033dc40a72f0.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/services/page-ae9f0bdf11d01a95.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/services/page-b10feb79ca5d75e5.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/sessions/page-13ebe7ef1c16ae11.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/sessions/page-e6c82b16d617f785.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/setup/page-0beb5f5b5a5c20fc.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/setup/page-2595e729eae30c0e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/status-dashboard/page-1037c987aecc3653.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/status-dashboard/page-2ffd147f6d3162ff.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/system/page-2c5798d58cafcd91.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/system/page-505b1ba4eceb01c3.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-auth/page-b0cad31d5cb1b2fa.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-auth/page-f3ecd7a8012df230.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-login/page-f35117fdc4105801.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-login/page-fb583a7924114906.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-sdk/page-50f116fd76935563.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-sdk/page-c37d8aa5ba623a44.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/tools/page-429aec7a707777ef.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/tools/page-5f705aad60e0c04e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/users/page-13476b8b0f3808cc.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/users/page-7e500d154ed5bba4.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/wa/page-cc4a9d8a5cb44d08.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/wa/page-ec3e429efbc79230.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/framework-9d29490f5ba089ba.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/main-1f554952e47a82c4.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/main-app-26fa8aed029082e5.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/main-app-97b0486ef6bcef25.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/pages/_app-6ce685456e616eb2.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/pages/_error-d4bce98d93fe21e7.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/webpack-fcebd240b7f8477d.js +1 -0
- ciris_engine/gui_static/_next/static/css/16b94b1fe0cc6e37.css +3 -0
- ciris_engine/gui_static/_next/static/css/77a24ceaae86deff.css +3 -0
- ciris_engine/gui_static/_next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/747892c23ea88013-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/8d697b304b401681-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/9610d9e46709d722-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/d8298875641ec7d4-s.p.woff2 +0 -0
- ciris_engine/gui_static/account/api-keys/index.html +1 -0
- ciris_engine/gui_static/account/api-keys/index.txt +27 -0
- ciris_engine/gui_static/account/consent/index.html +1 -0
- ciris_engine/gui_static/account/consent/index.txt +27 -0
- ciris_engine/gui_static/account/index.html +1 -0
- ciris_engine/gui_static/account/index.txt +27 -0
- ciris_engine/gui_static/account/privacy/index.html +1 -0
- ciris_engine/gui_static/account/privacy/index.txt +27 -0
- ciris_engine/gui_static/account/settings/index.html +1 -0
- ciris_engine/gui_static/account/settings/index.txt +27 -0
- ciris_engine/gui_static/adapters/index.html +1 -0
- ciris_engine/gui_static/adapters/index.txt +27 -0
- ciris_engine/gui_static/agents/index.html +1 -0
- ciris_engine/gui_static/agents/index.txt +27 -0
- ciris_engine/gui_static/andrew-roberts-euBRXcx57T4-unsplash.jpg +0 -0
- ciris_engine/gui_static/api-demo/index.html +1 -0
- ciris_engine/gui_static/api-demo/index.txt +27 -0
- ciris_engine/gui_static/audit/index.html +1 -0
- ciris_engine/gui_static/audit/index.txt +27 -0
- ciris_engine/gui_static/billing/index.html +1 -0
- ciris_engine/gui_static/billing/index.txt +27 -0
- ciris_engine/gui_static/blurryinfo.png +0 -0
- ciris_engine/gui_static/chip-vincent-PkQDwfl9Flc-unsplash.jpg +0 -0
- ciris_engine/gui_static/ciris-architecture.svg +338 -0
- ciris_engine/gui_static/comms/index.html +1 -0
- ciris_engine/gui_static/comms/index.txt +27 -0
- ciris_engine/gui_static/config/index.html +1 -0
- ciris_engine/gui_static/config/index.txt +27 -0
- ciris_engine/gui_static/consent/index.html +1 -0
- ciris_engine/gui_static/consent/index.txt +27 -0
- ciris_engine/gui_static/dashboard/index.html +1 -0
- ciris_engine/gui_static/dashboard/index.txt +27 -0
- ciris_engine/gui_static/docs/index.html +1 -0
- ciris_engine/gui_static/docs/index.txt +27 -0
- ciris_engine/gui_static/eric.png +0 -0
- ciris_engine/gui_static/file.svg +1 -0
- ciris_engine/gui_static/globe.svg +1 -0
- ciris_engine/gui_static/index.html +1 -0
- ciris_engine/gui_static/index.txt +27 -0
- ciris_engine/gui_static/infogfx-1@2x.png +0 -0
- ciris_engine/gui_static/infogfx-2.png +0 -0
- ciris_engine/gui_static/infogfx-dark-1.png +0 -0
- ciris_engine/gui_static/kelly-vohs-soSTXmIxTDU-unsplash.jpg +0 -0
- ciris_engine/gui_static/login/index.html +1 -0
- ciris_engine/gui_static/login/index.txt +27 -0
- ciris_engine/gui_static/logs/index.html +1 -0
- ciris_engine/gui_static/logs/index.txt +27 -0
- ciris_engine/gui_static/memory/index.html +1 -0
- ciris_engine/gui_static/memory/index.txt +27 -0
- ciris_engine/gui_static/nathan-farrish-ArcTfEoBgzs-unsplash.jpg +0 -0
- ciris_engine/gui_static/next.svg +1 -0
- ciris_engine/gui_static/overview.svg +512 -0
- ciris_engine/gui_static/overview1.svg +407 -0
- ciris_engine/gui_static/overview2.svg +370 -0
- ciris_engine/gui_static/pipeline-visualization.svg +278 -0
- ciris_engine/gui_static/privacy-policy.html +160 -0
- ciris_engine/gui_static/runtime/index.html +8 -0
- ciris_engine/gui_static/runtime/index.txt +27 -0
- ciris_engine/gui_static/services/index.html +1 -0
- ciris_engine/gui_static/services/index.txt +27 -0
- ciris_engine/gui_static/sessions/index.html +1 -0
- ciris_engine/gui_static/sessions/index.txt +27 -0
- ciris_engine/gui_static/setup/index.html +1 -0
- ciris_engine/gui_static/setup/index.txt +27 -0
- ciris_engine/gui_static/status-dashboard/index.html +1 -0
- ciris_engine/gui_static/status-dashboard/index.txt +27 -0
- ciris_engine/gui_static/system/index.html +1 -0
- ciris_engine/gui_static/system/index.txt +27 -0
- ciris_engine/gui_static/terms-of-service.html +174 -0
- ciris_engine/gui_static/test-auth/index.html +1 -0
- ciris_engine/gui_static/test-auth/index.txt +27 -0
- ciris_engine/gui_static/test-login/index.html +1 -0
- ciris_engine/gui_static/test-login/index.txt +27 -0
- ciris_engine/gui_static/test-sdk/index.html +1 -0
- ciris_engine/gui_static/test-sdk/index.txt +27 -0
- ciris_engine/gui_static/tools/index.html +1 -0
- ciris_engine/gui_static/tools/index.txt +27 -0
- ciris_engine/gui_static/users/index.html +1 -0
- ciris_engine/gui_static/users/index.txt +27 -0
- ciris_engine/gui_static/vercel.svg +1 -0
- ciris_engine/gui_static/videos/video1.mp4 +0 -0
- ciris_engine/gui_static/videos/video3.mp4 +0 -0
- ciris_engine/gui_static/wa/index.html +1 -0
- ciris_engine/gui_static/wa/index.txt +27 -0
- ciris_engine/gui_static/window.svg +1 -0
- ciris_engine/logic/__init__.py +8 -0
- ciris_engine/logic/adapters/__init__.py +74 -0
- ciris_engine/logic/adapters/api/__init__.py +5 -0
- ciris_engine/logic/adapters/api/adapter.py +1037 -0
- ciris_engine/logic/adapters/api/api_communication.py +370 -0
- ciris_engine/logic/adapters/api/api_document.py +330 -0
- ciris_engine/logic/adapters/api/api_observer.py +24 -0
- ciris_engine/logic/adapters/api/api_runtime_control.py +388 -0
- ciris_engine/logic/adapters/api/api_tools.py +299 -0
- ciris_engine/logic/adapters/api/api_vision.py +215 -0
- ciris_engine/logic/adapters/api/app.py +272 -0
- ciris_engine/logic/adapters/api/auth.py +159 -0
- ciris_engine/logic/adapters/api/config.py +101 -0
- ciris_engine/logic/adapters/api/constants.py +55 -0
- ciris_engine/logic/adapters/api/dependencies/__init__.py +1 -0
- ciris_engine/logic/adapters/api/dependencies/auth.py +260 -0
- ciris_engine/logic/adapters/api/endpoints/__init__.py +1 -0
- ciris_engine/logic/adapters/api/endpoints/emergency.py +86 -0
- ciris_engine/logic/adapters/api/middleware/__init__.py +1 -0
- ciris_engine/logic/adapters/api/middleware/rate_limiter.py +302 -0
- ciris_engine/logic/adapters/api/models.py +29 -0
- ciris_engine/logic/adapters/api/routes/__init__.py +52 -0
- ciris_engine/logic/adapters/api/routes/agent.py +1762 -0
- ciris_engine/logic/adapters/api/routes/audit.py +707 -0
- ciris_engine/logic/adapters/api/routes/auth.py +1745 -0
- ciris_engine/logic/adapters/api/routes/billing.py +895 -0
- ciris_engine/logic/adapters/api/routes/config.py +329 -0
- ciris_engine/logic/adapters/api/routes/connectors.py +534 -0
- ciris_engine/logic/adapters/api/routes/consent.py +637 -0
- ciris_engine/logic/adapters/api/routes/dsar.py +637 -0
- ciris_engine/logic/adapters/api/routes/dsar_multi_source.py +484 -0
- ciris_engine/logic/adapters/api/routes/emergency.py +302 -0
- ciris_engine/logic/adapters/api/routes/memory.py +733 -0
- ciris_engine/logic/adapters/api/routes/memory_filters.py +230 -0
- ciris_engine/logic/adapters/api/routes/memory_models.py +112 -0
- ciris_engine/logic/adapters/api/routes/memory_queries.py +236 -0
- ciris_engine/logic/adapters/api/routes/memory_query_helpers.py +394 -0
- ciris_engine/logic/adapters/api/routes/memory_visualization.py +359 -0
- ciris_engine/logic/adapters/api/routes/memory_visualization_helpers.py +110 -0
- ciris_engine/logic/adapters/api/routes/partnership.py +541 -0
- ciris_engine/logic/adapters/api/routes/setup.py +1374 -0
- ciris_engine/logic/adapters/api/routes/system.py +3049 -0
- ciris_engine/logic/adapters/api/routes/system_extensions.py +952 -0
- ciris_engine/logic/adapters/api/routes/telemetry.py +1987 -0
- ciris_engine/logic/adapters/api/routes/telemetry_converters.py +141 -0
- ciris_engine/logic/adapters/api/routes/telemetry_helpers.py +111 -0
- ciris_engine/logic/adapters/api/routes/telemetry_logs_reader.py +280 -0
- ciris_engine/logic/adapters/api/routes/telemetry_metrics.py +131 -0
- ciris_engine/logic/adapters/api/routes/telemetry_models.py +190 -0
- ciris_engine/logic/adapters/api/routes/telemetry_otlp.py +878 -0
- ciris_engine/logic/adapters/api/routes/telemetry_resource_helpers.py +191 -0
- ciris_engine/logic/adapters/api/routes/tickets.py +541 -0
- ciris_engine/logic/adapters/api/routes/tools.py +556 -0
- ciris_engine/logic/adapters/api/routes/transparency.py +281 -0
- ciris_engine/logic/adapters/api/routes/users.py +981 -0
- ciris_engine/logic/adapters/api/routes/verification.py +373 -0
- ciris_engine/logic/adapters/api/routes/wa.py +369 -0
- ciris_engine/logic/adapters/api/service_configuration.py +177 -0
- ciris_engine/logic/adapters/api/services/__init__.py +1 -0
- ciris_engine/logic/adapters/api/services/auth_service.py +1417 -0
- ciris_engine/logic/adapters/api/services/oauth_security.py +68 -0
- ciris_engine/logic/adapters/base.py +141 -0
- ciris_engine/logic/adapters/base_adapter.py +73 -0
- ciris_engine/logic/adapters/base_observer.py +1141 -0
- ciris_engine/logic/adapters/base_vision.py +312 -0
- ciris_engine/logic/adapters/cirisnode_client.py +307 -0
- ciris_engine/logic/adapters/cli/__init__.py +3 -0
- ciris_engine/logic/adapters/cli/adapter.py +207 -0
- ciris_engine/logic/adapters/cli/cli_adapter.py +902 -0
- ciris_engine/logic/adapters/cli/cli_observer.py +268 -0
- ciris_engine/logic/adapters/cli/cli_tools.py +427 -0
- ciris_engine/logic/adapters/cli/cli_wa_service.py +134 -0
- ciris_engine/logic/adapters/cli/config.py +73 -0
- ciris_engine/logic/adapters/discord/__init__.py +3 -0
- ciris_engine/logic/adapters/discord/adapter.py +783 -0
- ciris_engine/logic/adapters/discord/ciris_discord_client.py +159 -0
- ciris_engine/logic/adapters/discord/config.py +177 -0
- ciris_engine/logic/adapters/discord/constants.py +185 -0
- ciris_engine/logic/adapters/discord/discord-stubs.pyi +50 -0
- ciris_engine/logic/adapters/discord/discord_adapter.py +1584 -0
- ciris_engine/logic/adapters/discord/discord_audit.py +150 -0
- ciris_engine/logic/adapters/discord/discord_channel_manager.py +351 -0
- ciris_engine/logic/adapters/discord/discord_connection_manager.py +313 -0
- ciris_engine/logic/adapters/discord/discord_embed_formatter.py +369 -0
- ciris_engine/logic/adapters/discord/discord_error_classifier.py +302 -0
- ciris_engine/logic/adapters/discord/discord_error_handler.py +316 -0
- ciris_engine/logic/adapters/discord/discord_guidance_handler.py +460 -0
- ciris_engine/logic/adapters/discord/discord_message_handler.py +207 -0
- ciris_engine/logic/adapters/discord/discord_observer.py +670 -0
- ciris_engine/logic/adapters/discord/discord_rate_limiter.py +249 -0
- ciris_engine/logic/adapters/discord/discord_reaction_handler.py +278 -0
- ciris_engine/logic/adapters/discord/discord_tool_handler.py +465 -0
- ciris_engine/logic/adapters/discord/discord_tool_service.py +790 -0
- ciris_engine/logic/adapters/discord/discord_tools.py +90 -0
- ciris_engine/logic/adapters/discord/discord_vision_helper.py +148 -0
- ciris_engine/logic/adapters/discord/py.typed +0 -0
- ciris_engine/logic/adapters/document_parser.py +320 -0
- ciris_engine/logic/audit/__init__.py +10 -0
- ciris_engine/logic/audit/hash_chain.py +313 -0
- ciris_engine/logic/audit/signature_manager.py +352 -0
- ciris_engine/logic/audit/verifier.py +408 -0
- ciris_engine/logic/buses/__init__.py +21 -0
- ciris_engine/logic/buses/base_bus.py +178 -0
- ciris_engine/logic/buses/bus_manager.py +121 -0
- ciris_engine/logic/buses/communication_bus.py +387 -0
- ciris_engine/logic/buses/llm_bus.py +722 -0
- ciris_engine/logic/buses/memory_bus.py +577 -0
- ciris_engine/logic/buses/prohibitions.py +502 -0
- ciris_engine/logic/buses/runtime_control_bus.py +539 -0
- ciris_engine/logic/buses/tool_bus.py +482 -0
- ciris_engine/logic/buses/wise_bus.py +684 -0
- ciris_engine/logic/config/__init__.py +25 -0
- ciris_engine/logic/config/bootstrap.py +255 -0
- ciris_engine/logic/config/config_accessor.py +202 -0
- ciris_engine/logic/config/db_paths.py +194 -0
- ciris_engine/logic/config/env_utils.py +39 -0
- ciris_engine/logic/conscience/__init__.py +16 -0
- ciris_engine/logic/conscience/build_deferral_package.py +0 -0
- ciris_engine/logic/conscience/core.py +688 -0
- ciris_engine/logic/conscience/interface.py +33 -0
- ciris_engine/logic/conscience/registry.py +76 -0
- ciris_engine/logic/conscience/thought_depth_guardrail.py +231 -0
- ciris_engine/logic/conscience/updated_status_conscience.py +156 -0
- ciris_engine/logic/context/__init__.py +10 -0
- ciris_engine/logic/context/batch_context.py +550 -0
- ciris_engine/logic/context/builder.py +149 -0
- ciris_engine/logic/context/channel_resolution.py +136 -0
- ciris_engine/logic/context/secrets_snapshot.py +52 -0
- ciris_engine/logic/context/system_snapshot.py +116 -0
- ciris_engine/logic/context/system_snapshot_helpers.py +1651 -0
- ciris_engine/logic/covenant/__init__.py +33 -0
- ciris_engine/logic/covenant/executor.py +303 -0
- ciris_engine/logic/covenant/extractor.py +382 -0
- ciris_engine/logic/covenant/handler.py +241 -0
- ciris_engine/logic/covenant/verifier.py +383 -0
- ciris_engine/logic/dma/__init__.py +15 -0
- ciris_engine/logic/dma/action_selection/__init__.py +11 -0
- ciris_engine/logic/dma/action_selection/action_instruction_generator.py +444 -0
- ciris_engine/logic/dma/action_selection/context_builder.py +508 -0
- ciris_engine/logic/dma/action_selection/faculty_integration.py +193 -0
- ciris_engine/logic/dma/action_selection/special_cases.py +132 -0
- ciris_engine/logic/dma/action_selection_pdma.py +365 -0
- ciris_engine/logic/dma/base_dma.py +335 -0
- ciris_engine/logic/dma/csdma.py +239 -0
- ciris_engine/logic/dma/dma_executor.py +575 -0
- ciris_engine/logic/dma/dsdma_base.py +410 -0
- ciris_engine/logic/dma/exceptions.py +4 -0
- ciris_engine/logic/dma/factory.py +150 -0
- ciris_engine/logic/dma/pdma.py +120 -0
- ciris_engine/logic/dma/prompt_loader.py +189 -0
- ciris_engine/logic/dma/prompts/action_selection_pdma.yml +58 -0
- ciris_engine/logic/dma/prompts/csdma_common_sense.yml +28 -0
- ciris_engine/logic/dma/prompts/dsdma_base.yml +17 -0
- ciris_engine/logic/dma/prompts/pdma_ethical.yml +42 -0
- ciris_engine/logic/formatters/__init__.py +26 -0
- ciris_engine/logic/formatters/crisis_resources.py +80 -0
- ciris_engine/logic/formatters/escalation.py +21 -0
- ciris_engine/logic/formatters/identity.py +224 -0
- ciris_engine/logic/formatters/prompt_blocks.py +64 -0
- ciris_engine/logic/formatters/system_snapshot.py +193 -0
- ciris_engine/logic/formatters/user_profiles.py +108 -0
- ciris_engine/logic/handlers/__init__.py +1 -0
- ciris_engine/logic/handlers/control/__init__.py +1 -0
- ciris_engine/logic/handlers/control/defer_handler.py +195 -0
- ciris_engine/logic/handlers/control/ponder_handler.py +154 -0
- ciris_engine/logic/handlers/control/reject_handler.py +81 -0
- ciris_engine/logic/handlers/external/__init__.py +1 -0
- ciris_engine/logic/handlers/external/observe_handler.py +154 -0
- ciris_engine/logic/handlers/external/speak_handler.py +250 -0
- ciris_engine/logic/handlers/external/tool_handler.py +148 -0
- ciris_engine/logic/handlers/memory/__init__.py +1 -0
- ciris_engine/logic/handlers/memory/forget_handler.py +107 -0
- ciris_engine/logic/handlers/memory/memorize_handler.py +391 -0
- ciris_engine/logic/handlers/memory/recall_handler.py +213 -0
- ciris_engine/logic/handlers/terminal/__init__.py +1 -0
- ciris_engine/logic/handlers/terminal/task_complete_handler.py +299 -0
- ciris_engine/logic/infrastructure/__init__.py +1 -0
- ciris_engine/logic/infrastructure/handlers/__init__.py +8 -0
- ciris_engine/logic/infrastructure/handlers/action_dispatcher.py +382 -0
- ciris_engine/logic/infrastructure/handlers/base_handler.py +450 -0
- ciris_engine/logic/infrastructure/handlers/exceptions.py +2 -0
- ciris_engine/logic/infrastructure/handlers/handler_registry.py +59 -0
- ciris_engine/logic/infrastructure/handlers/helpers.py +55 -0
- ciris_engine/logic/infrastructure/step_streaming.py +149 -0
- ciris_engine/logic/infrastructure/sub_services/__init__.py +1 -0
- ciris_engine/logic/infrastructure/sub_services/identity_variance_monitor.py +1035 -0
- ciris_engine/logic/infrastructure/sub_services/pattern_analysis_loop.py +758 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_bootstrap.py +229 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_display.py +176 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_oauth.py +404 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_wizard.py +181 -0
- ciris_engine/logic/persistence/__init__.py +130 -0
- ciris_engine/logic/persistence/analytics.py +97 -0
- ciris_engine/logic/persistence/db/__init__.py +28 -0
- ciris_engine/logic/persistence/db/core.py +520 -0
- ciris_engine/logic/persistence/db/dialect.py +380 -0
- ciris_engine/logic/persistence/db/execution_helpers.py +216 -0
- ciris_engine/logic/persistence/db/migration_runner.py +191 -0
- ciris_engine/logic/persistence/db/operations.py +313 -0
- ciris_engine/logic/persistence/db/query_builder.py +232 -0
- ciris_engine/logic/persistence/db/retry.py +154 -0
- ciris_engine/logic/persistence/db/setup.py +18 -0
- ciris_engine/logic/persistence/migrations/postgres/001_initial_schema.sql +4 -0
- ciris_engine/logic/persistence/migrations/postgres/002_add_retry_status.sql +3 -0
- ciris_engine/logic/persistence/migrations/postgres/003_add_task_update_tracking.sql +8 -0
- ciris_engine/logic/persistence/migrations/postgres/004_add_occurrence_id.sql +54 -0
- ciris_engine/logic/persistence/migrations/postgres/005_add_consolidation_locks.sql +22 -0
- ciris_engine/logic/persistence/migrations/postgres/006_add_correlation_id_unique_index.sql +16 -0
- ciris_engine/logic/persistence/migrations/postgres/007_add_dsar_tickets.sql +39 -0
- ciris_engine/logic/persistence/migrations/postgres/008_rename_to_tickets_add_sop.sql +123 -0
- ciris_engine/logic/persistence/migrations/postgres/009_add_ticket_status_columns.sql +39 -0
- ciris_engine/logic/persistence/migrations/postgres/010_add_images_to_tasks.sql +5 -0
- ciris_engine/logic/persistence/migrations/sqlite/001_initial_schema.sql +357 -0
- ciris_engine/logic/persistence/migrations/sqlite/002_add_retry_status.sql +3 -0
- ciris_engine/logic/persistence/migrations/sqlite/003_add_task_update_tracking.sql +8 -0
- ciris_engine/logic/persistence/migrations/sqlite/004_add_occurrence_id.sql +45 -0
- ciris_engine/logic/persistence/migrations/sqlite/005_add_consolidation_locks.sql +22 -0
- ciris_engine/logic/persistence/migrations/sqlite/006_add_correlation_id_unique_index.sql +16 -0
- ciris_engine/logic/persistence/migrations/sqlite/007_add_dsar_tickets.sql +39 -0
- ciris_engine/logic/persistence/migrations/sqlite/008_rename_to_tickets_add_sop.sql +120 -0
- ciris_engine/logic/persistence/migrations/sqlite/009_add_ticket_status_columns.sql +129 -0
- ciris_engine/logic/persistence/migrations/sqlite/010_add_images_to_tasks.sql +17 -0
- ciris_engine/logic/persistence/models/__init__.py +141 -0
- ciris_engine/logic/persistence/models/correlations.py +881 -0
- ciris_engine/logic/persistence/models/deferral.py +68 -0
- ciris_engine/logic/persistence/models/dsar.py +286 -0
- ciris_engine/logic/persistence/models/graph.py +362 -0
- ciris_engine/logic/persistence/models/identity.py +264 -0
- ciris_engine/logic/persistence/models/queue_status.py +139 -0
- ciris_engine/logic/persistence/models/tasks.py +1043 -0
- ciris_engine/logic/persistence/models/thoughts.py +400 -0
- ciris_engine/logic/persistence/models/tickets.py +518 -0
- ciris_engine/logic/persistence/stores/__init__.py +13 -0
- ciris_engine/logic/persistence/stores/auth_helpers.py +117 -0
- ciris_engine/logic/persistence/stores/authentication_store.py +414 -0
- ciris_engine/logic/persistence/utils.py +212 -0
- ciris_engine/logic/processors/__init__.py +30 -0
- ciris_engine/logic/processors/core/__init__.py +1 -0
- ciris_engine/logic/processors/core/base_processor.py +280 -0
- ciris_engine/logic/processors/core/main_processor.py +1777 -0
- ciris_engine/logic/processors/core/step_decorators.py +1583 -0
- ciris_engine/logic/processors/core/thought_processor/__init__.py +20 -0
- ciris_engine/logic/processors/core/thought_processor/action_execution.py +49 -0
- ciris_engine/logic/processors/core/thought_processor/conscience_execution.py +382 -0
- ciris_engine/logic/processors/core/thought_processor/finalize_action.py +66 -0
- ciris_engine/logic/processors/core/thought_processor/gather_context.py +120 -0
- ciris_engine/logic/processors/core/thought_processor/main.py +920 -0
- ciris_engine/logic/processors/core/thought_processor/perform_aspdma.py +86 -0
- ciris_engine/logic/processors/core/thought_processor/perform_dmas.py +106 -0
- ciris_engine/logic/processors/core/thought_processor/recursive_processing.py +237 -0
- ciris_engine/logic/processors/core/thought_processor/round_complete.py +52 -0
- ciris_engine/logic/processors/core/thought_processor/start_round.py +64 -0
- ciris_engine/logic/processors/exceptions.py +59 -0
- ciris_engine/logic/processors/states/__init__.py +1 -0
- ciris_engine/logic/processors/states/dream_processor.py +1381 -0
- ciris_engine/logic/processors/states/play_processor.py +141 -0
- ciris_engine/logic/processors/states/shutdown_processor.py +623 -0
- ciris_engine/logic/processors/states/solitude_processor.py +305 -0
- ciris_engine/logic/processors/states/wakeup_processor.py +802 -0
- ciris_engine/logic/processors/states/work_processor.py +742 -0
- ciris_engine/logic/processors/support/__init__.py +1 -0
- ciris_engine/logic/processors/support/dma_orchestrator.py +336 -0
- ciris_engine/logic/processors/support/processing_queue.py +133 -0
- ciris_engine/logic/processors/support/shutdown_condition_evaluator.py +294 -0
- ciris_engine/logic/processors/support/state_manager.py +358 -0
- ciris_engine/logic/processors/support/task_manager.py +303 -0
- ciris_engine/logic/processors/support/thought_escalation.py +116 -0
- ciris_engine/logic/processors/support/thought_manager.py +328 -0
- ciris_engine/logic/processors/support/thought_manager_enhanced.py +105 -0
- ciris_engine/logic/registries/__init__.py +34 -0
- ciris_engine/logic/registries/base.py +653 -0
- ciris_engine/logic/registries/circuit_breaker.py +275 -0
- ciris_engine/logic/registries/typed_registries.py +184 -0
- ciris_engine/logic/runtime/__init__.py +7 -0
- ciris_engine/logic/runtime/adapter_loader.py +261 -0
- ciris_engine/logic/runtime/adapter_manager.py +1053 -0
- ciris_engine/logic/runtime/ciris_runtime.py +2342 -0
- ciris_engine/logic/runtime/ciris_runtime_helpers.py +923 -0
- ciris_engine/logic/runtime/component_builder.py +361 -0
- ciris_engine/logic/runtime/identity_manager.py +219 -0
- ciris_engine/logic/runtime/module_loader.py +207 -0
- ciris_engine/logic/runtime/prevent_sideeffects.py +30 -0
- ciris_engine/logic/runtime/runtime_interface.py +23 -0
- ciris_engine/logic/runtime/service_initializer.py +1623 -0
- ciris_engine/logic/secrets/__init__.py +30 -0
- ciris_engine/logic/secrets/encryption.py +175 -0
- ciris_engine/logic/secrets/filter.py +295 -0
- ciris_engine/logic/secrets/service.py +652 -0
- ciris_engine/logic/secrets/store.py +669 -0
- ciris_engine/logic/services/__init__.py +1 -0
- ciris_engine/logic/services/adaptation/__init__.py +3 -0
- ciris_engine/logic/services/base_graph_service.py +142 -0
- ciris_engine/logic/services/base_infrastructure_service.py +69 -0
- ciris_engine/logic/services/base_scheduled_service.py +136 -0
- ciris_engine/logic/services/base_service.py +247 -0
- ciris_engine/logic/services/governance/__init__.py +3 -0
- ciris_engine/logic/services/governance/adaptive_filter/__init__.py +14 -0
- ciris_engine/logic/services/governance/adaptive_filter/service.py +818 -0
- ciris_engine/logic/services/governance/consent/__init__.py +53 -0
- ciris_engine/logic/services/governance/consent/air.py +403 -0
- ciris_engine/logic/services/governance/consent/decay.py +324 -0
- ciris_engine/logic/services/governance/consent/dsar_automation.py +589 -0
- ciris_engine/logic/services/governance/consent/exceptions.py +106 -0
- ciris_engine/logic/services/governance/consent/metrics.py +270 -0
- ciris_engine/logic/services/governance/consent/partnership.py +533 -0
- ciris_engine/logic/services/governance/consent/service.py +1256 -0
- ciris_engine/logic/services/governance/dsar/__init__.py +29 -0
- ciris_engine/logic/services/governance/dsar/orchestrator.py +977 -0
- ciris_engine/logic/services/governance/dsar/schemas.py +141 -0
- ciris_engine/logic/services/governance/dsar/signature_service.py +283 -0
- ciris_engine/logic/services/governance/self_observation/__init__.py +20 -0
- ciris_engine/logic/services/governance/self_observation/service.py +1153 -0
- ciris_engine/logic/services/governance/visibility/__init__.py +17 -0
- ciris_engine/logic/services/governance/visibility/service.py +512 -0
- ciris_engine/logic/services/governance/wise_authority/__init__.py +15 -0
- ciris_engine/logic/services/governance/wise_authority/service.py +827 -0
- ciris_engine/logic/services/graph/__init__.py +5 -0
- ciris_engine/logic/services/graph/audit_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/audit_service/service.py +1675 -0
- ciris_engine/logic/services/graph/base.py +208 -0
- ciris_engine/logic/services/graph/config_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/config_service/service.py +372 -0
- ciris_engine/logic/services/graph/incident_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/incident_service/service.py +803 -0
- ciris_engine/logic/services/graph/memory_service.py +1120 -0
- ciris_engine/logic/services/graph/telemetry_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/telemetry_service/exceptions.py +104 -0
- ciris_engine/logic/services/graph/telemetry_service/helpers.py +1337 -0
- ciris_engine/logic/services/graph/telemetry_service/service.py +2429 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/__init__.py +17 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/aggregation_helpers.py +355 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/cleanup_helpers.py +438 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/compressor.py +260 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/__init__.py +27 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/audit.py +326 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/conversation.py +291 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/memory.py +197 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/metrics.py +251 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/task.py +257 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/trace.py +363 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/data_converter.py +545 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/date_calculation_helpers.py +193 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/db_query_helpers.py +296 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/edge_helpers.py +92 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/edge_manager.py +896 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/extensive_helpers.py +322 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/period_manager.py +152 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/profound_helpers.py +277 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/query_manager.py +812 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/service.py +1692 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/sql_builders.py +363 -0
- ciris_engine/logic/services/infrastructure/__init__.py +1 -0
- ciris_engine/logic/services/infrastructure/authentication/__init__.py +5 -0
- ciris_engine/logic/services/infrastructure/authentication/service.py +1634 -0
- ciris_engine/logic/services/infrastructure/database_maintenance/__init__.py +15 -0
- ciris_engine/logic/services/infrastructure/database_maintenance/service.py +764 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/__init__.py +7 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/ciris_billing_provider.py +755 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/service.py +409 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/simple_credit_provider.py +129 -0
- ciris_engine/logic/services/lifecycle/__init__.py +3 -0
- ciris_engine/logic/services/lifecycle/initialization/__init__.py +10 -0
- ciris_engine/logic/services/lifecycle/initialization/service.py +312 -0
- ciris_engine/logic/services/lifecycle/scheduler/__init__.py +5 -0
- ciris_engine/logic/services/lifecycle/scheduler/service.py +607 -0
- ciris_engine/logic/services/lifecycle/shutdown/__init__.py +9 -0
- ciris_engine/logic/services/lifecycle/shutdown/service.py +378 -0
- ciris_engine/logic/services/lifecycle/time/__init__.py +15 -0
- ciris_engine/logic/services/lifecycle/time/service.py +259 -0
- ciris_engine/logic/services/memory_service/__init__.py +8 -0
- ciris_engine/logic/services/mixins/__init__.py +13 -0
- ciris_engine/logic/services/mixins/example_usage.py +200 -0
- ciris_engine/logic/services/mixins/request_metrics.py +179 -0
- ciris_engine/logic/services/runtime/__init__.py +3 -0
- ciris_engine/logic/services/runtime/adapter_configuration/__init__.py +16 -0
- ciris_engine/logic/services/runtime/adapter_configuration/service.py +674 -0
- ciris_engine/logic/services/runtime/adapter_configuration/session.py +67 -0
- ciris_engine/logic/services/runtime/control_service/__init__.py +5 -0
- ciris_engine/logic/services/runtime/control_service/service.py +2269 -0
- ciris_engine/logic/services/runtime/llm_service/__init__.py +14 -0
- ciris_engine/logic/services/runtime/llm_service/pricing_calculator.py +279 -0
- ciris_engine/logic/services/runtime/llm_service/service.py +930 -0
- ciris_engine/logic/services/tools/__init__.py +5 -0
- ciris_engine/logic/services/tools/core_tool_service/__init__.py +8 -0
- ciris_engine/logic/services/tools/core_tool_service/service.py +852 -0
- ciris_engine/logic/setup/__init__.py +1 -0
- ciris_engine/logic/setup/first_run.py +250 -0
- ciris_engine/logic/setup/wizard.py +327 -0
- ciris_engine/logic/telemetry/__init__.py +46 -0
- ciris_engine/logic/telemetry/core.py +239 -0
- ciris_engine/logic/telemetry/hot_cold_config.py +133 -0
- ciris_engine/logic/telemetry/log_collector.py +190 -0
- ciris_engine/logic/telemetry/resource_monitor.py +7 -0
- ciris_engine/logic/telemetry/security.py +79 -0
- ciris_engine/logic/utils/__init__.py +18 -0
- ciris_engine/logic/utils/channel_utils.py +75 -0
- ciris_engine/logic/utils/consent/__init__.py +1 -0
- ciris_engine/logic/utils/consent/partnership_utils.py +172 -0
- ciris_engine/logic/utils/constants.py +92 -0
- ciris_engine/logic/utils/context_utils.py +145 -0
- ciris_engine/logic/utils/directory_setup.py +533 -0
- ciris_engine/logic/utils/graphql_context_provider.py +152 -0
- ciris_engine/logic/utils/identity_resolution.py +843 -0
- ciris_engine/logic/utils/incident_capture_handler.py +303 -0
- ciris_engine/logic/utils/initialization_manager.py +74 -0
- ciris_engine/logic/utils/jsondict_helpers.py +290 -0
- ciris_engine/logic/utils/log_sanitizer.py +97 -0
- ciris_engine/logic/utils/logging_config.py +151 -0
- ciris_engine/logic/utils/observability_decorators.py +544 -0
- ciris_engine/logic/utils/occurrence_utils.py +155 -0
- ciris_engine/logic/utils/path_resolution.py +281 -0
- ciris_engine/logic/utils/platform_detection.py +286 -0
- ciris_engine/logic/utils/privacy.py +266 -0
- ciris_engine/logic/utils/profile_loader.py +124 -0
- ciris_engine/logic/utils/profile_manager.py +16 -0
- ciris_engine/logic/utils/runtime_utils.py +69 -0
- ciris_engine/logic/utils/shutdown_manager.py +107 -0
- ciris_engine/logic/utils/task_formatters.py +60 -0
- ciris_engine/logic/utils/task_thought_factory.py +404 -0
- ciris_engine/logic/utils/thought_utils.py +54 -0
- ciris_engine/logic/utils/user_utils.py +70 -0
- ciris_engine/protocols/__init__.py +0 -0
- ciris_engine/protocols/adapters/__init__.py +35 -0
- ciris_engine/protocols/adapters/base.py +149 -0
- ciris_engine/protocols/adapters/configurable.py +265 -0
- ciris_engine/protocols/adapters/message.py +90 -0
- ciris_engine/protocols/audit/__init__.py +1 -0
- ciris_engine/protocols/buses/__init__.py +1 -0
- ciris_engine/protocols/config/__init__.py +1 -0
- ciris_engine/protocols/conscience/__init__.py +1 -0
- ciris_engine/protocols/consent.py +88 -0
- ciris_engine/protocols/context/__init__.py +1 -0
- ciris_engine/protocols/data/__init__.py +1 -0
- ciris_engine/protocols/dma/__init__.py +1 -0
- ciris_engine/protocols/dma/base.py +107 -0
- ciris_engine/protocols/faculties.py +34 -0
- ciris_engine/protocols/formatters/__init__.py +1 -0
- ciris_engine/protocols/handlers/__init__.py +1 -0
- ciris_engine/protocols/infrastructure/__init__.py +25 -0
- ciris_engine/protocols/infrastructure/base.py +377 -0
- ciris_engine/protocols/persistence/__init__.py +1 -0
- ciris_engine/protocols/pipeline_control.py +609 -0
- ciris_engine/protocols/processors/__init__.py +19 -0
- ciris_engine/protocols/processors/agent.py +299 -0
- ciris_engine/protocols/processors/base.py +130 -0
- ciris_engine/protocols/processors/orchestration.py +62 -0
- ciris_engine/protocols/registries/__init__.py +1 -0
- ciris_engine/protocols/runtime/__init__.py +1 -0
- ciris_engine/protocols/runtime/base.py +163 -0
- ciris_engine/protocols/secrets/__init__.py +1 -0
- ciris_engine/protocols/services/__init__.py +80 -0
- ciris_engine/protocols/services/adaptation/__init__.py +7 -0
- ciris_engine/protocols/services/adaptation/self_observation.py +265 -0
- ciris_engine/protocols/services/governance/__init__.py +20 -0
- ciris_engine/protocols/services/governance/communication.py +58 -0
- ciris_engine/protocols/services/governance/filter.py +56 -0
- ciris_engine/protocols/services/governance/visibility.py +32 -0
- ciris_engine/protocols/services/governance/wa_auth.py +192 -0
- ciris_engine/protocols/services/governance/wise_authority.py +75 -0
- ciris_engine/protocols/services/graph/__init__.py +19 -0
- ciris_engine/protocols/services/graph/audit.py +92 -0
- ciris_engine/protocols/services/graph/config.py +54 -0
- ciris_engine/protocols/services/graph/incident_management.py +103 -0
- ciris_engine/protocols/services/graph/memory.py +110 -0
- ciris_engine/protocols/services/graph/telemetry.py +51 -0
- ciris_engine/protocols/services/graph/tsdb_consolidation.py +87 -0
- ciris_engine/protocols/services/infrastructure/__init__.py +11 -0
- ciris_engine/protocols/services/infrastructure/authentication.py +159 -0
- ciris_engine/protocols/services/infrastructure/credit_gate.py +46 -0
- ciris_engine/protocols/services/infrastructure/database_maintenance.py +25 -0
- ciris_engine/protocols/services/infrastructure/resource_monitor.py +83 -0
- ciris_engine/protocols/services/lifecycle/__init__.py +13 -0
- ciris_engine/protocols/services/lifecycle/initialization.py +41 -0
- ciris_engine/protocols/services/lifecycle/scheduler.py +42 -0
- ciris_engine/protocols/services/lifecycle/shutdown.py +50 -0
- ciris_engine/protocols/services/lifecycle/time.py +31 -0
- ciris_engine/protocols/services/runtime/__init__.py +13 -0
- ciris_engine/protocols/services/runtime/llm.py +50 -0
- ciris_engine/protocols/services/runtime/runtime_control.py +193 -0
- ciris_engine/protocols/services/runtime/secrets.py +100 -0
- ciris_engine/protocols/services/runtime/tool.py +123 -0
- ciris_engine/protocols/telemetry/__init__.py +1 -0
- ciris_engine/protocols/utils/__init__.py +1 -0
- ciris_engine/schemas/__init__.py +112 -0
- ciris_engine/schemas/actions/__init__.py +37 -0
- ciris_engine/schemas/actions/parameters.py +137 -0
- ciris_engine/schemas/adapters/__init__.py +13 -0
- ciris_engine/schemas/adapters/cirisnode.py +135 -0
- ciris_engine/schemas/adapters/cli.py +97 -0
- ciris_engine/schemas/adapters/cli_tools.py +98 -0
- ciris_engine/schemas/adapters/discord.py +125 -0
- ciris_engine/schemas/adapters/graphql_core.py +144 -0
- ciris_engine/schemas/adapters/registration.py +47 -0
- ciris_engine/schemas/adapters/runtime_context.py +48 -0
- ciris_engine/schemas/adapters/tool_execution.py +45 -0
- ciris_engine/schemas/adapters/tools.py +96 -0
- ciris_engine/schemas/api/__init__.py +1 -0
- ciris_engine/schemas/api/agent.py +50 -0
- ciris_engine/schemas/api/audit.py +38 -0
- ciris_engine/schemas/api/auth.py +351 -0
- ciris_engine/schemas/api/config_security.py +242 -0
- ciris_engine/schemas/api/emergency.py +111 -0
- ciris_engine/schemas/api/responses.py +72 -0
- ciris_engine/schemas/api/runtime.py +26 -0
- ciris_engine/schemas/api/telemetry.py +109 -0
- ciris_engine/schemas/api/wa.py +90 -0
- ciris_engine/schemas/audit/__init__.py +13 -0
- ciris_engine/schemas/audit/core.py +139 -0
- ciris_engine/schemas/audit/hash_chain.py +58 -0
- ciris_engine/schemas/audit/verification.py +131 -0
- ciris_engine/schemas/buses/__init__.py +1 -0
- ciris_engine/schemas/config/__init__.py +41 -0
- ciris_engine/schemas/config/agent.py +279 -0
- ciris_engine/schemas/config/cognitive_state_behaviors.py +194 -0
- ciris_engine/schemas/config/default_dsar_sops.py +178 -0
- ciris_engine/schemas/config/essential.py +195 -0
- ciris_engine/schemas/config/tickets.py +86 -0
- ciris_engine/schemas/conscience/__init__.py +25 -0
- ciris_engine/schemas/conscience/context.py +34 -0
- ciris_engine/schemas/conscience/core.py +145 -0
- ciris_engine/schemas/conscience/results.py +24 -0
- ciris_engine/schemas/consent/__init__.py +5 -0
- ciris_engine/schemas/consent/core.py +404 -0
- ciris_engine/schemas/context/__init__.py +1 -0
- ciris_engine/schemas/covenant.py +382 -0
- ciris_engine/schemas/data/__init__.py +1 -0
- ciris_engine/schemas/dma/__init__.py +16 -0
- ciris_engine/schemas/dma/core.py +199 -0
- ciris_engine/schemas/dma/faculty.py +192 -0
- ciris_engine/schemas/dma/prompts.py +172 -0
- ciris_engine/schemas/dma/results.py +103 -0
- ciris_engine/schemas/formatters/__init__.py +1 -0
- ciris_engine/schemas/handlers/__init__.py +10 -0
- ciris_engine/schemas/handlers/context.py +119 -0
- ciris_engine/schemas/handlers/contexts.py +100 -0
- ciris_engine/schemas/handlers/core.py +167 -0
- ciris_engine/schemas/handlers/memory_schemas.py +67 -0
- ciris_engine/schemas/handlers/schemas.py +95 -0
- ciris_engine/schemas/identity.py +149 -0
- ciris_engine/schemas/infrastructure/__init__.py +1 -0
- ciris_engine/schemas/infrastructure/base.py +256 -0
- ciris_engine/schemas/infrastructure/behavioral_patterns.py +129 -0
- ciris_engine/schemas/infrastructure/feedback_loop.py +57 -0
- ciris_engine/schemas/infrastructure/identity_variance.py +141 -0
- ciris_engine/schemas/infrastructure/oauth.py +175 -0
- ciris_engine/schemas/infrastructure/wa_cli_wizard.py +54 -0
- ciris_engine/schemas/persistence/__init__.py +34 -0
- ciris_engine/schemas/persistence/core.py +140 -0
- ciris_engine/schemas/persistence/correlations.py +73 -0
- ciris_engine/schemas/persistence/postgres/__init__.py +1 -0
- ciris_engine/schemas/persistence/postgres/tables.py +280 -0
- ciris_engine/schemas/persistence/sqlite/__init__.py +1 -0
- ciris_engine/schemas/persistence/sqlite/tables.py +281 -0
- ciris_engine/schemas/platform.py +149 -0
- ciris_engine/schemas/processors/__init__.py +26 -0
- ciris_engine/schemas/processors/base.py +130 -0
- ciris_engine/schemas/processors/cognitive.py +77 -0
- ciris_engine/schemas/processors/context.py +35 -0
- ciris_engine/schemas/processors/core.py +152 -0
- ciris_engine/schemas/processors/dma.py +105 -0
- ciris_engine/schemas/processors/error.py +122 -0
- ciris_engine/schemas/processors/main.py +109 -0
- ciris_engine/schemas/processors/phase_results.py +21 -0
- ciris_engine/schemas/processors/results.py +99 -0
- ciris_engine/schemas/processors/solitude.py +79 -0
- ciris_engine/schemas/processors/state.py +202 -0
- ciris_engine/schemas/processors/state_example.py +177 -0
- ciris_engine/schemas/processors/states.py +21 -0
- ciris_engine/schemas/processors/status.py +34 -0
- ciris_engine/schemas/registries/__init__.py +1 -0
- ciris_engine/schemas/registries/base.py +66 -0
- ciris_engine/schemas/resources/__init__.py +15 -0
- ciris_engine/schemas/resources/crisis.py +315 -0
- ciris_engine/schemas/runtime/__init__.py +42 -0
- ciris_engine/schemas/runtime/adapter_management.py +186 -0
- ciris_engine/schemas/runtime/api.py +58 -0
- ciris_engine/schemas/runtime/audit.py +50 -0
- ciris_engine/schemas/runtime/bootstrap.py +33 -0
- ciris_engine/schemas/runtime/contexts.py +61 -0
- ciris_engine/schemas/runtime/core.py +161 -0
- ciris_engine/schemas/runtime/enums.py +167 -0
- ciris_engine/schemas/runtime/extended.py +232 -0
- ciris_engine/schemas/runtime/manifest.py +311 -0
- ciris_engine/schemas/runtime/memory.py +60 -0
- ciris_engine/schemas/runtime/messages.py +108 -0
- ciris_engine/schemas/runtime/models.py +156 -0
- ciris_engine/schemas/runtime/processing_context.py +43 -0
- ciris_engine/schemas/runtime/protocols_core.py +96 -0
- ciris_engine/schemas/runtime/resources.py +33 -0
- ciris_engine/schemas/runtime/system_context.py +417 -0
- ciris_engine/schemas/secrets/__init__.py +1 -0
- ciris_engine/schemas/secrets/core.py +267 -0
- ciris_engine/schemas/secrets/service.py +95 -0
- ciris_engine/schemas/services/__init__.py +33 -0
- ciris_engine/schemas/services/audit_summary_node.py +172 -0
- ciris_engine/schemas/services/authority/__init__.py +39 -0
- ciris_engine/schemas/services/authority/jwt.py +158 -0
- ciris_engine/schemas/services/authority/wa_updates.py +138 -0
- ciris_engine/schemas/services/authority/wise_authority.py +163 -0
- ciris_engine/schemas/services/authority_core.py +370 -0
- ciris_engine/schemas/services/capabilities.py +72 -0
- ciris_engine/schemas/services/community_core.py +95 -0
- ciris_engine/schemas/services/context.py +111 -0
- ciris_engine/schemas/services/conversation_summary_node.py +189 -0
- ciris_engine/schemas/services/core/__init__.py +153 -0
- ciris_engine/schemas/services/core/runtime.py +262 -0
- ciris_engine/schemas/services/core/runtime_config.py +117 -0
- ciris_engine/schemas/services/core/secrets.py +65 -0
- ciris_engine/schemas/services/correlation_node.py +179 -0
- ciris_engine/schemas/services/credit_gate.py +92 -0
- ciris_engine/schemas/services/discord_nodes.py +299 -0
- ciris_engine/schemas/services/feedback_core.py +131 -0
- ciris_engine/schemas/services/filters_core.py +270 -0
- ciris_engine/schemas/services/governance.py +26 -0
- ciris_engine/schemas/services/graph/__init__.py +26 -0
- ciris_engine/schemas/services/graph/attributes.py +254 -0
- ciris_engine/schemas/services/graph/audit.py +98 -0
- ciris_engine/schemas/services/graph/consolidation.py +338 -0
- ciris_engine/schemas/services/graph/edge_types.py +43 -0
- ciris_engine/schemas/services/graph/edges.py +88 -0
- ciris_engine/schemas/services/graph/incident.py +312 -0
- ciris_engine/schemas/services/graph/memory.py +84 -0
- ciris_engine/schemas/services/graph/node_data.py +174 -0
- ciris_engine/schemas/services/graph/query_results.py +82 -0
- ciris_engine/schemas/services/graph/telemetry.py +250 -0
- ciris_engine/schemas/services/graph/tsdb_consolidation.py +27 -0
- ciris_engine/schemas/services/graph/tsdb_models.py +107 -0
- ciris_engine/schemas/services/graph_core.py +196 -0
- ciris_engine/schemas/services/graph_typed_nodes.py +194 -0
- ciris_engine/schemas/services/infrastructure/__init__.py +1 -0
- ciris_engine/schemas/services/infrastructure/resource_monitor.py +20 -0
- ciris_engine/schemas/services/lifecycle/__init__.py +9 -0
- ciris_engine/schemas/services/lifecycle/initialization.py +33 -0
- ciris_engine/schemas/services/lifecycle/time.py +50 -0
- ciris_engine/schemas/services/llm.py +187 -0
- ciris_engine/schemas/services/metadata.py +43 -0
- ciris_engine/schemas/services/nodes.py +704 -0
- ciris_engine/schemas/services/operations.py +126 -0
- ciris_engine/schemas/services/requests.py +128 -0
- ciris_engine/schemas/services/resources_core.py +182 -0
- ciris_engine/schemas/services/runtime_control.py +1010 -0
- ciris_engine/schemas/services/shutdown.py +88 -0
- ciris_engine/schemas/services/special/__init__.py +0 -0
- ciris_engine/schemas/services/special/self_observation.py +396 -0
- ciris_engine/schemas/services/trace_summary_node.py +199 -0
- ciris_engine/schemas/services/visibility.py +98 -0
- ciris_engine/schemas/streaming/__init__.py +10 -0
- ciris_engine/schemas/streaming/reasoning_stream.py +95 -0
- ciris_engine/schemas/telemetry/__init__.py +0 -0
- ciris_engine/schemas/telemetry/collector.py +67 -0
- ciris_engine/schemas/telemetry/core.py +252 -0
- ciris_engine/schemas/telemetry/unified.py +59 -0
- ciris_engine/schemas/tools.py +72 -0
- ciris_engine/schemas/types.py +47 -0
- ciris_engine/schemas/utils/__init__.py +1 -0
- ciris_engine/schemas/utils/config_validator.py +54 -0
- ciris_engine/utils/__init__.py +1 -0
- ciris_engine/utils/serialization.py +35 -0
- ciris_sdk/__init__.py +124 -0
- ciris_sdk/auth_store.py +261 -0
- ciris_sdk/client.py +261 -0
- ciris_sdk/exceptions.py +73 -0
- ciris_sdk/model_types.py +258 -0
- ciris_sdk/models.py +354 -0
- ciris_sdk/pagination.py +214 -0
- ciris_sdk/rate_limiter.py +188 -0
- ciris_sdk/setup.py +17 -0
- ciris_sdk/telemetry_models.py +257 -0
- ciris_sdk/telemetry_responses.py +199 -0
- ciris_sdk/transport.py +177 -0
- ciris_sdk/websocket.py +400 -0
- main.py +766 -0
|
@@ -0,0 +1,1623 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Service initialization for CIRIS Agent runtime.
|
|
3
|
+
|
|
4
|
+
Handles the initialization of all core services.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
import aiofiles
|
|
14
|
+
|
|
15
|
+
from ciris_engine.config.ciris_services import get_billing_url
|
|
16
|
+
from ciris_engine.logic.buses import BusManager
|
|
17
|
+
from ciris_engine.logic.config.config_accessor import ConfigAccessor
|
|
18
|
+
from ciris_engine.logic.persistence import get_sqlite_db_full_path
|
|
19
|
+
from ciris_engine.logic.registries.base import Priority, ServiceRegistry
|
|
20
|
+
|
|
21
|
+
# CoreToolService removed - SELF_HELP moved to memory per user request
|
|
22
|
+
# BasicTelemetryCollector removed - using GraphTelemetryService instead
|
|
23
|
+
from ciris_engine.logic.secrets.service import SecretsService
|
|
24
|
+
from ciris_engine.logic.services.governance.adaptive_filter import AdaptiveFilterService
|
|
25
|
+
|
|
26
|
+
# Removed AuditSinkManager - audit is consolidated, no sink needed
|
|
27
|
+
from ciris_engine.logic.services.governance.wise_authority import WiseAuthorityService
|
|
28
|
+
from ciris_engine.logic.services.graph.audit_service import GraphAuditService as AuditService
|
|
29
|
+
from ciris_engine.logic.services.graph.memory_service import LocalGraphMemoryService
|
|
30
|
+
from ciris_engine.logic.services.infrastructure.database_maintenance import DatabaseMaintenanceService
|
|
31
|
+
from ciris_engine.logic.services.lifecycle.initialization import InitializationService
|
|
32
|
+
from ciris_engine.logic.services.lifecycle.shutdown import ShutdownService
|
|
33
|
+
|
|
34
|
+
# Import new infrastructure services
|
|
35
|
+
from ciris_engine.logic.services.lifecycle.time import TimeService
|
|
36
|
+
from ciris_engine.logic.services.runtime.llm_service import OpenAICompatibleClient
|
|
37
|
+
from ciris_engine.logic.utils.path_resolution import get_data_dir
|
|
38
|
+
from ciris_engine.protocols.services import LLMService, TelemetryService
|
|
39
|
+
from ciris_engine.schemas.config.essential import EssentialConfig
|
|
40
|
+
from ciris_engine.schemas.runtime.enums import ServiceType
|
|
41
|
+
from ciris_engine.schemas.runtime.manifest import ServiceManifest
|
|
42
|
+
from ciris_engine.schemas.services.capabilities import LLMCapabilities
|
|
43
|
+
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
# Total core services for startup logging (22 per architecture)
|
|
47
|
+
TOTAL_CORE_SERVICES = 22
|
|
48
|
+
|
|
49
|
+
# First-run minimal services (10 services needed to serve setup wizard)
|
|
50
|
+
FIRST_RUN_SERVICES = 10
|
|
51
|
+
|
|
52
|
+
# Services started during resume_from_first_run (remaining 12)
|
|
53
|
+
RESUME_SERVICES = 12
|
|
54
|
+
|
|
55
|
+
# Service names in initialization order for UI display
|
|
56
|
+
SERVICE_NAMES = [
|
|
57
|
+
"TimeService", # 1 - Infrastructure
|
|
58
|
+
"ShutdownService", # 2 - Infrastructure
|
|
59
|
+
"InitializationService", # 3 - Infrastructure
|
|
60
|
+
"ResourceMonitor", # 4 - Infrastructure
|
|
61
|
+
"SecretsService", # 5 - Memory Foundation
|
|
62
|
+
"MemoryService", # 6 - Memory Foundation
|
|
63
|
+
"ConfigService", # 7 - Graph Services
|
|
64
|
+
"AuditService", # 8 - Graph Services
|
|
65
|
+
"TelemetryService", # 9 - Graph Services
|
|
66
|
+
"IncidentManagement", # 10 - Graph Services
|
|
67
|
+
"TSDBConsolidation", # 11 - Graph Services
|
|
68
|
+
"ConsentService", # 12 - Graph Services
|
|
69
|
+
"WiseAuthority", # 13 - Security
|
|
70
|
+
"LLMService", # 14 - Runtime
|
|
71
|
+
"AuthenticationService", # 15 - Runtime (adapter-provided)
|
|
72
|
+
"DatabaseMaintenance", # 16 - Infrastructure
|
|
73
|
+
"RuntimeControl", # 17 - Runtime (adapter-provided)
|
|
74
|
+
"TaskScheduler", # 18 - Lifecycle
|
|
75
|
+
"AdaptiveFilter", # 19 - Governance
|
|
76
|
+
"VisibilityService", # 20 - Governance
|
|
77
|
+
"SelfObservation", # 21 - Governance
|
|
78
|
+
"SecretsToolService", # 22 - Tool Services
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
# Track which phase we're in for logging clarity
|
|
82
|
+
_current_phase: str = "STARTUP"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _set_service_phase(phase: str) -> None:
|
|
86
|
+
"""Set the current service initialization phase for logging."""
|
|
87
|
+
global _current_phase
|
|
88
|
+
_current_phase = phase
|
|
89
|
+
logger.warning(f"[SERVICES] === {phase} PHASE ===")
|
|
90
|
+
print(f"[SERVICES] === {phase} PHASE ===")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _log_service_started(service_num: int, service_name: str, success: bool = True) -> None:
|
|
94
|
+
"""Log service startup status in a format parseable by the UI."""
|
|
95
|
+
status = "STARTED" if success else "FAILED"
|
|
96
|
+
phase_prefix = f"[{_current_phase}] " if _current_phase != "STARTUP" else ""
|
|
97
|
+
msg = f"{phase_prefix}[SERVICE {service_num}/{TOTAL_CORE_SERVICES}] {service_name} {status}"
|
|
98
|
+
# Use WARNING level so it shows up in incident logs for easy parsing
|
|
99
|
+
logger.warning(msg)
|
|
100
|
+
# Also print to console/stdout for Android logcat visibility
|
|
101
|
+
print(msg)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class ServiceInitializer:
|
|
105
|
+
"""Manages initialization of all core services."""
|
|
106
|
+
|
|
107
|
+
def __init__(self, essential_config: Optional[EssentialConfig] = None) -> None:
|
|
108
|
+
self.service_registry: Optional[ServiceRegistry] = None
|
|
109
|
+
self.bus_manager: Optional[Any] = None # Will be BusManager
|
|
110
|
+
self.essential_config = essential_config or EssentialConfig()
|
|
111
|
+
self.config_accessor: Optional[ConfigAccessor] = None
|
|
112
|
+
|
|
113
|
+
# Infrastructure services (initialized first)
|
|
114
|
+
self.time_service: Optional[TimeService] = None
|
|
115
|
+
self.shutdown_service: Optional[ShutdownService] = None
|
|
116
|
+
self.initialization_service: Optional[InitializationService] = None
|
|
117
|
+
|
|
118
|
+
# Create initial config accessor without graph (bootstrap only)
|
|
119
|
+
self.config_accessor = ConfigAccessor(None, self.essential_config)
|
|
120
|
+
|
|
121
|
+
# Core services
|
|
122
|
+
self.memory_service: Optional[LocalGraphMemoryService] = None
|
|
123
|
+
self.secrets_service: Optional[SecretsService] = None
|
|
124
|
+
self.wa_auth_system: Optional[WiseAuthorityService] = None
|
|
125
|
+
self.telemetry_service: Optional[TelemetryService] = None
|
|
126
|
+
self.llm_service: Optional[LLMService] = None
|
|
127
|
+
self.audit_service: Optional[AuditService] = None
|
|
128
|
+
# Removed audit_sink_manager - audit is consolidated
|
|
129
|
+
self.adaptive_filter_service: Optional[AdaptiveFilterService] = None
|
|
130
|
+
self.secrets_tool_service: Optional[Any] = None # SecretsToolService
|
|
131
|
+
self.maintenance_service: Optional[DatabaseMaintenanceService] = None
|
|
132
|
+
self.incident_management_service: Optional[Any] = None # Will be IncidentManagementService
|
|
133
|
+
self.tsdb_consolidation_service: Optional[Any] = None # Will be TSDBConsolidationService
|
|
134
|
+
self.resource_monitor_service: Optional[Any] = None # Will be ResourceMonitorService
|
|
135
|
+
self.config_service: Optional[Any] = None # Will be GraphConfigService
|
|
136
|
+
self.self_observation_service: Optional[Any] = None # Will be SelfObservationService
|
|
137
|
+
self.visibility_service: Optional[Any] = None # Will be VisibilityService
|
|
138
|
+
self.consent_service: Optional[Any] = None # Will be ConsentService
|
|
139
|
+
self.runtime_control_service: Optional[Any] = None # Will be RuntimeControlService
|
|
140
|
+
|
|
141
|
+
# Module management
|
|
142
|
+
self.module_loader: Optional[Any] = None # Will be ModuleLoader
|
|
143
|
+
self.loaded_modules: List[str] = []
|
|
144
|
+
self._skip_llm_init: bool = False # Set to True if MOCK LLM module detected
|
|
145
|
+
|
|
146
|
+
# Metrics tracking for v1.4.3
|
|
147
|
+
self._services_started_count: int = 0
|
|
148
|
+
self._initialization_errors: int = 0
|
|
149
|
+
self._dependencies_resolved: int = 0
|
|
150
|
+
self._startup_start_time: Optional[float] = None
|
|
151
|
+
self._startup_end_time: Optional[float] = None
|
|
152
|
+
|
|
153
|
+
def _is_first_run_mode(self) -> bool:
|
|
154
|
+
"""Check if we're in first-run mode."""
|
|
155
|
+
from ciris_engine.logic.setup.first_run import is_first_run
|
|
156
|
+
|
|
157
|
+
return is_first_run()
|
|
158
|
+
|
|
159
|
+
async def initialize_infrastructure_services(self) -> None:
|
|
160
|
+
"""Initialize infrastructure services that all other services depend on."""
|
|
161
|
+
# Track startup time
|
|
162
|
+
import time
|
|
163
|
+
|
|
164
|
+
if self._startup_start_time is None:
|
|
165
|
+
self._startup_start_time = time.time()
|
|
166
|
+
|
|
167
|
+
# Set phase for logging - this is the first phase of initialization
|
|
168
|
+
_set_service_phase("FIRST-RUN" if self._is_first_run_mode() else "FULL-STARTUP")
|
|
169
|
+
|
|
170
|
+
# Initialize TimeService first - everyone needs time
|
|
171
|
+
try:
|
|
172
|
+
self.time_service = TimeService()
|
|
173
|
+
await self.time_service.start()
|
|
174
|
+
self._services_started_count += 1
|
|
175
|
+
_log_service_started(1, "TimeService")
|
|
176
|
+
except Exception as e:
|
|
177
|
+
self._initialization_errors += 1
|
|
178
|
+
_log_service_started(1, "TimeService", success=False)
|
|
179
|
+
logger.error(f"Failed to initialize TimeService: {e}")
|
|
180
|
+
raise
|
|
181
|
+
assert self.time_service is not None # For type checker
|
|
182
|
+
|
|
183
|
+
# Note: TimeService will be registered in ServiceRegistry later
|
|
184
|
+
# when the registry is created in initialize_all_services()
|
|
185
|
+
|
|
186
|
+
# Initialize ShutdownService
|
|
187
|
+
self.shutdown_service = ShutdownService()
|
|
188
|
+
await self.shutdown_service.start()
|
|
189
|
+
self._services_started_count += 1
|
|
190
|
+
_log_service_started(2, "ShutdownService")
|
|
191
|
+
|
|
192
|
+
# Initialize InitializationService with TimeService
|
|
193
|
+
self.initialization_service = InitializationService(self.time_service)
|
|
194
|
+
await self.initialization_service.start()
|
|
195
|
+
self._services_started_count += 1
|
|
196
|
+
_log_service_started(3, "InitializationService")
|
|
197
|
+
|
|
198
|
+
# Initialize ResourceMonitorService
|
|
199
|
+
from ciris_engine.logic.services.infrastructure.resource_monitor import ResourceMonitorService
|
|
200
|
+
from ciris_engine.schemas.services.resources_core import ResourceBudget
|
|
201
|
+
|
|
202
|
+
# Create default resource budget
|
|
203
|
+
budget = ResourceBudget() # Uses defaults from schema
|
|
204
|
+
|
|
205
|
+
# Credit provider: Controls billing for CIRIS LLM proxy usage
|
|
206
|
+
# - Server: CIRIS_BILLING_API_KEY set → API key auth
|
|
207
|
+
# - Android: Using CIRIS proxy + Google ID token → JWT auth
|
|
208
|
+
# - Not using CIRIS proxy → No billing (credit_provider = None)
|
|
209
|
+
from typing import Optional
|
|
210
|
+
|
|
211
|
+
from ciris_engine.protocols.services.infrastructure.credit_gate import CreditGateProtocol
|
|
212
|
+
|
|
213
|
+
credit_provider: Optional[CreditGateProtocol] = None
|
|
214
|
+
is_android = "ANDROID_DATA" in os.environ
|
|
215
|
+
|
|
216
|
+
# Check if using CIRIS LLM proxy (Android only - billing required for proxy)
|
|
217
|
+
# Matches both legacy ciris.ai and new ciris-services infrastructure
|
|
218
|
+
llm_base_url = os.getenv("OPENAI_API_BASE", "")
|
|
219
|
+
using_ciris_proxy = "ciris.ai" in llm_base_url or "ciris-services" in llm_base_url
|
|
220
|
+
|
|
221
|
+
# Server: Simple API key check
|
|
222
|
+
api_key = os.getenv("CIRIS_BILLING_API_KEY", "")
|
|
223
|
+
# Android: Google ID token for JWT auth with CIRIS proxy
|
|
224
|
+
google_id_token = os.getenv("CIRIS_BILLING_GOOGLE_ID_TOKEN", "")
|
|
225
|
+
|
|
226
|
+
if api_key and not is_android:
|
|
227
|
+
# Server with API key - use API key auth
|
|
228
|
+
from ciris_engine.logic.services.infrastructure.resource_monitor import CIRISBillingProvider
|
|
229
|
+
|
|
230
|
+
base_url = get_billing_url()
|
|
231
|
+
timeout = float(os.getenv("CIRIS_BILLING_TIMEOUT_SECONDS", "5.0"))
|
|
232
|
+
cache_ttl = int(os.getenv("CIRIS_BILLING_CACHE_TTL_SECONDS", "15"))
|
|
233
|
+
fail_open = os.getenv("CIRIS_BILLING_FAIL_OPEN", "false").lower() == "true"
|
|
234
|
+
|
|
235
|
+
credit_provider = CIRISBillingProvider(
|
|
236
|
+
api_key=api_key,
|
|
237
|
+
base_url=base_url,
|
|
238
|
+
timeout_seconds=timeout,
|
|
239
|
+
cache_ttl_seconds=cache_ttl,
|
|
240
|
+
fail_open=fail_open,
|
|
241
|
+
)
|
|
242
|
+
logger.info("Using CIRISBillingProvider with API key auth (URL: %s)", base_url)
|
|
243
|
+
|
|
244
|
+
elif is_android and using_ciris_proxy:
|
|
245
|
+
# Android using CIRIS LLM proxy - requires billing
|
|
246
|
+
if google_id_token:
|
|
247
|
+
# Have Google ID token - use JWT auth
|
|
248
|
+
from ciris_engine.logic.services.infrastructure.resource_monitor import CIRISBillingProvider
|
|
249
|
+
|
|
250
|
+
base_url = get_billing_url()
|
|
251
|
+
timeout = float(os.getenv("CIRIS_BILLING_TIMEOUT_SECONDS", "5.0"))
|
|
252
|
+
cache_ttl = int(os.getenv("CIRIS_BILLING_CACHE_TTL_SECONDS", "15"))
|
|
253
|
+
fail_open = os.getenv("CIRIS_BILLING_FAIL_OPEN", "false").lower() == "true"
|
|
254
|
+
|
|
255
|
+
credit_provider = CIRISBillingProvider(
|
|
256
|
+
google_id_token=google_id_token,
|
|
257
|
+
base_url=base_url,
|
|
258
|
+
timeout_seconds=timeout,
|
|
259
|
+
cache_ttl_seconds=cache_ttl,
|
|
260
|
+
fail_open=fail_open,
|
|
261
|
+
)
|
|
262
|
+
logger.info("Using CIRISBillingProvider with JWT auth (CIRIS LLM proxy)")
|
|
263
|
+
else:
|
|
264
|
+
# No token yet - user needs to sign in with Google
|
|
265
|
+
logger.warning(
|
|
266
|
+
"Android using CIRIS LLM proxy without Google ID token - "
|
|
267
|
+
"user needs to sign in with Google to use LLM features"
|
|
268
|
+
)
|
|
269
|
+
# credit_provider stays None - LLM calls will fail until signed in
|
|
270
|
+
|
|
271
|
+
elif is_android and not using_ciris_proxy:
|
|
272
|
+
# Android but not using CIRIS proxy - no billing needed
|
|
273
|
+
logger.info("Android not using CIRIS proxy - no billing required")
|
|
274
|
+
# credit_provider stays None
|
|
275
|
+
|
|
276
|
+
else:
|
|
277
|
+
# Server without API key - no billing
|
|
278
|
+
logger.info("No billing configured (CIRIS_BILLING_API_KEY not set)")
|
|
279
|
+
|
|
280
|
+
self.resource_monitor_service = ResourceMonitorService(
|
|
281
|
+
budget=budget,
|
|
282
|
+
db_path=get_sqlite_db_full_path(self.essential_config),
|
|
283
|
+
time_service=self.time_service,
|
|
284
|
+
credit_provider=credit_provider,
|
|
285
|
+
)
|
|
286
|
+
await self.resource_monitor_service.start()
|
|
287
|
+
self._services_started_count += 1
|
|
288
|
+
_log_service_started(4, "ResourceMonitor")
|
|
289
|
+
|
|
290
|
+
async def initialize_memory_service(self, config: Any) -> None:
|
|
291
|
+
"""Initialize the memory service."""
|
|
292
|
+
# Initialize secrets service first (memory service depends on it)
|
|
293
|
+
import os
|
|
294
|
+
from pathlib import Path
|
|
295
|
+
|
|
296
|
+
# Use configurable secrets key path from essential config
|
|
297
|
+
keys_dir = Path(self.essential_config.security.secrets_key_path)
|
|
298
|
+
keys_dir.mkdir(parents=True, exist_ok=True)
|
|
299
|
+
|
|
300
|
+
# Load or generate master key
|
|
301
|
+
master_key_path = keys_dir / "secrets_master.key"
|
|
302
|
+
master_key = None
|
|
303
|
+
is_android = "ANDROID_DATA" in os.environ
|
|
304
|
+
|
|
305
|
+
if is_android:
|
|
306
|
+
# Android: Use Keystore-wrapped key for hardware-backed protection
|
|
307
|
+
try:
|
|
308
|
+
from android_keystore import load_or_create_wrapped_master_key, migrate_plain_key_to_wrapped
|
|
309
|
+
|
|
310
|
+
# Migrate existing plain key if present
|
|
311
|
+
migrate_plain_key_to_wrapped(master_key_path)
|
|
312
|
+
|
|
313
|
+
# Load or create wrapped key
|
|
314
|
+
master_key = load_or_create_wrapped_master_key(master_key_path)
|
|
315
|
+
if master_key:
|
|
316
|
+
logger.info("Loaded secrets master key with Android Keystore protection")
|
|
317
|
+
else:
|
|
318
|
+
logger.error("Failed to load/create Keystore-wrapped master key")
|
|
319
|
+
except ImportError:
|
|
320
|
+
logger.warning("Android Keystore module not available, falling back to file storage")
|
|
321
|
+
is_android = False # Fall through to standard path
|
|
322
|
+
except Exception as e:
|
|
323
|
+
logger.error(f"Android Keystore error: {e}, falling back to file storage")
|
|
324
|
+
is_android = False
|
|
325
|
+
|
|
326
|
+
if not is_android:
|
|
327
|
+
# Standard path: plain file storage (server deployments)
|
|
328
|
+
if master_key_path.exists():
|
|
329
|
+
# Load existing master key
|
|
330
|
+
async with aiofiles.open(master_key_path, "rb") as f:
|
|
331
|
+
master_key = await f.read()
|
|
332
|
+
logger.info("Loaded existing secrets master key")
|
|
333
|
+
else:
|
|
334
|
+
# Generate new master key and save it
|
|
335
|
+
import secrets
|
|
336
|
+
|
|
337
|
+
master_key = secrets.token_bytes(32)
|
|
338
|
+
async with aiofiles.open(master_key_path, "wb") as f:
|
|
339
|
+
await f.write(master_key)
|
|
340
|
+
# Set restrictive permissions (owner read/write only)
|
|
341
|
+
os.chmod(master_key_path, 0o600)
|
|
342
|
+
logger.info("Generated and saved new secrets master key")
|
|
343
|
+
|
|
344
|
+
# Create README if it doesn't exist
|
|
345
|
+
readme_path = keys_dir / "README.md"
|
|
346
|
+
if not readme_path.exists():
|
|
347
|
+
readme_content = """# CIRIS Keys Directory
|
|
348
|
+
|
|
349
|
+
This directory contains critical cryptographic keys for the CIRIS system.
|
|
350
|
+
|
|
351
|
+
## Files
|
|
352
|
+
|
|
353
|
+
### secrets_master.key
|
|
354
|
+
- **Purpose**: Master encryption key for the SecretsService
|
|
355
|
+
- **Type**: 256-bit symmetric key
|
|
356
|
+
- **Usage**: Used to derive per-secret encryption keys via PBKDF2
|
|
357
|
+
- **Algorithm**: AES-256-GCM encryption
|
|
358
|
+
- **Critical**: Loss of this key means all encrypted secrets become unrecoverable
|
|
359
|
+
|
|
360
|
+
### audit_signing_private.pem
|
|
361
|
+
- **Purpose**: Private key for signing audit log entries
|
|
362
|
+
- **Type**: RSA 2048-bit private key
|
|
363
|
+
- **Usage**: Creates digital signatures for non-repudiation
|
|
364
|
+
- **Critical**: Keep this key secure - compromise allows forging audit entries
|
|
365
|
+
|
|
366
|
+
### audit_signing_public.pem
|
|
367
|
+
- **Purpose**: Public key for verifying audit signatures
|
|
368
|
+
- **Type**: RSA 2048-bit public key
|
|
369
|
+
- **Usage**: Verifies signatures on audit entries
|
|
370
|
+
- **Note**: Can be shared publicly for verification purposes
|
|
371
|
+
|
|
372
|
+
## Security Notes
|
|
373
|
+
|
|
374
|
+
1. **Permissions**: All key files should have restrictive permissions (600)
|
|
375
|
+
2. **Backup**: Regularly backup these keys to secure offline storage
|
|
376
|
+
3. **Rotation**: Consider key rotation policies for long-running deployments
|
|
377
|
+
4. **Access**: Only the CIRIS process should access these keys
|
|
378
|
+
|
|
379
|
+
## DO NOT
|
|
380
|
+
- Commit these files to version control
|
|
381
|
+
- Share the private keys or master key
|
|
382
|
+
- Store copies in insecure locations
|
|
383
|
+
"""
|
|
384
|
+
async with aiofiles.open(readme_path, "w") as f:
|
|
385
|
+
await f.write(readme_content)
|
|
386
|
+
logger.info("Created .ciris_keys/README.md")
|
|
387
|
+
|
|
388
|
+
# Use the proper helper function to get secrets database path
|
|
389
|
+
# This handles PostgreSQL URL query parameter preservation correctly
|
|
390
|
+
from ciris_engine.logic.config import get_secrets_db_full_path
|
|
391
|
+
|
|
392
|
+
secrets_db_path = get_secrets_db_full_path(self.essential_config)
|
|
393
|
+
|
|
394
|
+
if self.time_service is None:
|
|
395
|
+
raise RuntimeError("TimeService must be initialized before SecretsService")
|
|
396
|
+
|
|
397
|
+
self.secrets_service = SecretsService(
|
|
398
|
+
db_path=secrets_db_path, time_service=self.time_service, master_key=master_key
|
|
399
|
+
)
|
|
400
|
+
await self.secrets_service.start()
|
|
401
|
+
self._services_started_count += 1
|
|
402
|
+
_log_service_started(5, "SecretsService")
|
|
403
|
+
|
|
404
|
+
# Create and register CoreToolService
|
|
405
|
+
from ciris_engine.logic.services.tools import CoreToolService
|
|
406
|
+
|
|
407
|
+
self.secrets_tool_service = CoreToolService(
|
|
408
|
+
secrets_service=self.secrets_service,
|
|
409
|
+
time_service=self.time_service,
|
|
410
|
+
# Don't pass db_path - let persistence layer use current config
|
|
411
|
+
# This allows runtime database switching (SQLite → PostgreSQL via CIRIS_DB_URL)
|
|
412
|
+
)
|
|
413
|
+
await self.secrets_tool_service.start()
|
|
414
|
+
self._services_started_count += 1
|
|
415
|
+
_log_service_started(22, "SecretsToolService")
|
|
416
|
+
|
|
417
|
+
# LocalGraphMemoryService needs the correct db path from our config
|
|
418
|
+
db_path = get_sqlite_db_full_path(self.essential_config)
|
|
419
|
+
self.memory_service = LocalGraphMemoryService(
|
|
420
|
+
db_path=db_path, time_service=self.time_service, secrets_service=self.secrets_service
|
|
421
|
+
)
|
|
422
|
+
await self.memory_service.start()
|
|
423
|
+
self._services_started_count += 1
|
|
424
|
+
_log_service_started(6, "MemoryService")
|
|
425
|
+
|
|
426
|
+
# Initialize GraphConfigService now that memory service is ready
|
|
427
|
+
from ciris_engine.logic.registries.base import Priority, get_global_registry
|
|
428
|
+
from ciris_engine.logic.services.graph.config_service import GraphConfigService
|
|
429
|
+
from ciris_engine.schemas.runtime.enums import ServiceType
|
|
430
|
+
|
|
431
|
+
if self.time_service is None:
|
|
432
|
+
raise RuntimeError("TimeService must be initialized before GraphConfigService")
|
|
433
|
+
self.config_service = GraphConfigService(self.memory_service, self.time_service)
|
|
434
|
+
await self.config_service.start()
|
|
435
|
+
self._services_started_count += 1
|
|
436
|
+
_log_service_started(7, "ConfigService")
|
|
437
|
+
|
|
438
|
+
# Register config service immediately so it's available for persistence operations
|
|
439
|
+
registry = get_global_registry()
|
|
440
|
+
# Store essential config on the service so db_paths can find it
|
|
441
|
+
# Dynamic attribute assignment for runtime access to essential_config
|
|
442
|
+
self.config_service.essential_config = self.essential_config # type: ignore[attr-defined]
|
|
443
|
+
registry.register_service(
|
|
444
|
+
service_type=ServiceType.CONFIG,
|
|
445
|
+
provider=self.config_service,
|
|
446
|
+
priority=Priority.HIGH,
|
|
447
|
+
capabilities=["get_config", "set_config", "list_configs"],
|
|
448
|
+
metadata={"backend": "graph", "type": "essential"},
|
|
449
|
+
)
|
|
450
|
+
logger.info("Config service registered early in ServiceRegistry for persistence access")
|
|
451
|
+
|
|
452
|
+
# Create config accessor with graph service
|
|
453
|
+
self.config_accessor = ConfigAccessor(self.config_service, self.essential_config)
|
|
454
|
+
self._dependencies_resolved += 1 # Graph config service dependency
|
|
455
|
+
|
|
456
|
+
# Migrate essential config to graph
|
|
457
|
+
await self._migrate_config_to_graph()
|
|
458
|
+
|
|
459
|
+
async def verify_memory_service(self) -> bool:
|
|
460
|
+
"""Verify memory service is operational."""
|
|
461
|
+
if not self.memory_service:
|
|
462
|
+
logger.error("Memory service not initialized")
|
|
463
|
+
return False
|
|
464
|
+
|
|
465
|
+
# Test basic operations
|
|
466
|
+
try:
|
|
467
|
+
from ciris_engine.schemas.services.graph_core import GraphNode, GraphScope, NodeType
|
|
468
|
+
|
|
469
|
+
# Use a different node type for test - don't pollute CONFIG namespace
|
|
470
|
+
assert self.time_service is not None
|
|
471
|
+
now = self.time_service.now()
|
|
472
|
+
test_node = GraphNode(
|
|
473
|
+
id="_verification_test",
|
|
474
|
+
type=NodeType.OBSERVATION, # Use OBSERVATION type for system verification test
|
|
475
|
+
attributes={
|
|
476
|
+
"created_at": now.isoformat(), # Serialize to ISO string
|
|
477
|
+
"updated_at": now.isoformat(), # Serialize to ISO string
|
|
478
|
+
"created_by": "system_verification",
|
|
479
|
+
"tags": ["test", "verification"],
|
|
480
|
+
"verification_type": "memory_service", # Custom field in attributes dict
|
|
481
|
+
"verifier": "system", # Custom field in attributes dict
|
|
482
|
+
},
|
|
483
|
+
scope=GraphScope.LOCAL,
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
# Test memorize and recall
|
|
487
|
+
await self.memory_service.memorize(test_node)
|
|
488
|
+
|
|
489
|
+
from ciris_engine.schemas.services.operations import MemoryQuery
|
|
490
|
+
|
|
491
|
+
query = MemoryQuery(
|
|
492
|
+
node_id=test_node.id, scope=test_node.scope, type=test_node.type, include_edges=False, depth=1
|
|
493
|
+
)
|
|
494
|
+
nodes = await self.memory_service.recall(query)
|
|
495
|
+
|
|
496
|
+
if not nodes:
|
|
497
|
+
logger.error("Memory service verification failed: no nodes recalled")
|
|
498
|
+
return False
|
|
499
|
+
|
|
500
|
+
# Clean up
|
|
501
|
+
await self.memory_service.forget(test_node)
|
|
502
|
+
|
|
503
|
+
logger.info("✓ Memory service verified")
|
|
504
|
+
return True
|
|
505
|
+
|
|
506
|
+
except Exception as e:
|
|
507
|
+
logger.error(f"Memory service verification error: {e}")
|
|
508
|
+
return False
|
|
509
|
+
|
|
510
|
+
async def initialize_security_services(self, config: Any, app_config: Any) -> None:
|
|
511
|
+
"""Initialize security-related services."""
|
|
512
|
+
# SecretsService already initialized in initialize_memory_service
|
|
513
|
+
|
|
514
|
+
# Initialize AuthenticationService first
|
|
515
|
+
from ciris_engine.logic.services.infrastructure.authentication import AuthenticationService
|
|
516
|
+
|
|
517
|
+
if self.time_service is None:
|
|
518
|
+
raise RuntimeError("TimeService must be initialized before AuthenticationService")
|
|
519
|
+
|
|
520
|
+
if self.config_accessor is None:
|
|
521
|
+
raise RuntimeError("ConfigAccessor must be initialized before AuthenticationService")
|
|
522
|
+
# Get main database path for WiseAuthority (needs access to tasks table)
|
|
523
|
+
main_db_path = get_sqlite_db_full_path(self.essential_config)
|
|
524
|
+
|
|
525
|
+
# Use the proper helper function to get auth database path
|
|
526
|
+
# This handles PostgreSQL URL query parameter preservation correctly
|
|
527
|
+
from ciris_engine.logic.config import get_audit_db_full_path
|
|
528
|
+
|
|
529
|
+
auth_db_path = get_audit_db_full_path(self.essential_config)
|
|
530
|
+
self.auth_service = AuthenticationService(
|
|
531
|
+
db_path=auth_db_path, time_service=self.time_service, key_dir=None # Will use default ~/.ciris/
|
|
532
|
+
)
|
|
533
|
+
await self.auth_service.start()
|
|
534
|
+
self._services_started_count += 1
|
|
535
|
+
_log_service_started(15, "AuthenticationService")
|
|
536
|
+
|
|
537
|
+
# Process pending users from setup wizard if file exists
|
|
538
|
+
await self._process_pending_users_from_setup()
|
|
539
|
+
|
|
540
|
+
# Initialize WA authentication system with TimeService and AuthService
|
|
541
|
+
# Use the main database path - WiseAuthority needs access to tasks table
|
|
542
|
+
self.wa_auth_system = WiseAuthorityService(
|
|
543
|
+
time_service=self.time_service, auth_service=self.auth_service, db_path=main_db_path
|
|
544
|
+
)
|
|
545
|
+
await self.wa_auth_system.start()
|
|
546
|
+
self._services_started_count += 1
|
|
547
|
+
_log_service_started(13, "WiseAuthority")
|
|
548
|
+
|
|
549
|
+
# Log summary for first-run mode
|
|
550
|
+
if self._is_first_run_mode():
|
|
551
|
+
msg = f"[FIRST-RUN] ✓ {self._services_started_count}/{FIRST_RUN_SERVICES} minimal services started - ready for setup wizard"
|
|
552
|
+
logger.warning(msg)
|
|
553
|
+
print(msg)
|
|
554
|
+
|
|
555
|
+
async def verify_security_services(self) -> bool:
|
|
556
|
+
"""Verify security services are operational."""
|
|
557
|
+
# Verify secrets service
|
|
558
|
+
if not self.secrets_service:
|
|
559
|
+
logger.error("Secrets service not initialized")
|
|
560
|
+
return False
|
|
561
|
+
|
|
562
|
+
# Verify WA auth system
|
|
563
|
+
if not self.wa_auth_system:
|
|
564
|
+
logger.error("WA authentication system not initialized")
|
|
565
|
+
return False
|
|
566
|
+
|
|
567
|
+
# Verify WA service is healthy
|
|
568
|
+
if not await self.wa_auth_system.is_healthy():
|
|
569
|
+
logger.error("WA auth service not healthy")
|
|
570
|
+
return False
|
|
571
|
+
|
|
572
|
+
logger.info("✓ Security services verified")
|
|
573
|
+
return True
|
|
574
|
+
|
|
575
|
+
async def initialize_all_services(
|
|
576
|
+
self,
|
|
577
|
+
config: Any,
|
|
578
|
+
app_config: Any,
|
|
579
|
+
agent_id: str,
|
|
580
|
+
startup_channel_id: Optional[str] = None,
|
|
581
|
+
modules_to_load: Optional[List[str]] = None,
|
|
582
|
+
) -> None:
|
|
583
|
+
"""Initialize all remaining core services.
|
|
584
|
+
|
|
585
|
+
This is called:
|
|
586
|
+
- During normal startup: After first-run services (completes all 22)
|
|
587
|
+
- During resume_from_first_run: Starts the remaining 12 services after wizard
|
|
588
|
+
"""
|
|
589
|
+
# Set phase for logging - RESUME if coming from first-run, otherwise continue FULL-STARTUP
|
|
590
|
+
if self._services_started_count == FIRST_RUN_SERVICES:
|
|
591
|
+
_set_service_phase(f"RESUME ({RESUME_SERVICES} remaining services)")
|
|
592
|
+
else:
|
|
593
|
+
_set_service_phase("CORE-SERVICES")
|
|
594
|
+
|
|
595
|
+
from ciris_engine.logic.registries.base import get_global_registry
|
|
596
|
+
|
|
597
|
+
self.service_registry = get_global_registry()
|
|
598
|
+
|
|
599
|
+
# Register TimeService now that we have a registry
|
|
600
|
+
if self.time_service:
|
|
601
|
+
self.service_registry.register_service(
|
|
602
|
+
service_type=ServiceType.TIME,
|
|
603
|
+
provider=self.time_service,
|
|
604
|
+
priority=Priority.CRITICAL,
|
|
605
|
+
capabilities=["now", "format_timestamp", "parse_timestamp"],
|
|
606
|
+
metadata={"timezone": "UTC"},
|
|
607
|
+
)
|
|
608
|
+
self._dependencies_resolved += 1 # Service registry dependency
|
|
609
|
+
logger.info("TimeService registered in ServiceRegistry")
|
|
610
|
+
|
|
611
|
+
# Pre-load module loader to check for MOCK modules BEFORE initializing services
|
|
612
|
+
if modules_to_load:
|
|
613
|
+
logger.info(f"Checking modules to load: {modules_to_load}")
|
|
614
|
+
from ciris_engine.logic.runtime.module_loader import ModuleLoader
|
|
615
|
+
|
|
616
|
+
self.module_loader = ModuleLoader()
|
|
617
|
+
|
|
618
|
+
# Check modules for MOCK status WITHOUT loading them yet
|
|
619
|
+
for module_name in modules_to_load:
|
|
620
|
+
assert self.module_loader is not None
|
|
621
|
+
module_path = self.module_loader.modules_dir / module_name
|
|
622
|
+
manifest_path = module_path / "manifest.json"
|
|
623
|
+
logger.info(f"Checking for manifest at: {manifest_path}")
|
|
624
|
+
|
|
625
|
+
if manifest_path.exists():
|
|
626
|
+
try:
|
|
627
|
+
async with aiofiles.open(manifest_path) as f:
|
|
628
|
+
content = await f.read()
|
|
629
|
+
manifest_data = json.loads(content)
|
|
630
|
+
|
|
631
|
+
# Parse into typed manifest
|
|
632
|
+
manifest = ServiceManifest.model_validate(manifest_data)
|
|
633
|
+
|
|
634
|
+
if manifest.module.is_mock:
|
|
635
|
+
# This is a MOCK module - check what services it provides
|
|
636
|
+
for service in manifest.services:
|
|
637
|
+
if service.type == ServiceType.LLM:
|
|
638
|
+
logger.info(
|
|
639
|
+
f"Detected MOCK LLM module '{module_name}' will be loaded - skipping normal LLM initialization"
|
|
640
|
+
)
|
|
641
|
+
self._skip_llm_init = True
|
|
642
|
+
break
|
|
643
|
+
except Exception as e:
|
|
644
|
+
logger.warning(f"Failed to pre-check module {module_name}: {e}")
|
|
645
|
+
else:
|
|
646
|
+
modules_to_load = []
|
|
647
|
+
|
|
648
|
+
# Register previously initialized services in the registry
|
|
649
|
+
# Register previously initialized services in the registry as per CLAUDE.md
|
|
650
|
+
|
|
651
|
+
# Config service was already registered early in initialize_memory_service
|
|
652
|
+
# to ensure it's available for persistence operations
|
|
653
|
+
|
|
654
|
+
# Memory service was initialized in Phase 2, register it now
|
|
655
|
+
if self.memory_service:
|
|
656
|
+
self.service_registry.register_service(
|
|
657
|
+
service_type=ServiceType.MEMORY,
|
|
658
|
+
provider=self.memory_service,
|
|
659
|
+
priority=Priority.HIGH,
|
|
660
|
+
capabilities=[
|
|
661
|
+
"memorize",
|
|
662
|
+
"recall",
|
|
663
|
+
"forget",
|
|
664
|
+
"graph_operations",
|
|
665
|
+
"memorize_metric",
|
|
666
|
+
"memorize_log",
|
|
667
|
+
"recall_timeseries",
|
|
668
|
+
"export_identity_context",
|
|
669
|
+
"search",
|
|
670
|
+
],
|
|
671
|
+
metadata={"backend": "sqlite", "graph_type": "local"},
|
|
672
|
+
)
|
|
673
|
+
self._dependencies_resolved += 1 # Memory service dependency
|
|
674
|
+
logger.info("Memory service registered in ServiceRegistry")
|
|
675
|
+
|
|
676
|
+
# WiseAuthority service was initialized in security phase, register it now
|
|
677
|
+
if self.wa_auth_system:
|
|
678
|
+
self.service_registry.register_service(
|
|
679
|
+
service_type=ServiceType.WISE_AUTHORITY,
|
|
680
|
+
provider=self.wa_auth_system,
|
|
681
|
+
priority=Priority.HIGH,
|
|
682
|
+
capabilities=[
|
|
683
|
+
"authenticate",
|
|
684
|
+
"authorize",
|
|
685
|
+
"validate",
|
|
686
|
+
"guidance",
|
|
687
|
+
"send_deferral",
|
|
688
|
+
"get_pending_deferrals",
|
|
689
|
+
"resolve_deferral",
|
|
690
|
+
],
|
|
691
|
+
metadata={"type": "consolidated", "consensus": "single"},
|
|
692
|
+
)
|
|
693
|
+
self._dependencies_resolved += 1 # WiseAuthority service dependency
|
|
694
|
+
logger.info("WiseAuthority service registered in ServiceRegistry")
|
|
695
|
+
|
|
696
|
+
# Create BusManager first (without telemetry service)
|
|
697
|
+
assert self.service_registry is not None
|
|
698
|
+
assert self.time_service is not None
|
|
699
|
+
self.bus_manager = BusManager(
|
|
700
|
+
self.service_registry,
|
|
701
|
+
self.time_service,
|
|
702
|
+
None, # telemetry_service will be set later
|
|
703
|
+
None, # audit_service will be set later
|
|
704
|
+
)
|
|
705
|
+
self._dependencies_resolved += 1 # BusManager dependency
|
|
706
|
+
|
|
707
|
+
# Initialize telemetry service using GraphTelemetryService
|
|
708
|
+
# This implements the "Graph Memory as Identity Architecture" patent
|
|
709
|
+
# where telemetry IS memory stored in the agent's identity graph
|
|
710
|
+
from ciris_engine.logic.services.graph.telemetry_service import GraphTelemetryService
|
|
711
|
+
|
|
712
|
+
assert self.bus_manager is not None
|
|
713
|
+
assert self.time_service is not None
|
|
714
|
+
try:
|
|
715
|
+
# Create the concrete GraphTelemetryService instance
|
|
716
|
+
telemetry_service_impl = GraphTelemetryService(
|
|
717
|
+
memory_bus=self.bus_manager.memory, time_service=self.time_service # Now we have the memory bus
|
|
718
|
+
)
|
|
719
|
+
# Attach service registry using protocol pattern
|
|
720
|
+
# Use hasattr (protocol is not @runtime_checkable)
|
|
721
|
+
if self.service_registry and hasattr(telemetry_service_impl, "attach_registry"):
|
|
722
|
+
await telemetry_service_impl.attach_registry(self.service_registry)
|
|
723
|
+
await telemetry_service_impl.start()
|
|
724
|
+
# Assign to protocol-typed field after all setup is complete
|
|
725
|
+
# Note: GraphTelemetryService structurally implements TelemetryService protocol
|
|
726
|
+
self.telemetry_service = telemetry_service_impl # type: ignore[assignment]
|
|
727
|
+
self._services_started_count += 1
|
|
728
|
+
_log_service_started(9, "TelemetryService")
|
|
729
|
+
except Exception as e:
|
|
730
|
+
self._initialization_errors += 1
|
|
731
|
+
logger.error(f"Failed to initialize GraphTelemetryService: {e}")
|
|
732
|
+
raise
|
|
733
|
+
|
|
734
|
+
# Now set the telemetry service in bus manager and LLM bus
|
|
735
|
+
self.bus_manager.telemetry_service = self.telemetry_service
|
|
736
|
+
self.bus_manager.llm.telemetry_service = self.telemetry_service
|
|
737
|
+
|
|
738
|
+
# Initialize LLM service(s) based on configuration
|
|
739
|
+
await self._initialize_llm_services(config, modules_to_load)
|
|
740
|
+
|
|
741
|
+
# Secrets service no longer needs LLM service reference
|
|
742
|
+
|
|
743
|
+
# Initialize ALL THREE REQUIRED audit services
|
|
744
|
+
await self._initialize_audit_services(config, agent_id)
|
|
745
|
+
|
|
746
|
+
# Initialize adaptive filter service
|
|
747
|
+
assert self.memory_service is not None
|
|
748
|
+
assert self.time_service is not None
|
|
749
|
+
assert self.config_service is not None
|
|
750
|
+
self.adaptive_filter_service = AdaptiveFilterService(
|
|
751
|
+
memory_service=self.memory_service,
|
|
752
|
+
time_service=self.time_service,
|
|
753
|
+
llm_service=self.llm_service,
|
|
754
|
+
config_service=self.config_service, # Pass GraphConfigService
|
|
755
|
+
)
|
|
756
|
+
await self.adaptive_filter_service.start()
|
|
757
|
+
self._services_started_count += 1
|
|
758
|
+
_log_service_started(19, "AdaptiveFilter")
|
|
759
|
+
|
|
760
|
+
# GraphConfigService (initialized earlier) handles all configuration including agent config
|
|
761
|
+
# No separate agent configuration service needed - see GraphConfigService documentation
|
|
762
|
+
|
|
763
|
+
# Transaction orchestrator not needed - bus-based architecture handles
|
|
764
|
+
# coordination without requiring distributed transactions
|
|
765
|
+
|
|
766
|
+
# CoreToolService removed - tools are adapter-only per user request
|
|
767
|
+
# SELF_HELP moved to memory service
|
|
768
|
+
|
|
769
|
+
# Initialize task scheduler service
|
|
770
|
+
from ciris_engine.logic.services.lifecycle.scheduler import TaskSchedulerService
|
|
771
|
+
|
|
772
|
+
# Get the correct db path from our essential config
|
|
773
|
+
db_path = get_sqlite_db_full_path(self.essential_config)
|
|
774
|
+
self.task_scheduler_service = TaskSchedulerService(db_path=db_path, time_service=self.time_service)
|
|
775
|
+
await self.task_scheduler_service.start()
|
|
776
|
+
self._services_started_count += 1
|
|
777
|
+
_log_service_started(18, "TaskScheduler")
|
|
778
|
+
|
|
779
|
+
# Initialize TSDB consolidation service BEFORE maintenance
|
|
780
|
+
# This ensures we consolidate any missed windows before maintenance runs
|
|
781
|
+
from ciris_engine.logic.services.graph.tsdb_consolidation import TSDBConsolidationService
|
|
782
|
+
|
|
783
|
+
assert self.bus_manager is not None
|
|
784
|
+
assert self.time_service is not None
|
|
785
|
+
|
|
786
|
+
# Get configuration from essential config
|
|
787
|
+
config = self.essential_config
|
|
788
|
+
graph_config = config.graph if hasattr(config, "graph") else None
|
|
789
|
+
|
|
790
|
+
# Get the correct db path from our essential config
|
|
791
|
+
db_path = get_sqlite_db_full_path(self.essential_config)
|
|
792
|
+
self.tsdb_consolidation_service = TSDBConsolidationService(
|
|
793
|
+
memory_bus=self.bus_manager.memory, # Use memory bus, not direct service
|
|
794
|
+
time_service=self.time_service, # Pass time service
|
|
795
|
+
consolidation_interval_hours=6, # Fixed for calendar alignment
|
|
796
|
+
raw_retention_hours=graph_config.tsdb_raw_retention_hours if graph_config else 24,
|
|
797
|
+
db_path=db_path,
|
|
798
|
+
)
|
|
799
|
+
await self.tsdb_consolidation_service.start()
|
|
800
|
+
self._services_started_count += 1
|
|
801
|
+
_log_service_started(11, "TSDBConsolidation")
|
|
802
|
+
|
|
803
|
+
# Register TSDBConsolidationService in registry
|
|
804
|
+
self.service_registry.register_service(
|
|
805
|
+
service_type=ServiceType.TSDB_CONSOLIDATION,
|
|
806
|
+
provider=self.tsdb_consolidation_service,
|
|
807
|
+
priority=Priority.NORMAL,
|
|
808
|
+
capabilities=["consolidate_data", "get_summaries"],
|
|
809
|
+
metadata={"consolidation_interval": "6h", "type": "tsdb"},
|
|
810
|
+
)
|
|
811
|
+
logger.info("TSDBConsolidationService registered in ServiceRegistry")
|
|
812
|
+
|
|
813
|
+
# Initialize maintenance service AFTER consolidation
|
|
814
|
+
archive_dir_config = getattr(config, "data_archive_dir", "data_archive")
|
|
815
|
+
# Resolve relative paths to absolute (critical for Android where CWD is read-only)
|
|
816
|
+
archive_path = Path(archive_dir_config)
|
|
817
|
+
if not archive_path.is_absolute():
|
|
818
|
+
archive_path = get_data_dir() / archive_dir_config
|
|
819
|
+
archive_dir = str(archive_path)
|
|
820
|
+
archive_hours = getattr(config, "archive_older_than_hours", 24)
|
|
821
|
+
assert self.time_service is not None
|
|
822
|
+
assert self.config_service is not None
|
|
823
|
+
assert self.bus_manager is not None
|
|
824
|
+
self.maintenance_service = DatabaseMaintenanceService(
|
|
825
|
+
time_service=self.time_service,
|
|
826
|
+
archive_dir_path=archive_dir,
|
|
827
|
+
archive_older_than_hours=archive_hours,
|
|
828
|
+
config_service=self.config_service,
|
|
829
|
+
bus_manager=self.bus_manager,
|
|
830
|
+
)
|
|
831
|
+
await self.maintenance_service.start()
|
|
832
|
+
self._services_started_count += 1
|
|
833
|
+
_log_service_started(16, "DatabaseMaintenance")
|
|
834
|
+
|
|
835
|
+
# Initialize self observation service
|
|
836
|
+
from ciris_engine.logic.services.governance.self_observation import SelfObservationService
|
|
837
|
+
|
|
838
|
+
assert self.time_service is not None
|
|
839
|
+
assert self.bus_manager is not None
|
|
840
|
+
self.self_observation_service = SelfObservationService(
|
|
841
|
+
time_service=self.time_service,
|
|
842
|
+
memory_bus=self.bus_manager.memory,
|
|
843
|
+
variance_threshold=0.20, # 20% max variance from baseline
|
|
844
|
+
observation_interval_hours=6,
|
|
845
|
+
)
|
|
846
|
+
# Attach service registry using protocol pattern
|
|
847
|
+
# Use hasattr (protocol is not @runtime_checkable)
|
|
848
|
+
if self.service_registry and hasattr(self.self_observation_service, "attach_registry"):
|
|
849
|
+
await self.self_observation_service.attach_registry(self.service_registry)
|
|
850
|
+
# Start the service for API mode (in other modes DREAM processor starts it)
|
|
851
|
+
await self.self_observation_service.start()
|
|
852
|
+
self._services_started_count += 1
|
|
853
|
+
_log_service_started(21, "SelfObservation")
|
|
854
|
+
|
|
855
|
+
# Initialize visibility service
|
|
856
|
+
from ciris_engine.logic.services.governance.visibility import VisibilityService
|
|
857
|
+
|
|
858
|
+
assert self.bus_manager is not None
|
|
859
|
+
assert self.time_service is not None
|
|
860
|
+
self.visibility_service = VisibilityService(
|
|
861
|
+
bus_manager=self.bus_manager,
|
|
862
|
+
time_service=self.time_service,
|
|
863
|
+
db_path=get_sqlite_db_full_path(self.essential_config),
|
|
864
|
+
)
|
|
865
|
+
await self.visibility_service.start()
|
|
866
|
+
self._services_started_count += 1
|
|
867
|
+
_log_service_started(20, "VisibilityService")
|
|
868
|
+
|
|
869
|
+
# Initialize consent service (Governance Service #5)
|
|
870
|
+
from ciris_engine.logic.services.governance.consent import ConsentService
|
|
871
|
+
|
|
872
|
+
assert self.time_service is not None
|
|
873
|
+
assert self.bus_manager is not None
|
|
874
|
+
self.consent_service = ConsentService(
|
|
875
|
+
time_service=self.time_service,
|
|
876
|
+
memory_bus=self.bus_manager.memory, # Use memory bus for impact reporting and audit trail
|
|
877
|
+
db_path=get_sqlite_db_full_path(self.essential_config),
|
|
878
|
+
)
|
|
879
|
+
await self.consent_service.start()
|
|
880
|
+
self._services_started_count += 1
|
|
881
|
+
_log_service_started(12, "ConsentService")
|
|
882
|
+
|
|
883
|
+
# Initialize runtime control service
|
|
884
|
+
from ciris_engine.logic.services.runtime.control_service import RuntimeControlService
|
|
885
|
+
|
|
886
|
+
assert self.config_service is not None
|
|
887
|
+
assert self.time_service is not None
|
|
888
|
+
self.runtime_control_service = RuntimeControlService(
|
|
889
|
+
runtime=None, # Will be set by runtime after initialization
|
|
890
|
+
adapter_manager=None, # Will be created on demand
|
|
891
|
+
config_manager=self.config_service,
|
|
892
|
+
time_service=self.time_service,
|
|
893
|
+
)
|
|
894
|
+
await self.runtime_control_service.start()
|
|
895
|
+
self._services_started_count += 1
|
|
896
|
+
_log_service_started(17, "RuntimeControl")
|
|
897
|
+
|
|
898
|
+
# Mark end of startup process
|
|
899
|
+
import time
|
|
900
|
+
|
|
901
|
+
self._startup_end_time = time.time()
|
|
902
|
+
|
|
903
|
+
def _get_llm_service_config_value(self, config: Any, attr_name: str, default: Any) -> Any:
|
|
904
|
+
"""Get LLM service config value safely with fallback to default.
|
|
905
|
+
|
|
906
|
+
Args:
|
|
907
|
+
config: Configuration object
|
|
908
|
+
attr_name: Attribute name to get from config.services
|
|
909
|
+
default: Default value if not found
|
|
910
|
+
|
|
911
|
+
Returns:
|
|
912
|
+
Config value or default
|
|
913
|
+
"""
|
|
914
|
+
if config and hasattr(config, "services") and config.services:
|
|
915
|
+
return getattr(config.services, attr_name, default)
|
|
916
|
+
return default
|
|
917
|
+
|
|
918
|
+
async def _initialize_llm_services(self, config: Any, modules_to_load: Optional[List[str]] = None) -> None:
|
|
919
|
+
"""Initialize LLM service(s) based on configuration.
|
|
920
|
+
|
|
921
|
+
CRITICAL: Only mock OR real LLM services are active, never both.
|
|
922
|
+
This prevents attack vectors where mock responses could be confused with real ones.
|
|
923
|
+
"""
|
|
924
|
+
# Skip if mock LLM module is being loaded
|
|
925
|
+
if self._skip_llm_init:
|
|
926
|
+
logger.info("🤖 MOCK LLM module detected - skipping real LLM service initialization")
|
|
927
|
+
return
|
|
928
|
+
|
|
929
|
+
# Validate config
|
|
930
|
+
if not hasattr(config, "services"):
|
|
931
|
+
raise ValueError("Configuration missing LLM service settings")
|
|
932
|
+
|
|
933
|
+
# Get API key
|
|
934
|
+
api_key = os.environ.get("OPENAI_API_KEY", "")
|
|
935
|
+
if not api_key:
|
|
936
|
+
logger.warning("No OPENAI_API_KEY found - LLM service will not be initialized")
|
|
937
|
+
return
|
|
938
|
+
|
|
939
|
+
# Initialize real LLM service
|
|
940
|
+
logger.info("Initializing real LLM service")
|
|
941
|
+
from ciris_engine.logic.services.runtime.llm_service import OpenAIConfig
|
|
942
|
+
|
|
943
|
+
# Get config values using helper to reduce complexity
|
|
944
|
+
base_url = os.environ.get("OPENAI_API_BASE") or self._get_llm_service_config_value(
|
|
945
|
+
config, "llm_endpoint", "http://localhost:11434/v1"
|
|
946
|
+
)
|
|
947
|
+
model_name = os.environ.get("OPENAI_MODEL") or self._get_llm_service_config_value(
|
|
948
|
+
config, "llm_model", "gpt-4o-mini"
|
|
949
|
+
)
|
|
950
|
+
|
|
951
|
+
llm_config = OpenAIConfig(
|
|
952
|
+
base_url=base_url,
|
|
953
|
+
model_name=model_name,
|
|
954
|
+
api_key=api_key,
|
|
955
|
+
instructor_mode=os.environ.get("INSTRUCTOR_MODE", "JSON"),
|
|
956
|
+
timeout_seconds=self._get_llm_service_config_value(config, "llm_timeout", 60),
|
|
957
|
+
max_retries=self._get_llm_service_config_value(config, "llm_max_retries", 3),
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
# Create and start service
|
|
961
|
+
openai_service = OpenAICompatibleClient(
|
|
962
|
+
config=llm_config, telemetry_service=self.telemetry_service, time_service=self.time_service
|
|
963
|
+
)
|
|
964
|
+
await openai_service.start()
|
|
965
|
+
|
|
966
|
+
# Register service
|
|
967
|
+
if self.service_registry:
|
|
968
|
+
self.service_registry.register_service(
|
|
969
|
+
service_type=ServiceType.LLM,
|
|
970
|
+
provider=openai_service,
|
|
971
|
+
priority=Priority.HIGH,
|
|
972
|
+
capabilities=[LLMCapabilities.CALL_LLM_STRUCTURED],
|
|
973
|
+
metadata={"provider": "openai", "model": llm_config.model_name},
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
# Store reference
|
|
977
|
+
self.llm_service = openai_service
|
|
978
|
+
self._services_started_count += 1
|
|
979
|
+
_log_service_started(14, "LLMService")
|
|
980
|
+
|
|
981
|
+
# Register token refresh signal handler for ciris.ai authentication
|
|
982
|
+
# This connects the LLM service to ResourceMonitor's signal bus
|
|
983
|
+
if self.resource_monitor_service and hasattr(self.resource_monitor_service, "signal_bus"):
|
|
984
|
+
self.resource_monitor_service.signal_bus.register("token_refreshed", openai_service.handle_token_refreshed)
|
|
985
|
+
logger.info("Registered LLM service token refresh handler with ResourceMonitor")
|
|
986
|
+
|
|
987
|
+
# Optional: Initialize secondary LLM service
|
|
988
|
+
# Supports both API key auth and CIRIS proxy with JWT auth (Google ID token)
|
|
989
|
+
second_api_key = os.environ.get("CIRIS_OPENAI_API_KEY_2", "")
|
|
990
|
+
second_base_url = os.environ.get("CIRIS_OPENAI_API_BASE_2", "")
|
|
991
|
+
google_id_token = os.environ.get("CIRIS_BILLING_GOOGLE_ID_TOKEN", "")
|
|
992
|
+
|
|
993
|
+
# Check if secondary LLM is CIRIS proxy (requires JWT auth, not API key)
|
|
994
|
+
is_ciris_proxy_secondary = "ciris.ai" in second_base_url
|
|
995
|
+
|
|
996
|
+
if second_api_key:
|
|
997
|
+
# Standard API key auth
|
|
998
|
+
await self._initialize_secondary_llm(config, second_api_key)
|
|
999
|
+
elif is_ciris_proxy_secondary and google_id_token:
|
|
1000
|
+
# CIRIS proxy with JWT auth - use Google ID token as auth
|
|
1001
|
+
logger.info("Secondary LLM using CIRIS proxy with JWT auth")
|
|
1002
|
+
await self._initialize_secondary_llm(config, google_id_token)
|
|
1003
|
+
|
|
1004
|
+
async def _initialize_secondary_llm(self, config: Any, api_key: str) -> None:
|
|
1005
|
+
"""Initialize optional secondary LLM service."""
|
|
1006
|
+
logger.info("Initializing secondary LLM service")
|
|
1007
|
+
|
|
1008
|
+
from ciris_engine.logic.services.runtime.llm_service import OpenAIConfig
|
|
1009
|
+
|
|
1010
|
+
# Get configuration from environment using helper
|
|
1011
|
+
base_url = os.environ.get(
|
|
1012
|
+
"CIRIS_OPENAI_API_BASE_2",
|
|
1013
|
+
self._get_llm_service_config_value(config, "llm_endpoint", "http://localhost:11434/v1"),
|
|
1014
|
+
)
|
|
1015
|
+
model_name = os.environ.get(
|
|
1016
|
+
"CIRIS_OPENAI_MODEL_NAME_2",
|
|
1017
|
+
self._get_llm_service_config_value(config, "llm_model", "llama3.2"),
|
|
1018
|
+
)
|
|
1019
|
+
|
|
1020
|
+
# Create config
|
|
1021
|
+
llm_config = OpenAIConfig(
|
|
1022
|
+
base_url=base_url,
|
|
1023
|
+
model_name=model_name,
|
|
1024
|
+
api_key=api_key,
|
|
1025
|
+
instructor_mode=os.environ.get("INSTRUCTOR_MODE", "JSON"),
|
|
1026
|
+
timeout_seconds=self._get_llm_service_config_value(config, "llm_timeout", 60),
|
|
1027
|
+
max_retries=self._get_llm_service_config_value(config, "llm_max_retries", 3),
|
|
1028
|
+
)
|
|
1029
|
+
|
|
1030
|
+
# Create and start service
|
|
1031
|
+
service = OpenAICompatibleClient(
|
|
1032
|
+
config=llm_config, telemetry_service=self.telemetry_service, time_service=self.time_service
|
|
1033
|
+
)
|
|
1034
|
+
await service.start()
|
|
1035
|
+
|
|
1036
|
+
# Register with lower priority
|
|
1037
|
+
if self.service_registry:
|
|
1038
|
+
self.service_registry.register_service(
|
|
1039
|
+
service_type=ServiceType.LLM,
|
|
1040
|
+
provider=service,
|
|
1041
|
+
priority=Priority.NORMAL,
|
|
1042
|
+
capabilities=[LLMCapabilities.CALL_LLM_STRUCTURED],
|
|
1043
|
+
metadata={"provider": "openai_secondary", "model": model_name, "base_url": base_url},
|
|
1044
|
+
)
|
|
1045
|
+
|
|
1046
|
+
logger.info(f"Secondary LLM service initialized: {model_name}")
|
|
1047
|
+
|
|
1048
|
+
async def _process_pending_users_from_setup(self) -> None:
|
|
1049
|
+
"""Process pending user creation from setup wizard.
|
|
1050
|
+
|
|
1051
|
+
Checks for ~/.ciris/.ciris_pending_users.json file and creates users if found.
|
|
1052
|
+
This file is created by the setup wizard during first-run configuration.
|
|
1053
|
+
"""
|
|
1054
|
+
import json
|
|
1055
|
+
from pathlib import Path
|
|
1056
|
+
|
|
1057
|
+
# Check for pending users file in ~/.ciris directory
|
|
1058
|
+
pending_users_file = Path.home() / ".ciris" / ".ciris_pending_users.json"
|
|
1059
|
+
|
|
1060
|
+
if not pending_users_file.exists():
|
|
1061
|
+
logger.debug("No pending users file found - skipping user creation")
|
|
1062
|
+
return
|
|
1063
|
+
|
|
1064
|
+
try:
|
|
1065
|
+
logger.info("=" * 80)
|
|
1066
|
+
logger.info("Processing pending users from setup wizard")
|
|
1067
|
+
logger.info("=" * 80)
|
|
1068
|
+
|
|
1069
|
+
# Read pending users data asynchronously
|
|
1070
|
+
async with aiofiles.open(pending_users_file, "r") as f:
|
|
1071
|
+
content = await f.read()
|
|
1072
|
+
users_data = json.loads(content)
|
|
1073
|
+
|
|
1074
|
+
logger.info(f"Loaded pending users file created at: {users_data.get('created_at')}")
|
|
1075
|
+
|
|
1076
|
+
# Process new user if specified
|
|
1077
|
+
if "new_user" in users_data:
|
|
1078
|
+
from ciris_engine.schemas.services.authority_core import WARole
|
|
1079
|
+
|
|
1080
|
+
new_user = users_data["new_user"]
|
|
1081
|
+
username = new_user["username"]
|
|
1082
|
+
password = new_user["password"]
|
|
1083
|
+
role_str = new_user.get("role", "OBSERVER")
|
|
1084
|
+
|
|
1085
|
+
# Map role string to WARole enum
|
|
1086
|
+
role_map = {
|
|
1087
|
+
"ADMIN": WARole.AUTHORITY,
|
|
1088
|
+
"AUTHORITY": WARole.AUTHORITY,
|
|
1089
|
+
"OBSERVER": WARole.OBSERVER,
|
|
1090
|
+
"USER": WARole.OBSERVER,
|
|
1091
|
+
}
|
|
1092
|
+
wa_role = role_map.get(role_str.upper(), WARole.OBSERVER)
|
|
1093
|
+
|
|
1094
|
+
logger.info(f"Creating new user: {username} with role: {wa_role}")
|
|
1095
|
+
|
|
1096
|
+
# Create WA certificate for the user
|
|
1097
|
+
wa_cert = await self.auth_service.create_wa(
|
|
1098
|
+
name=username,
|
|
1099
|
+
email=f"{username}@local", # Placeholder email for local users
|
|
1100
|
+
scopes=["read:any", "write:any"] if wa_role == WARole.AUTHORITY else ["read:any"],
|
|
1101
|
+
role=wa_role,
|
|
1102
|
+
)
|
|
1103
|
+
|
|
1104
|
+
# Hash password and update the WA
|
|
1105
|
+
password_hash = self.auth_service.hash_password(password)
|
|
1106
|
+
await self.auth_service.update_wa(wa_id=wa_cert.wa_id, password_hash=password_hash)
|
|
1107
|
+
|
|
1108
|
+
logger.info(f"✅ Successfully created user: {username} (WA: {wa_cert.wa_id})")
|
|
1109
|
+
|
|
1110
|
+
# Process system admin password update if specified
|
|
1111
|
+
if "system_admin" in users_data:
|
|
1112
|
+
admin_data = users_data["system_admin"]
|
|
1113
|
+
admin_username = admin_data["username"]
|
|
1114
|
+
new_password = admin_data["password"]
|
|
1115
|
+
|
|
1116
|
+
logger.info(f"Updating system admin password for: {admin_username}")
|
|
1117
|
+
|
|
1118
|
+
# Find the admin WA by username
|
|
1119
|
+
all_was = await self.auth_service.list_was(active_only=True)
|
|
1120
|
+
admin_wa = next((wa for wa in all_was if wa.name == admin_username), None)
|
|
1121
|
+
|
|
1122
|
+
if admin_wa:
|
|
1123
|
+
# Hash new password and update
|
|
1124
|
+
password_hash = self.auth_service.hash_password(new_password)
|
|
1125
|
+
await self.auth_service.update_wa(wa_id=admin_wa.wa_id, password_hash=password_hash)
|
|
1126
|
+
logger.info(f"✅ Successfully updated admin password for {admin_username}")
|
|
1127
|
+
else:
|
|
1128
|
+
logger.warning(f"⚠️ Admin user '{admin_username}' not found")
|
|
1129
|
+
|
|
1130
|
+
# Delete the pending users file after processing
|
|
1131
|
+
pending_users_file.unlink()
|
|
1132
|
+
logger.info("Deleted pending users file after successful processing")
|
|
1133
|
+
logger.info("=" * 80)
|
|
1134
|
+
|
|
1135
|
+
except Exception as e:
|
|
1136
|
+
logger.error(f"Error processing pending users file: {e}", exc_info=True)
|
|
1137
|
+
# Don't delete the file if processing failed - allow retry on next startup
|
|
1138
|
+
raise
|
|
1139
|
+
|
|
1140
|
+
async def _initialize_audit_services(self, config: Any, agent_id: str) -> None:
|
|
1141
|
+
"""Initialize the consolidated audit service with three storage backends.
|
|
1142
|
+
|
|
1143
|
+
The single GraphAuditService writes to three places:
|
|
1144
|
+
1. SQLite hash chain database (cryptographic integrity)
|
|
1145
|
+
2. Graph memory via MemoryBus (primary storage, searchable)
|
|
1146
|
+
3. File export (optional, for compliance)
|
|
1147
|
+
"""
|
|
1148
|
+
# Initialize the consolidated GraphAuditService
|
|
1149
|
+
logger.info("Initializing consolidated GraphAuditService...")
|
|
1150
|
+
|
|
1151
|
+
# The GraphAuditService combines all audit functionality:
|
|
1152
|
+
# - Graph-based storage (primary)
|
|
1153
|
+
# - Optional file export for compliance
|
|
1154
|
+
# - Cryptographic hash chain for integrity
|
|
1155
|
+
# - Time-series capabilities built-in
|
|
1156
|
+
# Use config accessor for audit configuration
|
|
1157
|
+
assert self.config_accessor is not None
|
|
1158
|
+
audit_db_path = await self.config_accessor.get_path("database.audit_db", Path("data/ciris_audit.db"))
|
|
1159
|
+
audit_key_path = await self.config_accessor.get_path("security.audit_key_path", Path(".ciris_keys"))
|
|
1160
|
+
retention_days = await self.config_accessor.get_int("security.audit_retention_days", 90)
|
|
1161
|
+
|
|
1162
|
+
from ciris_engine.logic.services.graph.audit_service import GraphAuditService
|
|
1163
|
+
|
|
1164
|
+
# Use platform-aware path for audit log export (critical for Android)
|
|
1165
|
+
audit_export_path = get_data_dir() / "audit_logs.jsonl"
|
|
1166
|
+
graph_audit = GraphAuditService(
|
|
1167
|
+
memory_bus=None, # Will be set via service registry
|
|
1168
|
+
time_service=self.time_service,
|
|
1169
|
+
export_path=str(audit_export_path), # Platform-aware audit log path
|
|
1170
|
+
export_format="jsonl",
|
|
1171
|
+
enable_hash_chain=True,
|
|
1172
|
+
db_path=str(audit_db_path),
|
|
1173
|
+
key_path=str(audit_key_path),
|
|
1174
|
+
retention_days=retention_days,
|
|
1175
|
+
)
|
|
1176
|
+
# Runtime will be set later when available
|
|
1177
|
+
# Attach service registry using protocol pattern
|
|
1178
|
+
# Use hasattr (protocol is not @runtime_checkable)
|
|
1179
|
+
if self.service_registry and hasattr(graph_audit, "attach_registry"):
|
|
1180
|
+
await graph_audit.attach_registry(self.service_registry)
|
|
1181
|
+
await graph_audit.start()
|
|
1182
|
+
self._services_started_count += 1
|
|
1183
|
+
self.audit_service = graph_audit
|
|
1184
|
+
_log_service_started(8, "AuditService")
|
|
1185
|
+
|
|
1186
|
+
# Update BusManager with the initialized audit service
|
|
1187
|
+
if self.bus_manager is not None:
|
|
1188
|
+
self.bus_manager.audit_service = self.audit_service
|
|
1189
|
+
logger.info(f"Updated BusManager with audit_service: {self.audit_service}")
|
|
1190
|
+
|
|
1191
|
+
# Inject graph audit service into incident capture handlers
|
|
1192
|
+
from ciris_engine.logic.utils.incident_capture_handler import inject_graph_audit_service_to_handlers
|
|
1193
|
+
|
|
1194
|
+
updated_handlers = inject_graph_audit_service_to_handlers(self.audit_service)
|
|
1195
|
+
logger.info(f"Injected graph audit service into {updated_handlers} incident capture handler(s)")
|
|
1196
|
+
|
|
1197
|
+
# Audit sink manager removed - GraphAuditService handles its own lifecycle
|
|
1198
|
+
logger.info("GraphAuditService handles its own retention and cleanup")
|
|
1199
|
+
|
|
1200
|
+
# Initialize incident management service (processes audit events as incidents)
|
|
1201
|
+
from ciris_engine.logic.services.graph.incident_service import IncidentManagementService
|
|
1202
|
+
|
|
1203
|
+
assert self.bus_manager is not None
|
|
1204
|
+
self.incident_management_service = IncidentManagementService(
|
|
1205
|
+
memory_bus=self.bus_manager.memory, time_service=self.time_service
|
|
1206
|
+
)
|
|
1207
|
+
await self.incident_management_service.start()
|
|
1208
|
+
self._services_started_count += 1
|
|
1209
|
+
_log_service_started(10, "IncidentManagement")
|
|
1210
|
+
|
|
1211
|
+
def verify_core_services(self) -> bool:
|
|
1212
|
+
"""Verify all core services are operational."""
|
|
1213
|
+
try:
|
|
1214
|
+
# Check service registry
|
|
1215
|
+
if not self.service_registry:
|
|
1216
|
+
logger.error("Service registry not initialized")
|
|
1217
|
+
return False
|
|
1218
|
+
|
|
1219
|
+
# Check critical services (LLM service is optional during first-run)
|
|
1220
|
+
from typing import Any, List
|
|
1221
|
+
|
|
1222
|
+
from ciris_engine.logic.setup.first_run import is_first_run
|
|
1223
|
+
|
|
1224
|
+
# Use named dict for better error messages
|
|
1225
|
+
critical_services: dict[str, Any] = {
|
|
1226
|
+
"telemetry_service": self.telemetry_service,
|
|
1227
|
+
"memory_service": self.memory_service,
|
|
1228
|
+
"secrets_service": self.secrets_service,
|
|
1229
|
+
"adaptive_filter_service": self.adaptive_filter_service,
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
# Only require LLM service if not in first-run mode
|
|
1233
|
+
if not is_first_run():
|
|
1234
|
+
critical_services["llm_service"] = self.llm_service
|
|
1235
|
+
elif not self.llm_service:
|
|
1236
|
+
logger.info("LLM service not initialized (first-run mode - will be initialized after setup)")
|
|
1237
|
+
|
|
1238
|
+
for name, service in critical_services.items():
|
|
1239
|
+
if not service:
|
|
1240
|
+
logger.error(f"Critical service '{name}' not initialized (is None)")
|
|
1241
|
+
return False
|
|
1242
|
+
|
|
1243
|
+
# Verify audit service
|
|
1244
|
+
if not self.audit_service:
|
|
1245
|
+
logger.error("Audit service not initialized")
|
|
1246
|
+
return False
|
|
1247
|
+
|
|
1248
|
+
logger.info("✓ All core services verified")
|
|
1249
|
+
return True
|
|
1250
|
+
except Exception as e:
|
|
1251
|
+
logger.error(f"Core services verification failed: {e}")
|
|
1252
|
+
return False
|
|
1253
|
+
|
|
1254
|
+
def _find_service_manifest(self, service_name: str, discovered_services: List[Any]) -> Any:
|
|
1255
|
+
"""Find matching service manifest by normalized name.
|
|
1256
|
+
|
|
1257
|
+
Args:
|
|
1258
|
+
service_name: Name to search for
|
|
1259
|
+
discovered_services: List of discovered service manifests
|
|
1260
|
+
|
|
1261
|
+
Returns:
|
|
1262
|
+
Matching manifest or None
|
|
1263
|
+
"""
|
|
1264
|
+
search_name_normalized = service_name.lower().replace("_adapter", "")
|
|
1265
|
+
for svc in discovered_services:
|
|
1266
|
+
svc_name_normalized = svc.module.name.lower().replace("_adapter", "")
|
|
1267
|
+
if svc_name_normalized == search_name_normalized:
|
|
1268
|
+
return svc
|
|
1269
|
+
return None
|
|
1270
|
+
|
|
1271
|
+
def _register_tool_service(self, service_instance: Any, manifest: Any, service_def: Any) -> None:
|
|
1272
|
+
"""Register a TOOL service with ServiceRegistry."""
|
|
1273
|
+
if not self.service_registry:
|
|
1274
|
+
return
|
|
1275
|
+
|
|
1276
|
+
logger.info(f"Registering {manifest.module.name} as TOOL service")
|
|
1277
|
+
from ciris_engine.logic.registries.base import Priority
|
|
1278
|
+
|
|
1279
|
+
priority_map = {
|
|
1280
|
+
"CRITICAL": Priority.CRITICAL,
|
|
1281
|
+
"HIGH": Priority.HIGH,
|
|
1282
|
+
"NORMAL": Priority.NORMAL,
|
|
1283
|
+
"LOW": Priority.LOW,
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
priority_value = (
|
|
1287
|
+
service_def.priority.value if hasattr(service_def.priority, "value") else service_def.priority.name
|
|
1288
|
+
)
|
|
1289
|
+
priority = priority_map.get(priority_value, Priority.NORMAL)
|
|
1290
|
+
|
|
1291
|
+
self.service_registry.register_service(
|
|
1292
|
+
service_type=ServiceType.TOOL,
|
|
1293
|
+
provider=service_instance,
|
|
1294
|
+
priority=priority,
|
|
1295
|
+
capabilities=service_def.capabilities,
|
|
1296
|
+
)
|
|
1297
|
+
|
|
1298
|
+
def _register_communication_service(self, service_instance: Any, manifest: Any, service_def: Any) -> None:
|
|
1299
|
+
"""Register a COMMUNICATION service with ServiceRegistry."""
|
|
1300
|
+
if not self.service_registry:
|
|
1301
|
+
return
|
|
1302
|
+
|
|
1303
|
+
logger.info(f"Registering {manifest.module.name} as COMMUNICATION service")
|
|
1304
|
+
from ciris_engine.logic.registries.base import Priority
|
|
1305
|
+
|
|
1306
|
+
priority_map = {
|
|
1307
|
+
"CRITICAL": Priority.CRITICAL,
|
|
1308
|
+
"HIGH": Priority.HIGH,
|
|
1309
|
+
"NORMAL": Priority.NORMAL,
|
|
1310
|
+
"LOW": Priority.LOW,
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
priority_value = (
|
|
1314
|
+
service_def.priority.value if hasattr(service_def.priority, "value") else service_def.priority.name
|
|
1315
|
+
)
|
|
1316
|
+
priority = priority_map.get(priority_value, Priority.NORMAL)
|
|
1317
|
+
|
|
1318
|
+
self.service_registry.register_service(
|
|
1319
|
+
service_type=ServiceType.COMMUNICATION,
|
|
1320
|
+
provider=service_instance,
|
|
1321
|
+
priority=priority,
|
|
1322
|
+
capabilities=service_def.capabilities,
|
|
1323
|
+
)
|
|
1324
|
+
|
|
1325
|
+
def _register_llm_service(self, service_instance: Any, manifest: Any, service_def: Any) -> None:
|
|
1326
|
+
"""Register an LLM service with ServiceRegistry."""
|
|
1327
|
+
if not self.service_registry:
|
|
1328
|
+
return
|
|
1329
|
+
|
|
1330
|
+
logger.info(f"Registering {manifest.module.name} as LLM service")
|
|
1331
|
+
from ciris_engine.logic.registries.base import Priority
|
|
1332
|
+
|
|
1333
|
+
priority_map = {
|
|
1334
|
+
"CRITICAL": Priority.CRITICAL,
|
|
1335
|
+
"HIGH": Priority.HIGH,
|
|
1336
|
+
"NORMAL": Priority.NORMAL,
|
|
1337
|
+
"LOW": Priority.LOW,
|
|
1338
|
+
}
|
|
1339
|
+
priority_value = (
|
|
1340
|
+
service_def.priority.value if hasattr(service_def.priority, "value") else service_def.priority.name
|
|
1341
|
+
)
|
|
1342
|
+
priority = priority_map.get(priority_value, Priority.NORMAL)
|
|
1343
|
+
|
|
1344
|
+
self.service_registry.register_service(
|
|
1345
|
+
service_type=ServiceType.LLM,
|
|
1346
|
+
provider=service_instance,
|
|
1347
|
+
priority=priority,
|
|
1348
|
+
capabilities=service_def.capabilities,
|
|
1349
|
+
)
|
|
1350
|
+
|
|
1351
|
+
def _register_adapter(self, service_instance: Any, manifest: Any, service_def: Any) -> None:
|
|
1352
|
+
"""Register a adapter with the appropriate bus/registry based on type."""
|
|
1353
|
+
if service_def.type == ServiceType.TOOL:
|
|
1354
|
+
self._register_tool_service(service_instance, manifest, service_def)
|
|
1355
|
+
elif service_def.type == ServiceType.COMMUNICATION:
|
|
1356
|
+
self._register_communication_service(service_instance, manifest, service_def)
|
|
1357
|
+
elif service_def.type == ServiceType.LLM:
|
|
1358
|
+
self._register_llm_service(service_instance, manifest, service_def)
|
|
1359
|
+
|
|
1360
|
+
async def _load_adapter(self, service_name: str) -> None:
|
|
1361
|
+
"""Load a adapter and register its services with appropriate buses.
|
|
1362
|
+
|
|
1363
|
+
Args:
|
|
1364
|
+
service_name: Name of the adapter to load (e.g. "reddit_adapter")
|
|
1365
|
+
"""
|
|
1366
|
+
from ciris_engine.logic.runtime.adapter_loader import AdapterLoader
|
|
1367
|
+
|
|
1368
|
+
logger.info(f"Loading adapter: {service_name}")
|
|
1369
|
+
|
|
1370
|
+
# Discover and find the service
|
|
1371
|
+
adapter_loader = AdapterLoader()
|
|
1372
|
+
discovered_services = adapter_loader.discover_services()
|
|
1373
|
+
|
|
1374
|
+
manifest = self._find_service_manifest(service_name, discovered_services)
|
|
1375
|
+
if not manifest:
|
|
1376
|
+
raise ValueError(f"Adapter '{service_name}' not found")
|
|
1377
|
+
|
|
1378
|
+
logger.info(f"Found manifest for adapter '{manifest.module.name}'")
|
|
1379
|
+
|
|
1380
|
+
# Load each service defined in the manifest
|
|
1381
|
+
for service_def in manifest.services:
|
|
1382
|
+
try:
|
|
1383
|
+
# Load the specific service class for this service definition
|
|
1384
|
+
service_class = adapter_loader.load_service_class(manifest, service_def.class_path)
|
|
1385
|
+
if not service_class:
|
|
1386
|
+
logger.error(f"Failed to load service class for {manifest.module.name}")
|
|
1387
|
+
continue
|
|
1388
|
+
|
|
1389
|
+
# Instantiate the service (services usually need minimal initialization)
|
|
1390
|
+
# Most adapters are self-contained and load config from env
|
|
1391
|
+
# Some services (like observers) may need runtime dependencies
|
|
1392
|
+
try:
|
|
1393
|
+
# Try to inject runtime dependencies if the service accepts them
|
|
1394
|
+
# Cast to Any for duck-typed optional runtime dependency injection
|
|
1395
|
+
from typing import Any, cast
|
|
1396
|
+
|
|
1397
|
+
service_instance = cast(Any, service_class)(
|
|
1398
|
+
bus_manager=self.bus_manager,
|
|
1399
|
+
memory_service=self.memory_service,
|
|
1400
|
+
agent_id=None, # Will be set by observer from identity service
|
|
1401
|
+
filter_service=self.adaptive_filter_service,
|
|
1402
|
+
secrets_service=self.secrets_service,
|
|
1403
|
+
time_service=self.time_service,
|
|
1404
|
+
agent_occurrence_id=self.essential_config.agent_occurrence_id,
|
|
1405
|
+
)
|
|
1406
|
+
except TypeError:
|
|
1407
|
+
# Service doesn't accept runtime dependencies, instantiate without them
|
|
1408
|
+
service_instance = service_class()
|
|
1409
|
+
|
|
1410
|
+
# Start the service before registration to initialize resources (HTTP clients, credentials, etc.)
|
|
1411
|
+
if hasattr(service_instance, "start"):
|
|
1412
|
+
start_result = service_instance.start()
|
|
1413
|
+
# Handle both async and sync start methods
|
|
1414
|
+
if hasattr(start_result, "__await__"):
|
|
1415
|
+
await start_result
|
|
1416
|
+
logger.info(f"Started adapter {manifest.module.name}")
|
|
1417
|
+
|
|
1418
|
+
# Register with appropriate bus based on service type
|
|
1419
|
+
self._register_adapter(service_instance, manifest, service_def)
|
|
1420
|
+
|
|
1421
|
+
logger.info(f"Successfully loaded and registered adapter: {manifest.module.name}")
|
|
1422
|
+
self.loaded_modules.append(f"modular:{service_name}")
|
|
1423
|
+
|
|
1424
|
+
except Exception as e:
|
|
1425
|
+
logger.error(
|
|
1426
|
+
f"Failed to load service {service_def.class_path} from {manifest.module.name}: {e}", exc_info=True
|
|
1427
|
+
)
|
|
1428
|
+
raise
|
|
1429
|
+
|
|
1430
|
+
async def load_modules(self, modules: List[str], disable_core_on_mock: bool = True) -> None:
|
|
1431
|
+
"""Load external modules with MOCK safety checks.
|
|
1432
|
+
|
|
1433
|
+
Args:
|
|
1434
|
+
modules: List of module names to load (e.g. ["mockllm", "custom_tool", "modular:reddit_adapter"])
|
|
1435
|
+
disable_core_on_mock: If True, MOCK modules disable core services
|
|
1436
|
+
"""
|
|
1437
|
+
if not self.module_loader:
|
|
1438
|
+
from ciris_engine.logic.runtime.module_loader import ModuleLoader
|
|
1439
|
+
|
|
1440
|
+
self.module_loader = ModuleLoader()
|
|
1441
|
+
|
|
1442
|
+
for module_name in modules:
|
|
1443
|
+
try:
|
|
1444
|
+
# Check if this is a adapter
|
|
1445
|
+
if module_name.startswith("modular:"):
|
|
1446
|
+
service_name = module_name[8:] # Remove "modular:" prefix
|
|
1447
|
+
await self._load_adapter(service_name)
|
|
1448
|
+
continue
|
|
1449
|
+
|
|
1450
|
+
# Load module with safety checks
|
|
1451
|
+
if self.module_loader.load_module(module_name, disable_core_on_mock):
|
|
1452
|
+
# Initialize services from module
|
|
1453
|
+
result = await self.module_loader.initialize_module_services(module_name, self.service_registry)
|
|
1454
|
+
|
|
1455
|
+
if result.success:
|
|
1456
|
+
self.loaded_modules.append(module_name)
|
|
1457
|
+
logger.info(f"Module {module_name} loaded with {len(result.services_loaded)} services")
|
|
1458
|
+
|
|
1459
|
+
# Store first LLM service for compatibility
|
|
1460
|
+
# Need to get actual service instance from registry
|
|
1461
|
+
for service_meta in result.services_loaded:
|
|
1462
|
+
if service_meta.service_type == ServiceType.LLM:
|
|
1463
|
+
# Get the actual service from registry
|
|
1464
|
+
if self.service_registry:
|
|
1465
|
+
providers = self.service_registry.get_services_by_type(ServiceType.LLM)
|
|
1466
|
+
if providers:
|
|
1467
|
+
self.llm_service = providers[0] # First provider
|
|
1468
|
+
break
|
|
1469
|
+
else:
|
|
1470
|
+
logger.error(f"Failed to initialize services from {module_name}: {result.errors}")
|
|
1471
|
+
for warning in result.warnings:
|
|
1472
|
+
logger.warning(warning)
|
|
1473
|
+
else:
|
|
1474
|
+
logger.error(f"Failed to load module: {module_name}")
|
|
1475
|
+
|
|
1476
|
+
except Exception as e:
|
|
1477
|
+
logger.error(f"Error loading module {module_name}: {e}")
|
|
1478
|
+
raise
|
|
1479
|
+
|
|
1480
|
+
# Display MOCK warnings if any
|
|
1481
|
+
if self.module_loader is not None:
|
|
1482
|
+
warnings = self.module_loader.get_mock_warnings()
|
|
1483
|
+
for warning in warnings:
|
|
1484
|
+
logger.warning(warning)
|
|
1485
|
+
|
|
1486
|
+
def register_core_services(self) -> None:
|
|
1487
|
+
"""Register core services in the service registry."""
|
|
1488
|
+
if not self.service_registry:
|
|
1489
|
+
return
|
|
1490
|
+
|
|
1491
|
+
# Infrastructure services are single-instance - NO ServiceRegistry needed
|
|
1492
|
+
# Direct references only per "No Exceptions" principle
|
|
1493
|
+
|
|
1494
|
+
# Memory service already registered above with full capabilities in initialize_all_services()
|
|
1495
|
+
# Don't re-register as it would overwrite the full capability list
|
|
1496
|
+
|
|
1497
|
+
# Audit service is single-instance - NO ServiceRegistry needed
|
|
1498
|
+
|
|
1499
|
+
# Telemetry service is single-instance - NO ServiceRegistry needed
|
|
1500
|
+
|
|
1501
|
+
# Register LLM service(s) - handled by _initialize_llm_services
|
|
1502
|
+
|
|
1503
|
+
# Secrets service is single-instance - NO ServiceRegistry needed
|
|
1504
|
+
|
|
1505
|
+
# Adaptive filter service is single-instance - NO ServiceRegistry needed
|
|
1506
|
+
|
|
1507
|
+
# Register WA service - can have multiple wisdom sources
|
|
1508
|
+
if self.wa_auth_system:
|
|
1509
|
+
self.service_registry.register_service(
|
|
1510
|
+
service_type=ServiceType.WISE_AUTHORITY,
|
|
1511
|
+
provider=self.wa_auth_system,
|
|
1512
|
+
priority=Priority.CRITICAL,
|
|
1513
|
+
capabilities=[
|
|
1514
|
+
"authenticate",
|
|
1515
|
+
"verify_token",
|
|
1516
|
+
"provision_certificate",
|
|
1517
|
+
"handle_deferral",
|
|
1518
|
+
"provide_guidance",
|
|
1519
|
+
"oauth_flow",
|
|
1520
|
+
"send_deferral",
|
|
1521
|
+
"get_pending_deferrals",
|
|
1522
|
+
"resolve_deferral",
|
|
1523
|
+
],
|
|
1524
|
+
metadata={"service_name": "WiseAuthorityService"},
|
|
1525
|
+
)
|
|
1526
|
+
|
|
1527
|
+
# Config service is single-instance - NO ServiceRegistry needed
|
|
1528
|
+
# But it's used by RuntimeControlService so needs to be accessible
|
|
1529
|
+
|
|
1530
|
+
# Transaction orchestrator is single-instance - NO ServiceRegistry needed
|
|
1531
|
+
|
|
1532
|
+
# Register SecretsToolService for core secrets tools
|
|
1533
|
+
if self.secrets_tool_service:
|
|
1534
|
+
self.service_registry.register_service(
|
|
1535
|
+
service_type=ServiceType.TOOL,
|
|
1536
|
+
provider=self.secrets_tool_service,
|
|
1537
|
+
priority=Priority.HIGH,
|
|
1538
|
+
capabilities=[
|
|
1539
|
+
"execute_tool",
|
|
1540
|
+
"get_available_tools",
|
|
1541
|
+
"get_tool_result",
|
|
1542
|
+
"validate_parameters",
|
|
1543
|
+
"get_tool_info",
|
|
1544
|
+
"get_all_tool_info",
|
|
1545
|
+
],
|
|
1546
|
+
metadata={"service_name": "SecretsToolService", "provider": "core"},
|
|
1547
|
+
)
|
|
1548
|
+
logger.info("SecretsToolService registered in ServiceRegistry")
|
|
1549
|
+
|
|
1550
|
+
# Register ConsentService as a tool service (v1.4.6)
|
|
1551
|
+
if self.consent_service:
|
|
1552
|
+
self.service_registry.register_service(
|
|
1553
|
+
service_type=ServiceType.TOOL,
|
|
1554
|
+
provider=self.consent_service,
|
|
1555
|
+
priority=Priority.HIGH,
|
|
1556
|
+
capabilities=[
|
|
1557
|
+
"execute_tool",
|
|
1558
|
+
"get_available_tools",
|
|
1559
|
+
"upgrade_relationship",
|
|
1560
|
+
"degrade_relationship",
|
|
1561
|
+
],
|
|
1562
|
+
metadata={"service_name": "ConsentService", "provider": "core"},
|
|
1563
|
+
)
|
|
1564
|
+
logger.info("ConsentService registered in ServiceRegistry as TOOL service")
|
|
1565
|
+
|
|
1566
|
+
# Task scheduler is single-instance - NO ServiceRegistry needed
|
|
1567
|
+
|
|
1568
|
+
# Incident management is single-instance - NO ServiceRegistry needed
|
|
1569
|
+
|
|
1570
|
+
async def _migrate_config_to_graph(self) -> None:
|
|
1571
|
+
"""Migrate essential config to graph for runtime management."""
|
|
1572
|
+
if not self.config_service:
|
|
1573
|
+
logger.warning("Cannot migrate config - GraphConfigService not available")
|
|
1574
|
+
return
|
|
1575
|
+
|
|
1576
|
+
logger.info("Migrating essential configuration to graph...")
|
|
1577
|
+
|
|
1578
|
+
# Migrate each config section
|
|
1579
|
+
config_dict = self.essential_config.model_dump()
|
|
1580
|
+
|
|
1581
|
+
for section_name, section_data in config_dict.items():
|
|
1582
|
+
if isinstance(section_data, dict):
|
|
1583
|
+
# Migrate each key in the section
|
|
1584
|
+
for key, value in section_data.items():
|
|
1585
|
+
full_key = f"{section_name}.{key}"
|
|
1586
|
+
await self.config_service.set_config(
|
|
1587
|
+
key=full_key,
|
|
1588
|
+
value=value, # Pass raw value, set_config will wrap it
|
|
1589
|
+
updated_by="system_bootstrap",
|
|
1590
|
+
)
|
|
1591
|
+
logger.debug(f"Migrated config: {full_key}")
|
|
1592
|
+
else:
|
|
1593
|
+
# Top-level config value
|
|
1594
|
+
await self.config_service.set_config(
|
|
1595
|
+
key=section_name,
|
|
1596
|
+
value=section_data, # Pass raw value, set_config will wrap it
|
|
1597
|
+
updated_by="system_bootstrap",
|
|
1598
|
+
)
|
|
1599
|
+
logger.debug(f"Migrated config: {section_name}")
|
|
1600
|
+
|
|
1601
|
+
logger.info("Configuration migration complete")
|
|
1602
|
+
|
|
1603
|
+
def get_metrics(self) -> Dict[str, float]:
|
|
1604
|
+
"""Get initializer metrics from the v1.4.3 set.
|
|
1605
|
+
|
|
1606
|
+
Returns EXACTLY these metrics:
|
|
1607
|
+
- initializer_services_started: Services started count
|
|
1608
|
+
- initializer_startup_time_ms: Total startup time
|
|
1609
|
+
- initializer_errors: Initialization errors
|
|
1610
|
+
- initializer_dependencies_resolved: Dependencies resolved
|
|
1611
|
+
"""
|
|
1612
|
+
# Calculate startup time in milliseconds
|
|
1613
|
+
startup_time_ms = 0.0
|
|
1614
|
+
if self._startup_start_time is not None and self._startup_end_time is not None:
|
|
1615
|
+
duration_seconds = self._startup_end_time - self._startup_start_time
|
|
1616
|
+
startup_time_ms = duration_seconds * 1000.0
|
|
1617
|
+
|
|
1618
|
+
return {
|
|
1619
|
+
"initializer_services_started": float(self._services_started_count),
|
|
1620
|
+
"initializer_startup_time_ms": startup_time_ms,
|
|
1621
|
+
"initializer_errors": float(self._initialization_errors),
|
|
1622
|
+
"initializer_dependencies_resolved": float(self._dependencies_resolved),
|
|
1623
|
+
}
|