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,1037 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API adapter for CIRIS v1.
|
|
3
|
+
|
|
4
|
+
Provides RESTful API and WebSocket interfaces to the CIRIS agent.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
import uuid
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from typing import Any, Awaitable, Callable, List, Optional
|
|
12
|
+
|
|
13
|
+
import uvicorn
|
|
14
|
+
from fastapi import FastAPI
|
|
15
|
+
from uvicorn import Server
|
|
16
|
+
|
|
17
|
+
from ciris_engine.logic import persistence
|
|
18
|
+
from ciris_engine.logic.adapters.base import Service
|
|
19
|
+
from ciris_engine.logic.persistence.models.correlations import get_active_channels_by_adapter, is_admin_channel
|
|
20
|
+
from ciris_engine.logic.registries.base import Priority
|
|
21
|
+
from ciris_engine.logic.services.runtime.adapter_configuration import AdapterConfigurationService
|
|
22
|
+
from ciris_engine.schemas.adapters import AdapterServiceRegistration
|
|
23
|
+
from ciris_engine.schemas.runtime.enums import ServiceType
|
|
24
|
+
from ciris_engine.schemas.runtime.messages import IncomingMessage, MessageHandlingResult
|
|
25
|
+
from ciris_engine.schemas.runtime.system_context import ChannelContext
|
|
26
|
+
from ciris_engine.schemas.telemetry.core import (
|
|
27
|
+
ServiceCorrelation,
|
|
28
|
+
ServiceCorrelationStatus,
|
|
29
|
+
ServiceRequestData,
|
|
30
|
+
ServiceResponseData,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from .api_communication import APICommunicationService
|
|
34
|
+
from .api_observer import APIObserver
|
|
35
|
+
from .api_runtime_control import APIRuntimeControlService
|
|
36
|
+
from .api_tools import APIToolService
|
|
37
|
+
from .app import create_app
|
|
38
|
+
from .config import APIAdapterConfig
|
|
39
|
+
from .service_configuration import ApiServiceConfiguration
|
|
40
|
+
from .services.auth_service import APIAuthService
|
|
41
|
+
|
|
42
|
+
logger = logging.getLogger(__name__)
|
|
43
|
+
|
|
44
|
+
# Constants
|
|
45
|
+
MANIFEST_FILENAME = "manifest.json"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ApiPlatform(Service):
|
|
49
|
+
"""API adapter platform for CIRIS v1."""
|
|
50
|
+
|
|
51
|
+
config: APIAdapterConfig # type: ignore[assignment]
|
|
52
|
+
|
|
53
|
+
def __init__(self, runtime: Any, context: Optional[Any] = None, **kwargs: Any) -> None:
|
|
54
|
+
"""Initialize API adapter."""
|
|
55
|
+
super().__init__(config=kwargs.get("adapter_config"))
|
|
56
|
+
self.runtime = runtime
|
|
57
|
+
|
|
58
|
+
# Initialize and load configuration
|
|
59
|
+
self.config = self._load_config(kwargs)
|
|
60
|
+
|
|
61
|
+
# Create FastAPI app - services will be injected later in start()
|
|
62
|
+
self.app: FastAPI = create_app(runtime, self.config)
|
|
63
|
+
self._server: Server | None = None
|
|
64
|
+
self._server_task: asyncio.Task[Any] | None = None
|
|
65
|
+
self._startup_error: str | None = None # Track server startup errors
|
|
66
|
+
|
|
67
|
+
# Message observer for handling incoming messages (will be created in start())
|
|
68
|
+
self.message_observer: APIObserver | None = None
|
|
69
|
+
|
|
70
|
+
# Communication service for API responses
|
|
71
|
+
self.communication = APICommunicationService(config=self.config)
|
|
72
|
+
# Pass time service if available
|
|
73
|
+
if hasattr(runtime, "time_service"):
|
|
74
|
+
self.communication._time_service = runtime.time_service
|
|
75
|
+
# Pass app state reference for message tracking
|
|
76
|
+
self.communication._app_state = self.app.state # type: ignore[attr-defined]
|
|
77
|
+
|
|
78
|
+
# Runtime control service
|
|
79
|
+
self.runtime_control = APIRuntimeControlService(runtime, time_service=getattr(runtime, "time_service", None))
|
|
80
|
+
|
|
81
|
+
# Tool service
|
|
82
|
+
self.tool_service = APIToolService(time_service=getattr(runtime, "time_service", None))
|
|
83
|
+
|
|
84
|
+
# Adapter configuration service for interactive adapter setup
|
|
85
|
+
self.adapter_configuration_service = AdapterConfigurationService()
|
|
86
|
+
|
|
87
|
+
# Debug logging
|
|
88
|
+
logger.debug(f"[DEBUG] adapter_config in kwargs: {'adapter_config' in kwargs}")
|
|
89
|
+
if "adapter_config" in kwargs and kwargs["adapter_config"] is not None:
|
|
90
|
+
logger.debug(f"[DEBUG] adapter_config type: {type(kwargs['adapter_config'])}")
|
|
91
|
+
if hasattr(kwargs["adapter_config"], "host"):
|
|
92
|
+
logger.debug(f"[DEBUG] adapter_config.host: {kwargs['adapter_config'].host}")
|
|
93
|
+
|
|
94
|
+
logger.info(f"API adapter initialized - host: {self.config.host}, " f"port: {self.config.port}")
|
|
95
|
+
|
|
96
|
+
def _load_config(self, kwargs: dict[str, Any]) -> APIAdapterConfig:
|
|
97
|
+
"""Load and merge configuration from various sources.
|
|
98
|
+
|
|
99
|
+
Priority (highest to lowest):
|
|
100
|
+
1. adapter_config parameter (APIAdapterConfig object or dict)
|
|
101
|
+
2. Flat kwargs (host, port)
|
|
102
|
+
3. Environment variables
|
|
103
|
+
"""
|
|
104
|
+
config = APIAdapterConfig()
|
|
105
|
+
config.load_env_vars()
|
|
106
|
+
|
|
107
|
+
logger.info(f"[API_ADAPTER_INIT] kwargs keys: {list(kwargs.keys())}")
|
|
108
|
+
logger.info(f"[API_ADAPTER_INIT] adapter_config in kwargs: {'adapter_config' in kwargs}")
|
|
109
|
+
|
|
110
|
+
adapter_config = kwargs.get("adapter_config")
|
|
111
|
+
if adapter_config is not None:
|
|
112
|
+
logger.info(f"[API_ADAPTER_INIT] adapter_config value: {adapter_config}, type: {type(adapter_config)}")
|
|
113
|
+
config = self._apply_adapter_config(config, adapter_config)
|
|
114
|
+
elif "host" in kwargs or "port" in kwargs:
|
|
115
|
+
config = self._apply_flat_kwargs(config, kwargs)
|
|
116
|
+
else:
|
|
117
|
+
logger.info(f"[API_ADAPTER_INIT] No config provided, using env defaults, port={config.port}")
|
|
118
|
+
|
|
119
|
+
return config
|
|
120
|
+
|
|
121
|
+
def _apply_adapter_config(self, config: APIAdapterConfig, adapter_config: Any) -> APIAdapterConfig:
|
|
122
|
+
"""Apply adapter_config parameter to configuration."""
|
|
123
|
+
if isinstance(adapter_config, APIAdapterConfig):
|
|
124
|
+
logger.info(f"[API_ADAPTER_INIT] Using APIAdapterConfig object, port={adapter_config.port}")
|
|
125
|
+
return adapter_config
|
|
126
|
+
elif isinstance(adapter_config, dict):
|
|
127
|
+
new_config = APIAdapterConfig(**adapter_config)
|
|
128
|
+
logger.info(f"[API_ADAPTER_INIT] Created APIAdapterConfig from dict, port={new_config.port}")
|
|
129
|
+
return new_config
|
|
130
|
+
# If adapter_config is provided but not dict/APIAdapterConfig, keep env-loaded config
|
|
131
|
+
return config
|
|
132
|
+
|
|
133
|
+
def _apply_flat_kwargs(self, config: APIAdapterConfig, kwargs: dict[str, Any]) -> APIAdapterConfig:
|
|
134
|
+
"""Apply flat kwargs (host, port) to configuration."""
|
|
135
|
+
if "host" in kwargs:
|
|
136
|
+
config.host = kwargs["host"]
|
|
137
|
+
if "port" in kwargs:
|
|
138
|
+
config.port = kwargs["port"]
|
|
139
|
+
logger.info(f"[API_ADAPTER_INIT] Applied flat kwargs: host={config.host}, port={config.port}")
|
|
140
|
+
return config
|
|
141
|
+
|
|
142
|
+
def get_services_to_register(self) -> List[AdapterServiceRegistration]:
|
|
143
|
+
"""Get services provided by this adapter."""
|
|
144
|
+
registrations = []
|
|
145
|
+
|
|
146
|
+
# Register communication service with all capabilities
|
|
147
|
+
registrations.append(
|
|
148
|
+
AdapterServiceRegistration(
|
|
149
|
+
service_type=ServiceType.COMMUNICATION,
|
|
150
|
+
provider=self.communication,
|
|
151
|
+
priority=Priority.CRITICAL,
|
|
152
|
+
capabilities=["send_message", "fetch_messages"],
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Register runtime control service
|
|
157
|
+
registrations.append(
|
|
158
|
+
AdapterServiceRegistration(
|
|
159
|
+
service_type=ServiceType.RUNTIME_CONTROL,
|
|
160
|
+
provider=self.runtime_control,
|
|
161
|
+
priority=Priority.CRITICAL,
|
|
162
|
+
capabilities=[
|
|
163
|
+
"pause_processing",
|
|
164
|
+
"resume_processing",
|
|
165
|
+
"request_state_transition",
|
|
166
|
+
"get_runtime_status",
|
|
167
|
+
],
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Register tool service
|
|
172
|
+
registrations.append(
|
|
173
|
+
AdapterServiceRegistration(
|
|
174
|
+
service_type=ServiceType.TOOL,
|
|
175
|
+
provider=self.tool_service,
|
|
176
|
+
priority=Priority.CRITICAL,
|
|
177
|
+
capabilities=[
|
|
178
|
+
"execute_tool",
|
|
179
|
+
"get_available_tools",
|
|
180
|
+
"get_tool_result",
|
|
181
|
+
"validate_parameters",
|
|
182
|
+
"get_tool_info",
|
|
183
|
+
"get_all_tool_info",
|
|
184
|
+
],
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return registrations
|
|
189
|
+
|
|
190
|
+
def _inject_services(self) -> None:
|
|
191
|
+
"""Inject services into FastAPI app state after initialization."""
|
|
192
|
+
logger.info("Injecting services into FastAPI app state...")
|
|
193
|
+
|
|
194
|
+
# Store adapter config for routes to access
|
|
195
|
+
self.app.state.api_config = self.config
|
|
196
|
+
self.app.state.agent_template = getattr(self.runtime, "agent_template", None)
|
|
197
|
+
self.app.state.db_path = getattr(self.runtime.essential_config, "database_path", None)
|
|
198
|
+
logger.info(f"Injected API config with interaction_timeout={self.config.interaction_timeout}s")
|
|
199
|
+
|
|
200
|
+
# Get service mappings from declarative configuration
|
|
201
|
+
service_mappings = ApiServiceConfiguration.get_current_mappings_as_tuples()
|
|
202
|
+
|
|
203
|
+
# Inject services using mapping
|
|
204
|
+
for runtime_attr, app_attrs, handler_name in service_mappings:
|
|
205
|
+
# Convert handler name to actual method if provided
|
|
206
|
+
handler = getattr(self, handler_name) if handler_name else None
|
|
207
|
+
self._inject_service(runtime_attr, app_attrs, handler)
|
|
208
|
+
|
|
209
|
+
# Inject adapter-created services using configuration
|
|
210
|
+
for adapter_service in ApiServiceConfiguration.ADAPTER_CREATED_SERVICES:
|
|
211
|
+
service = getattr(self, adapter_service.attr_name)
|
|
212
|
+
setattr(self.app.state, adapter_service.app_state_name, service)
|
|
213
|
+
logger.info(f"Injected {adapter_service.app_state_name} ({adapter_service.description})")
|
|
214
|
+
|
|
215
|
+
# Set up message handling
|
|
216
|
+
self._setup_message_handling()
|
|
217
|
+
|
|
218
|
+
def reinject_services(self) -> None:
|
|
219
|
+
"""Re-inject services after they become available (e.g., after first-run setup).
|
|
220
|
+
|
|
221
|
+
This is called from resume_from_first_run() to update the FastAPI app state
|
|
222
|
+
with services that were None during initial adapter startup in first-run mode.
|
|
223
|
+
"""
|
|
224
|
+
logger.info("Re-injecting services into FastAPI app state after first-run setup...")
|
|
225
|
+
|
|
226
|
+
# Get service mappings from declarative configuration
|
|
227
|
+
service_mappings = ApiServiceConfiguration.get_current_mappings_as_tuples()
|
|
228
|
+
|
|
229
|
+
# Count how many services we successfully inject
|
|
230
|
+
injected_count = 0
|
|
231
|
+
skipped_count = 0
|
|
232
|
+
|
|
233
|
+
# Re-inject services using mapping
|
|
234
|
+
for runtime_attr, app_attrs, handler_name in service_mappings:
|
|
235
|
+
runtime = self.runtime
|
|
236
|
+
if hasattr(runtime, runtime_attr) and getattr(runtime, runtime_attr) is not None:
|
|
237
|
+
service = getattr(runtime, runtime_attr)
|
|
238
|
+
setattr(self.app.state, app_attrs, service)
|
|
239
|
+
|
|
240
|
+
# Call special handler if provided
|
|
241
|
+
if handler_name:
|
|
242
|
+
handler = getattr(self, handler_name)
|
|
243
|
+
handler(service)
|
|
244
|
+
|
|
245
|
+
injected_count += 1
|
|
246
|
+
logger.debug(f"Re-injected {runtime_attr}")
|
|
247
|
+
else:
|
|
248
|
+
skipped_count += 1
|
|
249
|
+
|
|
250
|
+
logger.info(f"Re-injection complete: {injected_count} services injected, {skipped_count} still unavailable")
|
|
251
|
+
|
|
252
|
+
# Now that services are available, inject adapter_manager into APIRuntimeControlService
|
|
253
|
+
# This was skipped during first-run startup because RuntimeControlService didn't exist
|
|
254
|
+
try:
|
|
255
|
+
self._inject_adapter_manager_to_api_runtime_control()
|
|
256
|
+
except RuntimeError as e:
|
|
257
|
+
logger.warning(f"Could not inject adapter_manager during re-injection: {e}")
|
|
258
|
+
|
|
259
|
+
def _log_service_registry(self, service: Any) -> None:
|
|
260
|
+
"""Log service registry details."""
|
|
261
|
+
try:
|
|
262
|
+
all_services = service.get_all_services()
|
|
263
|
+
service_count = len(all_services) if hasattr(all_services, "__len__") else 0
|
|
264
|
+
logger.info(f"[API] Injected service_registry {id(service)} with {service_count} services")
|
|
265
|
+
service_names = [s.__class__.__name__ for s in all_services] if all_services else []
|
|
266
|
+
logger.info(f"[API] Services in injected registry: {service_names}")
|
|
267
|
+
except (TypeError, AttributeError):
|
|
268
|
+
logger.info("[API] Injected service_registry (mock or test mode)")
|
|
269
|
+
|
|
270
|
+
def _inject_service(
|
|
271
|
+
self, runtime_attr: str, app_state_name: str, handler: Callable[[Any], None] | None = None
|
|
272
|
+
) -> None:
|
|
273
|
+
"""Inject a single service from runtime to app state."""
|
|
274
|
+
runtime = self.runtime
|
|
275
|
+
if hasattr(runtime, runtime_attr) and getattr(runtime, runtime_attr) is not None:
|
|
276
|
+
service = getattr(runtime, runtime_attr)
|
|
277
|
+
setattr(self.app.state, app_state_name, service)
|
|
278
|
+
|
|
279
|
+
# Call special handler if provided
|
|
280
|
+
if handler:
|
|
281
|
+
handler(service)
|
|
282
|
+
|
|
283
|
+
# Special logging for service_registry
|
|
284
|
+
if runtime_attr == "service_registry":
|
|
285
|
+
self._log_service_registry(service)
|
|
286
|
+
else:
|
|
287
|
+
logger.info(f"Injected {runtime_attr}")
|
|
288
|
+
else:
|
|
289
|
+
# Log when service is not injected
|
|
290
|
+
if not hasattr(runtime, runtime_attr):
|
|
291
|
+
logger.warning(f"Runtime does not have attribute '{runtime_attr}' - skipping injection")
|
|
292
|
+
else:
|
|
293
|
+
logger.warning(f"Runtime attribute '{runtime_attr}' is None - skipping injection")
|
|
294
|
+
|
|
295
|
+
def _inject_adapter_manager_to_api_runtime_control(self) -> None:
|
|
296
|
+
"""Inject main RuntimeControlService's adapter_manager into APIRuntimeControlService.
|
|
297
|
+
|
|
298
|
+
This ensures a single source of truth for loaded adapters. Without this,
|
|
299
|
+
adapters loaded via one service won't be visible in the other.
|
|
300
|
+
|
|
301
|
+
CRITICAL: This must be called after _inject_services() so main_runtime_control_service
|
|
302
|
+
is available in app.state.
|
|
303
|
+
|
|
304
|
+
In first-run mode, RuntimeControlService is not yet initialized (services start after
|
|
305
|
+
the setup wizard completes), so we skip this injection. It will be called again
|
|
306
|
+
during reinject_services() after resume_from_first_run().
|
|
307
|
+
"""
|
|
308
|
+
from ciris_engine.logic.setup.first_run import is_first_run
|
|
309
|
+
|
|
310
|
+
# In first-run mode, RuntimeControlService doesn't exist yet - skip injection
|
|
311
|
+
# It will be injected after resume_from_first_run() completes
|
|
312
|
+
if is_first_run():
|
|
313
|
+
logger.info("First-run mode: Skipping adapter_manager injection (will inject after setup)")
|
|
314
|
+
return
|
|
315
|
+
|
|
316
|
+
main_runtime_control = getattr(self.app.state, "main_runtime_control_service", None)
|
|
317
|
+
if not main_runtime_control:
|
|
318
|
+
raise RuntimeError(
|
|
319
|
+
"CRITICAL: main_runtime_control_service not available in app.state. "
|
|
320
|
+
"This indicates a startup sequencing issue. Cannot inject adapter_manager."
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
# Trigger lazy initialization of adapter_manager if needed
|
|
324
|
+
# The main RuntimeControlService has _ensure_adapter_manager_initialized() for this
|
|
325
|
+
if hasattr(main_runtime_control, "_ensure_adapter_manager_initialized"):
|
|
326
|
+
main_runtime_control._ensure_adapter_manager_initialized()
|
|
327
|
+
|
|
328
|
+
adapter_manager = getattr(main_runtime_control, "adapter_manager", None)
|
|
329
|
+
if not adapter_manager:
|
|
330
|
+
raise RuntimeError(
|
|
331
|
+
"CRITICAL: main_runtime_control_service has no adapter_manager even after "
|
|
332
|
+
"_ensure_adapter_manager_initialized(). This indicates the main RuntimeControlService "
|
|
333
|
+
"has no runtime reference. Check service initialization order."
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
# Inject into APIRuntimeControlService
|
|
337
|
+
self.runtime_control.adapter_manager = adapter_manager
|
|
338
|
+
logger.info(
|
|
339
|
+
f"Injected main RuntimeControlService's adapter_manager (id: {id(adapter_manager)}) "
|
|
340
|
+
f"into APIRuntimeControlService - single source of truth established"
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
def _handle_auth_service(self, auth_service: Any) -> None:
|
|
344
|
+
"""Special handler for authentication service."""
|
|
345
|
+
# CRITICAL: Preserve existing APIAuthService if it already exists (has stored API keys)
|
|
346
|
+
# During re-injection after first-run setup, we must NOT create a new instance
|
|
347
|
+
# because the existing instance has in-memory API keys that would be lost!
|
|
348
|
+
existing_auth_service = getattr(self.app.state, "auth_service", None)
|
|
349
|
+
if existing_auth_service is not None and isinstance(existing_auth_service, APIAuthService):
|
|
350
|
+
# Update the existing instance's auth_service reference but preserve API keys
|
|
351
|
+
existing_auth_service._auth_service = auth_service
|
|
352
|
+
logger.info(
|
|
353
|
+
f"[AUTH SERVICE DEBUG] Preserved existing APIAuthService (instance #{existing_auth_service._instance_id}) with {len(existing_auth_service._api_keys)} API keys - updated _auth_service reference"
|
|
354
|
+
)
|
|
355
|
+
else:
|
|
356
|
+
# First time initialization - create new instance
|
|
357
|
+
self.app.state.auth_service = APIAuthService(auth_service)
|
|
358
|
+
logger.info("Initialized APIAuthService with authentication service for persistence")
|
|
359
|
+
|
|
360
|
+
def _handle_bus_manager(self, bus_manager: Any) -> None:
|
|
361
|
+
"""Special handler for bus manager - inject individual buses into app.state."""
|
|
362
|
+
# Inject tool_bus and memory_bus for DSAR multi-source operations
|
|
363
|
+
self.app.state.tool_bus = bus_manager.tool
|
|
364
|
+
self.app.state.memory_bus = bus_manager.memory
|
|
365
|
+
logger.info("Injected tool_bus and memory_bus from bus_manager for multi-source DSAR operations")
|
|
366
|
+
|
|
367
|
+
def _setup_message_handling(self) -> None:
|
|
368
|
+
"""Set up message handling and correlation tracking."""
|
|
369
|
+
# Store message ID to channel mapping for response routing
|
|
370
|
+
self.app.state.message_channel_map = {}
|
|
371
|
+
|
|
372
|
+
# Create and assign message handler
|
|
373
|
+
self.app.state.on_message = self._create_message_handler()
|
|
374
|
+
logger.info("Set up message handler via observer pattern with correlation tracking")
|
|
375
|
+
|
|
376
|
+
def _create_message_handler(self) -> Callable[[IncomingMessage], Awaitable[MessageHandlingResult]]:
|
|
377
|
+
"""Create the message handler function."""
|
|
378
|
+
|
|
379
|
+
async def handle_message_via_observer(msg: IncomingMessage) -> MessageHandlingResult:
|
|
380
|
+
"""Handle incoming messages by creating passive observations."""
|
|
381
|
+
try:
|
|
382
|
+
logger.info(f"handle_message_via_observer called for message {msg.message_id}")
|
|
383
|
+
if self.message_observer:
|
|
384
|
+
# Store the message ID to channel mapping
|
|
385
|
+
self.app.state.message_channel_map[msg.channel_id] = msg.message_id
|
|
386
|
+
|
|
387
|
+
# Create correlation
|
|
388
|
+
await self._create_message_correlation(msg)
|
|
389
|
+
|
|
390
|
+
# Pass to observer for task creation and get result
|
|
391
|
+
result = await self.message_observer.handle_incoming_message(msg)
|
|
392
|
+
if result:
|
|
393
|
+
logger.info(f"Message {msg.message_id} passed to observer, result: {result.status}")
|
|
394
|
+
return result
|
|
395
|
+
else:
|
|
396
|
+
logger.warning(f"Message {msg.message_id} passed to observer but no result returned")
|
|
397
|
+
# Return a default result for backward compatibility with tests
|
|
398
|
+
from ciris_engine.schemas.runtime.messages import MessageHandlingResult, MessageHandlingStatus
|
|
399
|
+
|
|
400
|
+
return MessageHandlingResult(
|
|
401
|
+
status=MessageHandlingStatus.TASK_CREATED,
|
|
402
|
+
message_id=msg.message_id,
|
|
403
|
+
channel_id=msg.channel_id or "unknown",
|
|
404
|
+
)
|
|
405
|
+
else:
|
|
406
|
+
logger.error("Message observer not available")
|
|
407
|
+
raise RuntimeError("Message observer not available")
|
|
408
|
+
except Exception as e:
|
|
409
|
+
logger.error(f"Error in handle_message_via_observer: {e}", exc_info=True)
|
|
410
|
+
raise
|
|
411
|
+
|
|
412
|
+
return handle_message_via_observer
|
|
413
|
+
|
|
414
|
+
async def _create_message_correlation(self, msg: Any) -> None:
|
|
415
|
+
"""Create an observe correlation for incoming message."""
|
|
416
|
+
correlation_id = str(uuid.uuid4())
|
|
417
|
+
now = datetime.now(timezone.utc)
|
|
418
|
+
|
|
419
|
+
# Create correlation for the incoming message
|
|
420
|
+
correlation = ServiceCorrelation(
|
|
421
|
+
correlation_id=correlation_id,
|
|
422
|
+
service_type="api",
|
|
423
|
+
handler_name="APIAdapter",
|
|
424
|
+
action_type="observe",
|
|
425
|
+
request_data=ServiceRequestData(
|
|
426
|
+
service_type="api",
|
|
427
|
+
method_name="observe",
|
|
428
|
+
channel_id=msg.channel_id,
|
|
429
|
+
parameters={
|
|
430
|
+
"content": msg.content,
|
|
431
|
+
"author_id": msg.author_id,
|
|
432
|
+
"author_name": msg.author_name,
|
|
433
|
+
"message_id": msg.message_id,
|
|
434
|
+
},
|
|
435
|
+
request_timestamp=now,
|
|
436
|
+
),
|
|
437
|
+
response_data=ServiceResponseData(
|
|
438
|
+
success=True, result_summary="Message observed", execution_time_ms=0, response_timestamp=now
|
|
439
|
+
),
|
|
440
|
+
status=ServiceCorrelationStatus.COMPLETED,
|
|
441
|
+
created_at=now,
|
|
442
|
+
updated_at=now,
|
|
443
|
+
timestamp=now,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Get time service if available
|
|
447
|
+
time_service = getattr(self.runtime, "time_service", None)
|
|
448
|
+
persistence.add_correlation(correlation, time_service)
|
|
449
|
+
logger.debug(f"Created observe correlation for message {msg.message_id}")
|
|
450
|
+
|
|
451
|
+
def _discover_and_register_configurable_adapters(self) -> None:
|
|
452
|
+
"""Discover and register adapters that support interactive configuration.
|
|
453
|
+
|
|
454
|
+
Scans the ciris_adapters directory for adapter manifests that define
|
|
455
|
+
interactive_config sections and registers them with the AdapterConfigurationService.
|
|
456
|
+
"""
|
|
457
|
+
from pathlib import Path
|
|
458
|
+
|
|
459
|
+
# Find ciris_adapters directory - try multiple methods for Android compatibility
|
|
460
|
+
adapters_dir = Path(__file__).resolve().parent.parent.parent.parent.parent / "ciris_adapters"
|
|
461
|
+
|
|
462
|
+
if not adapters_dir.exists():
|
|
463
|
+
# Fallback for Android: use importlib.resources to discover adapters dynamically
|
|
464
|
+
logger.info(f"Filesystem adapters directory not found ({adapters_dir}), using importlib discovery")
|
|
465
|
+
self._discover_adapters_via_importlib()
|
|
466
|
+
return
|
|
467
|
+
|
|
468
|
+
registered_count = 0
|
|
469
|
+
for adapter_path in adapters_dir.iterdir():
|
|
470
|
+
if self._process_adapter_path(adapter_path):
|
|
471
|
+
registered_count += 1
|
|
472
|
+
|
|
473
|
+
logger.info(f"Discovered and registered {registered_count} configurable adapter(s)")
|
|
474
|
+
|
|
475
|
+
def _process_adapter_path(self, adapter_path: Any) -> bool:
|
|
476
|
+
"""Process a single adapter directory and register if configurable.
|
|
477
|
+
|
|
478
|
+
Returns True if adapter was successfully registered.
|
|
479
|
+
"""
|
|
480
|
+
import json
|
|
481
|
+
|
|
482
|
+
if not adapter_path.is_dir():
|
|
483
|
+
return False
|
|
484
|
+
|
|
485
|
+
manifest_path = adapter_path / MANIFEST_FILENAME
|
|
486
|
+
if not manifest_path.exists():
|
|
487
|
+
return False
|
|
488
|
+
|
|
489
|
+
try:
|
|
490
|
+
with open(manifest_path) as f:
|
|
491
|
+
manifest_data = json.load(f)
|
|
492
|
+
return self._register_adapter_from_manifest(manifest_data, adapter_path.name)
|
|
493
|
+
except Exception as e:
|
|
494
|
+
logger.warning(f"Failed to process manifest for {adapter_path.name}: {e}")
|
|
495
|
+
return False
|
|
496
|
+
|
|
497
|
+
def _register_adapter_from_manifest(self, manifest_data: dict[str, Any], adapter_type: str) -> bool:
|
|
498
|
+
"""Register an adapter from its manifest data.
|
|
499
|
+
|
|
500
|
+
Returns True if adapter was successfully registered.
|
|
501
|
+
"""
|
|
502
|
+
interactive_config_data = manifest_data.get("interactive_config")
|
|
503
|
+
if not interactive_config_data:
|
|
504
|
+
return False
|
|
505
|
+
|
|
506
|
+
interactive_config = self._parse_interactive_config(interactive_config_data)
|
|
507
|
+
exports = manifest_data.get("exports", {})
|
|
508
|
+
configurable_class_path = exports.get("configurable")
|
|
509
|
+
|
|
510
|
+
if not configurable_class_path:
|
|
511
|
+
logger.debug(f"Adapter {adapter_type} has interactive_config but no configurable export")
|
|
512
|
+
return False
|
|
513
|
+
|
|
514
|
+
return self._load_and_register_configurable(adapter_type, interactive_config, configurable_class_path)
|
|
515
|
+
|
|
516
|
+
def _parse_interactive_config(self, config_data: dict[str, Any]) -> Any:
|
|
517
|
+
"""Parse interactive configuration data into InteractiveConfiguration object."""
|
|
518
|
+
from ciris_engine.schemas.runtime.manifest import ConfigurationStep, InteractiveConfiguration
|
|
519
|
+
|
|
520
|
+
steps = [ConfigurationStep.model_validate(step_data) for step_data in config_data.get("steps", [])]
|
|
521
|
+
|
|
522
|
+
return InteractiveConfiguration(
|
|
523
|
+
required=config_data.get("required", False),
|
|
524
|
+
workflow_type=config_data.get("workflow_type", "wizard"),
|
|
525
|
+
steps=steps,
|
|
526
|
+
completion_method=config_data.get("completion_method", "apply_config"),
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
def _load_and_register_configurable(
|
|
530
|
+
self, adapter_type: str, interactive_config: Any, configurable_class_path: str
|
|
531
|
+
) -> bool:
|
|
532
|
+
"""Load configurable class and register with configuration service.
|
|
533
|
+
|
|
534
|
+
Returns True if successful.
|
|
535
|
+
"""
|
|
536
|
+
import importlib
|
|
537
|
+
|
|
538
|
+
try:
|
|
539
|
+
module_path, class_name = configurable_class_path.rsplit(".", 1)
|
|
540
|
+
if not module_path.startswith("ciris_adapters"):
|
|
541
|
+
module_path = f"ciris_adapters.{module_path}"
|
|
542
|
+
module = importlib.import_module(module_path)
|
|
543
|
+
configurable_class = getattr(module, class_name)
|
|
544
|
+
adapter_instance = configurable_class()
|
|
545
|
+
|
|
546
|
+
self.adapter_configuration_service.register_adapter_config(
|
|
547
|
+
adapter_type=adapter_type,
|
|
548
|
+
interactive_config=interactive_config,
|
|
549
|
+
adapter_instance=adapter_instance,
|
|
550
|
+
)
|
|
551
|
+
logger.info(f"Registered configurable adapter: {adapter_type}")
|
|
552
|
+
return True
|
|
553
|
+
except Exception as e:
|
|
554
|
+
logger.warning(f"Failed to load configurable class for {adapter_type}: {e}")
|
|
555
|
+
return False
|
|
556
|
+
|
|
557
|
+
def _discover_adapters_via_importlib(self) -> None:
|
|
558
|
+
"""Discover adapters dynamically using importlib (Android/Chaquopy compatible).
|
|
559
|
+
|
|
560
|
+
Uses pkgutil.iter_modules to find all subpackages in ciris_adapters,
|
|
561
|
+
then checks each for a manifest.json with interactive_config.
|
|
562
|
+
"""
|
|
563
|
+
adapter_names = self._get_adapter_package_names()
|
|
564
|
+
if not adapter_names:
|
|
565
|
+
return
|
|
566
|
+
|
|
567
|
+
registered_count = 0
|
|
568
|
+
for adapter_name in adapter_names:
|
|
569
|
+
if self._process_adapter_via_importlib(adapter_name):
|
|
570
|
+
registered_count += 1
|
|
571
|
+
|
|
572
|
+
logger.info(f"Discovered and registered {registered_count} configurable adapter(s) via importlib")
|
|
573
|
+
|
|
574
|
+
def _get_adapter_package_names(self) -> list[str]:
|
|
575
|
+
"""Get list of adapter package names via pkgutil."""
|
|
576
|
+
import pkgutil
|
|
577
|
+
|
|
578
|
+
try:
|
|
579
|
+
import ciris_adapters
|
|
580
|
+
|
|
581
|
+
adapter_names = [
|
|
582
|
+
name
|
|
583
|
+
for importer, name, ispkg in pkgutil.iter_modules(ciris_adapters.__path__)
|
|
584
|
+
if ispkg and not name.startswith("_")
|
|
585
|
+
]
|
|
586
|
+
logger.info(f"Discovered {len(adapter_names)} adapter packages via pkgutil: {adapter_names}")
|
|
587
|
+
return adapter_names
|
|
588
|
+
except ImportError:
|
|
589
|
+
logger.warning("ciris_adapters package not found, no adapters to discover")
|
|
590
|
+
return []
|
|
591
|
+
|
|
592
|
+
def _process_adapter_via_importlib(self, adapter_name: str) -> bool:
|
|
593
|
+
"""Process a single adapter package via importlib.
|
|
594
|
+
|
|
595
|
+
Returns True if adapter was successfully registered.
|
|
596
|
+
"""
|
|
597
|
+
import importlib
|
|
598
|
+
|
|
599
|
+
try:
|
|
600
|
+
importlib.import_module(f"ciris_adapters.{adapter_name}")
|
|
601
|
+
except ImportError:
|
|
602
|
+
logger.debug(f"Adapter package not found: ciris_adapters.{adapter_name}")
|
|
603
|
+
return False
|
|
604
|
+
|
|
605
|
+
manifest_data = self._read_manifest_via_importlib(adapter_name)
|
|
606
|
+
if manifest_data is None:
|
|
607
|
+
return False
|
|
608
|
+
|
|
609
|
+
try:
|
|
610
|
+
return self._register_adapter_from_manifest(manifest_data, adapter_name)
|
|
611
|
+
except Exception as e:
|
|
612
|
+
logger.warning(f"Failed to process adapter {adapter_name}: {e}")
|
|
613
|
+
return False
|
|
614
|
+
|
|
615
|
+
def _read_manifest_via_importlib(self, adapter_name: str) -> dict[str, Any] | None:
|
|
616
|
+
"""Read manifest.json using importlib.resources.
|
|
617
|
+
|
|
618
|
+
Returns manifest data dict or None if not found.
|
|
619
|
+
"""
|
|
620
|
+
import importlib.resources as pkg_resources
|
|
621
|
+
import json
|
|
622
|
+
|
|
623
|
+
package_name = f"ciris_adapters.{adapter_name}"
|
|
624
|
+
try:
|
|
625
|
+
# Try files() API first (Python 3.9+)
|
|
626
|
+
files = pkg_resources.files(package_name)
|
|
627
|
+
manifest_path = files.joinpath(MANIFEST_FILENAME)
|
|
628
|
+
manifest_text = manifest_path.read_text()
|
|
629
|
+
except (TypeError, AttributeError):
|
|
630
|
+
# Fallback for older API
|
|
631
|
+
try:
|
|
632
|
+
with pkg_resources.open_text(package_name, MANIFEST_FILENAME) as f:
|
|
633
|
+
manifest_text = f.read()
|
|
634
|
+
except Exception as e:
|
|
635
|
+
logger.warning(f"Could not read manifest for {adapter_name}: {e}")
|
|
636
|
+
return None
|
|
637
|
+
except Exception as e:
|
|
638
|
+
logger.warning(f"Could not read manifest for {adapter_name}: {e}")
|
|
639
|
+
return None
|
|
640
|
+
|
|
641
|
+
logger.info(f"Successfully read manifest for {adapter_name}")
|
|
642
|
+
result: dict[str, Any] = json.loads(manifest_text)
|
|
643
|
+
return result
|
|
644
|
+
|
|
645
|
+
async def _restore_persisted_adapter_configs(self) -> None:
|
|
646
|
+
"""Restore adapter configurations that were persisted for load-on-startup.
|
|
647
|
+
|
|
648
|
+
This is called during API adapter startup to restore adapters that were
|
|
649
|
+
previously configured and marked for automatic loading.
|
|
650
|
+
"""
|
|
651
|
+
# Get config service from runtime
|
|
652
|
+
config_service = getattr(self.runtime, "config_service", None)
|
|
653
|
+
if not config_service:
|
|
654
|
+
logger.debug("No config_service available - skipping persisted adapter restoration")
|
|
655
|
+
return
|
|
656
|
+
|
|
657
|
+
# Get runtime control service for loading adapters
|
|
658
|
+
runtime_control_service = self.runtime_control
|
|
659
|
+
|
|
660
|
+
try:
|
|
661
|
+
restored_count = await self.adapter_configuration_service.restore_persisted_adapters(
|
|
662
|
+
config_service=config_service,
|
|
663
|
+
runtime_control_service=runtime_control_service,
|
|
664
|
+
)
|
|
665
|
+
if restored_count > 0:
|
|
666
|
+
logger.info(f"Restored {restored_count} persisted adapter configuration(s)")
|
|
667
|
+
except Exception as e:
|
|
668
|
+
logger.warning(f"Failed to restore persisted adapter configurations: {e}")
|
|
669
|
+
|
|
670
|
+
def _is_android_platform(self) -> bool:
|
|
671
|
+
"""Check if running on Android platform."""
|
|
672
|
+
import os
|
|
673
|
+
|
|
674
|
+
return os.environ.get("ANDROID_DATA") is not None or os.path.exists("/data/data")
|
|
675
|
+
|
|
676
|
+
def _has_google_auth(self) -> bool:
|
|
677
|
+
"""Check if Google authentication token is available."""
|
|
678
|
+
import os
|
|
679
|
+
|
|
680
|
+
return bool(os.environ.get("CIRIS_BILLING_GOOGLE_ID_TOKEN"))
|
|
681
|
+
|
|
682
|
+
def _is_hosted_tools_loaded(self) -> bool:
|
|
683
|
+
"""Check if ciris_hosted_tools adapter is already loaded."""
|
|
684
|
+
runtime_control = self.runtime_control
|
|
685
|
+
if not runtime_control or not hasattr(runtime_control, "adapter_manager"):
|
|
686
|
+
return False
|
|
687
|
+
adapter_manager = runtime_control.adapter_manager
|
|
688
|
+
if not adapter_manager or not adapter_manager.loaded_adapters:
|
|
689
|
+
return False
|
|
690
|
+
return any("ciris_hosted_tools" in adapter_id for adapter_id in adapter_manager.loaded_adapters.keys())
|
|
691
|
+
|
|
692
|
+
async def _auto_enable_android_adapters(self) -> None:
|
|
693
|
+
"""Auto-enable Android-specific adapters when conditions are met.
|
|
694
|
+
|
|
695
|
+
This enables ciris_hosted_tools (web_search) when:
|
|
696
|
+
1. Running on Android platform (detected via env var or platform check)
|
|
697
|
+
2. Google authentication is available (CIRIS_BILLING_GOOGLE_ID_TOKEN is set)
|
|
698
|
+
3. The adapter is not already loaded
|
|
699
|
+
|
|
700
|
+
Called at startup and after resume_from_first_run().
|
|
701
|
+
"""
|
|
702
|
+
if not self._is_android_platform():
|
|
703
|
+
logger.debug("[AUTO_ENABLE] Not on Android, skipping auto-enable of ciris_hosted_tools")
|
|
704
|
+
return
|
|
705
|
+
|
|
706
|
+
if not self._has_google_auth():
|
|
707
|
+
logger.debug("[AUTO_ENABLE] No Google auth token found, skipping auto-enable of ciris_hosted_tools")
|
|
708
|
+
return
|
|
709
|
+
|
|
710
|
+
if self._is_hosted_tools_loaded():
|
|
711
|
+
logger.debug("[AUTO_ENABLE] ciris_hosted_tools already loaded, skipping")
|
|
712
|
+
return
|
|
713
|
+
|
|
714
|
+
logger.info("[AUTO_ENABLE] Android platform with Google auth detected - enabling ciris_hosted_tools adapter")
|
|
715
|
+
await self._load_hosted_tools_adapter()
|
|
716
|
+
|
|
717
|
+
async def _load_hosted_tools_adapter(self) -> None:
|
|
718
|
+
"""Load the ciris_hosted_tools adapter."""
|
|
719
|
+
try:
|
|
720
|
+
main_runtime_control = getattr(self.runtime, "runtime_control_service", None) or self.runtime_control
|
|
721
|
+
if not main_runtime_control:
|
|
722
|
+
logger.warning("[AUTO_ENABLE] No runtime control service available for adapter loading")
|
|
723
|
+
return
|
|
724
|
+
|
|
725
|
+
result = await main_runtime_control.load_adapter(
|
|
726
|
+
adapter_type="ciris_hosted_tools",
|
|
727
|
+
adapter_id="ciris_hosted_tools_auto",
|
|
728
|
+
config={},
|
|
729
|
+
)
|
|
730
|
+
|
|
731
|
+
if result.success:
|
|
732
|
+
logger.info(f"[AUTO_ENABLE] Successfully enabled ciris_hosted_tools adapter (id: {result.adapter_id})")
|
|
733
|
+
logger.info("[AUTO_ENABLE] web_search tool is now available")
|
|
734
|
+
else:
|
|
735
|
+
logger.warning(f"[AUTO_ENABLE] Failed to enable ciris_hosted_tools: {result.error}")
|
|
736
|
+
except Exception as e:
|
|
737
|
+
logger.warning(f"[AUTO_ENABLE] Error enabling ciris_hosted_tools: {e}")
|
|
738
|
+
|
|
739
|
+
async def _wait_for_port_available(self, max_retries: int = 10, retry_delay: float = 1.0) -> None:
|
|
740
|
+
"""Wait for port to become available, with retries for TIME_WAIT state.
|
|
741
|
+
|
|
742
|
+
Raises:
|
|
743
|
+
RuntimeError: If port remains in use after all retries.
|
|
744
|
+
"""
|
|
745
|
+
import socket
|
|
746
|
+
|
|
747
|
+
for attempt in range(max_retries):
|
|
748
|
+
if self._check_port_available():
|
|
749
|
+
if attempt > 0:
|
|
750
|
+
logger.info(f"[API_ADAPTER] Port {self.config.port} became available after {attempt} retries")
|
|
751
|
+
return
|
|
752
|
+
|
|
753
|
+
if attempt < max_retries - 1:
|
|
754
|
+
logger.warning(
|
|
755
|
+
f"[API_ADAPTER] Port {self.config.port} in use, waiting {retry_delay}s "
|
|
756
|
+
f"(attempt {attempt + 1}/{max_retries})"
|
|
757
|
+
)
|
|
758
|
+
await asyncio.sleep(retry_delay)
|
|
759
|
+
else:
|
|
760
|
+
error_msg = f"Port {self.config.port} is already in use on {self.config.host}"
|
|
761
|
+
logger.error(f"[API_ADAPTER] {error_msg}")
|
|
762
|
+
self._startup_error = error_msg
|
|
763
|
+
raise RuntimeError(error_msg)
|
|
764
|
+
|
|
765
|
+
def _check_port_available(self) -> bool:
|
|
766
|
+
"""Check if the configured port is available."""
|
|
767
|
+
import socket
|
|
768
|
+
|
|
769
|
+
try:
|
|
770
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
771
|
+
s.settimeout(1)
|
|
772
|
+
host = self.config.host if self.config.host != "0.0.0.0" else "127.0.0.1"
|
|
773
|
+
result = s.connect_ex((host, self.config.port))
|
|
774
|
+
return result != 0 # Non-zero means port is available
|
|
775
|
+
except Exception as e:
|
|
776
|
+
logger.warning(f"Could not check port availability: {e}, will attempt to start anyway")
|
|
777
|
+
return True
|
|
778
|
+
|
|
779
|
+
async def start(self) -> None:
|
|
780
|
+
"""Start the API server."""
|
|
781
|
+
logger.debug(f"[DEBUG] At start() - config.host: {self.config.host}, config.port: {self.config.port}")
|
|
782
|
+
await super().start()
|
|
783
|
+
|
|
784
|
+
# Track start time for metrics
|
|
785
|
+
import time
|
|
786
|
+
|
|
787
|
+
self._start_time = time.time()
|
|
788
|
+
|
|
789
|
+
# Start the communication service
|
|
790
|
+
await self.communication.start()
|
|
791
|
+
logger.info("Started API communication service")
|
|
792
|
+
|
|
793
|
+
# Start the tool service
|
|
794
|
+
await self.tool_service.start()
|
|
795
|
+
logger.info("Started API tool service")
|
|
796
|
+
|
|
797
|
+
# Create message observer for handling incoming messages
|
|
798
|
+
resource_monitor_from_runtime = getattr(self.runtime, "resource_monitor_service", None)
|
|
799
|
+
logger.info(
|
|
800
|
+
f"[OBSERVER_INIT] resource_monitor_service from runtime: {resource_monitor_from_runtime is not None}, type={type(resource_monitor_from_runtime).__name__ if resource_monitor_from_runtime else 'None'}"
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
self.message_observer = APIObserver(
|
|
804
|
+
on_observe=lambda _: asyncio.sleep(0),
|
|
805
|
+
bus_manager=getattr(self.runtime, "bus_manager", None),
|
|
806
|
+
memory_service=getattr(self.runtime, "memory_service", None),
|
|
807
|
+
agent_id=getattr(self.runtime, "agent_id", None),
|
|
808
|
+
filter_service=getattr(self.runtime, "adaptive_filter_service", None),
|
|
809
|
+
secrets_service=getattr(self.runtime, "secrets_service", None),
|
|
810
|
+
time_service=getattr(self.runtime, "time_service", None),
|
|
811
|
+
agent_occurrence_id=getattr(self.runtime.essential_config, "agent_occurrence_id", "default"),
|
|
812
|
+
origin_service="api",
|
|
813
|
+
resource_monitor=resource_monitor_from_runtime,
|
|
814
|
+
)
|
|
815
|
+
await self.message_observer.start()
|
|
816
|
+
logger.info("Started API message observer")
|
|
817
|
+
|
|
818
|
+
# Inject services now that they're initialized
|
|
819
|
+
self._inject_services()
|
|
820
|
+
|
|
821
|
+
# Inject main RuntimeControlService's adapter_manager into APIRuntimeControlService
|
|
822
|
+
# This ensures a single source of truth for loaded adapters
|
|
823
|
+
self._inject_adapter_manager_to_api_runtime_control()
|
|
824
|
+
|
|
825
|
+
# Discover and register configurable adapters
|
|
826
|
+
self._discover_and_register_configurable_adapters()
|
|
827
|
+
|
|
828
|
+
# Restore any persisted adapter configurations from previous sessions
|
|
829
|
+
await self._restore_persisted_adapter_configs()
|
|
830
|
+
|
|
831
|
+
# Auto-enable Android-specific adapters (ciris_hosted_tools with web_search)
|
|
832
|
+
await self._auto_enable_android_adapters()
|
|
833
|
+
|
|
834
|
+
# Start runtime control service now that services are available
|
|
835
|
+
await self.runtime_control.start()
|
|
836
|
+
logger.info("Started API runtime control service")
|
|
837
|
+
|
|
838
|
+
# Wait for port to become available (handles TIME_WAIT from previous shutdown)
|
|
839
|
+
await self._wait_for_port_available()
|
|
840
|
+
|
|
841
|
+
# Configure uvicorn
|
|
842
|
+
config = uvicorn.Config(
|
|
843
|
+
self.app,
|
|
844
|
+
host=self.config.host,
|
|
845
|
+
port=self.config.port,
|
|
846
|
+
log_level="info",
|
|
847
|
+
access_log=True,
|
|
848
|
+
timeout_graceful_shutdown=30, # Force shutdown after 30s to prevent hang
|
|
849
|
+
)
|
|
850
|
+
|
|
851
|
+
# Create and start server with error handling wrapper
|
|
852
|
+
self._server = uvicorn.Server(config)
|
|
853
|
+
assert self._server is not None
|
|
854
|
+
|
|
855
|
+
async def _run_server_safely() -> None:
|
|
856
|
+
"""Run server and catch SystemExit to prevent process crash."""
|
|
857
|
+
try:
|
|
858
|
+
await self._server.serve() # type: ignore[union-attr]
|
|
859
|
+
except SystemExit as e:
|
|
860
|
+
# uvicorn calls sys.exit(1) on startup failures - catch it!
|
|
861
|
+
logger.error(f"[API_ADAPTER] Server startup failed with SystemExit: {e}")
|
|
862
|
+
self._startup_error = f"Server startup failed: {e}"
|
|
863
|
+
raise RuntimeError(self._startup_error) from e
|
|
864
|
+
except Exception as e:
|
|
865
|
+
logger.error(f"[API_ADAPTER] Server error: {e}", exc_info=True)
|
|
866
|
+
self._startup_error = str(e)
|
|
867
|
+
raise RuntimeError(self._startup_error) from e
|
|
868
|
+
|
|
869
|
+
self._server_task = asyncio.create_task(_run_server_safely())
|
|
870
|
+
|
|
871
|
+
logger.info(f"API server starting on http://{self.config.host}:{self.config.port}")
|
|
872
|
+
|
|
873
|
+
# Wait a moment for server to start and check for immediate failures
|
|
874
|
+
await asyncio.sleep(1)
|
|
875
|
+
|
|
876
|
+
# Check if server task failed immediately
|
|
877
|
+
if self._server_task.done():
|
|
878
|
+
error = getattr(self, "_startup_error", None)
|
|
879
|
+
if error:
|
|
880
|
+
raise RuntimeError(f"API server failed to start: {error}")
|
|
881
|
+
|
|
882
|
+
async def stop(self) -> None:
|
|
883
|
+
"""Stop the API server."""
|
|
884
|
+
logger.info("Stopping API server...")
|
|
885
|
+
|
|
886
|
+
# Stop runtime control service
|
|
887
|
+
await self.runtime_control.stop()
|
|
888
|
+
|
|
889
|
+
# Stop communication service
|
|
890
|
+
await self.communication.stop()
|
|
891
|
+
|
|
892
|
+
# Stop tool service
|
|
893
|
+
await self.tool_service.stop()
|
|
894
|
+
|
|
895
|
+
# Stop server
|
|
896
|
+
if self._server:
|
|
897
|
+
self._server.should_exit = True
|
|
898
|
+
if self._server_task:
|
|
899
|
+
await self._server_task
|
|
900
|
+
|
|
901
|
+
await super().stop()
|
|
902
|
+
|
|
903
|
+
def get_channel_list(self) -> List[ChannelContext]:
|
|
904
|
+
"""
|
|
905
|
+
Get list of available API channels from correlations.
|
|
906
|
+
|
|
907
|
+
Returns:
|
|
908
|
+
List of ChannelContext objects for API channels.
|
|
909
|
+
"""
|
|
910
|
+
from datetime import datetime
|
|
911
|
+
|
|
912
|
+
# Get active channels from last 30 days
|
|
913
|
+
channels_data = get_active_channels_by_adapter("api", since_days=30)
|
|
914
|
+
|
|
915
|
+
# Convert to ChannelContext objects
|
|
916
|
+
channels = []
|
|
917
|
+
for data in channels_data:
|
|
918
|
+
# Determine allowed actions based on admin status
|
|
919
|
+
is_admin = is_admin_channel(data.channel_id)
|
|
920
|
+
allowed_actions = ["speak", "observe", "memorize", "recall", "tool"]
|
|
921
|
+
if is_admin:
|
|
922
|
+
allowed_actions.extend(["wa_defer", "runtime_control"])
|
|
923
|
+
|
|
924
|
+
channel = ChannelContext(
|
|
925
|
+
channel_id=data.channel_id,
|
|
926
|
+
channel_type="api",
|
|
927
|
+
created_at=data.last_activity if data.last_activity else datetime.now(timezone.utc),
|
|
928
|
+
channel_name=data.channel_name or data.channel_id, # API channels use ID as name if no name
|
|
929
|
+
is_private=False, # API channels are not private
|
|
930
|
+
participants=[], # Could track user IDs if needed
|
|
931
|
+
is_active=data.is_active,
|
|
932
|
+
last_activity=data.last_activity,
|
|
933
|
+
message_count=data.message_count,
|
|
934
|
+
allowed_actions=allowed_actions,
|
|
935
|
+
moderation_level="standard",
|
|
936
|
+
)
|
|
937
|
+
channels.append(channel)
|
|
938
|
+
|
|
939
|
+
return channels
|
|
940
|
+
|
|
941
|
+
def is_healthy(self) -> bool:
|
|
942
|
+
"""Check if the API server is healthy and running."""
|
|
943
|
+
if self._server is None or self._server_task is None:
|
|
944
|
+
return False
|
|
945
|
+
|
|
946
|
+
# Check if the server task is still running
|
|
947
|
+
return not self._server_task.done()
|
|
948
|
+
|
|
949
|
+
def get_metrics(self) -> dict[str, float]:
|
|
950
|
+
"""Get all metrics including base, custom, and v1.4.3 specific."""
|
|
951
|
+
# Initialize base metrics
|
|
952
|
+
import time
|
|
953
|
+
|
|
954
|
+
uptime = time.time() - self._start_time if hasattr(self, "_start_time") else 0.0
|
|
955
|
+
metrics = {
|
|
956
|
+
"uptime_seconds": uptime,
|
|
957
|
+
"healthy": self.is_healthy(),
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
# Add v1.4.3 specific metrics
|
|
961
|
+
try:
|
|
962
|
+
# Get metrics from communication service
|
|
963
|
+
comm_status = self.communication.get_status()
|
|
964
|
+
comm_metrics = comm_status.metrics if hasattr(comm_status, "metrics") else {}
|
|
965
|
+
|
|
966
|
+
# Get active WebSocket connections count
|
|
967
|
+
active_connections = 0
|
|
968
|
+
if hasattr(self.communication, "_websocket_clients"):
|
|
969
|
+
try:
|
|
970
|
+
active_connections = len(self.communication._websocket_clients)
|
|
971
|
+
except (TypeError, AttributeError):
|
|
972
|
+
active_connections = 0
|
|
973
|
+
|
|
974
|
+
# Extract values with defaults
|
|
975
|
+
requests_total = float(comm_metrics.get("requests_handled", 0))
|
|
976
|
+
errors_total = float(comm_metrics.get("error_count", 0))
|
|
977
|
+
avg_response_time = float(comm_metrics.get("avg_response_time_ms", 0.0))
|
|
978
|
+
|
|
979
|
+
metrics.update(
|
|
980
|
+
{
|
|
981
|
+
"api_requests_total": requests_total,
|
|
982
|
+
"api_errors_total": errors_total,
|
|
983
|
+
"api_response_time_ms": avg_response_time,
|
|
984
|
+
"api_active_connections": float(active_connections),
|
|
985
|
+
}
|
|
986
|
+
)
|
|
987
|
+
|
|
988
|
+
except Exception as e:
|
|
989
|
+
logger.warning(f"Failed to get API adapter metrics: {e}")
|
|
990
|
+
# Return zeros on error rather than failing
|
|
991
|
+
metrics.update(
|
|
992
|
+
{
|
|
993
|
+
"api_requests_total": 0.0,
|
|
994
|
+
"api_errors_total": 0.0,
|
|
995
|
+
"api_response_time_ms": 0.0,
|
|
996
|
+
"api_active_connections": 0.0,
|
|
997
|
+
}
|
|
998
|
+
)
|
|
999
|
+
|
|
1000
|
+
return metrics
|
|
1001
|
+
|
|
1002
|
+
async def run_lifecycle(self, agent_run_task: Optional[asyncio.Task[Any]]) -> None:
|
|
1003
|
+
"""Run the adapter lifecycle - API runs until agent stops."""
|
|
1004
|
+
logger.info("API adapter running lifecycle")
|
|
1005
|
+
|
|
1006
|
+
try:
|
|
1007
|
+
# In first-run mode, agent_run_task is None - just keep server running
|
|
1008
|
+
if agent_run_task is None:
|
|
1009
|
+
logger.info("First-run mode: API server will run until manually stopped")
|
|
1010
|
+
# Just wait for server task to complete (or CTRL+C)
|
|
1011
|
+
if self._server_task:
|
|
1012
|
+
await self._server_task
|
|
1013
|
+
return
|
|
1014
|
+
|
|
1015
|
+
# Normal mode: Wait for either the agent task or server task to complete
|
|
1016
|
+
while not agent_run_task.done():
|
|
1017
|
+
# Check if server is still running
|
|
1018
|
+
if not self._server_task or self._server_task.done():
|
|
1019
|
+
# Server stopped unexpectedly
|
|
1020
|
+
if self._server_task:
|
|
1021
|
+
exc = self._server_task.exception()
|
|
1022
|
+
if exc:
|
|
1023
|
+
logger.error(f"API server stopped with error: {exc}")
|
|
1024
|
+
raise exc
|
|
1025
|
+
logger.warning("API server stopped unexpectedly")
|
|
1026
|
+
break
|
|
1027
|
+
|
|
1028
|
+
await asyncio.sleep(0.1)
|
|
1029
|
+
|
|
1030
|
+
except asyncio.CancelledError:
|
|
1031
|
+
logger.info("API adapter lifecycle cancelled")
|
|
1032
|
+
raise
|
|
1033
|
+
except Exception as e:
|
|
1034
|
+
logger.error(f"API adapter lifecycle error: {e}")
|
|
1035
|
+
raise
|
|
1036
|
+
finally:
|
|
1037
|
+
logger.info("API adapter lifecycle ending")
|