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,722 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LLM message bus - handles all LLM service operations with redundancy and distribution
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import logging
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union, cast
|
|
8
|
+
|
|
9
|
+
from ciris_engine.logic.utils.jsondict_helpers import get_float, get_int
|
|
10
|
+
from ciris_engine.schemas.types import JSONDict
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ciris_engine.logic.registries.base import ServiceRegistry
|
|
14
|
+
from ciris_engine.schemas.services.llm import LLMMessage
|
|
15
|
+
|
|
16
|
+
from collections import defaultdict
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from enum import Enum
|
|
20
|
+
|
|
21
|
+
from pydantic import BaseModel
|
|
22
|
+
|
|
23
|
+
from ciris_engine.logic.registries.circuit_breaker import CircuitBreaker, CircuitBreakerConfig, CircuitState
|
|
24
|
+
from ciris_engine.protocols.services import LLMService
|
|
25
|
+
from ciris_engine.protocols.services.graph.telemetry import TelemetryServiceProtocol
|
|
26
|
+
from ciris_engine.protocols.services.lifecycle.time import TimeServiceProtocol
|
|
27
|
+
from ciris_engine.protocols.services.runtime.llm import MessageDict
|
|
28
|
+
from ciris_engine.schemas.infrastructure.base import BusMetrics
|
|
29
|
+
from ciris_engine.schemas.runtime.enums import ServiceType
|
|
30
|
+
from ciris_engine.schemas.runtime.resources import ResourceUsage
|
|
31
|
+
from ciris_engine.schemas.services.capabilities import LLMCapabilities
|
|
32
|
+
|
|
33
|
+
from .base_bus import BaseBus, BusMessage
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DistributionStrategy(str, Enum):
|
|
39
|
+
"""Strategy for distributing requests among services at the same priority"""
|
|
40
|
+
|
|
41
|
+
ROUND_ROBIN = "round_robin"
|
|
42
|
+
LATENCY_BASED = "latency_based"
|
|
43
|
+
RANDOM = "random"
|
|
44
|
+
LEAST_LOADED = "least_loaded"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class ServiceMetrics:
|
|
49
|
+
"""Metrics for a single LLM service instance"""
|
|
50
|
+
|
|
51
|
+
total_requests: int = 0
|
|
52
|
+
failed_requests: int = 0
|
|
53
|
+
total_latency_ms: float = 0.0
|
|
54
|
+
last_request_time: Optional[datetime] = None
|
|
55
|
+
last_failure_time: Optional[datetime] = None
|
|
56
|
+
consecutive_failures: int = 0
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def average_latency_ms(self) -> float:
|
|
60
|
+
"""Calculate average latency"""
|
|
61
|
+
if self.total_requests == 0:
|
|
62
|
+
return 0.0
|
|
63
|
+
return self.total_latency_ms / self.total_requests
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def failure_rate(self) -> float:
|
|
67
|
+
"""Calculate failure rate"""
|
|
68
|
+
if self.total_requests == 0:
|
|
69
|
+
return 0.0
|
|
70
|
+
return self.failed_requests / self.total_requests
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class LLMBusMessage(BusMessage):
|
|
74
|
+
"""Bus message for LLM generation"""
|
|
75
|
+
|
|
76
|
+
messages: List[MessageDict]
|
|
77
|
+
response_model: Type[BaseModel]
|
|
78
|
+
max_tokens: int = 4096
|
|
79
|
+
temperature: float = 0.0
|
|
80
|
+
# For async responses
|
|
81
|
+
future: Optional[asyncio.Future[Any]] = None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class LLMBus(BaseBus[LLMService]):
|
|
85
|
+
"""
|
|
86
|
+
Message bus for all LLM operations with redundancy and distribution.
|
|
87
|
+
|
|
88
|
+
Features:
|
|
89
|
+
- Multiple redundant LLM providers
|
|
90
|
+
- Priority-based selection
|
|
91
|
+
- Distribution strategies (round-robin, latency-based)
|
|
92
|
+
- Circuit breakers per service
|
|
93
|
+
- Automatic failover
|
|
94
|
+
- Metrics tracking
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
def __init__(
|
|
98
|
+
self,
|
|
99
|
+
service_registry: "ServiceRegistry",
|
|
100
|
+
time_service: TimeServiceProtocol,
|
|
101
|
+
telemetry_service: Optional[TelemetryServiceProtocol] = None,
|
|
102
|
+
distribution_strategy: DistributionStrategy = DistributionStrategy.LATENCY_BASED,
|
|
103
|
+
circuit_breaker_config: Optional[JSONDict] = None,
|
|
104
|
+
):
|
|
105
|
+
super().__init__(service_type=ServiceType.LLM, service_registry=service_registry)
|
|
106
|
+
|
|
107
|
+
self._time_service = time_service
|
|
108
|
+
self._start_time = time_service.now() if time_service else None
|
|
109
|
+
self.distribution_strategy = distribution_strategy
|
|
110
|
+
self.circuit_breaker_config = circuit_breaker_config or {}
|
|
111
|
+
self.telemetry_service = telemetry_service
|
|
112
|
+
|
|
113
|
+
# Service metrics and circuit breakers
|
|
114
|
+
self.service_metrics: dict[str, ServiceMetrics] = defaultdict(ServiceMetrics)
|
|
115
|
+
self.circuit_breakers: dict[str, CircuitBreaker] = {}
|
|
116
|
+
|
|
117
|
+
# Track services that have had full error logs to reduce log verbosity
|
|
118
|
+
self._services_with_full_error_logged: set[str] = set()
|
|
119
|
+
|
|
120
|
+
# Round-robin state
|
|
121
|
+
self.round_robin_index: dict[int, int] = defaultdict(int) # priority -> index
|
|
122
|
+
|
|
123
|
+
logger.info(f"LLMBus initialized with {distribution_strategy} distribution strategy")
|
|
124
|
+
|
|
125
|
+
def _normalize_messages(self, messages: Union[List[JSONDict], List["LLMMessage"]]) -> List[JSONDict]:
|
|
126
|
+
"""Normalize messages to dict format for LLM providers.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
messages: List of message dictionaries or LLMMessage objects
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
List of normalized message dictionaries
|
|
133
|
+
"""
|
|
134
|
+
from ciris_engine.schemas.services.llm import LLMMessage
|
|
135
|
+
|
|
136
|
+
normalized_messages: List[JSONDict] = []
|
|
137
|
+
for msg in messages:
|
|
138
|
+
if isinstance(msg, LLMMessage):
|
|
139
|
+
# Use exclude_none=True to avoid sending name: None to providers
|
|
140
|
+
# Some providers (e.g., Together AI) reject null values for optional fields
|
|
141
|
+
msg_dict = msg.model_dump(exclude_none=True)
|
|
142
|
+
normalized_messages.append(msg_dict)
|
|
143
|
+
else:
|
|
144
|
+
# Only strip the optional "name" field if it's None
|
|
145
|
+
# IMPORTANT: Don't strip required fields like "content" even if None
|
|
146
|
+
# (tool-call assistant messages require "content": None to be present)
|
|
147
|
+
msg_copy = dict(msg)
|
|
148
|
+
if "name" in msg_copy and msg_copy["name"] is None:
|
|
149
|
+
del msg_copy["name"]
|
|
150
|
+
normalized_messages.append(msg_copy)
|
|
151
|
+
return normalized_messages
|
|
152
|
+
|
|
153
|
+
async def call_llm_structured(
|
|
154
|
+
self,
|
|
155
|
+
messages: Union[List[JSONDict], List["LLMMessage"]],
|
|
156
|
+
response_model: Type[BaseModel],
|
|
157
|
+
max_tokens: int = 4096,
|
|
158
|
+
temperature: float = 0.0,
|
|
159
|
+
handler_name: str = "default",
|
|
160
|
+
domain: Optional[str] = None, # NEW: Domain-aware routing
|
|
161
|
+
thought_id: Optional[str] = None, # NEW: For resource tracking per thought
|
|
162
|
+
task_id: Optional[str] = None, # For ciris.ai billing - all calls with same task_id share 1 credit
|
|
163
|
+
) -> Tuple[BaseModel, ResourceUsage]:
|
|
164
|
+
"""
|
|
165
|
+
Generate structured output using LLM with optional domain routing.
|
|
166
|
+
|
|
167
|
+
This method handles:
|
|
168
|
+
- Domain-aware service filtering (e.g., medical, legal, financial)
|
|
169
|
+
- Service discovery by priority
|
|
170
|
+
- Distribution based on strategy
|
|
171
|
+
- Circuit breaker checks
|
|
172
|
+
- Automatic failover
|
|
173
|
+
- Metrics collection
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
messages: List of message dictionaries or LLMMessage objects
|
|
177
|
+
response_model: Pydantic model for structured response
|
|
178
|
+
max_tokens: Maximum tokens to generate
|
|
179
|
+
temperature: Sampling temperature
|
|
180
|
+
handler_name: Handler identifier for metrics
|
|
181
|
+
domain: Optional domain for routing to specialized LLMs
|
|
182
|
+
"""
|
|
183
|
+
# Normalize messages to dicts
|
|
184
|
+
normalized_messages = self._normalize_messages(messages)
|
|
185
|
+
start_time = self._time_service.timestamp()
|
|
186
|
+
|
|
187
|
+
# Get all available LLM services, filtered by domain if specified
|
|
188
|
+
services = await self._get_prioritized_services(handler_name, domain=domain)
|
|
189
|
+
|
|
190
|
+
if not services:
|
|
191
|
+
raise RuntimeError(f"No LLM services available for {handler_name}")
|
|
192
|
+
|
|
193
|
+
# Group services by priority
|
|
194
|
+
priority_groups = self._group_by_priority(services)
|
|
195
|
+
|
|
196
|
+
# Try each priority group in order
|
|
197
|
+
last_error = None
|
|
198
|
+
for priority, service_group in sorted(priority_groups.items()):
|
|
199
|
+
# Select service from this priority group based on strategy
|
|
200
|
+
selected_service = await self._select_service(service_group, priority, handler_name)
|
|
201
|
+
|
|
202
|
+
if not selected_service:
|
|
203
|
+
continue
|
|
204
|
+
|
|
205
|
+
service_name = f"{type(selected_service).__name__}_{id(selected_service)}"
|
|
206
|
+
|
|
207
|
+
# Check circuit breaker
|
|
208
|
+
if not self._check_circuit_breaker(service_name):
|
|
209
|
+
logger.warning(f"Circuit breaker OPEN for {service_name}, skipping")
|
|
210
|
+
continue
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
# Make the LLM call
|
|
214
|
+
logger.debug(f"Calling LLM service {service_name} for {handler_name}")
|
|
215
|
+
|
|
216
|
+
result, usage = await selected_service.call_llm_structured( # type: ignore[attr-defined]
|
|
217
|
+
messages=normalized_messages,
|
|
218
|
+
response_model=response_model,
|
|
219
|
+
max_tokens=max_tokens,
|
|
220
|
+
temperature=temperature,
|
|
221
|
+
thought_id=thought_id,
|
|
222
|
+
task_id=task_id,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Record success
|
|
226
|
+
latency_ms = (self._time_service.timestamp() - start_time) * 1000
|
|
227
|
+
self._record_success(service_name, latency_ms)
|
|
228
|
+
|
|
229
|
+
# Record telemetry for resource usage
|
|
230
|
+
await self._record_resource_telemetry(
|
|
231
|
+
service_name=service_name,
|
|
232
|
+
handler_name=handler_name,
|
|
233
|
+
usage=usage,
|
|
234
|
+
latency_ms=latency_ms,
|
|
235
|
+
thought_id=thought_id,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
logger.debug(f"LLM call successful via {service_name} " f"(latency: {latency_ms:.2f}ms)")
|
|
239
|
+
|
|
240
|
+
return result, usage
|
|
241
|
+
|
|
242
|
+
except Exception as e:
|
|
243
|
+
# Check for billing errors - these should not be retried
|
|
244
|
+
from ciris_engine.logic.adapters.base_observer import BillingServiceError
|
|
245
|
+
|
|
246
|
+
if isinstance(e, BillingServiceError):
|
|
247
|
+
logger.error(f"LLM billing error (not retrying): {e}")
|
|
248
|
+
raise # Don't retry billing errors - surface to user immediately
|
|
249
|
+
|
|
250
|
+
# Record failure
|
|
251
|
+
self._record_failure(service_name)
|
|
252
|
+
last_error = e
|
|
253
|
+
|
|
254
|
+
# Log full stack trace only once per service to reduce log verbosity
|
|
255
|
+
# Subsequent failures for the same service will be logged as warnings
|
|
256
|
+
if service_name not in self._services_with_full_error_logged:
|
|
257
|
+
logger.error(f"LLM service {service_name} failed: {e}", exc_info=True)
|
|
258
|
+
self._services_with_full_error_logged.add(service_name)
|
|
259
|
+
else:
|
|
260
|
+
logger.warning(f"LLM service {service_name} failed (repeated): {e}")
|
|
261
|
+
|
|
262
|
+
# Continue to next service
|
|
263
|
+
continue
|
|
264
|
+
|
|
265
|
+
# All services failed
|
|
266
|
+
raise RuntimeError(f"All LLM services failed for {handler_name}. " f"Last error: {last_error}")
|
|
267
|
+
|
|
268
|
+
# Note: This method is not in the protocol but kept for internal use
|
|
269
|
+
async def _generate_structured_sync(
|
|
270
|
+
self,
|
|
271
|
+
messages: List[JSONDict],
|
|
272
|
+
response_model: Type[BaseModel],
|
|
273
|
+
handler_name: str,
|
|
274
|
+
max_tokens: int = 4096,
|
|
275
|
+
temperature: float = 0.0,
|
|
276
|
+
domain: Optional[str] = None,
|
|
277
|
+
) -> Tuple[BaseModel, ResourceUsage]:
|
|
278
|
+
"""
|
|
279
|
+
Synchronous version of generate_structured with domain routing.
|
|
280
|
+
|
|
281
|
+
This is what the handlers will call directly.
|
|
282
|
+
"""
|
|
283
|
+
return await self.call_llm_structured(
|
|
284
|
+
messages=messages,
|
|
285
|
+
response_model=response_model,
|
|
286
|
+
handler_name=handler_name,
|
|
287
|
+
max_tokens=max_tokens,
|
|
288
|
+
temperature=temperature,
|
|
289
|
+
domain=domain,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
def _check_service_capabilities(self, service: Any) -> bool:
|
|
293
|
+
"""Check if service has required LLM capabilities."""
|
|
294
|
+
if not hasattr(service, "get_capabilities"):
|
|
295
|
+
return True
|
|
296
|
+
|
|
297
|
+
caps = service.get_capabilities()
|
|
298
|
+
if hasattr(caps, "supports_operation_list"):
|
|
299
|
+
return LLMCapabilities.CALL_LLM_STRUCTURED.value in caps.supports_operation_list
|
|
300
|
+
elif hasattr(caps, "actions"):
|
|
301
|
+
return LLMCapabilities.CALL_LLM_STRUCTURED.value in caps.actions
|
|
302
|
+
return True
|
|
303
|
+
|
|
304
|
+
def _get_service_priority_and_metadata(self, service: Any) -> Tuple[int, JSONDict]:
|
|
305
|
+
"""Get priority value and metadata for a service."""
|
|
306
|
+
provider_info = self.service_registry.get_provider_info(service_type=ServiceType.LLM)
|
|
307
|
+
priority_map = {"CRITICAL": 0, "HIGH": 1, "NORMAL": 2, "LOW": 3, "FALLBACK": 9}
|
|
308
|
+
|
|
309
|
+
for providers in provider_info.get("services", {}).get(ServiceType.LLM, []):
|
|
310
|
+
if providers["name"].endswith(str(id(service))):
|
|
311
|
+
priority_value = priority_map.get(providers["priority"], 2)
|
|
312
|
+
service_metadata = providers.get("metadata", {})
|
|
313
|
+
return priority_value, service_metadata
|
|
314
|
+
|
|
315
|
+
return 0, {} # Default to highest priority, empty metadata
|
|
316
|
+
|
|
317
|
+
def _should_include_service_for_domain(self, service_metadata: JSONDict, domain: Optional[str]) -> Tuple[bool, int]:
|
|
318
|
+
"""Check if service should be included based on domain and get priority adjustment.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
Tuple of (should_include, priority_adjustment)
|
|
322
|
+
"""
|
|
323
|
+
if not domain:
|
|
324
|
+
return True, 0
|
|
325
|
+
|
|
326
|
+
service_domain = service_metadata.get("domain", "general")
|
|
327
|
+
|
|
328
|
+
# Skip services that don't match domain and aren't general
|
|
329
|
+
if service_domain != domain and service_domain != "general":
|
|
330
|
+
logger.debug(f"Skipping service with domain {service_domain} (requested: {domain})")
|
|
331
|
+
return False, 0
|
|
332
|
+
|
|
333
|
+
# Boost priority for exact domain match
|
|
334
|
+
if service_domain == domain:
|
|
335
|
+
return True, -1
|
|
336
|
+
|
|
337
|
+
return True, 0
|
|
338
|
+
|
|
339
|
+
async def _get_prioritized_services(self, handler_name: str, domain: Optional[str] = None) -> List[Tuple[Any, int]]:
|
|
340
|
+
"""Get all available LLM services with their priorities, optionally filtered by domain.
|
|
341
|
+
|
|
342
|
+
NOTE: This method does NOT filter by health/circuit breaker state. That check
|
|
343
|
+
happens during service selection in call_llm_structured() to enable proper
|
|
344
|
+
failover from services with open circuit breakers to lower-priority services.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
handler_name: Handler identifier
|
|
348
|
+
domain: Optional domain filter (e.g., 'medical', 'legal', 'financial')
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
List of (service, priority) tuples
|
|
352
|
+
"""
|
|
353
|
+
services = []
|
|
354
|
+
all_llm_services = self.service_registry.get_services_by_type(ServiceType.LLM)
|
|
355
|
+
|
|
356
|
+
for service in all_llm_services:
|
|
357
|
+
# Check capabilities
|
|
358
|
+
if not self._check_service_capabilities(service):
|
|
359
|
+
continue
|
|
360
|
+
|
|
361
|
+
# Get priority and metadata
|
|
362
|
+
priority_value, service_metadata = self._get_service_priority_and_metadata(service)
|
|
363
|
+
|
|
364
|
+
# Check domain filtering
|
|
365
|
+
should_include, priority_adjustment = self._should_include_service_for_domain(service_metadata, domain)
|
|
366
|
+
if not should_include:
|
|
367
|
+
continue
|
|
368
|
+
|
|
369
|
+
# Apply priority adjustment for domain matching
|
|
370
|
+
priority_value = max(0, priority_value + priority_adjustment)
|
|
371
|
+
services.append((service, priority_value))
|
|
372
|
+
|
|
373
|
+
return services
|
|
374
|
+
|
|
375
|
+
def _group_by_priority(self, services: List[Tuple[Any, int]]) -> dict[int, List[object]]:
|
|
376
|
+
"""Group services by priority"""
|
|
377
|
+
groups: dict[int, List[object]] = defaultdict(list)
|
|
378
|
+
for service, priority in services:
|
|
379
|
+
groups[priority].append(service)
|
|
380
|
+
return groups
|
|
381
|
+
|
|
382
|
+
async def _select_service(self, services: List[object], priority: int, handler_name: str) -> Optional[object]:
|
|
383
|
+
"""Select a service from a priority group based on distribution strategy"""
|
|
384
|
+
if not services:
|
|
385
|
+
return None
|
|
386
|
+
|
|
387
|
+
if len(services) == 1:
|
|
388
|
+
return services[0]
|
|
389
|
+
|
|
390
|
+
if self.distribution_strategy == DistributionStrategy.ROUND_ROBIN:
|
|
391
|
+
# Round-robin selection
|
|
392
|
+
index = self.round_robin_index[priority] % len(services)
|
|
393
|
+
self.round_robin_index[priority] += 1
|
|
394
|
+
return services[index]
|
|
395
|
+
|
|
396
|
+
elif self.distribution_strategy == DistributionStrategy.LATENCY_BASED:
|
|
397
|
+
# Select service with lowest average latency
|
|
398
|
+
best_service = None
|
|
399
|
+
best_latency = float("inf")
|
|
400
|
+
|
|
401
|
+
for service in services:
|
|
402
|
+
service_name = f"{type(service).__name__}_{id(service)}"
|
|
403
|
+
metrics = self.service_metrics[service_name]
|
|
404
|
+
|
|
405
|
+
# New services get a chance
|
|
406
|
+
if metrics.total_requests == 0:
|
|
407
|
+
return service
|
|
408
|
+
|
|
409
|
+
if metrics.average_latency_ms < best_latency:
|
|
410
|
+
best_latency = metrics.average_latency_ms
|
|
411
|
+
best_service = service
|
|
412
|
+
|
|
413
|
+
return best_service or services[0]
|
|
414
|
+
|
|
415
|
+
elif self.distribution_strategy == DistributionStrategy.RANDOM:
|
|
416
|
+
# Random selection for load distribution (not cryptographic)
|
|
417
|
+
import random
|
|
418
|
+
|
|
419
|
+
return random.choice(services)
|
|
420
|
+
|
|
421
|
+
else: # DistributionStrategy.LEAST_LOADED
|
|
422
|
+
# Select service with fewest active requests
|
|
423
|
+
# This would require tracking active requests
|
|
424
|
+
# For now, use the one with fewest total requests
|
|
425
|
+
return min(services, key=lambda s: self.service_metrics[f"{type(s).__name__}_{id(s)}"].total_requests)
|
|
426
|
+
|
|
427
|
+
def _check_circuit_breaker(self, service_name: str) -> bool:
|
|
428
|
+
"""Check if circuit breaker allows execution"""
|
|
429
|
+
if service_name not in self.circuit_breakers:
|
|
430
|
+
# Create CircuitBreakerConfig from the dict config - use jsondict_helpers for type safety
|
|
431
|
+
config = CircuitBreakerConfig(
|
|
432
|
+
failure_threshold=get_int(self.circuit_breaker_config, "failure_threshold", 5),
|
|
433
|
+
recovery_timeout=get_float(self.circuit_breaker_config, "recovery_timeout", 60.0),
|
|
434
|
+
success_threshold=get_int(self.circuit_breaker_config, "half_open_max_calls", 3),
|
|
435
|
+
timeout_duration=get_float(self.circuit_breaker_config, "timeout_duration", 30.0),
|
|
436
|
+
)
|
|
437
|
+
self.circuit_breakers[service_name] = CircuitBreaker(name=service_name, config=config)
|
|
438
|
+
|
|
439
|
+
return self.circuit_breakers[service_name].is_available()
|
|
440
|
+
|
|
441
|
+
def _record_success(self, service_name: str, latency_ms: float) -> None:
|
|
442
|
+
"""Record successful call metrics"""
|
|
443
|
+
metrics = self.service_metrics[service_name]
|
|
444
|
+
metrics.total_requests += 1
|
|
445
|
+
metrics.total_latency_ms += latency_ms
|
|
446
|
+
metrics.last_request_time = self._time_service.now()
|
|
447
|
+
metrics.consecutive_failures = 0
|
|
448
|
+
|
|
449
|
+
if service_name in self.circuit_breakers:
|
|
450
|
+
self.circuit_breakers[service_name].record_success()
|
|
451
|
+
|
|
452
|
+
def _record_failure(self, service_name: str) -> None:
|
|
453
|
+
"""Record failed call metrics"""
|
|
454
|
+
metrics = self.service_metrics[service_name]
|
|
455
|
+
metrics.total_requests += 1
|
|
456
|
+
metrics.failed_requests += 1
|
|
457
|
+
metrics.last_failure_time = self._time_service.now()
|
|
458
|
+
metrics.consecutive_failures += 1
|
|
459
|
+
|
|
460
|
+
if service_name in self.circuit_breakers:
|
|
461
|
+
self.circuit_breakers[service_name].record_failure()
|
|
462
|
+
|
|
463
|
+
async def _record_resource_telemetry(
|
|
464
|
+
self,
|
|
465
|
+
service_name: str,
|
|
466
|
+
handler_name: str,
|
|
467
|
+
usage: ResourceUsage,
|
|
468
|
+
latency_ms: float,
|
|
469
|
+
thought_id: Optional[str] = None,
|
|
470
|
+
) -> None:
|
|
471
|
+
"""Record detailed telemetry for resource usage"""
|
|
472
|
+
if not self.telemetry_service:
|
|
473
|
+
return
|
|
474
|
+
|
|
475
|
+
try:
|
|
476
|
+
# Build base tags
|
|
477
|
+
base_tags = {
|
|
478
|
+
"service": service_name,
|
|
479
|
+
"model": usage.model_used or "unknown",
|
|
480
|
+
"handler": handler_name,
|
|
481
|
+
}
|
|
482
|
+
# Add thought_id if provided for per-thought resource tracking
|
|
483
|
+
if thought_id:
|
|
484
|
+
base_tags["thought_id"] = thought_id
|
|
485
|
+
|
|
486
|
+
# Record token usage
|
|
487
|
+
await self.telemetry_service.record_metric(
|
|
488
|
+
metric_name="llm.tokens.total",
|
|
489
|
+
value=float(usage.tokens_used),
|
|
490
|
+
handler_name=handler_name,
|
|
491
|
+
tags=base_tags,
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
# Record input/output tokens separately
|
|
495
|
+
if usage.tokens_input > 0:
|
|
496
|
+
await self.telemetry_service.record_metric(
|
|
497
|
+
metric_name="llm.tokens.input",
|
|
498
|
+
value=float(usage.tokens_input),
|
|
499
|
+
handler_name=handler_name,
|
|
500
|
+
tags=base_tags,
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
if usage.tokens_output > 0:
|
|
504
|
+
await self.telemetry_service.record_metric(
|
|
505
|
+
metric_name="llm.tokens.output",
|
|
506
|
+
value=float(usage.tokens_output),
|
|
507
|
+
handler_name=handler_name,
|
|
508
|
+
tags=base_tags,
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
# Record cost
|
|
512
|
+
if usage.cost_cents > 0:
|
|
513
|
+
await self.telemetry_service.record_metric(
|
|
514
|
+
metric_name="llm.cost.cents",
|
|
515
|
+
value=usage.cost_cents,
|
|
516
|
+
handler_name=handler_name,
|
|
517
|
+
tags=base_tags,
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
# Record environmental impact
|
|
521
|
+
if usage.carbon_grams > 0:
|
|
522
|
+
await self.telemetry_service.record_metric(
|
|
523
|
+
metric_name="llm.environmental.carbon_grams",
|
|
524
|
+
value=usage.carbon_grams,
|
|
525
|
+
handler_name=handler_name,
|
|
526
|
+
tags=base_tags,
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
if usage.energy_kwh > 0:
|
|
530
|
+
await self.telemetry_service.record_metric(
|
|
531
|
+
metric_name="llm.environmental.energy_kwh",
|
|
532
|
+
value=usage.energy_kwh,
|
|
533
|
+
handler_name=handler_name,
|
|
534
|
+
tags=base_tags,
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
# Record latency
|
|
538
|
+
await self.telemetry_service.record_metric(
|
|
539
|
+
metric_name="llm.latency.ms",
|
|
540
|
+
value=latency_ms,
|
|
541
|
+
handler_name=handler_name,
|
|
542
|
+
tags=base_tags,
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
except Exception as e:
|
|
546
|
+
logger.warning(f"Failed to record telemetry: {e}")
|
|
547
|
+
|
|
548
|
+
def get_service_stats(self) -> JSONDict:
|
|
549
|
+
"""Get detailed statistics for all services"""
|
|
550
|
+
stats: JSONDict = {}
|
|
551
|
+
|
|
552
|
+
for service_name, metrics in self.service_metrics.items():
|
|
553
|
+
circuit_breaker = self.circuit_breakers.get(service_name)
|
|
554
|
+
|
|
555
|
+
stats[service_name] = {
|
|
556
|
+
"total_requests": metrics.total_requests,
|
|
557
|
+
"failed_requests": metrics.failed_requests,
|
|
558
|
+
"failure_rate": f"{metrics.failure_rate * 100:.2f}%",
|
|
559
|
+
"average_latency_ms": f"{metrics.average_latency_ms:.2f}",
|
|
560
|
+
"consecutive_failures": metrics.consecutive_failures,
|
|
561
|
+
"circuit_breaker_state": circuit_breaker.state.value if circuit_breaker else "none",
|
|
562
|
+
"last_request": metrics.last_request_time.isoformat() if metrics.last_request_time else None,
|
|
563
|
+
"last_failure": metrics.last_failure_time.isoformat() if metrics.last_failure_time else None,
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return stats
|
|
567
|
+
|
|
568
|
+
async def get_available_models(self, handler_name: str = "default") -> List[str]:
|
|
569
|
+
"""Get list of available LLM models"""
|
|
570
|
+
service = await self.get_service(handler_name=handler_name, required_capabilities=["get_available_models"])
|
|
571
|
+
|
|
572
|
+
if not service:
|
|
573
|
+
logger.error(f"No LLM service available for {handler_name}")
|
|
574
|
+
return []
|
|
575
|
+
|
|
576
|
+
try:
|
|
577
|
+
# Cast to Any to handle dynamic method access
|
|
578
|
+
service_any = cast(Any, service)
|
|
579
|
+
result: List[str] = await service_any.get_available_models()
|
|
580
|
+
return result
|
|
581
|
+
except Exception as e:
|
|
582
|
+
logger.error(f"Error getting available models: {e}", exc_info=True)
|
|
583
|
+
return []
|
|
584
|
+
|
|
585
|
+
async def is_healthy(self, handler_name: str = "default") -> bool:
|
|
586
|
+
"""Check if LLM service is healthy"""
|
|
587
|
+
service = await self.get_service(handler_name=handler_name)
|
|
588
|
+
if not service:
|
|
589
|
+
return False
|
|
590
|
+
try:
|
|
591
|
+
return await service.is_healthy()
|
|
592
|
+
except Exception as e:
|
|
593
|
+
logger.error(f"Failed to check health: {e}")
|
|
594
|
+
return False
|
|
595
|
+
|
|
596
|
+
async def get_capabilities(self, handler_name: str = "default") -> List[str]:
|
|
597
|
+
"""Get LLM service capabilities"""
|
|
598
|
+
service = await self.get_service(handler_name=handler_name)
|
|
599
|
+
if not service:
|
|
600
|
+
return []
|
|
601
|
+
try:
|
|
602
|
+
capabilities = service.get_capabilities()
|
|
603
|
+
return capabilities.supports_operation_list if hasattr(capabilities, "supports_operation_list") else []
|
|
604
|
+
except Exception as e:
|
|
605
|
+
logger.error(f"Failed to get capabilities: {e}")
|
|
606
|
+
return []
|
|
607
|
+
|
|
608
|
+
async def _process_message(self, message: BusMessage) -> None:
|
|
609
|
+
"""Process an LLM message from the queue"""
|
|
610
|
+
if isinstance(message, LLMBusMessage):
|
|
611
|
+
# For async processing, we would handle the request here
|
|
612
|
+
# and set the result on the future
|
|
613
|
+
# For now, LLM calls are synchronous
|
|
614
|
+
logger.warning("Async LLM processing not yet implemented")
|
|
615
|
+
else:
|
|
616
|
+
logger.error(f"Unknown message type: {type(message)}")
|
|
617
|
+
|
|
618
|
+
def get_stats(self) -> JSONDict:
|
|
619
|
+
"""Get bus statistics including service stats"""
|
|
620
|
+
base_stats = super().get_stats()
|
|
621
|
+
base_stats["service_stats"] = self.get_service_stats()
|
|
622
|
+
base_stats["distribution_strategy"] = self.distribution_strategy.value
|
|
623
|
+
return base_stats
|
|
624
|
+
|
|
625
|
+
def _collect_metrics(self) -> dict[str, float]:
|
|
626
|
+
"""Collect base metrics for the LLM bus."""
|
|
627
|
+
# Calculate uptime
|
|
628
|
+
uptime_seconds = 0.0
|
|
629
|
+
if hasattr(self, "_time_service") and self._time_service:
|
|
630
|
+
if hasattr(self, "_start_time") and self._start_time:
|
|
631
|
+
uptime_seconds = (self._time_service.now() - self._start_time).total_seconds()
|
|
632
|
+
|
|
633
|
+
# Calculate aggregate metrics from service metrics
|
|
634
|
+
total_requests = sum(m.total_requests for m in self.service_metrics.values())
|
|
635
|
+
failed_requests = sum(m.failed_requests for m in self.service_metrics.values())
|
|
636
|
+
total_latency = sum(m.total_latency_ms for m in self.service_metrics.values())
|
|
637
|
+
avg_latency = total_latency / total_requests if total_requests > 0 else 0.0
|
|
638
|
+
|
|
639
|
+
# Count circuit breakers open
|
|
640
|
+
circuit_breakers_open = sum(1 for cb in self.circuit_breakers.values() if cb.state == CircuitState.OPEN)
|
|
641
|
+
|
|
642
|
+
return {
|
|
643
|
+
"llm_requests_total": float(total_requests),
|
|
644
|
+
"llm_failed_requests": float(failed_requests),
|
|
645
|
+
"llm_average_latency_ms": avg_latency,
|
|
646
|
+
"llm_circuit_breakers_open": float(circuit_breakers_open),
|
|
647
|
+
"llm_providers_available": float(len(self.service_metrics)),
|
|
648
|
+
"llm_uptime_seconds": uptime_seconds,
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
def get_metrics(self) -> BusMetrics:
|
|
652
|
+
"""Get all LLM bus metrics as typed BusMetrics schema."""
|
|
653
|
+
# Calculate aggregate metrics from service metrics
|
|
654
|
+
total_requests = sum(m.total_requests for m in self.service_metrics.values())
|
|
655
|
+
failed_requests = sum(m.failed_requests for m in self.service_metrics.values())
|
|
656
|
+
total_latency = sum(m.total_latency_ms for m in self.service_metrics.values())
|
|
657
|
+
avg_latency = total_latency / total_requests if total_requests > 0 else 0.0
|
|
658
|
+
|
|
659
|
+
# Calculate uptime
|
|
660
|
+
uptime_seconds = 0.0
|
|
661
|
+
if hasattr(self, "_time_service") and self._time_service:
|
|
662
|
+
if hasattr(self, "_start_time") and self._start_time:
|
|
663
|
+
uptime_seconds = (self._time_service.now() - self._start_time).total_seconds()
|
|
664
|
+
|
|
665
|
+
# Count circuit breakers open
|
|
666
|
+
circuit_breakers_open = sum(1 for cb in self.circuit_breakers.values() if cb.state == CircuitState.OPEN)
|
|
667
|
+
|
|
668
|
+
# Find busiest service (service with most requests)
|
|
669
|
+
busiest_service = None
|
|
670
|
+
max_requests = 0
|
|
671
|
+
for service_name, metrics in self.service_metrics.items():
|
|
672
|
+
if metrics.total_requests > max_requests:
|
|
673
|
+
max_requests = metrics.total_requests
|
|
674
|
+
busiest_service = service_name
|
|
675
|
+
|
|
676
|
+
# Map to BusMetrics schema
|
|
677
|
+
return BusMetrics(
|
|
678
|
+
messages_sent=total_requests, # Total LLM requests sent
|
|
679
|
+
messages_received=total_requests, # Same as sent (synchronous)
|
|
680
|
+
messages_dropped=0, # Not tracked yet
|
|
681
|
+
average_latency_ms=avg_latency,
|
|
682
|
+
active_subscriptions=len(self.service_metrics), # Number of LLM services with metrics
|
|
683
|
+
queue_depth=self.get_queue_size(),
|
|
684
|
+
errors_last_hour=failed_requests, # Total failed requests (not windowed yet)
|
|
685
|
+
busiest_service=busiest_service,
|
|
686
|
+
additional_metrics={
|
|
687
|
+
"llm_requests_total": total_requests,
|
|
688
|
+
"llm_failed_requests": failed_requests,
|
|
689
|
+
"llm_circuit_breakers_open": circuit_breakers_open,
|
|
690
|
+
"llm_providers_available": len(self.service_metrics),
|
|
691
|
+
"llm_uptime_seconds": uptime_seconds,
|
|
692
|
+
},
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
def _is_service_available_sync(self, service: object) -> bool:
|
|
696
|
+
"""Synchronous check if a service is available (for metrics collection)."""
|
|
697
|
+
try:
|
|
698
|
+
# Check if service has basic capabilities
|
|
699
|
+
if not self._check_service_capabilities(service):
|
|
700
|
+
return False
|
|
701
|
+
|
|
702
|
+
# Check circuit breaker state
|
|
703
|
+
service_name = f"{type(service).__name__}_{id(service)}"
|
|
704
|
+
if not self._check_circuit_breaker(service_name):
|
|
705
|
+
return False
|
|
706
|
+
|
|
707
|
+
# Service is considered active if it passes basic checks
|
|
708
|
+
return True
|
|
709
|
+
except Exception:
|
|
710
|
+
return False
|
|
711
|
+
|
|
712
|
+
def clear_circuit_breakers(self) -> None:
|
|
713
|
+
"""Clear all circuit breakers - useful for testing.
|
|
714
|
+
|
|
715
|
+
WARNING: This should ONLY be used in test environments to ensure
|
|
716
|
+
clean state between test runs. Using this in production could
|
|
717
|
+
hide real service failures.
|
|
718
|
+
"""
|
|
719
|
+
logger.warning("Clearing all LLM circuit breakers - this should only happen in tests!")
|
|
720
|
+
self.circuit_breakers.clear()
|
|
721
|
+
# Also clear service metrics to ensure clean state
|
|
722
|
+
self.service_metrics.clear()
|