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