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,667 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Home Assistant ConfigurableAdapterProtocol implementation.
|
|
3
|
+
|
|
4
|
+
Provides interactive configuration workflow for Home Assistant integration:
|
|
5
|
+
1. Discovery - Find HA instances via mDNS/Zeroconf
|
|
6
|
+
2. OAuth - Authenticate via Home Assistant's IndieAuth-style OAuth2
|
|
7
|
+
3. Select - Choose which features to enable
|
|
8
|
+
4. Confirm - Review and apply configuration
|
|
9
|
+
|
|
10
|
+
Home Assistant OAuth2 (per https://developers.home-assistant.io/docs/auth_api/):
|
|
11
|
+
- Authorization endpoint: /auth/authorize
|
|
12
|
+
- Token endpoint: /auth/token
|
|
13
|
+
- Client ID: IndieAuth-style (your application's website URL)
|
|
14
|
+
- No pre-registration required
|
|
15
|
+
- Access tokens valid 1800 seconds, refresh tokens available
|
|
16
|
+
|
|
17
|
+
SAFE DOMAIN: Home automation only. Medical/health capabilities are prohibited.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import asyncio
|
|
21
|
+
import base64
|
|
22
|
+
import hashlib
|
|
23
|
+
import logging
|
|
24
|
+
import os
|
|
25
|
+
import secrets
|
|
26
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
27
|
+
from urllib.parse import urlencode
|
|
28
|
+
|
|
29
|
+
import aiohttp
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
# Optional mDNS discovery support
|
|
34
|
+
try:
|
|
35
|
+
from zeroconf import ServiceBrowser, Zeroconf
|
|
36
|
+
|
|
37
|
+
ZEROCONF_AVAILABLE = True
|
|
38
|
+
except ImportError:
|
|
39
|
+
ZEROCONF_AVAILABLE = False
|
|
40
|
+
logger.info("Zeroconf not available - mDNS discovery disabled")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class HADiscoveryListener:
|
|
44
|
+
"""Zeroconf listener for Home Assistant instances."""
|
|
45
|
+
|
|
46
|
+
def __init__(self) -> None:
|
|
47
|
+
self.services: List[Dict[str, Any]] = []
|
|
48
|
+
|
|
49
|
+
def add_service(self, zc: Any, type_: str, name: str) -> None:
|
|
50
|
+
"""Handle discovered service."""
|
|
51
|
+
info = zc.get_service_info(type_, name)
|
|
52
|
+
if info:
|
|
53
|
+
addresses = info.parsed_addresses()
|
|
54
|
+
port = info.port
|
|
55
|
+
if addresses:
|
|
56
|
+
ip_address = addresses[0]
|
|
57
|
+
|
|
58
|
+
# Prefer homeassistant.local if server name indicates it's available
|
|
59
|
+
# The server field contains the hostname (e.g., "homeassistant.local.")
|
|
60
|
+
server = getattr(info, "server", None)
|
|
61
|
+
if server and "homeassistant" in server.lower():
|
|
62
|
+
# Strip trailing dot from mDNS name
|
|
63
|
+
hostname = server.rstrip(".")
|
|
64
|
+
host = hostname
|
|
65
|
+
logger.info(f"[mDNS DISCOVERY] Using hostname: {hostname}")
|
|
66
|
+
else:
|
|
67
|
+
host = ip_address
|
|
68
|
+
|
|
69
|
+
url = f"http://{host}:{port}"
|
|
70
|
+
logger.info(f"[mDNS DISCOVERY] Found Home Assistant at {url}")
|
|
71
|
+
logger.info(f"[mDNS DISCOVERY] IP: {ip_address}, Host: {host}, Port: {port}, Name: {name}")
|
|
72
|
+
self.services.append(
|
|
73
|
+
{
|
|
74
|
+
"id": f"ha_{ip_address}_{port}",
|
|
75
|
+
"label": f"Home Assistant ({host}:{port})",
|
|
76
|
+
"description": name.replace("._home-assistant._tcp.local.", ""),
|
|
77
|
+
"metadata": {
|
|
78
|
+
"host": host,
|
|
79
|
+
"ip": ip_address,
|
|
80
|
+
"port": port,
|
|
81
|
+
"name": name,
|
|
82
|
+
"url": url,
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
logger.warning(f"[mDNS DISCOVERY] Service {name} has no addresses")
|
|
88
|
+
else:
|
|
89
|
+
logger.warning(f"[mDNS DISCOVERY] Could not get service info for {name}")
|
|
90
|
+
|
|
91
|
+
def remove_service(self, zc: Any, type_: str, name: str) -> None:
|
|
92
|
+
"""Handle removed service."""
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
def update_service(self, zc: Any, type_: str, name: str) -> None:
|
|
96
|
+
"""Handle updated service."""
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class HAConfigurableAdapter:
|
|
101
|
+
"""Home Assistant configurable adapter with OAuth2 support.
|
|
102
|
+
|
|
103
|
+
Implements ConfigurableAdapterProtocol for Home Assistant using the
|
|
104
|
+
IndieAuth-style OAuth2 flow documented at:
|
|
105
|
+
https://developers.home-assistant.io/docs/auth_api/
|
|
106
|
+
|
|
107
|
+
OAuth2 Flow:
|
|
108
|
+
1. User navigates to HA's /auth/authorize with client_id (our app URL)
|
|
109
|
+
2. User logs in and authorizes the application
|
|
110
|
+
3. HA redirects to redirect_uri with authorization code
|
|
111
|
+
4. We exchange code for access_token + refresh_token at /auth/token
|
|
112
|
+
5. Access token used for API calls (valid 1800 seconds)
|
|
113
|
+
|
|
114
|
+
Usage via API:
|
|
115
|
+
1. POST /adapters/home_assistant/configure/start
|
|
116
|
+
2. POST /adapters/configure/{session_id}/step (discovery)
|
|
117
|
+
3. POST /adapters/configure/{session_id}/step (oauth - returns auth URL)
|
|
118
|
+
4. GET /adapters/configure/{session_id}/oauth/callback (handle redirect)
|
|
119
|
+
5. POST /adapters/configure/{session_id}/step (select features)
|
|
120
|
+
6. POST /adapters/configure/{session_id}/complete
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
# Home Assistant mDNS service type
|
|
124
|
+
HA_SERVICE_TYPE = "_home-assistant._tcp.local."
|
|
125
|
+
|
|
126
|
+
# OAuth2 endpoints (relative to HA instance URL)
|
|
127
|
+
OAUTH_AUTHORIZE_PATH = "/auth/authorize"
|
|
128
|
+
OAUTH_TOKEN_PATH = "/auth/token"
|
|
129
|
+
|
|
130
|
+
# Default client ID for local deployments
|
|
131
|
+
# For IndieAuth, this must match the redirect_uri host
|
|
132
|
+
# Local deployments use http://127.0.0.1:8080 as client_id
|
|
133
|
+
DEFAULT_CLIENT_ID = "http://127.0.0.1:8080"
|
|
134
|
+
|
|
135
|
+
# Available features that can be enabled
|
|
136
|
+
AVAILABLE_FEATURES = {
|
|
137
|
+
"device_control": {
|
|
138
|
+
"label": "Device Control",
|
|
139
|
+
"description": "Control lights, switches, and other devices",
|
|
140
|
+
"default": True,
|
|
141
|
+
},
|
|
142
|
+
"automation_trigger": {
|
|
143
|
+
"label": "Automation Triggers",
|
|
144
|
+
"description": "Trigger Home Assistant automations",
|
|
145
|
+
"default": True,
|
|
146
|
+
},
|
|
147
|
+
"sensor_data": {
|
|
148
|
+
"label": "Sensor Data",
|
|
149
|
+
"description": "Read sensor values and entity states",
|
|
150
|
+
"default": True,
|
|
151
|
+
},
|
|
152
|
+
"event_detection": {
|
|
153
|
+
"label": "Event Detection",
|
|
154
|
+
"description": "Monitor camera events and motion detection",
|
|
155
|
+
"default": False,
|
|
156
|
+
},
|
|
157
|
+
"camera_frames": {
|
|
158
|
+
"label": "Camera Frames",
|
|
159
|
+
"description": "Extract frames from camera streams",
|
|
160
|
+
"default": False,
|
|
161
|
+
},
|
|
162
|
+
"notifications": {
|
|
163
|
+
"label": "Notifications",
|
|
164
|
+
"description": "Send notifications via Home Assistant",
|
|
165
|
+
"default": True,
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
def __init__(self, config: Optional[Dict[str, Any]] = None) -> None:
|
|
170
|
+
"""Initialize the HA configurable adapter.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
config: Optional existing configuration
|
|
174
|
+
"""
|
|
175
|
+
self.config = config or {}
|
|
176
|
+
self._applied_config: Optional[Dict[str, Any]] = None
|
|
177
|
+
self._discovered_instances: List[Dict[str, Any]] = []
|
|
178
|
+
|
|
179
|
+
# PKCE challenge storage (state -> code_verifier)
|
|
180
|
+
self._pkce_verifiers: Dict[str, str] = {}
|
|
181
|
+
|
|
182
|
+
# Get client_id from env or use default
|
|
183
|
+
self._client_id = os.getenv("CIRIS_OAUTH_CLIENT_ID", self.DEFAULT_CLIENT_ID)
|
|
184
|
+
|
|
185
|
+
logger.info("HAConfigurableAdapter initialized")
|
|
186
|
+
|
|
187
|
+
async def discover(self, discovery_type: str) -> List[Dict[str, Any]]:
|
|
188
|
+
"""Discover Home Assistant instances.
|
|
189
|
+
|
|
190
|
+
Supports:
|
|
191
|
+
- "mdns" / "zeroconf": Use mDNS/Zeroconf discovery
|
|
192
|
+
- "manual": Return empty list (user enters URL manually)
|
|
193
|
+
- "env": Check environment variables
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
discovery_type: Type of discovery to perform
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
List of discovered HA instances
|
|
200
|
+
"""
|
|
201
|
+
logger.info(f"Running HA discovery: {discovery_type}")
|
|
202
|
+
|
|
203
|
+
if discovery_type in ("mdns", "zeroconf"):
|
|
204
|
+
return await self._discover_mdns()
|
|
205
|
+
elif discovery_type == "env":
|
|
206
|
+
return self._discover_from_env()
|
|
207
|
+
elif discovery_type == "manual":
|
|
208
|
+
return []
|
|
209
|
+
|
|
210
|
+
# Default: try mDNS first, then env
|
|
211
|
+
instances = await self._discover_mdns()
|
|
212
|
+
if not instances:
|
|
213
|
+
instances = self._discover_from_env()
|
|
214
|
+
return instances
|
|
215
|
+
|
|
216
|
+
async def _discover_mdns(self) -> List[Dict[str, Any]]:
|
|
217
|
+
"""Discover HA instances via mDNS/Zeroconf."""
|
|
218
|
+
if not ZEROCONF_AVAILABLE:
|
|
219
|
+
logger.warning("Zeroconf not available for mDNS discovery")
|
|
220
|
+
return []
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
listener = HADiscoveryListener()
|
|
224
|
+
zeroconf = Zeroconf()
|
|
225
|
+
|
|
226
|
+
browser = ServiceBrowser(zeroconf, self.HA_SERVICE_TYPE, listener)
|
|
227
|
+
|
|
228
|
+
# Wait for discovery (3 seconds)
|
|
229
|
+
await asyncio.sleep(3)
|
|
230
|
+
|
|
231
|
+
# Cleanup
|
|
232
|
+
browser.cancel()
|
|
233
|
+
zeroconf.close()
|
|
234
|
+
|
|
235
|
+
self._discovered_instances = listener.services
|
|
236
|
+
logger.info(f"[mDNS DISCOVERY] Complete: Found {len(listener.services)} HA instances")
|
|
237
|
+
for svc in listener.services:
|
|
238
|
+
logger.info(f"[mDNS DISCOVERY] → {svc['metadata']['url']} ({svc['description']})")
|
|
239
|
+
return listener.services
|
|
240
|
+
|
|
241
|
+
except Exception as e:
|
|
242
|
+
logger.error(f"mDNS discovery error: {e}")
|
|
243
|
+
return []
|
|
244
|
+
|
|
245
|
+
def _discover_from_env(self) -> List[Dict[str, Any]]:
|
|
246
|
+
"""Check environment variables for HA configuration."""
|
|
247
|
+
ha_url = os.getenv("HOME_ASSISTANT_URL")
|
|
248
|
+
if ha_url:
|
|
249
|
+
return [
|
|
250
|
+
{
|
|
251
|
+
"id": "ha_env",
|
|
252
|
+
"label": f"Home Assistant (from env: {ha_url})",
|
|
253
|
+
"description": "Configured via HOME_ASSISTANT_URL environment variable",
|
|
254
|
+
"metadata": {
|
|
255
|
+
"url": ha_url.rstrip("/"),
|
|
256
|
+
"source": "environment",
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
return []
|
|
261
|
+
|
|
262
|
+
def _generate_pkce_challenge(self, state: str) -> Tuple[str, str]:
|
|
263
|
+
"""Generate PKCE code_verifier and code_challenge.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
state: OAuth state to associate with verifier
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
(code_verifier, code_challenge) tuple
|
|
270
|
+
"""
|
|
271
|
+
# Generate random code_verifier (43-128 chars, URL-safe)
|
|
272
|
+
code_verifier = secrets.token_urlsafe(32)
|
|
273
|
+
|
|
274
|
+
# Store for later token exchange
|
|
275
|
+
self._pkce_verifiers[state] = code_verifier
|
|
276
|
+
|
|
277
|
+
# Generate code_challenge = BASE64URL(SHA256(code_verifier))
|
|
278
|
+
digest = hashlib.sha256(code_verifier.encode()).digest()
|
|
279
|
+
code_challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode()
|
|
280
|
+
|
|
281
|
+
return code_verifier, code_challenge
|
|
282
|
+
|
|
283
|
+
async def get_oauth_url(
|
|
284
|
+
self,
|
|
285
|
+
base_url: str,
|
|
286
|
+
state: str,
|
|
287
|
+
code_challenge: Optional[str] = None,
|
|
288
|
+
callback_base_url: Optional[str] = None,
|
|
289
|
+
redirect_uri: Optional[str] = None,
|
|
290
|
+
platform: Optional[str] = None,
|
|
291
|
+
) -> str:
|
|
292
|
+
"""Generate OAuth2 authorization URL for Home Assistant.
|
|
293
|
+
|
|
294
|
+
Home Assistant uses IndieAuth-style OAuth2:
|
|
295
|
+
- client_id is your application's website URL
|
|
296
|
+
- No pre-registration required
|
|
297
|
+
- Redirect URI must match client_id's host (or be declared via link tag)
|
|
298
|
+
|
|
299
|
+
For local/mobile deployments, pass callback_base_url to redirect to the
|
|
300
|
+
local API instead of the production server.
|
|
301
|
+
|
|
302
|
+
For Android with system browser, pass redirect_uri="ciris://oauth/callback"
|
|
303
|
+
and platform="android" to use deep link callback. The deep link is handled
|
|
304
|
+
by OAuthCallbackActivity which forwards to the local server.
|
|
305
|
+
|
|
306
|
+
Note: This adapter generates its own PKCE challenge internally using
|
|
307
|
+
_generate_pkce_challenge(). The code_challenge parameter is accepted
|
|
308
|
+
for protocol conformance but not used directly.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
base_url: Base URL of the HA instance (e.g., http://192.168.1.100:8123)
|
|
312
|
+
state: State parameter for CSRF protection (session_id)
|
|
313
|
+
code_challenge: PKCE code challenge (unused - HA adapter generates its own)
|
|
314
|
+
callback_base_url: Optional base URL for OAuth callback (e.g., http://127.0.0.1:8080)
|
|
315
|
+
If provided, uses this for redirect_uri instead of client_id
|
|
316
|
+
redirect_uri: Optional explicit redirect URI (e.g., ciris://oauth/callback for Android)
|
|
317
|
+
platform: Optional platform hint (android, ios, web, desktop)
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
Full OAuth authorization URL
|
|
321
|
+
"""
|
|
322
|
+
# Generate PKCE challenge (we always generate our own, ignore passed code_challenge)
|
|
323
|
+
_, generated_code_challenge = self._generate_pkce_challenge(state)
|
|
324
|
+
|
|
325
|
+
# Determine redirect URI and client_id
|
|
326
|
+
# Priority:
|
|
327
|
+
# 1. If explicit redirect_uri provided (e.g., ciris:// for Android), use it
|
|
328
|
+
# 2. If callback_base_url provided, use localhost callback
|
|
329
|
+
# 3. Otherwise use production callback
|
|
330
|
+
|
|
331
|
+
if redirect_uri and redirect_uri.startswith("ciris://"):
|
|
332
|
+
# Android requested deep link - but Home Assistant requires:
|
|
333
|
+
# 1. client_id must be a website URL
|
|
334
|
+
# 2. redirect_uri host must match client_id host, OR
|
|
335
|
+
# 3. redirect_uri must be whitelisted via <link rel='redirect_uri'> on client_id website
|
|
336
|
+
#
|
|
337
|
+
# Since we can't host a website with the link tag, we fall back to localhost redirect
|
|
338
|
+
# which works because system browser CAN access localhost on the device.
|
|
339
|
+
# The local Python server handles the callback.
|
|
340
|
+
logger.info("=" * 60)
|
|
341
|
+
logger.info("[OAUTH] ANDROID: Deep link requested but HA requires website client_id")
|
|
342
|
+
logger.info(f" Falling back to localhost redirect (system browser can access localhost)")
|
|
343
|
+
logger.info("=" * 60)
|
|
344
|
+
# Fall through to callback_base_url handling below
|
|
345
|
+
|
|
346
|
+
if callback_base_url:
|
|
347
|
+
# Local redirect - use local API as both client_id and redirect_uri
|
|
348
|
+
client_id = callback_base_url.rstrip("/")
|
|
349
|
+
final_redirect_uri = f"{client_id}/v1/system/adapters/configure/{state}/oauth/callback"
|
|
350
|
+
logger.info("=" * 60)
|
|
351
|
+
logger.info("[OAUTH] LOCAL CALLBACK REDIRECT URI:")
|
|
352
|
+
logger.info(f" callback_base_url: {callback_base_url}")
|
|
353
|
+
logger.info(f" client_id: {client_id}")
|
|
354
|
+
logger.info(f" state/session_id: {state}")
|
|
355
|
+
logger.info(f" FULL redirect_uri: {final_redirect_uri}")
|
|
356
|
+
logger.info(f" Expected route: /v1/system/adapters/configure/{{session_id}}/oauth/callback")
|
|
357
|
+
logger.info("=" * 60)
|
|
358
|
+
else:
|
|
359
|
+
# No callback_base_url provided - use default localhost
|
|
360
|
+
client_id = self._client_id # http://127.0.0.1:8080
|
|
361
|
+
final_redirect_uri = f"{client_id}/v1/system/adapters/configure/{state}/oauth/callback"
|
|
362
|
+
logger.info(f"[OAUTH] Using default localhost callback: {final_redirect_uri}")
|
|
363
|
+
|
|
364
|
+
# Build authorization URL
|
|
365
|
+
params = {
|
|
366
|
+
"client_id": client_id,
|
|
367
|
+
"redirect_uri": final_redirect_uri,
|
|
368
|
+
"response_type": "code",
|
|
369
|
+
"state": state,
|
|
370
|
+
# PKCE for additional security
|
|
371
|
+
"code_challenge": generated_code_challenge,
|
|
372
|
+
"code_challenge_method": "S256",
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
auth_url = f"{base_url.rstrip('/')}{self.OAUTH_AUTHORIZE_PATH}?{urlencode(params)}"
|
|
376
|
+
|
|
377
|
+
logger.info(f"Generated HA OAuth URL for state: {state[:8]}...")
|
|
378
|
+
return auth_url
|
|
379
|
+
|
|
380
|
+
async def handle_oauth_callback(
|
|
381
|
+
self,
|
|
382
|
+
code: str,
|
|
383
|
+
state: str,
|
|
384
|
+
base_url: str,
|
|
385
|
+
code_verifier: Optional[str] = None,
|
|
386
|
+
callback_base_url: Optional[str] = None,
|
|
387
|
+
redirect_uri: Optional[str] = None,
|
|
388
|
+
platform: Optional[str] = None,
|
|
389
|
+
) -> Dict[str, Any]:
|
|
390
|
+
"""Exchange authorization code for tokens.
|
|
391
|
+
|
|
392
|
+
Performs the OAuth2 token exchange with Home Assistant's token endpoint.
|
|
393
|
+
|
|
394
|
+
Note: This adapter stores its own PKCE verifier internally in _pkce_verifiers
|
|
395
|
+
and retrieves it by state. The code_verifier parameter is accepted for
|
|
396
|
+
protocol conformance but will be overridden by the stored value if available.
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
code: Authorization code from OAuth callback
|
|
400
|
+
state: State parameter for validation
|
|
401
|
+
base_url: HA instance URL
|
|
402
|
+
code_verifier: PKCE verifier (optional - HA adapter uses internally stored one)
|
|
403
|
+
callback_base_url: If provided, use this as client_id (for local OAuth)
|
|
404
|
+
redirect_uri: If provided, the redirect_uri used in authorization (for Android deep links)
|
|
405
|
+
platform: Platform hint (android, ios, web, desktop)
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
Token response with access_token, refresh_token, etc.
|
|
409
|
+
"""
|
|
410
|
+
logger.info(f"Exchanging OAuth code for tokens (state: {state[:8]}...)")
|
|
411
|
+
|
|
412
|
+
# Get stored PKCE verifier (overrides any passed code_verifier)
|
|
413
|
+
stored_verifier = self._pkce_verifiers.pop(state, None)
|
|
414
|
+
if stored_verifier:
|
|
415
|
+
code_verifier = stored_verifier
|
|
416
|
+
|
|
417
|
+
# Build token request
|
|
418
|
+
token_url = f"{base_url.rstrip('/')}{self.OAUTH_TOKEN_PATH}"
|
|
419
|
+
|
|
420
|
+
# Determine client_id - must match what was used in get_oauth_url
|
|
421
|
+
# For local/mobile deployments, we use the callback_base_url as client_id
|
|
422
|
+
if callback_base_url:
|
|
423
|
+
client_id = callback_base_url.rstrip("/")
|
|
424
|
+
else:
|
|
425
|
+
# Fallback - should not happen in local-only deployments
|
|
426
|
+
client_id = "http://127.0.0.1:8080"
|
|
427
|
+
logger.warning(f"[OAUTH CALLBACK] No callback_base_url provided, using default: {client_id}")
|
|
428
|
+
|
|
429
|
+
data = {
|
|
430
|
+
"grant_type": "authorization_code",
|
|
431
|
+
"code": code,
|
|
432
|
+
"client_id": client_id,
|
|
433
|
+
}
|
|
434
|
+
logger.info(f"Token exchange with client_id: {client_id}")
|
|
435
|
+
|
|
436
|
+
# Include PKCE verifier if we have one
|
|
437
|
+
if code_verifier:
|
|
438
|
+
data["code_verifier"] = code_verifier
|
|
439
|
+
|
|
440
|
+
try:
|
|
441
|
+
async with aiohttp.ClientSession() as session:
|
|
442
|
+
async with session.post(
|
|
443
|
+
token_url,
|
|
444
|
+
data=data,
|
|
445
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
446
|
+
timeout=aiohttp.ClientTimeout(total=30),
|
|
447
|
+
) as response:
|
|
448
|
+
if response.status == 200:
|
|
449
|
+
token_data = await response.json()
|
|
450
|
+
logger.info("Successfully obtained HA access token")
|
|
451
|
+
return {
|
|
452
|
+
"access_token": token_data.get("access_token"),
|
|
453
|
+
"refresh_token": token_data.get("refresh_token"),
|
|
454
|
+
"token_type": token_data.get("token_type", "Bearer"),
|
|
455
|
+
"expires_in": token_data.get("expires_in", 1800),
|
|
456
|
+
"ha_auth_provider_type": token_data.get("ha_auth_provider_type"),
|
|
457
|
+
"ha_auth_provider_id": token_data.get("ha_auth_provider_id"),
|
|
458
|
+
}
|
|
459
|
+
else:
|
|
460
|
+
error_text = await response.text()
|
|
461
|
+
logger.error(f"Token exchange failed: {response.status} - {error_text}")
|
|
462
|
+
return {
|
|
463
|
+
"error": "token_exchange_failed",
|
|
464
|
+
"error_description": f"HTTP {response.status}: {error_text}",
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
except Exception as e:
|
|
468
|
+
logger.error(f"Token exchange error: {e}")
|
|
469
|
+
return {
|
|
470
|
+
"error": "token_exchange_error",
|
|
471
|
+
"error_description": str(e),
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async def get_config_options(self, step_id: str, context: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
475
|
+
"""Get options for a selection step.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
step_id: ID of the configuration step
|
|
479
|
+
context: Current configuration context
|
|
480
|
+
|
|
481
|
+
Returns:
|
|
482
|
+
List of available options
|
|
483
|
+
"""
|
|
484
|
+
logger.info(f"Getting config options for step: {step_id}")
|
|
485
|
+
|
|
486
|
+
if step_id == "select_instance":
|
|
487
|
+
# Return discovered instances
|
|
488
|
+
return self._discovered_instances
|
|
489
|
+
|
|
490
|
+
elif step_id == "select_features":
|
|
491
|
+
# Return available features
|
|
492
|
+
return [
|
|
493
|
+
{
|
|
494
|
+
"id": feature_id,
|
|
495
|
+
"label": feature["label"],
|
|
496
|
+
"description": feature["description"],
|
|
497
|
+
"metadata": {"default": feature["default"]},
|
|
498
|
+
}
|
|
499
|
+
for feature_id, feature in self.AVAILABLE_FEATURES.items()
|
|
500
|
+
]
|
|
501
|
+
|
|
502
|
+
elif step_id == "select_cameras":
|
|
503
|
+
# Return cameras from HA if we have a token
|
|
504
|
+
# Token may be at top level or nested in oauth_tokens
|
|
505
|
+
access_token = context.get("access_token")
|
|
506
|
+
if not access_token:
|
|
507
|
+
oauth_tokens = context.get("oauth_tokens", {})
|
|
508
|
+
access_token = oauth_tokens.get("access_token")
|
|
509
|
+
|
|
510
|
+
base_url = context.get("base_url")
|
|
511
|
+
logger.info(f"[select_cameras] base_url={base_url}, has_token={bool(access_token)}")
|
|
512
|
+
|
|
513
|
+
if access_token and base_url:
|
|
514
|
+
return await self._get_ha_cameras(base_url, access_token)
|
|
515
|
+
return []
|
|
516
|
+
|
|
517
|
+
return []
|
|
518
|
+
|
|
519
|
+
async def _get_ha_cameras(self, base_url: str, access_token: str) -> List[Dict[str, Any]]:
|
|
520
|
+
"""Fetch camera entities from Home Assistant."""
|
|
521
|
+
try:
|
|
522
|
+
headers = {
|
|
523
|
+
"Authorization": f"Bearer {access_token}",
|
|
524
|
+
"Content-Type": "application/json",
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
async with aiohttp.ClientSession() as session:
|
|
528
|
+
async with session.get(
|
|
529
|
+
f"{base_url}/api/states",
|
|
530
|
+
headers=headers,
|
|
531
|
+
timeout=aiohttp.ClientTimeout(total=15),
|
|
532
|
+
) as response:
|
|
533
|
+
if response.status == 200:
|
|
534
|
+
entities = await response.json()
|
|
535
|
+
cameras = []
|
|
536
|
+
for entity in entities:
|
|
537
|
+
entity_id = entity.get("entity_id", "")
|
|
538
|
+
if entity_id.startswith("camera."):
|
|
539
|
+
cameras.append(
|
|
540
|
+
{
|
|
541
|
+
"id": entity_id,
|
|
542
|
+
"label": entity.get("attributes", {}).get("friendly_name", entity_id),
|
|
543
|
+
"description": f"Camera entity: {entity_id}",
|
|
544
|
+
"metadata": {
|
|
545
|
+
"entity_id": entity_id,
|
|
546
|
+
"state": entity.get("state"),
|
|
547
|
+
},
|
|
548
|
+
}
|
|
549
|
+
)
|
|
550
|
+
return cameras
|
|
551
|
+
|
|
552
|
+
except Exception as e:
|
|
553
|
+
logger.error(f"Error fetching HA cameras: {e}")
|
|
554
|
+
|
|
555
|
+
return []
|
|
556
|
+
|
|
557
|
+
async def validate_config(self, config: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
|
|
558
|
+
"""Validate HA configuration before applying.
|
|
559
|
+
|
|
560
|
+
Performs:
|
|
561
|
+
- Required field validation
|
|
562
|
+
- URL format validation
|
|
563
|
+
- Token connectivity test
|
|
564
|
+
|
|
565
|
+
Args:
|
|
566
|
+
config: Complete configuration to validate
|
|
567
|
+
|
|
568
|
+
Returns:
|
|
569
|
+
(is_valid, error_message) tuple
|
|
570
|
+
"""
|
|
571
|
+
logger.info("Validating HA configuration")
|
|
572
|
+
|
|
573
|
+
if not config:
|
|
574
|
+
return False, "Configuration is empty"
|
|
575
|
+
|
|
576
|
+
# Check required fields
|
|
577
|
+
base_url = config.get("base_url")
|
|
578
|
+
if not base_url:
|
|
579
|
+
return False, "base_url is required"
|
|
580
|
+
|
|
581
|
+
if not base_url.startswith(("http://", "https://")):
|
|
582
|
+
return False, f"Invalid base_url: {base_url} (must start with http:// or https://)"
|
|
583
|
+
|
|
584
|
+
# Get access_token - may be at top level or nested in oauth_tokens
|
|
585
|
+
access_token = config.get("access_token")
|
|
586
|
+
if not access_token:
|
|
587
|
+
oauth_tokens = config.get("oauth_tokens", {})
|
|
588
|
+
access_token = oauth_tokens.get("access_token")
|
|
589
|
+
|
|
590
|
+
if not access_token:
|
|
591
|
+
return False, "access_token is required (complete OAuth flow first)"
|
|
592
|
+
|
|
593
|
+
# Test connectivity with the token
|
|
594
|
+
try:
|
|
595
|
+
headers = {
|
|
596
|
+
"Authorization": f"Bearer {access_token}",
|
|
597
|
+
"Content-Type": "application/json",
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
async with aiohttp.ClientSession() as session:
|
|
601
|
+
async with session.get(
|
|
602
|
+
f"{base_url}/api/",
|
|
603
|
+
headers=headers,
|
|
604
|
+
timeout=aiohttp.ClientTimeout(total=10),
|
|
605
|
+
) as response:
|
|
606
|
+
if response.status == 401:
|
|
607
|
+
return False, "Access token is invalid or expired"
|
|
608
|
+
elif response.status != 200:
|
|
609
|
+
return False, f"HA connection failed: HTTP {response.status}"
|
|
610
|
+
|
|
611
|
+
except aiohttp.ClientError as e:
|
|
612
|
+
return False, f"HA connection error: {e}"
|
|
613
|
+
except Exception as e:
|
|
614
|
+
return False, f"Validation error: {e}"
|
|
615
|
+
|
|
616
|
+
# Validate enabled_features if present
|
|
617
|
+
features = config.get("enabled_features", [])
|
|
618
|
+
if features:
|
|
619
|
+
valid_features = set(self.AVAILABLE_FEATURES.keys())
|
|
620
|
+
invalid = set(features) - valid_features
|
|
621
|
+
if invalid:
|
|
622
|
+
return False, f"Invalid features: {invalid}"
|
|
623
|
+
|
|
624
|
+
logger.info("HA configuration validated successfully")
|
|
625
|
+
return True, None
|
|
626
|
+
|
|
627
|
+
async def apply_config(self, config: Dict[str, Any]) -> bool:
|
|
628
|
+
"""Apply the configuration.
|
|
629
|
+
|
|
630
|
+
Stores configuration and sets up environment for the service.
|
|
631
|
+
|
|
632
|
+
Args:
|
|
633
|
+
config: Validated configuration to apply
|
|
634
|
+
|
|
635
|
+
Returns:
|
|
636
|
+
True if applied successfully
|
|
637
|
+
"""
|
|
638
|
+
logger.info("Applying HA configuration")
|
|
639
|
+
|
|
640
|
+
self._applied_config = config.copy()
|
|
641
|
+
|
|
642
|
+
# Get tokens - may be at top level or nested in oauth_tokens
|
|
643
|
+
oauth_tokens = config.get("oauth_tokens", {})
|
|
644
|
+
access_token = config.get("access_token") or oauth_tokens.get("access_token")
|
|
645
|
+
refresh_token = config.get("refresh_token") or oauth_tokens.get("refresh_token")
|
|
646
|
+
|
|
647
|
+
# Set environment variables for the HA service
|
|
648
|
+
if config.get("base_url"):
|
|
649
|
+
os.environ["HOME_ASSISTANT_URL"] = config["base_url"]
|
|
650
|
+
if access_token:
|
|
651
|
+
os.environ["HOME_ASSISTANT_TOKEN"] = access_token
|
|
652
|
+
if refresh_token:
|
|
653
|
+
os.environ["HOME_ASSISTANT_REFRESH_TOKEN"] = refresh_token
|
|
654
|
+
|
|
655
|
+
# Log sanitized config
|
|
656
|
+
safe_config = {k: ("***" if "token" in k.lower() else v) for k, v in config.items()}
|
|
657
|
+
logger.info(f"HA configuration applied: {safe_config}")
|
|
658
|
+
|
|
659
|
+
return True
|
|
660
|
+
|
|
661
|
+
def get_applied_config(self) -> Optional[Dict[str, Any]]:
|
|
662
|
+
"""Get the currently applied configuration.
|
|
663
|
+
|
|
664
|
+
Returns:
|
|
665
|
+
Applied configuration or None if not configured
|
|
666
|
+
"""
|
|
667
|
+
return self._applied_config
|