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,952 @@
|
|
|
1
|
+
"""
|
|
2
|
+
System management endpoint extensions for CIRIS API v1.
|
|
3
|
+
|
|
4
|
+
Adds runtime queue, service management, and processor state endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import copy
|
|
8
|
+
import logging
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from typing import Any, Dict, List, Optional, Union
|
|
11
|
+
|
|
12
|
+
from fastapi import APIRouter, Body, Depends, HTTPException, Query, Request
|
|
13
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
14
|
+
|
|
15
|
+
from ciris_engine.schemas.api.auth import AuthContext
|
|
16
|
+
from ciris_engine.schemas.api.responses import ResponseMetadata, SuccessResponse
|
|
17
|
+
from ciris_engine.schemas.services.core.runtime import (
|
|
18
|
+
ProcessorQueueStatus,
|
|
19
|
+
ServiceHealthStatus,
|
|
20
|
+
ServiceSelectionExplanation,
|
|
21
|
+
)
|
|
22
|
+
from ciris_engine.schemas.services.runtime_control import PipelineState, StepPoint
|
|
23
|
+
from ciris_engine.schemas.services.runtime_control import StepResultUnion as StepResult
|
|
24
|
+
from ciris_engine.schemas.types import JSONDict
|
|
25
|
+
|
|
26
|
+
from ..constants import (
|
|
27
|
+
DESC_CURRENT_COGNITIVE_STATE,
|
|
28
|
+
DESC_HUMAN_READABLE_STATUS,
|
|
29
|
+
ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE,
|
|
30
|
+
)
|
|
31
|
+
from ..dependencies.auth import require_admin, require_observer
|
|
32
|
+
|
|
33
|
+
router = APIRouter(prefix="/system", tags=["system-extensions"])
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Runtime Control Extensions
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@router.get("/runtime/queue", response_model=SuccessResponse[ProcessorQueueStatus])
|
|
41
|
+
async def get_processing_queue_status(
|
|
42
|
+
request: Request, auth: AuthContext = Depends(require_observer)
|
|
43
|
+
) -> SuccessResponse[ProcessorQueueStatus]:
|
|
44
|
+
"""
|
|
45
|
+
Get processing queue status.
|
|
46
|
+
|
|
47
|
+
Returns information about pending thoughts, tasks, and processing metrics.
|
|
48
|
+
"""
|
|
49
|
+
# Try main runtime control service first (has all methods), fall back to API runtime control
|
|
50
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
51
|
+
if not runtime_control:
|
|
52
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
53
|
+
if not runtime_control:
|
|
54
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
queue_status = await runtime_control.get_processor_queue_status()
|
|
58
|
+
return SuccessResponse(data=queue_status)
|
|
59
|
+
except Exception as e:
|
|
60
|
+
logger.error(f"Error getting queue status: {e}")
|
|
61
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class RuntimeControlResponse(BaseModel):
|
|
65
|
+
"""Response to runtime control actions."""
|
|
66
|
+
|
|
67
|
+
success: bool = Field(..., description="Whether action succeeded")
|
|
68
|
+
message: str = Field(..., description=DESC_HUMAN_READABLE_STATUS)
|
|
69
|
+
processor_state: str = Field(..., description="Current processor state")
|
|
70
|
+
cognitive_state: Optional[str] = Field(None, description=DESC_CURRENT_COGNITIVE_STATE)
|
|
71
|
+
queue_depth: int = Field(0, description="Number of items in processing queue")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class SingleStepResponse(RuntimeControlResponse):
|
|
75
|
+
"""Response for single-step operations with detailed step point data.
|
|
76
|
+
|
|
77
|
+
Extends the basic RuntimeControlResponse with comprehensive step point information,
|
|
78
|
+
pipeline state, and demo-ready data for transparent AI operation visibility.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
model_config = ConfigDict(
|
|
82
|
+
json_schema_extra={
|
|
83
|
+
"example": {
|
|
84
|
+
"success": True,
|
|
85
|
+
"message": "Single step completed: Processed PERFORM_DMAS for thought_001",
|
|
86
|
+
"processor_state": "paused",
|
|
87
|
+
"cognitive_state": "WORK",
|
|
88
|
+
"queue_depth": 3,
|
|
89
|
+
"step_point": "PERFORM_DMAS",
|
|
90
|
+
"step_result": {
|
|
91
|
+
"step_point": "PERFORM_DMAS",
|
|
92
|
+
"thought_id": "thought_001",
|
|
93
|
+
"ethical_dma": {"reasoning": "Analyzed ethical implications", "confidence_level": 0.85},
|
|
94
|
+
"common_sense_dma": {"reasoning": "Applied common sense principles", "confidence_level": 0.90},
|
|
95
|
+
"domain_dma": {"reasoning": "Domain expertise applied", "confidence_level": 0.80},
|
|
96
|
+
},
|
|
97
|
+
"pipeline_state": {
|
|
98
|
+
"is_paused": True,
|
|
99
|
+
"current_round": 5,
|
|
100
|
+
"thoughts_by_step": {"BUILD_CONTEXT": [], "PERFORM_DMAS": []},
|
|
101
|
+
},
|
|
102
|
+
"processing_time_ms": 1250.0,
|
|
103
|
+
"tokens_used": 150,
|
|
104
|
+
"demo_data": {
|
|
105
|
+
"category": "ethical_reasoning",
|
|
106
|
+
"step_description": "Multi-perspective DMA analysis",
|
|
107
|
+
"key_insights": {
|
|
108
|
+
"ethical_confidence": 0.85,
|
|
109
|
+
"dmas_executed": ["ethical", "common_sense", "domain"],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Step Point Information
|
|
117
|
+
step_point: Optional[StepPoint] = Field(None, description="The step point that was just executed")
|
|
118
|
+
step_result: Optional[JSONDict] = Field(None, description="Complete step result data with full context")
|
|
119
|
+
|
|
120
|
+
# Pipeline State
|
|
121
|
+
pipeline_state: Optional[PipelineState] = Field(None, description="Current pipeline state with all thoughts")
|
|
122
|
+
|
|
123
|
+
# Performance Metrics
|
|
124
|
+
processing_time_ms: float = Field(0.0, description="Total processing time for this step in milliseconds")
|
|
125
|
+
tokens_used: Optional[int] = Field(None, description="LLM tokens consumed during this step")
|
|
126
|
+
|
|
127
|
+
# Transparency Data
|
|
128
|
+
transparency_data: Optional[JSONDict] = Field(
|
|
129
|
+
None, description="Detailed reasoning and system state data for transparency"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# Helper functions for single-step processor
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _extract_cognitive_state(runtime: Any) -> Optional[str]:
|
|
137
|
+
"""Extract cognitive state from runtime safely."""
|
|
138
|
+
try:
|
|
139
|
+
if runtime and hasattr(runtime, "agent_processor") and runtime.agent_processor:
|
|
140
|
+
if hasattr(runtime.agent_processor, "state_manager") and runtime.agent_processor.state_manager:
|
|
141
|
+
current_state = runtime.agent_processor.state_manager.get_state()
|
|
142
|
+
return str(current_state) if current_state else None
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.debug(f"Could not extract cognitive state: {e}")
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
async def _get_queue_depth(runtime_control: Any) -> int:
|
|
149
|
+
"""Get queue depth safely."""
|
|
150
|
+
try:
|
|
151
|
+
queue_status = await runtime_control.get_processor_queue_status()
|
|
152
|
+
return queue_status.queue_size if queue_status else 0
|
|
153
|
+
except Exception as e:
|
|
154
|
+
logger.debug(f"Could not get queue depth: {e}")
|
|
155
|
+
return 0
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _get_pipeline_controller(runtime: Any) -> Any:
|
|
159
|
+
"""Safely extract pipeline controller from runtime."""
|
|
160
|
+
if not runtime:
|
|
161
|
+
return None
|
|
162
|
+
if not hasattr(runtime, "pipeline_controller"):
|
|
163
|
+
return None
|
|
164
|
+
return runtime.pipeline_controller
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _get_pipeline_state(pipeline_controller: Any) -> Optional[Any]:
|
|
168
|
+
"""Get current pipeline state, returning None on error."""
|
|
169
|
+
if not pipeline_controller:
|
|
170
|
+
return None
|
|
171
|
+
try:
|
|
172
|
+
return pipeline_controller.get_current_state()
|
|
173
|
+
except Exception as e:
|
|
174
|
+
logger.debug(f"Could not get pipeline state: {e}")
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _get_latest_step_data(pipeline_controller: Any) -> tuple[Optional[Any], Optional[JSONDict]]:
|
|
179
|
+
"""Extract step point and result from pipeline controller."""
|
|
180
|
+
if not pipeline_controller:
|
|
181
|
+
return None, None
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
latest_step_result = pipeline_controller.get_latest_step_result()
|
|
185
|
+
if not latest_step_result:
|
|
186
|
+
return None, None
|
|
187
|
+
|
|
188
|
+
step_point = latest_step_result.step_point
|
|
189
|
+
step_result = (
|
|
190
|
+
latest_step_result.model_dump() if hasattr(latest_step_result, "model_dump") else dict(latest_step_result)
|
|
191
|
+
)
|
|
192
|
+
return step_point, step_result
|
|
193
|
+
except Exception as e:
|
|
194
|
+
logger.debug(f"Could not get step result: {e}")
|
|
195
|
+
return None, None
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _get_processing_metrics(pipeline_controller: Any) -> tuple[float, Optional[int]]:
|
|
199
|
+
"""Extract processing time and token usage from metrics."""
|
|
200
|
+
if not pipeline_controller:
|
|
201
|
+
return 0.0, None
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
metrics = pipeline_controller.get_processing_metrics()
|
|
205
|
+
if not metrics:
|
|
206
|
+
return 0.0, None
|
|
207
|
+
|
|
208
|
+
processing_time_ms = metrics.get("total_processing_time_ms", 0.0)
|
|
209
|
+
tokens_used = metrics.get("tokens_used")
|
|
210
|
+
return processing_time_ms, tokens_used
|
|
211
|
+
except Exception as e:
|
|
212
|
+
logger.debug(f"Could not get processing metrics: {e}")
|
|
213
|
+
return 0.0, None
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _extract_pipeline_data(
|
|
217
|
+
runtime: Any,
|
|
218
|
+
) -> tuple[Optional[Any], Optional[JSONDict], Optional[Any], float, Optional[int], Optional[JSONDict]]:
|
|
219
|
+
"""Extract pipeline state, step result, and processing metrics."""
|
|
220
|
+
try:
|
|
221
|
+
pipeline_controller = _get_pipeline_controller(runtime)
|
|
222
|
+
pipeline_state = _get_pipeline_state(pipeline_controller)
|
|
223
|
+
step_point, step_result = _get_latest_step_data(pipeline_controller)
|
|
224
|
+
processing_time_ms, tokens_used = _get_processing_metrics(pipeline_controller)
|
|
225
|
+
demo_data = None # Demo data removed - using transparency_data from real step results
|
|
226
|
+
|
|
227
|
+
return step_point, step_result, pipeline_state, processing_time_ms, tokens_used, demo_data
|
|
228
|
+
except Exception as e:
|
|
229
|
+
logger.debug(f"Could not extract enhanced data: {e}")
|
|
230
|
+
return None, None, None, 0.0, None, None
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _get_runtime_control_service_for_step(request: Request) -> Any:
|
|
234
|
+
"""Get runtime control service for single step operations."""
|
|
235
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
236
|
+
if not runtime_control:
|
|
237
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
238
|
+
if not runtime_control:
|
|
239
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
240
|
+
return runtime_control
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _create_basic_response_data(result: Any, cognitive_state: Optional[str], queue_depth: int) -> JSONDict:
|
|
244
|
+
"""Create basic response data for single step."""
|
|
245
|
+
return {
|
|
246
|
+
"success": result.success,
|
|
247
|
+
"message": f"Single step {'completed' if result.success else 'failed'}: {result.error or 'No additional info'}",
|
|
248
|
+
"processor_state": result.new_status.value if hasattr(result.new_status, "value") else str(result.new_status),
|
|
249
|
+
"cognitive_state": cognitive_state,
|
|
250
|
+
"queue_depth": queue_depth,
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _convert_step_point(result: Any) -> Optional[Any]:
|
|
255
|
+
"""Convert step_point string to enum if needed."""
|
|
256
|
+
from ciris_engine.schemas.services.runtime_control import StepPoint
|
|
257
|
+
|
|
258
|
+
if not result.step_point:
|
|
259
|
+
return None
|
|
260
|
+
|
|
261
|
+
try:
|
|
262
|
+
return StepPoint(result.step_point.lower()) if isinstance(result.step_point, str) else result.step_point
|
|
263
|
+
except (ValueError, AttributeError):
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _consolidate_step_results(result: Any) -> Optional[JSONDict]:
|
|
268
|
+
"""Convert step_results list to consolidated step_result dict for API response."""
|
|
269
|
+
if not (result.step_results and isinstance(result.step_results, list)):
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
# Group step results by round number (from parent current_round)
|
|
273
|
+
results_by_round = {}
|
|
274
|
+
current_round = getattr(result, "current_round", None)
|
|
275
|
+
|
|
276
|
+
if current_round is not None:
|
|
277
|
+
# Create a round entry with the step results
|
|
278
|
+
round_data = {
|
|
279
|
+
"round_number": current_round,
|
|
280
|
+
"step_data": result.step_results[0].model_dump() if result.step_results else {},
|
|
281
|
+
}
|
|
282
|
+
# Add task_id from first step result if available
|
|
283
|
+
if result.step_results and hasattr(result.step_results[0], "task_id"):
|
|
284
|
+
round_data["task_id"] = result.step_results[0].task_id
|
|
285
|
+
|
|
286
|
+
results_by_round[str(current_round)] = round_data
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
"steps_processed": len(result.step_results),
|
|
290
|
+
"results_by_round": results_by_round,
|
|
291
|
+
"summary": result.step_results[0].model_dump() if result.step_results else None,
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@router.post("/runtime/step", response_model=SuccessResponse[SingleStepResponse])
|
|
296
|
+
async def single_step_processor(
|
|
297
|
+
request: Request, auth: AuthContext = Depends(require_admin), body: JSONDict = Body(default={})
|
|
298
|
+
) -> SuccessResponse[SingleStepResponse]:
|
|
299
|
+
"""
|
|
300
|
+
Execute a single processing step.
|
|
301
|
+
|
|
302
|
+
Useful for debugging and demonstrations. Processes one item from the queue.
|
|
303
|
+
Always returns detailed H3ERE step data for transparency.
|
|
304
|
+
Requires ADMIN role.
|
|
305
|
+
"""
|
|
306
|
+
runtime_control = _get_runtime_control_service_for_step(request)
|
|
307
|
+
|
|
308
|
+
try:
|
|
309
|
+
result = await runtime_control.single_step()
|
|
310
|
+
|
|
311
|
+
# Get basic runtime data
|
|
312
|
+
runtime = getattr(request.app.state, "runtime", None)
|
|
313
|
+
cognitive_state = _extract_cognitive_state(runtime)
|
|
314
|
+
queue_depth = await _get_queue_depth(runtime_control)
|
|
315
|
+
|
|
316
|
+
# Create response components
|
|
317
|
+
basic_response_data = _create_basic_response_data(result, cognitive_state, queue_depth)
|
|
318
|
+
safe_step_point = _convert_step_point(result)
|
|
319
|
+
safe_step_result = _consolidate_step_results(result)
|
|
320
|
+
|
|
321
|
+
# Extract other safe data
|
|
322
|
+
safe_pipeline_state = result.pipeline_state
|
|
323
|
+
safe_processing_time = result.processing_time_ms or 0.0
|
|
324
|
+
safe_tokens_used = None # Not yet implemented in ProcessorControlResponse
|
|
325
|
+
safe_transparency_data = None # Real transparency data from step results
|
|
326
|
+
|
|
327
|
+
single_step_response = SingleStepResponse(
|
|
328
|
+
**basic_response_data,
|
|
329
|
+
step_point=safe_step_point,
|
|
330
|
+
step_result=safe_step_result,
|
|
331
|
+
pipeline_state=safe_pipeline_state,
|
|
332
|
+
processing_time_ms=safe_processing_time,
|
|
333
|
+
tokens_used=safe_tokens_used,
|
|
334
|
+
transparency_data=safe_transparency_data,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
return SuccessResponse(data=single_step_response)
|
|
338
|
+
|
|
339
|
+
except Exception as e:
|
|
340
|
+
logger.error(f"Error in single step: {e}")
|
|
341
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
# Service Management Extensions
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
class ServicePriorityUpdateRequest(BaseModel):
|
|
348
|
+
"""Request to update service priority."""
|
|
349
|
+
|
|
350
|
+
priority: str = Field(..., description="New priority level (CRITICAL, HIGH, NORMAL, LOW, FALLBACK)")
|
|
351
|
+
priority_group: Optional[int] = Field(None, description="Priority group (0, 1, 2...)")
|
|
352
|
+
strategy: Optional[str] = Field(None, description="Selection strategy (FALLBACK, ROUND_ROBIN)")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@router.get("/services/health", response_model=SuccessResponse[ServiceHealthStatus])
|
|
356
|
+
async def get_service_health_details(
|
|
357
|
+
request: Request, auth: AuthContext = Depends(require_observer)
|
|
358
|
+
) -> SuccessResponse[ServiceHealthStatus]:
|
|
359
|
+
"""
|
|
360
|
+
Get detailed service health status.
|
|
361
|
+
|
|
362
|
+
Returns comprehensive health information including circuit breaker states,
|
|
363
|
+
error rates, and recommendations.
|
|
364
|
+
"""
|
|
365
|
+
# Try main runtime control service first (has all methods), fall back to API runtime control
|
|
366
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
367
|
+
if not runtime_control:
|
|
368
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
369
|
+
if not runtime_control:
|
|
370
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
371
|
+
|
|
372
|
+
try:
|
|
373
|
+
health_status = await runtime_control.get_service_health_status()
|
|
374
|
+
return SuccessResponse(data=health_status)
|
|
375
|
+
except Exception as e:
|
|
376
|
+
logger.error(f"Error getting service health: {e}")
|
|
377
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class ServicePriorityUpdateResponse(BaseModel):
|
|
381
|
+
"""Response from service priority update."""
|
|
382
|
+
|
|
383
|
+
provider_name: str = Field(..., description="Provider name that was updated")
|
|
384
|
+
old_priority: str = Field(..., description="Previous priority level")
|
|
385
|
+
new_priority: str = Field(..., description="New priority level")
|
|
386
|
+
old_priority_group: Optional[int] = Field(None, description="Previous priority group")
|
|
387
|
+
new_priority_group: Optional[int] = Field(None, description="New priority group")
|
|
388
|
+
old_strategy: Optional[str] = Field(None, description="Previous selection strategy")
|
|
389
|
+
new_strategy: Optional[str] = Field(None, description="New selection strategy")
|
|
390
|
+
message: str = Field(..., description="Status message")
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@router.put("/services/{provider_name}/priority", response_model=SuccessResponse[ServicePriorityUpdateResponse])
|
|
394
|
+
async def update_service_priority(
|
|
395
|
+
provider_name: str, body: ServicePriorityUpdateRequest, request: Request, auth: AuthContext = Depends(require_admin)
|
|
396
|
+
) -> SuccessResponse[ServicePriorityUpdateResponse]:
|
|
397
|
+
"""
|
|
398
|
+
Update service provider priority.
|
|
399
|
+
|
|
400
|
+
Changes the priority, priority group, and/or selection strategy for a service provider.
|
|
401
|
+
Requires ADMIN role.
|
|
402
|
+
"""
|
|
403
|
+
# Try main runtime control service first (has all methods), fall back to API runtime control
|
|
404
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
405
|
+
if not runtime_control:
|
|
406
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
407
|
+
if not runtime_control:
|
|
408
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
409
|
+
|
|
410
|
+
try:
|
|
411
|
+
result = await runtime_control.update_service_priority(
|
|
412
|
+
provider_name=provider_name,
|
|
413
|
+
new_priority=body.priority,
|
|
414
|
+
new_priority_group=body.priority_group,
|
|
415
|
+
new_strategy=body.strategy,
|
|
416
|
+
)
|
|
417
|
+
# Convert the result dict to our typed response
|
|
418
|
+
response = ServicePriorityUpdateResponse(
|
|
419
|
+
provider_name=result.get("provider_name", provider_name),
|
|
420
|
+
old_priority=result.get("old_priority", "NORMAL"),
|
|
421
|
+
new_priority=result.get("new_priority", body.priority),
|
|
422
|
+
old_priority_group=result.get("old_priority_group"),
|
|
423
|
+
new_priority_group=result.get("new_priority_group"),
|
|
424
|
+
old_strategy=result.get("old_strategy"),
|
|
425
|
+
new_strategy=result.get("new_strategy"),
|
|
426
|
+
message=result.get("message", "Priority updated successfully"),
|
|
427
|
+
)
|
|
428
|
+
return SuccessResponse(data=response)
|
|
429
|
+
except Exception as e:
|
|
430
|
+
logger.error(f"Error updating service priority: {e}")
|
|
431
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
class CircuitBreakerResetRequest(BaseModel):
|
|
435
|
+
"""Request to reset circuit breakers."""
|
|
436
|
+
|
|
437
|
+
service_type: Optional[str] = Field(None, description="Specific service type to reset, or all if not specified")
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
class CircuitBreakerResetResponse(BaseModel):
|
|
441
|
+
"""Response from circuit breaker reset."""
|
|
442
|
+
|
|
443
|
+
service_type: Optional[str] = Field(None, description="Service type that was reset")
|
|
444
|
+
reset_count: int = Field(..., description="Number of circuit breakers reset")
|
|
445
|
+
services_affected: List[str] = Field(default_factory=list, description="List of affected services")
|
|
446
|
+
message: str = Field(..., description="Status message")
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
@router.post("/services/circuit-breakers/reset", response_model=SuccessResponse[CircuitBreakerResetResponse])
|
|
450
|
+
async def reset_service_circuit_breakers(
|
|
451
|
+
body: CircuitBreakerResetRequest, request: Request, auth: AuthContext = Depends(require_admin)
|
|
452
|
+
) -> SuccessResponse[CircuitBreakerResetResponse]:
|
|
453
|
+
"""
|
|
454
|
+
Reset circuit breakers.
|
|
455
|
+
|
|
456
|
+
Resets circuit breakers for specified service type or all services.
|
|
457
|
+
Useful for recovering from transient failures.
|
|
458
|
+
Requires ADMIN role.
|
|
459
|
+
"""
|
|
460
|
+
# Try main runtime control service first (has all methods), fall back to API runtime control
|
|
461
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
462
|
+
if not runtime_control:
|
|
463
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
464
|
+
if not runtime_control:
|
|
465
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
466
|
+
|
|
467
|
+
try:
|
|
468
|
+
result = await runtime_control.reset_circuit_breakers(body.service_type)
|
|
469
|
+
# Convert the result dict to our typed response
|
|
470
|
+
response = CircuitBreakerResetResponse(
|
|
471
|
+
service_type=body.service_type,
|
|
472
|
+
reset_count=result.get("reset_count", 0),
|
|
473
|
+
services_affected=result.get("services_affected", []),
|
|
474
|
+
message=result.get("message", "Circuit breakers reset successfully"),
|
|
475
|
+
)
|
|
476
|
+
return SuccessResponse(data=response)
|
|
477
|
+
except Exception as e:
|
|
478
|
+
logger.error(f"Error resetting circuit breakers: {e}")
|
|
479
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
@router.get("/services/selection-logic", response_model=SuccessResponse[ServiceSelectionExplanation])
|
|
483
|
+
async def get_service_selection_explanation(
|
|
484
|
+
request: Request, auth: AuthContext = Depends(require_observer)
|
|
485
|
+
) -> SuccessResponse[ServiceSelectionExplanation]:
|
|
486
|
+
"""
|
|
487
|
+
Get service selection logic explanation.
|
|
488
|
+
|
|
489
|
+
Returns detailed explanation of how services are selected, including
|
|
490
|
+
priority groups, priorities, strategies, and circuit breaker behavior.
|
|
491
|
+
"""
|
|
492
|
+
# Try main runtime control service first (has all methods), fall back to API runtime control
|
|
493
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
494
|
+
if not runtime_control:
|
|
495
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
496
|
+
if not runtime_control:
|
|
497
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
498
|
+
|
|
499
|
+
try:
|
|
500
|
+
explanation = await runtime_control.get_service_selection_explanation()
|
|
501
|
+
return SuccessResponse(data=explanation)
|
|
502
|
+
except Exception as e:
|
|
503
|
+
logger.error(f"Error getting service selection explanation: {e}")
|
|
504
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
# Processor State Information
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
class ProcessorStateInfo(BaseModel):
|
|
511
|
+
"""Information about a processor state."""
|
|
512
|
+
|
|
513
|
+
name: str = Field(..., description="State name (WAKEUP, WORK, DREAM, etc.)")
|
|
514
|
+
is_active: bool = Field(..., description="Whether this state is currently active")
|
|
515
|
+
description: str = Field(..., description="State description")
|
|
516
|
+
capabilities: List[str] = Field(default_factory=list, description="What this state can do")
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
def _get_current_state_name(runtime: Any) -> Optional[str]:
|
|
520
|
+
"""Extract current state name from runtime."""
|
|
521
|
+
if not hasattr(runtime.agent_processor, "state_manager") or not runtime.agent_processor.state_manager:
|
|
522
|
+
return None
|
|
523
|
+
|
|
524
|
+
current_state = runtime.agent_processor.state_manager.get_state()
|
|
525
|
+
if not current_state:
|
|
526
|
+
return None
|
|
527
|
+
|
|
528
|
+
# Handle both enum objects and string representations like "AgentState.WORK"
|
|
529
|
+
current_state_str = str(current_state)
|
|
530
|
+
return current_state_str.split(".")[-1] if "." in current_state_str else current_state_str
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def _create_processor_state(
|
|
534
|
+
name: str, description: str, capabilities: List[str], is_active: bool
|
|
535
|
+
) -> ProcessorStateInfo:
|
|
536
|
+
"""Create a ProcessorStateInfo object."""
|
|
537
|
+
return ProcessorStateInfo(
|
|
538
|
+
name=name,
|
|
539
|
+
is_active=is_active,
|
|
540
|
+
description=description,
|
|
541
|
+
capabilities=capabilities,
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def _get_processor_state_definitions(current_state_name: Optional[str]) -> List[ProcessorStateInfo]:
|
|
546
|
+
"""Get all processor state definitions."""
|
|
547
|
+
states = [
|
|
548
|
+
(
|
|
549
|
+
"WAKEUP",
|
|
550
|
+
"Initial state for identity confirmation and system initialization",
|
|
551
|
+
["identity_confirmation", "system_checks", "initial_setup"],
|
|
552
|
+
),
|
|
553
|
+
(
|
|
554
|
+
"WORK",
|
|
555
|
+
"Normal task processing and interaction state",
|
|
556
|
+
["task_processing", "user_interaction", "tool_usage", "memory_operations"],
|
|
557
|
+
),
|
|
558
|
+
(
|
|
559
|
+
"DREAM",
|
|
560
|
+
"Deep introspection and memory consolidation state",
|
|
561
|
+
["memory_consolidation", "pattern_analysis", "self_reflection"],
|
|
562
|
+
),
|
|
563
|
+
(
|
|
564
|
+
"PLAY",
|
|
565
|
+
"Creative exploration and experimentation state",
|
|
566
|
+
["creative_tasks", "exploration", "learning", "experimentation"],
|
|
567
|
+
),
|
|
568
|
+
(
|
|
569
|
+
"SOLITUDE",
|
|
570
|
+
"Quiet reflection and planning state",
|
|
571
|
+
["planning", "reflection", "goal_setting", "strategy_development"],
|
|
572
|
+
),
|
|
573
|
+
(
|
|
574
|
+
"SHUTDOWN",
|
|
575
|
+
"Graceful shutdown and cleanup state",
|
|
576
|
+
["cleanup", "final_messages", "state_persistence", "resource_release"],
|
|
577
|
+
),
|
|
578
|
+
]
|
|
579
|
+
|
|
580
|
+
return [
|
|
581
|
+
_create_processor_state(name, description, capabilities, current_state_name == name)
|
|
582
|
+
for name, description, capabilities in states
|
|
583
|
+
]
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
@router.get("/processors", response_model=SuccessResponse[List[ProcessorStateInfo]])
|
|
587
|
+
async def get_processor_states(
|
|
588
|
+
request: Request, auth: AuthContext = Depends(require_observer)
|
|
589
|
+
) -> SuccessResponse[List[ProcessorStateInfo]]:
|
|
590
|
+
"""
|
|
591
|
+
Get information about all processor states.
|
|
592
|
+
|
|
593
|
+
Returns the list of available processor states (WAKEUP, WORK, DREAM, PLAY,
|
|
594
|
+
SOLITUDE, SHUTDOWN) and which one is currently active.
|
|
595
|
+
"""
|
|
596
|
+
runtime = getattr(request.app.state, "runtime", None)
|
|
597
|
+
if not runtime or not hasattr(runtime, "agent_processor"):
|
|
598
|
+
raise HTTPException(status_code=503, detail="Agent processor not available")
|
|
599
|
+
|
|
600
|
+
try:
|
|
601
|
+
current_state_name = _get_current_state_name(runtime)
|
|
602
|
+
processor_states = _get_processor_state_definitions(current_state_name)
|
|
603
|
+
return SuccessResponse(data=processor_states)
|
|
604
|
+
|
|
605
|
+
except Exception as e:
|
|
606
|
+
logger.error(f"Error getting processor states: {e}")
|
|
607
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
def _determine_user_role(current_user: JSONDict) -> Any:
|
|
611
|
+
"""Determine user role from current_user dict."""
|
|
612
|
+
from ciris_engine.schemas.api.auth import UserRole
|
|
613
|
+
|
|
614
|
+
user_role = current_user.get("role", UserRole.OBSERVER)
|
|
615
|
+
if isinstance(user_role, str):
|
|
616
|
+
try:
|
|
617
|
+
user_role = UserRole(user_role)
|
|
618
|
+
except ValueError:
|
|
619
|
+
user_role = UserRole.OBSERVER
|
|
620
|
+
return user_role
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
async def _get_user_allowed_channel_ids(auth_service: Any, user_id: str) -> set[str]:
|
|
624
|
+
"""Get set of channel IDs user is allowed to see (user_id + OAuth links + API-prefixed versions)."""
|
|
625
|
+
import sqlite3
|
|
626
|
+
|
|
627
|
+
allowed_channel_ids = {user_id}
|
|
628
|
+
# BUGFIX: API adapter prefixes channel_id with "api_"
|
|
629
|
+
# See agent.py:221: channel_id = f"api_{auth.user_id}"
|
|
630
|
+
allowed_channel_ids.add(f"api_{user_id}")
|
|
631
|
+
|
|
632
|
+
try:
|
|
633
|
+
# Use database abstraction layer to support both SQLite and PostgreSQL
|
|
634
|
+
from ciris_engine.logic.persistence.db.core import get_db_connection
|
|
635
|
+
|
|
636
|
+
db_path = auth_service.db_path
|
|
637
|
+
query = """
|
|
638
|
+
SELECT oauth_provider, oauth_external_id
|
|
639
|
+
FROM wa_cert
|
|
640
|
+
WHERE wa_id = ? AND oauth_provider IS NOT NULL AND oauth_external_id IS NOT NULL AND active = 1
|
|
641
|
+
"""
|
|
642
|
+
with get_db_connection(db_path) as conn:
|
|
643
|
+
cursor = conn.cursor()
|
|
644
|
+
cursor.execute(query, (user_id,))
|
|
645
|
+
rows = cursor.fetchall()
|
|
646
|
+
for row in rows:
|
|
647
|
+
# Handle both SQLite Row and PostgreSQL RealDictRow
|
|
648
|
+
if hasattr(row, "keys"):
|
|
649
|
+
oauth_provider, oauth_external_id = row["oauth_provider"], row["oauth_external_id"]
|
|
650
|
+
else:
|
|
651
|
+
oauth_provider, oauth_external_id = row
|
|
652
|
+
# Add OAuth channel ID formats
|
|
653
|
+
oauth_channel = f"{oauth_provider}:{oauth_external_id}"
|
|
654
|
+
allowed_channel_ids.add(oauth_channel)
|
|
655
|
+
allowed_channel_ids.add(oauth_external_id)
|
|
656
|
+
# BUGFIX: Also add API-prefixed versions for SSE filtering
|
|
657
|
+
allowed_channel_ids.add(f"api_{oauth_channel}")
|
|
658
|
+
allowed_channel_ids.add(f"api_{oauth_external_id}")
|
|
659
|
+
except Exception as e:
|
|
660
|
+
logger.error(f"Error fetching OAuth links for user {user_id}: {e}", exc_info=True)
|
|
661
|
+
|
|
662
|
+
return allowed_channel_ids
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
async def _batch_fetch_task_channel_ids(task_ids: List[str]) -> Dict[str, str]:
|
|
666
|
+
"""Batch fetch channel_ids for multiple task_ids from main database."""
|
|
667
|
+
task_channel_map: Dict[str, str] = {}
|
|
668
|
+
if not task_ids:
|
|
669
|
+
return task_channel_map
|
|
670
|
+
|
|
671
|
+
try:
|
|
672
|
+
# Tasks are stored in the main database
|
|
673
|
+
# Use the proper database path helper which gets config from ServiceRegistry
|
|
674
|
+
from ciris_engine.logic.persistence import get_sqlite_db_full_path
|
|
675
|
+
from ciris_engine.logic.persistence.db.core import get_db_connection
|
|
676
|
+
from ciris_engine.logic.persistence.db.dialect import get_adapter
|
|
677
|
+
|
|
678
|
+
main_db_path = get_sqlite_db_full_path() # Gets main DB path from config via registry
|
|
679
|
+
logger.debug(f"SSE Filter: Fetching from main_db_path={main_db_path}")
|
|
680
|
+
|
|
681
|
+
# Get database adapter for proper placeholder handling
|
|
682
|
+
adapter = get_adapter()
|
|
683
|
+
placeholder = "%s" if adapter.is_postgresql() else "?"
|
|
684
|
+
placeholders = ",".join([placeholder] * len(task_ids))
|
|
685
|
+
query = f"SELECT task_id, channel_id FROM tasks WHERE task_id IN ({placeholders})"
|
|
686
|
+
|
|
687
|
+
with get_db_connection(main_db_path) as conn:
|
|
688
|
+
cursor = conn.cursor()
|
|
689
|
+
cursor.execute(query, task_ids)
|
|
690
|
+
rows = cursor.fetchall()
|
|
691
|
+
logger.debug(f"SSE Filter: Query returned {len(rows)} rows")
|
|
692
|
+
for row in rows:
|
|
693
|
+
# Handle both SQLite Row (tuple) and PostgreSQL RealDictRow (dict)
|
|
694
|
+
if hasattr(row, "keys"):
|
|
695
|
+
tid, cid = row["task_id"], row["channel_id"]
|
|
696
|
+
else:
|
|
697
|
+
tid, cid = row
|
|
698
|
+
task_channel_map[tid] = cid
|
|
699
|
+
logger.debug(f"SSE Filter: Found task_id={tid} -> channel_id={cid}")
|
|
700
|
+
except Exception as e:
|
|
701
|
+
logger.error(f"Error batch fetching task channel_ids: {e}", exc_info=True)
|
|
702
|
+
|
|
703
|
+
return task_channel_map
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def _filter_events_by_channel_access(
|
|
707
|
+
events: List[Any], allowed_channel_ids: set[str], task_channel_cache: Dict[str, str]
|
|
708
|
+
) -> List[Any]:
|
|
709
|
+
"""Filter events to only those the user can access based on channel_id whitelist."""
|
|
710
|
+
filtered_events = []
|
|
711
|
+
for event in events:
|
|
712
|
+
task_id = event.get("task_id")
|
|
713
|
+
event_type = event.get("event_type", "unknown")
|
|
714
|
+
|
|
715
|
+
if not task_id:
|
|
716
|
+
# No task_id means system event - skip for non-admin users
|
|
717
|
+
logger.debug(f"SSE Filter: Skipping event {event_type} - no task_id")
|
|
718
|
+
continue
|
|
719
|
+
|
|
720
|
+
channel_id = task_channel_cache.get(task_id)
|
|
721
|
+
if not channel_id:
|
|
722
|
+
logger.warning(f"SSE Filter: No channel_id found for task_id={task_id}, event_type={event_type}")
|
|
723
|
+
continue
|
|
724
|
+
|
|
725
|
+
if channel_id in allowed_channel_ids:
|
|
726
|
+
logger.debug(f"SSE Filter: ALLOWED event {event_type} - task_id={task_id}, channel_id={channel_id}")
|
|
727
|
+
filtered_events.append(event)
|
|
728
|
+
else:
|
|
729
|
+
logger.warning(
|
|
730
|
+
f"SSE Filter: BLOCKED event {event_type} - task_id={task_id}, "
|
|
731
|
+
f"channel_id={channel_id} not in allowed_channel_ids={allowed_channel_ids}"
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
return filtered_events
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
def _is_snapshot_event(event: Any) -> bool:
|
|
738
|
+
"""Check if event is a snapshot_and_context event that needs redaction."""
|
|
739
|
+
return bool(event.get("event_type") == "snapshot_and_context")
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def _remove_task_summaries(system_snapshot: JSONDict) -> None:
|
|
743
|
+
"""Remove sensitive task summaries from system snapshot."""
|
|
744
|
+
system_snapshot["recently_completed_tasks_summary"] = []
|
|
745
|
+
system_snapshot["top_pending_tasks_summary"] = []
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
def _filter_user_profiles(user_profiles: Any, allowed_user_ids: set[str]) -> Any:
|
|
749
|
+
"""Filter user profiles to only allowed user IDs."""
|
|
750
|
+
if isinstance(user_profiles, list):
|
|
751
|
+
return [
|
|
752
|
+
profile
|
|
753
|
+
for profile in user_profiles
|
|
754
|
+
if isinstance(profile, dict) and profile.get("user_id") in allowed_user_ids
|
|
755
|
+
]
|
|
756
|
+
elif isinstance(user_profiles, dict):
|
|
757
|
+
return {user_id: profile for user_id, profile in user_profiles.items() if user_id in allowed_user_ids}
|
|
758
|
+
return user_profiles
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
def _redact_system_snapshot(system_snapshot: JSONDict, allowed_user_ids: set[str]) -> None:
|
|
762
|
+
"""Redact sensitive data from system snapshot in-place."""
|
|
763
|
+
_remove_task_summaries(system_snapshot)
|
|
764
|
+
|
|
765
|
+
if "user_profiles" in system_snapshot and system_snapshot["user_profiles"]:
|
|
766
|
+
system_snapshot["user_profiles"] = _filter_user_profiles(system_snapshot["user_profiles"], allowed_user_ids)
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
def _redact_observer_sensitive_data(events: List[Any], allowed_user_ids: set[str]) -> List[Any]:
|
|
770
|
+
"""Redact sensitive task and user information from events for OBSERVER users.
|
|
771
|
+
|
|
772
|
+
Removes:
|
|
773
|
+
- recently_completed_tasks_summary
|
|
774
|
+
- top_pending_tasks_summary
|
|
775
|
+
|
|
776
|
+
Filters:
|
|
777
|
+
- user_profiles (only shows user's OWN profile based on allowed_user_ids)
|
|
778
|
+
|
|
779
|
+
from system_snapshot in SNAPSHOT_AND_CONTEXT events.
|
|
780
|
+
|
|
781
|
+
Args:
|
|
782
|
+
events: List of events to redact
|
|
783
|
+
allowed_user_ids: Set of user IDs the user is allowed to see (self + OAuth links)
|
|
784
|
+
"""
|
|
785
|
+
redacted_events = []
|
|
786
|
+
for event in events:
|
|
787
|
+
if _is_snapshot_event(event):
|
|
788
|
+
event = copy.deepcopy(event)
|
|
789
|
+
if "system_snapshot" in event and event["system_snapshot"]:
|
|
790
|
+
_redact_system_snapshot(event["system_snapshot"], allowed_user_ids)
|
|
791
|
+
|
|
792
|
+
redacted_events.append(event)
|
|
793
|
+
|
|
794
|
+
return redacted_events
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
@router.get("/runtime/reasoning-stream")
|
|
798
|
+
async def reasoning_stream(request: Request, auth: AuthContext = Depends(require_observer)) -> Any:
|
|
799
|
+
"""
|
|
800
|
+
Stream live H3ERE reasoning steps as they occur.
|
|
801
|
+
|
|
802
|
+
Provides real-time streaming of step-by-step reasoning for live UI generation.
|
|
803
|
+
Returns Server-Sent Events (SSE) with step data as processing happens.
|
|
804
|
+
Requires OBSERVER role or higher.
|
|
805
|
+
"""
|
|
806
|
+
import asyncio
|
|
807
|
+
import json
|
|
808
|
+
|
|
809
|
+
from fastapi.responses import StreamingResponse
|
|
810
|
+
|
|
811
|
+
from ciris_engine.schemas.api.auth import UserRole
|
|
812
|
+
|
|
813
|
+
# Get runtime control service
|
|
814
|
+
runtime_control = getattr(request.app.state, "main_runtime_control_service", None)
|
|
815
|
+
if not runtime_control:
|
|
816
|
+
runtime_control = getattr(request.app.state, "runtime_control_service", None)
|
|
817
|
+
if not runtime_control:
|
|
818
|
+
raise HTTPException(status_code=503, detail=ERROR_RUNTIME_CONTROL_SERVICE_NOT_AVAILABLE)
|
|
819
|
+
|
|
820
|
+
# Get authentication service for OAuth lookup
|
|
821
|
+
auth_service = getattr(request.app.state, "authentication_service", None)
|
|
822
|
+
if not auth_service:
|
|
823
|
+
raise HTTPException(status_code=503, detail="Authentication service not available")
|
|
824
|
+
|
|
825
|
+
# SECURITY: Determine if user can see all events (ADMIN or higher)
|
|
826
|
+
user_role = auth.role
|
|
827
|
+
can_see_all = user_role in (UserRole.ADMIN, UserRole.SYSTEM_ADMIN, UserRole.AUTHORITY)
|
|
828
|
+
|
|
829
|
+
# SECURITY: Get user's allowed channel IDs (user_id + linked OAuth accounts)
|
|
830
|
+
allowed_channel_ids: set[str] = set()
|
|
831
|
+
allowed_user_ids: set[str] = set() # User IDs for profile filtering
|
|
832
|
+
task_channel_cache: dict[str, str] = {} # Cache task_id -> channel_id lookups
|
|
833
|
+
|
|
834
|
+
if not can_see_all:
|
|
835
|
+
user_id = auth.user_id
|
|
836
|
+
if not user_id:
|
|
837
|
+
raise HTTPException(status_code=401, detail="User ID not found in token")
|
|
838
|
+
|
|
839
|
+
allowed_channel_ids = await _get_user_allowed_channel_ids(auth_service, user_id)
|
|
840
|
+
allowed_user_ids = {user_id} # User can only see their own profile
|
|
841
|
+
|
|
842
|
+
# DEBUG: Log allowed channel IDs for OBSERVER users
|
|
843
|
+
logger.info(f"SSE Filter: OBSERVER user_id={user_id}, allowed_channel_ids={allowed_channel_ids}")
|
|
844
|
+
|
|
845
|
+
async def stream_reasoning_steps() -> Any:
|
|
846
|
+
"""Generate Server-Sent Events for live reasoning steps."""
|
|
847
|
+
try:
|
|
848
|
+
# Subscribe to the global reasoning event stream
|
|
849
|
+
from ciris_engine.logic.infrastructure.step_streaming import reasoning_event_stream
|
|
850
|
+
|
|
851
|
+
# Create a queue for this client
|
|
852
|
+
stream_queue: asyncio.Queue[Any] = asyncio.Queue(maxsize=100)
|
|
853
|
+
reasoning_event_stream.subscribe(stream_queue)
|
|
854
|
+
|
|
855
|
+
logger.debug(
|
|
856
|
+
f" SSE stream connected - user_id={auth.user_id}, role={user_role}, can_see_all={can_see_all}, allowed_channel_ids={allowed_channel_ids}"
|
|
857
|
+
)
|
|
858
|
+
|
|
859
|
+
try:
|
|
860
|
+
# Send initial connection event
|
|
861
|
+
yield f"event: connected\ndata: {json.dumps({'status': 'connected', 'timestamp': datetime.now().isoformat()})}\n\n"
|
|
862
|
+
|
|
863
|
+
# Stream live step results as they occur
|
|
864
|
+
while True:
|
|
865
|
+
try:
|
|
866
|
+
# Wait for step results with timeout to send keepalive
|
|
867
|
+
step_update = await asyncio.wait_for(stream_queue.get(), timeout=30.0)
|
|
868
|
+
|
|
869
|
+
logger.debug(
|
|
870
|
+
f" SSE received update from queue - events_count={len(step_update.get('events', []))}, can_see_all={can_see_all}"
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
# SECURITY: Filter events for OBSERVER users
|
|
874
|
+
# ADMIN+ users bypass filtering and see all events
|
|
875
|
+
if not can_see_all:
|
|
876
|
+
events = step_update.get("events", [])
|
|
877
|
+
if not events:
|
|
878
|
+
logger.debug(" SSE no events in update, skipping")
|
|
879
|
+
continue
|
|
880
|
+
|
|
881
|
+
# Batch lookup uncached task IDs
|
|
882
|
+
uncached_task_ids = [
|
|
883
|
+
event.get("task_id")
|
|
884
|
+
for event in events
|
|
885
|
+
if event.get("task_id") and event.get("task_id") not in task_channel_cache
|
|
886
|
+
]
|
|
887
|
+
|
|
888
|
+
# SECURITY: Batch fetch channel_ids for efficiency
|
|
889
|
+
if uncached_task_ids:
|
|
890
|
+
logger.info(f"SSE Filter: Fetching channel_ids for uncached tasks: {uncached_task_ids}")
|
|
891
|
+
new_mappings = await _batch_fetch_task_channel_ids(uncached_task_ids)
|
|
892
|
+
logger.info(f"SSE Filter: Fetched task->channel mappings: {new_mappings}")
|
|
893
|
+
task_channel_cache.update(new_mappings)
|
|
894
|
+
|
|
895
|
+
# DEBUG: Log event task_ids before filtering
|
|
896
|
+
event_task_ids = [event.get("task_id") for event in events if event.get("task_id")]
|
|
897
|
+
logger.info(f"SSE Filter: Processing {len(events)} events with task_ids: {event_task_ids}")
|
|
898
|
+
logger.info(f"SSE Filter: Current task_channel_cache: {task_channel_cache}")
|
|
899
|
+
|
|
900
|
+
# Filter events based on channel_id whitelist
|
|
901
|
+
filtered_events = _filter_events_by_channel_access(
|
|
902
|
+
events, allowed_channel_ids, task_channel_cache
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
# DEBUG: Log filtering results
|
|
906
|
+
logger.info(f"SSE Filter: Filtered to {len(filtered_events)}/{len(events)} events")
|
|
907
|
+
|
|
908
|
+
# SECURITY: Redact sensitive task information for OBSERVER users
|
|
909
|
+
# This removes recently_completed_tasks and pending_tasks from snapshots
|
|
910
|
+
# and filters user_profiles to only show user's OWN profile
|
|
911
|
+
if filtered_events and user_role == UserRole.OBSERVER:
|
|
912
|
+
filtered_events = _redact_observer_sensitive_data(filtered_events, allowed_user_ids)
|
|
913
|
+
|
|
914
|
+
# Replace events with filtered list
|
|
915
|
+
if filtered_events:
|
|
916
|
+
step_update = {"events": filtered_events}
|
|
917
|
+
logger.debug(f" SSE sending {len(filtered_events)} events to client")
|
|
918
|
+
else:
|
|
919
|
+
# No events for this user, skip this update silently
|
|
920
|
+
logger.debug(" SSE all events filtered out, skipping update")
|
|
921
|
+
continue
|
|
922
|
+
|
|
923
|
+
# Stream the step update
|
|
924
|
+
yield f"event: step_update\ndata: {json.dumps(step_update, default=str)}\n\n"
|
|
925
|
+
|
|
926
|
+
except asyncio.TimeoutError:
|
|
927
|
+
# Send keepalive every 30 seconds
|
|
928
|
+
yield f"event: keepalive\ndata: {json.dumps({'timestamp': datetime.now().isoformat()})}\n\n"
|
|
929
|
+
|
|
930
|
+
except Exception as step_error:
|
|
931
|
+
logger.error(f"Error processing step result in stream: {step_error}")
|
|
932
|
+
yield f"event: error\ndata: {json.dumps({'error': str(step_error)})}\n\n"
|
|
933
|
+
break
|
|
934
|
+
|
|
935
|
+
finally:
|
|
936
|
+
# Clean up subscription
|
|
937
|
+
reasoning_event_stream.unsubscribe(stream_queue)
|
|
938
|
+
|
|
939
|
+
except Exception as e:
|
|
940
|
+
logger.error(f"Error in reasoning stream: {e}")
|
|
941
|
+
yield f"event: error\ndata: {json.dumps({'error': str(e)})}\n\n"
|
|
942
|
+
|
|
943
|
+
return StreamingResponse(
|
|
944
|
+
stream_reasoning_steps(),
|
|
945
|
+
media_type="text/event-stream",
|
|
946
|
+
headers={
|
|
947
|
+
"Cache-Control": "no-cache",
|
|
948
|
+
"Connection": "keep-alive",
|
|
949
|
+
"Access-Control-Allow-Origin": "*",
|
|
950
|
+
"Access-Control-Allow-Headers": "Cache-Control",
|
|
951
|
+
},
|
|
952
|
+
)
|