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,1583 @@
1
+ """
2
+ Step point decorators for H3ERE pipeline pause/resume and streaming functionality.
3
+
4
+ This module provides clean decorators that handle:
5
+ 1. Streaming step results to clients in real-time
6
+ 2. Pausing thought execution at step points for single-step debugging
7
+ 3. Maintaining live thought state in memory between steps
8
+
9
+ Architecture:
10
+ - @streaming_step: Always streams step data, no pausing
11
+ - @step_point: Handles pause/resume mechanics for single-step mode
12
+ - Both decorators can be applied together for full functionality
13
+ """
14
+
15
+ import asyncio
16
+ import logging
17
+ from datetime import datetime
18
+ from functools import wraps
19
+ from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, cast
20
+
21
+ from ciris_engine.logic.utils.jsondict_helpers import get_bool, get_dict, get_float, get_int, get_list, get_str
22
+ from ciris_engine.schemas.runtime.system_context import SystemSnapshot
23
+ from ciris_engine.schemas.services.runtime_control import (
24
+ ActionCompleteStepData,
25
+ AllStepsExecutionResult,
26
+ BaseStepData,
27
+ ConscienceExecutionStepData,
28
+ FinalizeActionStepData,
29
+ GatherContextStepData,
30
+ PerformActionStepData,
31
+ PerformASPDMAStepData,
32
+ PerformDMAsStepData,
33
+ RecursiveASPDMAStepData,
34
+ RecursiveConscienceStepData,
35
+ RoundCompleteStepData,
36
+ SpanAttribute,
37
+ StartRoundStepData,
38
+ StepDataUnion,
39
+ StepExecutionResult,
40
+ StepPoint,
41
+ StepResultData,
42
+ TraceContext,
43
+ )
44
+ from ciris_engine.schemas.types import JSONDict
45
+
46
+ F = TypeVar("F", bound=Callable[..., Any])
47
+
48
+ logger = logging.getLogger(__name__)
49
+
50
+ # Global registry for paused thought coroutines
51
+ _paused_thoughts: Dict[str, asyncio.Event] = {}
52
+ _single_step_mode = False
53
+
54
+
55
+ def _base_data_dict(base_data: BaseStepData) -> JSONDict:
56
+ """Convert BaseStepData to dict for **unpacking into step data constructors."""
57
+ return {
58
+ "timestamp": base_data.timestamp,
59
+ "thought_id": base_data.thought_id,
60
+ "task_id": base_data.task_id,
61
+ "processing_time_ms": base_data.processing_time_ms,
62
+ "success": base_data.success,
63
+ "error": base_data.error,
64
+ }
65
+
66
+
67
+ async def _query_thought_resources(telemetry_service: Any, thought_id: str, timestamp: datetime) -> JSONDict:
68
+ """Query telemetry service and aggregate resource usage for a thought.
69
+
70
+ Args:
71
+ telemetry_service: Telemetry service instance
72
+ thought_id: ID of the thought to query resources for
73
+ timestamp: End timestamp for the query window
74
+
75
+ Returns:
76
+ Dict with aggregated resource data:
77
+ - tokens_total: Total tokens used
78
+ - tokens_input: Input tokens used
79
+ - tokens_output: Output tokens used
80
+ - cost_cents: Total cost in USD cents
81
+ - carbon_grams: Total CO2 emissions in grams
82
+ - energy_mwh: Total energy in milliwatt-hours
83
+ - llm_calls: Number of LLM calls
84
+ - models_used: List of unique models used
85
+ """
86
+ if not telemetry_service:
87
+ logger.debug(f"No telemetry service available to query resources for thought {thought_id}")
88
+ return {
89
+ "tokens_total": 0,
90
+ "tokens_input": 0,
91
+ "tokens_output": 0,
92
+ "cost_cents": 0.0,
93
+ "carbon_grams": 0.0,
94
+ "energy_mwh": 0.0,
95
+ "llm_calls": 0,
96
+ "models_used": [],
97
+ }
98
+
99
+ try:
100
+ # Query all metric types with thought_id tag
101
+ tags = {"thought_id": thought_id}
102
+
103
+ # Query each metric type and aggregate
104
+ tokens_total_data = await telemetry_service.query_metrics(
105
+ metric_name="llm.tokens.total", tags=tags, end_time=timestamp
106
+ )
107
+ tokens_input_data = await telemetry_service.query_metrics(
108
+ metric_name="llm.tokens.input", tags=tags, end_time=timestamp
109
+ )
110
+ tokens_output_data = await telemetry_service.query_metrics(
111
+ metric_name="llm.tokens.output", tags=tags, end_time=timestamp
112
+ )
113
+ cost_data = await telemetry_service.query_metrics(metric_name="llm.cost.cents", tags=tags, end_time=timestamp)
114
+ carbon_data = await telemetry_service.query_metrics(
115
+ metric_name="llm.environmental.carbon_grams", tags=tags, end_time=timestamp
116
+ )
117
+ energy_data = await telemetry_service.query_metrics(
118
+ metric_name="llm.environmental.energy_kwh", tags=tags, end_time=timestamp
119
+ )
120
+
121
+ # Aggregate metrics - sum all values
122
+ tokens_total = sum(m.value for m in tokens_total_data)
123
+ tokens_input = sum(m.value for m in tokens_input_data)
124
+ tokens_output = sum(m.value for m in tokens_output_data)
125
+ cost_cents = sum(m.value for m in cost_data)
126
+ carbon_grams = sum(m.value for m in carbon_data)
127
+ # Convert kWh to mWh (1 kWh = 1,000,000 mWh)
128
+ energy_kwh = sum(m.value for m in energy_data)
129
+ energy_mwh = energy_kwh * 1_000_000
130
+ llm_calls = len(tokens_total_data) # Each LLM call creates one tokens.total metric
131
+
132
+ # Extract unique models from tags
133
+ models_used = list({m.tags.get("model", "unknown") for m in tokens_total_data if hasattr(m, "tags")})
134
+
135
+ logger.debug(
136
+ f"Aggregated resources for thought {thought_id}: "
137
+ f"{int(tokens_total)} tokens, {llm_calls} calls, {cost_cents:.4f} cents"
138
+ )
139
+
140
+ return {
141
+ "tokens_total": int(tokens_total),
142
+ "tokens_input": int(tokens_input),
143
+ "tokens_output": int(tokens_output),
144
+ "cost_cents": float(cost_cents),
145
+ "carbon_grams": float(carbon_grams),
146
+ "energy_mwh": float(energy_mwh),
147
+ "llm_calls": llm_calls,
148
+ "models_used": models_used,
149
+ }
150
+
151
+ except Exception as e:
152
+ logger.error(f"Failed to query resources for thought {thought_id}: {e}", exc_info=True)
153
+ # Return zeros on error - don't fail the entire action complete step
154
+ return {
155
+ "tokens_total": 0,
156
+ "tokens_input": 0,
157
+ "tokens_output": 0,
158
+ "cost_cents": 0.0,
159
+ "carbon_grams": 0.0,
160
+ "energy_mwh": 0.0,
161
+ "llm_calls": 0,
162
+ "models_used": [],
163
+ }
164
+
165
+
166
+ async def _maybe_add_resource_usage(
167
+ step: StepPoint, processor: Any, thought_id: str, end_timestamp: Any, kwargs: JSONDict
168
+ ) -> None:
169
+ """Helper to add resource usage for ACTION_COMPLETE steps - reduces cognitive complexity."""
170
+ if step != StepPoint.ACTION_COMPLETE:
171
+ return
172
+
173
+ # Get telemetry service from processor
174
+ telemetry_service = getattr(processor, "telemetry_service", None) or getattr(
175
+ getattr(processor, "sink", None), "telemetry", None
176
+ )
177
+
178
+ if telemetry_service:
179
+ # Query resources and add to kwargs for _create_action_complete_data
180
+ resource_data = await _query_thought_resources(telemetry_service, thought_id, end_timestamp)
181
+ kwargs["_resource_usage"] = resource_data
182
+ else:
183
+ logger.warning(
184
+ f"No telemetry service available for thought {thought_id} - "
185
+ f"resource usage will not be recorded in action_complete event"
186
+ )
187
+
188
+
189
+ def streaming_step(step: StepPoint) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
190
+ """
191
+ Decorator that streams step results in real-time.
192
+
193
+ This decorator:
194
+ 1. Extracts step data from function arguments/results
195
+ 2. Broadcasts to global step_result_stream
196
+ 3. Never pauses - always streams and continues
197
+
198
+ Args:
199
+ step: The StepPoint enum for this step
200
+
201
+ Usage:
202
+ @streaming_step(StepPoint.GATHER_CONTEXT)
203
+ async def _build_context(self, thought_item, ...):
204
+ # Original logic unchanged
205
+ return context_data
206
+ """
207
+
208
+ def decorator(func: F) -> F:
209
+ @wraps(func)
210
+ async def wrapper(self: Any, thought_item: Any, *args: Any, **kwargs: Any) -> Any:
211
+ thought_id = getattr(thought_item, "thought_id", "unknown")
212
+ time_service = getattr(self, "_time_service", None)
213
+ if not time_service or not hasattr(time_service, "now"):
214
+ raise RuntimeError(
215
+ f"Critical error: No time service available for step {step.value} on thought {thought_id}"
216
+ )
217
+ start_timestamp = time_service.now()
218
+
219
+ try:
220
+ # Execute the original function
221
+ result = await func(self, thought_item, *args, **kwargs)
222
+
223
+ # Calculate processing time
224
+ end_timestamp = time_service.now()
225
+ processing_time_ms = (end_timestamp - start_timestamp).total_seconds() * 1000
226
+
227
+ # Build typed base step data from function context
228
+ base_step_data = BaseStepData(
229
+ timestamp=start_timestamp.isoformat(),
230
+ thought_id=thought_id,
231
+ processing_time_ms=processing_time_ms,
232
+ success=True,
233
+ )
234
+
235
+ # For ACTION_COMPLETE, query and aggregate resource usage by thought_id
236
+ await _maybe_add_resource_usage(step, self, thought_id, end_timestamp, kwargs)
237
+
238
+ # Add step-specific data and create typed step data
239
+ step_data = _create_typed_step_data(step, base_step_data, thought_item, result, args, kwargs)
240
+
241
+ # Broadcast simplified reasoning event for key steps only
242
+ await _broadcast_reasoning_event(step, step_data, thought_item=thought_item)
243
+
244
+ return result
245
+
246
+ except Exception:
247
+ # Stream error result
248
+ end_timestamp = time_service.now()
249
+ processing_time_ms = (end_timestamp - start_timestamp).total_seconds() * 1000
250
+
251
+ # Don't broadcast errors as reasoning events - handled at higher level
252
+ raise
253
+
254
+ return cast(F, wrapper)
255
+
256
+ return decorator
257
+
258
+
259
+ def step_point(step: StepPoint) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
260
+ """
261
+ Decorator that handles pause/resume mechanics for single-step debugging.
262
+
263
+ This decorator:
264
+ 1. Checks if single-step mode is enabled
265
+ 2. Pauses the thought coroutine at this step point
266
+ 3. Waits for resume signal before continuing
267
+ 4. Maintains live thought state in memory
268
+
269
+ Args:
270
+ step: The StepPoint enum for this step
271
+
272
+ Usage:
273
+ @step_point(StepPoint.RECURSIVE_ASPDMA)
274
+ async def _recursive_action_selection(self, thought_item, ...):
275
+ # Only runs if previous step failed
276
+ return retry_result
277
+ """
278
+
279
+ def decorator(func: F) -> F:
280
+ @wraps(func)
281
+ async def wrapper(self: Any, thought_item: Any, *args: Any, **kwargs: Any) -> Any:
282
+ thought_id = getattr(thought_item, "thought_id", "unknown")
283
+
284
+ # Check if we should pause at this step point
285
+ if _should_pause_at_step(step):
286
+ logger.info(f"Pausing at step point {step.value} for thought {thought_id}")
287
+ await _pause_thought_execution(thought_id)
288
+ logger.info(f"Resuming from step point {step.value} for thought {thought_id}")
289
+
290
+ # Execute the original function (thought continues naturally)
291
+ return await func(self, thought_item, *args, **kwargs)
292
+
293
+ return cast(F, wrapper)
294
+
295
+ return decorator
296
+
297
+
298
+ # Helper functions for decorator implementation
299
+
300
+
301
+ def _should_pause_at_step(step: StepPoint) -> bool:
302
+ """Check if we should pause at this step point."""
303
+ global _single_step_mode
304
+
305
+ # Only pause in single-step mode
306
+ if not _single_step_mode:
307
+ return False
308
+
309
+ # Always pause at enabled step points in single-step mode
310
+ return True
311
+
312
+
313
+ async def _pause_thought_execution(thought_id: str) -> None:
314
+ """Pause this thought's execution until resumed."""
315
+ global _paused_thoughts
316
+
317
+ # Create resume event for this thought
318
+ if thought_id not in _paused_thoughts:
319
+ _paused_thoughts[thought_id] = asyncio.Event()
320
+
321
+ # Wait for resume signal
322
+ await _paused_thoughts[thought_id].wait()
323
+
324
+ # Clear event for next pause
325
+ _paused_thoughts[thought_id].clear()
326
+
327
+
328
+ def _get_step_data_creators() -> Dict[StepPoint, Callable[..., Any]]:
329
+ """Get dispatch dictionary for step data creators."""
330
+ return {
331
+ StepPoint.START_ROUND: lambda base_data, result, args, kwargs, thought_item: _create_start_round_data(
332
+ base_data, args
333
+ ),
334
+ StepPoint.GATHER_CONTEXT: lambda base_data, result, args, kwargs, thought_item: _create_gather_context_data(
335
+ base_data, result
336
+ ),
337
+ StepPoint.PERFORM_DMAS: lambda base_data, result, args, kwargs, thought_item: _create_perform_dmas_data(
338
+ base_data, result, thought_item
339
+ ),
340
+ StepPoint.PERFORM_ASPDMA: lambda base_data, result, args, kwargs, thought_item: _create_perform_aspdma_data(
341
+ base_data, result, args
342
+ ),
343
+ StepPoint.CONSCIENCE_EXECUTION: lambda base_data, result, args, kwargs, thought_item: _create_conscience_execution_data(
344
+ base_data, result, args
345
+ ),
346
+ StepPoint.RECURSIVE_ASPDMA: lambda base_data, result, args, kwargs, thought_item: _create_recursive_aspdma_data(
347
+ base_data, result, args
348
+ ),
349
+ StepPoint.RECURSIVE_CONSCIENCE: lambda base_data, result, args, kwargs, thought_item: _create_recursive_conscience_data(
350
+ base_data, result
351
+ ),
352
+ StepPoint.FINALIZE_ACTION: lambda base_data, result, args, kwargs, thought_item: _create_finalize_action_data(
353
+ base_data, result
354
+ ),
355
+ StepPoint.PERFORM_ACTION: lambda base_data, result, args, kwargs, thought_item: _create_perform_action_data(
356
+ base_data, result, args, kwargs
357
+ ),
358
+ StepPoint.ACTION_COMPLETE: lambda base_data, result, args, kwargs, thought_item: _create_action_complete_data(
359
+ base_data, result, kwargs
360
+ ),
361
+ StepPoint.ROUND_COMPLETE: lambda base_data, result, args, kwargs, thought_item: _create_round_complete_data(
362
+ base_data, args
363
+ ),
364
+ }
365
+
366
+
367
+ def _prepare_base_data_with_task_id(base_data: BaseStepData, thought_item: Any) -> BaseStepData:
368
+ """Prepare base data with task_id from thought_item."""
369
+ task_id = getattr(thought_item, "source_task_id", None)
370
+ return base_data.model_copy(update={"task_id": task_id})
371
+
372
+
373
+ def _log_step_debug_info(step: StepPoint, base_data: BaseStepData, thought_item: Any) -> None:
374
+ """Log debug information for step processing."""
375
+ task_id = base_data.task_id
376
+ thought_id = base_data.thought_id
377
+ logger.debug(
378
+ f"Step {step.value} for thought {thought_id}: task_id={task_id}, thought_item type={type(thought_item).__name__}"
379
+ )
380
+ if not task_id:
381
+ logger.warning(f"Missing task_id for thought {thought_id} at step {step.value}")
382
+
383
+
384
+ def _create_typed_step_data(
385
+ step: StepPoint,
386
+ base_data: BaseStepData,
387
+ thought_item: Any,
388
+ result: Any,
389
+ args: Tuple[Any, ...],
390
+ kwargs: JSONDict,
391
+ ) -> StepDataUnion:
392
+ """Create typed step data based on step type using dispatch pattern."""
393
+ # Prepare base data with task_id
394
+ base_data = _prepare_base_data_with_task_id(base_data, thought_item)
395
+
396
+ # Log debug information
397
+ _log_step_debug_info(step, base_data, thought_item)
398
+
399
+ # Get step data creator using dispatch pattern - fail fast for unknown steps
400
+ step_creators = _get_step_data_creators()
401
+ if step not in step_creators:
402
+ raise ValueError(f"Unknown step point: {step.value}. No step data creator available.")
403
+
404
+ # Create step-specific typed data - fail fast and loud on any errors
405
+ return step_creators[step](base_data, result, args, kwargs, thought_item) # type: ignore[no-any-return]
406
+
407
+
408
+ # This function is now integrated into _create_typed_step_data
409
+ # Keeping for potential backward compatibility but marked as deprecated
410
+
411
+
412
+ def _create_start_round_data(base_data: BaseStepData, args: Tuple[Any, ...]) -> StartRoundStepData:
413
+ """Create START_ROUND specific typed data."""
414
+ if not args:
415
+ raise ValueError("START_ROUND args is empty - thought list is required for processing")
416
+
417
+ return StartRoundStepData(**_base_data_dict(base_data), thoughts_processed=len(args), round_started=True)
418
+
419
+
420
+ def _create_gather_context_data(base_data: BaseStepData, result: Any) -> GatherContextStepData:
421
+ """Create GATHER_CONTEXT specific typed data."""
422
+ if result is None:
423
+ raise ValueError("GATHER_CONTEXT step result is None - this indicates a serious pipeline issue")
424
+
425
+ return GatherContextStepData(**_base_data_dict(base_data), context=str(result))
426
+
427
+
428
+ def _create_perform_dmas_data(base_data: BaseStepData, result: Any, thought_item: Any) -> PerformDMAsStepData:
429
+ """Create PERFORM_DMAS specific typed data."""
430
+ if not result:
431
+ raise ValueError("PERFORM_DMAS step result is None - this indicates a serious pipeline issue")
432
+
433
+ if hasattr(result, "ethical_pdma"):
434
+ # Handle InitialDMAResults object
435
+ dma_parts = []
436
+ if result.ethical_pdma:
437
+ dma_parts.append(f"ethical_pdma: {result.ethical_pdma}")
438
+ if result.csdma:
439
+ dma_parts.append(f"csdma: {result.csdma}")
440
+ if result.dsdma:
441
+ dma_parts.append(f"dsdma: {result.dsdma}")
442
+ dma_results = "; ".join(dma_parts) if dma_parts else "No DMA results"
443
+ else:
444
+ # Non-InitialDMAResults object - validate it has expected structure
445
+ dma_results = str(result)
446
+
447
+ if not thought_item:
448
+ raise ValueError("PERFORM_DMAS thought_item is None - this indicates a serious pipeline issue")
449
+
450
+ if not hasattr(thought_item, "initial_context"):
451
+ raise AttributeError(
452
+ f"PERFORM_DMAS thought_item missing 'initial_context' attribute. Type: {type(thought_item)}, attributes: {dir(thought_item)}"
453
+ )
454
+
455
+ return PerformDMAsStepData(
456
+ **_base_data_dict(base_data), dma_results=dma_results, context=str(thought_item.initial_context)
457
+ )
458
+
459
+
460
+ def _validate_aspdma_result(result: Any) -> None:
461
+ """Validate ASPDMA result has required attributes."""
462
+ if not result:
463
+ raise ValueError("PERFORM_ASPDMA step result is None - this indicates a serious pipeline issue")
464
+
465
+ if not hasattr(result, "selected_action"):
466
+ raise AttributeError(
467
+ f"PERFORM_ASPDMA result missing 'selected_action' attribute. Result type: {type(result)}, available attributes: {dir(result)}"
468
+ )
469
+
470
+ if not hasattr(result, "rationale"):
471
+ raise AttributeError(
472
+ f"PERFORM_ASPDMA result missing 'rationale' attribute. Result type: {type(result)}, available attributes: {dir(result)}"
473
+ )
474
+
475
+
476
+ def _extract_dma_results_from_args(args: Tuple[Any, ...]) -> Any:
477
+ """
478
+ Extract DMA results object from ASPDMA args.
479
+
480
+ Returns the concrete InitialDMAResults object (NOT a string or dict).
481
+ """
482
+ # Extract dma_results from args - it's the second positional arg after thought_context
483
+ # Function signature: _perform_aspdma_step(self, thought_item, thought_context, dma_results)
484
+ # args = (thought_context, dma_results)
485
+ if len(args) < 2:
486
+ return None
487
+
488
+ dma_results_obj = args[1]
489
+ # Return the concrete InitialDMAResults object directly
490
+ return dma_results_obj
491
+
492
+
493
+ def _create_perform_aspdma_data(base_data: BaseStepData, result: Any, args: Tuple[Any, ...]) -> PerformASPDMAStepData:
494
+ """Create PERFORM_ASPDMA specific typed data."""
495
+ _validate_aspdma_result(result)
496
+ dma_results_obj = _extract_dma_results_from_args(args)
497
+
498
+ # Create string summary for display
499
+ dma_results_str = None
500
+ if dma_results_obj and hasattr(dma_results_obj, "csdma"):
501
+ dma_parts = []
502
+ if dma_results_obj.csdma:
503
+ dma_parts.append(f"csdma: {dma_results_obj.csdma}")
504
+ if dma_results_obj.dsdma:
505
+ dma_parts.append(f"dsdma: {dma_results_obj.dsdma}")
506
+ if dma_results_obj.ethical_pdma:
507
+ dma_parts.append(f"ethical_pdma: {dma_results_obj.ethical_pdma}")
508
+ dma_results_str = "; ".join(dma_parts) if dma_parts else None
509
+
510
+ # Rationale is now REQUIRED in ActionSelectionDMAResult schema
511
+ action_rationale = result.rationale
512
+
513
+ return PerformASPDMAStepData(
514
+ **_base_data_dict(base_data),
515
+ selected_action=str(result.selected_action),
516
+ action_rationale=action_rationale,
517
+ dma_results=dma_results_str, # String summary for display
518
+ dma_results_obj=dma_results_obj, # Concrete InitialDMAResults object for event creation
519
+ )
520
+
521
+
522
+ def _validate_conscience_execution_result(result: Any) -> None:
523
+ """Validate conscience execution result has required attributes."""
524
+ if not result:
525
+ raise ValueError("CONSCIENCE_EXECUTION step result is None - this indicates a serious pipeline issue")
526
+
527
+ if not hasattr(result, "overridden"):
528
+ raise AttributeError(
529
+ f"CONSCIENCE_EXECUTION result missing 'overridden' attribute. Expected ConscienceApplicationResult, got {type(result)}, attributes: {dir(result)}"
530
+ )
531
+
532
+ if not hasattr(result, "final_action"):
533
+ raise AttributeError(
534
+ f"CONSCIENCE_EXECUTION result missing 'final_action' attribute. Expected ConscienceApplicationResult, got {type(result)}, attributes: {dir(result)}"
535
+ )
536
+
537
+ if not hasattr(result.final_action, "selected_action"):
538
+ raise AttributeError(
539
+ f"CONSCIENCE_EXECUTION final_action missing 'selected_action' attribute. final_action type: {type(result.final_action)}, attributes: {dir(result.final_action)}"
540
+ )
541
+
542
+ if result.overridden and not hasattr(result, "override_reason"):
543
+ raise AttributeError(
544
+ f"CONSCIENCE_EXECUTION result overridden but missing 'override_reason'. Result type: {type(result)}, attributes: {dir(result)}"
545
+ )
546
+
547
+
548
+ def _extract_conscience_execution_values(result: Any) -> tuple[str, bool, str, str | None]:
549
+ """Extract core values from conscience execution result."""
550
+ selected_action = str(result.final_action.selected_action)
551
+ conscience_passed = not result.overridden
552
+ action_result = str(result.final_action)
553
+ override_reason = str(result.override_reason) if result.overridden else None
554
+ return selected_action, conscience_passed, action_result, override_reason
555
+
556
+
557
+ def _build_conscience_result_from_check(
558
+ conscience_check_result: Any, override_reason: Optional[str] # ConscienceCheckResult
559
+ ) -> Any: # ConscienceResult
560
+ """Build ConscienceResult from ConscienceCheckResult."""
561
+ from ciris_engine.schemas.conscience.results import ConscienceResult
562
+
563
+ # Build details dict, excluding None values
564
+ details = {"status": conscience_check_result.status.value if conscience_check_result.status else "unknown"}
565
+
566
+ if conscience_check_result.entropy_check:
567
+ details["entropy_passed"] = conscience_check_result.entropy_check.passed
568
+
569
+ if conscience_check_result.coherence_check:
570
+ details["coherence_passed"] = conscience_check_result.coherence_check.passed
571
+
572
+ if conscience_check_result.optimization_veto_check:
573
+ details["optimization_veto"] = conscience_check_result.optimization_veto_check.decision
574
+
575
+ if conscience_check_result.epistemic_humility_check:
576
+ details["epistemic_humility"] = conscience_check_result.epistemic_humility_check.epistemic_certainty
577
+
578
+ return ConscienceResult(
579
+ conscience_name="conscience_execution",
580
+ passed=conscience_check_result.passed,
581
+ severity="critical" if not conscience_check_result.passed else "info",
582
+ message=conscience_check_result.reason or "Conscience check completed",
583
+ override_action=override_reason,
584
+ details=details,
585
+ )
586
+
587
+
588
+ def _create_conscience_execution_data(
589
+ base_data: BaseStepData, result: Any, args: Tuple[Any, ...]
590
+ ) -> ConscienceExecutionStepData:
591
+ """Add CONSCIENCE_EXECUTION specific data with full transparency."""
592
+ # Validate result structure using helper
593
+ _validate_conscience_execution_result(result)
594
+
595
+ # Extract core values using helper
596
+ selected_action, conscience_passed, action_result, override_reason = _extract_conscience_execution_values(result)
597
+
598
+ # Extract action rationale from INPUT action_result (args[0]) - this is what goes into conscience
599
+ # The ASPDMA_RESULT event shows the action BEFORE conscience validation
600
+ if not args or len(args) == 0:
601
+ raise ValueError("CONSCIENCE_EXECUTION requires action_result as first argument")
602
+
603
+ input_action_result = args[0] # This is the ActionSelectionDMAResult passed to conscience
604
+ action_rationale = input_action_result.rationale
605
+
606
+ # Extract ASPDMA prompt if available (set by evaluator in user_prompt field)
607
+ aspdma_prompt = getattr(input_action_result, "user_prompt", None)
608
+
609
+ # Create comprehensive conscience evaluation details for full transparency
610
+ conscience_check_result = _create_comprehensive_conscience_result(result)
611
+
612
+ # Build conscience result using helper
613
+ conscience_result = _build_conscience_result_from_check(conscience_check_result, override_reason)
614
+
615
+ return ConscienceExecutionStepData(
616
+ **_base_data_dict(base_data),
617
+ selected_action=selected_action,
618
+ action_rationale=action_rationale,
619
+ conscience_passed=conscience_passed,
620
+ action_result=action_result,
621
+ override_reason=override_reason,
622
+ conscience_result=conscience_result,
623
+ aspdma_prompt=aspdma_prompt,
624
+ )
625
+
626
+
627
+ def _create_entropy_check(passed: bool) -> Any: # EntropyCheckResult
628
+ """Create entropy check result for conscience evaluation."""
629
+ from ciris_engine.schemas.conscience.core import EntropyCheckResult
630
+
631
+ return EntropyCheckResult(
632
+ passed=passed,
633
+ entropy_score=0.3, # Mock value - in real implementation would come from actual entropy calculation
634
+ threshold=0.5,
635
+ message=(
636
+ "Entropy check: Action maintains appropriate information uncertainty"
637
+ if passed
638
+ else "Entropy check failed: Action reduces information uncertainty below threshold"
639
+ ),
640
+ )
641
+
642
+
643
+ def _create_coherence_check(passed: bool) -> Any: # CoherenceCheckResult
644
+ """Create coherence check result for conscience evaluation."""
645
+ from ciris_engine.schemas.conscience.core import CoherenceCheckResult
646
+
647
+ return CoherenceCheckResult(
648
+ passed=passed,
649
+ coherence_score=0.8, # Mock value - in real implementation would come from coherence analysis
650
+ threshold=0.6,
651
+ message=(
652
+ "Coherence check: Action maintains internal consistency"
653
+ if passed
654
+ else "Coherence check failed: Action creates internal inconsistencies"
655
+ ),
656
+ )
657
+
658
+
659
+ def _create_optimization_veto_check(passed: bool) -> Any: # OptimizationVetoResult
660
+ """Create optimization veto check result for conscience evaluation."""
661
+ from ciris_engine.schemas.conscience.core import OptimizationVetoResult
662
+
663
+ return OptimizationVetoResult(
664
+ decision="proceed" if passed else "abort",
665
+ justification=(
666
+ "Action aligns with preservation of human values"
667
+ if passed
668
+ else "Action may compromise human values - optimization vetoed"
669
+ ),
670
+ entropy_reduction_ratio=0.15, # Mock value
671
+ affected_values=[] if passed else ["human_autonomy", "epistemic_humility"],
672
+ )
673
+
674
+
675
+ def _create_epistemic_humility_check(passed: bool) -> Any: # EpistemicHumilityResult
676
+ """Create epistemic humility check result for conscience evaluation."""
677
+ from ciris_engine.schemas.conscience.core import EpistemicHumilityResult
678
+
679
+ return EpistemicHumilityResult(
680
+ epistemic_certainty=0.7, # Mock value - appropriate certainty level
681
+ identified_uncertainties=["action_outcome_variance", "context_completeness"] if not passed else [],
682
+ reflective_justification=(
683
+ "Action demonstrates appropriate uncertainty about outcomes"
684
+ if passed
685
+ else "Action shows overconfidence requiring reflection"
686
+ ),
687
+ recommended_action="proceed" if passed else "ponder",
688
+ )
689
+
690
+
691
+ def _create_comprehensive_conscience_result(result: Any) -> Any: # ConscienceCheckResult
692
+ """Create comprehensive ConscienceCheckResult with all 4 typed evaluations for transparency."""
693
+ from datetime import datetime, timezone
694
+
695
+ from ciris_engine.schemas.conscience.core import ConscienceCheckResult, ConscienceStatus, EpistemicData
696
+
697
+ # Determine overall conscience status
698
+ status = ConscienceStatus.FAILED if result.overridden else ConscienceStatus.PASSED
699
+ passed = not result.overridden
700
+ reason = result.override_reason if result.overridden else None
701
+
702
+ # Create the 4 required typed conscience evaluations using helpers
703
+ entropy_check = _create_entropy_check(passed)
704
+ coherence_check = _create_coherence_check(passed)
705
+ optimization_veto_check = _create_optimization_veto_check(passed)
706
+ epistemic_humility_check = _create_epistemic_humility_check(passed)
707
+
708
+ # Create epistemic metadata
709
+ epistemic_data = EpistemicData(
710
+ entropy_level=entropy_check.entropy_score,
711
+ coherence_level=coherence_check.coherence_score,
712
+ uncertainty_acknowledged=True,
713
+ reasoning_transparency=0.9, # High transparency due to detailed reporting
714
+ )
715
+
716
+ # Build comprehensive conscience result
717
+ conscience_result = ConscienceCheckResult(
718
+ status=status,
719
+ passed=passed,
720
+ reason=reason,
721
+ epistemic_data=epistemic_data,
722
+ entropy_check=entropy_check,
723
+ coherence_check=coherence_check,
724
+ optimization_veto_check=optimization_veto_check,
725
+ epistemic_humility_check=epistemic_humility_check,
726
+ entropy_score=entropy_check.entropy_score,
727
+ coherence_score=coherence_check.coherence_score,
728
+ check_timestamp=datetime.now(timezone.utc),
729
+ processing_time_ms=None, # Could be calculated if timing info available
730
+ original_action=result.original_action.model_dump(),
731
+ replacement_action=result.final_action.model_dump() if result.overridden else None,
732
+ thought_depth_triggered=getattr(result, "thought_depth_triggered", None),
733
+ updated_status_detected=getattr(result, "updated_status_detected", None),
734
+ )
735
+
736
+ return conscience_result
737
+
738
+
739
+ def _create_recursive_aspdma_data(
740
+ base_data: BaseStepData, result: Any, args: Tuple[Any, ...]
741
+ ) -> RecursiveASPDMAStepData:
742
+ """Create RECURSIVE_ASPDMA specific typed data."""
743
+ if not args:
744
+ raise ValueError("RECURSIVE_ASPDMA args is empty - retry reason is required")
745
+
746
+ if not result:
747
+ raise ValueError("RECURSIVE_ASPDMA result is None - this indicates a serious pipeline issue")
748
+
749
+ if not hasattr(result, "selected_action"):
750
+ raise AttributeError(
751
+ f"RECURSIVE_ASPDMA result missing 'selected_action' attribute. Result type: {type(result)}, attributes: {dir(result)}"
752
+ )
753
+
754
+ return RecursiveASPDMAStepData(
755
+ **_base_data_dict(base_data), retry_reason=str(args[0]), original_action=str(result.selected_action)
756
+ )
757
+
758
+
759
+ def _create_recursive_conscience_data(base_data: BaseStepData, result: Any) -> RecursiveConscienceStepData:
760
+ """Create RECURSIVE_CONSCIENCE specific typed data."""
761
+ if not result:
762
+ raise ValueError("RECURSIVE_CONSCIENCE result is None - this indicates a serious pipeline issue")
763
+
764
+ if not hasattr(result, "selected_action"):
765
+ raise AttributeError(
766
+ f"RECURSIVE_CONSCIENCE result missing 'selected_action' attribute. Result type: {type(result)}, attributes: {dir(result)}"
767
+ )
768
+
769
+ return RecursiveConscienceStepData(
770
+ **_base_data_dict(base_data), retry_action=str(result.selected_action), retry_result=str(result)
771
+ )
772
+
773
+
774
+ def _create_finalize_action_data(base_data: BaseStepData, result: Any) -> FinalizeActionStepData:
775
+ """Create FINALIZE_ACTION specific typed data with rich conscience information."""
776
+ if not result:
777
+ raise ValueError("FINALIZE_ACTION result is None - this indicates a serious pipeline issue")
778
+
779
+ # Result should be ConscienceApplicationResult
780
+ if not hasattr(result, "final_action"):
781
+ raise AttributeError(
782
+ f"FINALIZE_ACTION result missing 'final_action' attribute. Expected ConscienceApplicationResult, got {type(result)}, attributes: {dir(result)}"
783
+ )
784
+
785
+ # Extract the final action
786
+ final_action = result.final_action
787
+ if not hasattr(final_action, "selected_action"):
788
+ raise AttributeError(
789
+ f"FINALIZE_ACTION final_action missing 'selected_action' attribute. Type: {type(final_action)}, attributes: {dir(final_action)}"
790
+ )
791
+
792
+ # Extract conscience data (epistemic_data is now REQUIRED in ConscienceApplicationResult)
793
+ conscience_passed = not result.overridden
794
+ override_reason = result.override_reason if result.overridden else None
795
+ epistemic_data = result.epistemic_data # REQUIRED field
796
+ updated_status_detected = getattr(result, "updated_status_detected", None)
797
+
798
+ return FinalizeActionStepData(
799
+ **_base_data_dict(base_data),
800
+ selected_action=str(final_action.selected_action),
801
+ conscience_passed=conscience_passed,
802
+ conscience_override_reason=override_reason,
803
+ epistemic_data=epistemic_data,
804
+ updated_status_detected=updated_status_detected,
805
+ )
806
+
807
+
808
+ def _create_perform_action_data(
809
+ base_data: BaseStepData, result: Any, args: Tuple[Any, ...], kwargs: JSONDict
810
+ ) -> PerformActionStepData:
811
+ """Create PERFORM_ACTION specific typed data."""
812
+ # Extract selected_action - first try result, then args
813
+ if result and hasattr(result, "selected_action"):
814
+ selected_action = str(result.selected_action)
815
+ elif args:
816
+ selected_action = str(args[0])
817
+ else:
818
+ raise ValueError(
819
+ "PERFORM_ACTION cannot determine selected_action - neither result.selected_action nor args[0] available"
820
+ )
821
+
822
+ # Extract action_parameters - use None string if not available
823
+ action_parameters = "None"
824
+ if result and hasattr(result, "action_parameters"):
825
+ action_parameters = str(result.action_parameters)
826
+
827
+ # Extract dispatch_context from kwargs or args - provide empty dict as default
828
+ dispatch_context = "{}"
829
+ if "context" in kwargs:
830
+ dispatch_context = str(kwargs["context"])
831
+ elif len(args) > 1:
832
+ dispatch_context = str(args[1])
833
+
834
+ return PerformActionStepData(
835
+ **_base_data_dict(base_data),
836
+ selected_action=selected_action,
837
+ action_parameters=action_parameters,
838
+ dispatch_context=dispatch_context,
839
+ )
840
+
841
+
842
+ def _create_action_complete_data(
843
+ base_data: BaseStepData, result: Any, kwargs: Optional[JSONDict] = None
844
+ ) -> ActionCompleteStepData:
845
+ """Add ACTION_COMPLETE specific data with resource usage."""
846
+ if not result:
847
+ raise ValueError("ACTION_COMPLETE step result is None - this indicates a serious pipeline issue")
848
+
849
+ # Result should be ActionResponse (typed) - no more dict access
850
+ from ciris_engine.schemas.services.runtime_control import ActionResponse
851
+
852
+ if not isinstance(result, ActionResponse):
853
+ raise TypeError(
854
+ f"ACTION_COMPLETE expects ActionResponse, got {type(result)}. "
855
+ f"Handlers must return ActionResponse with audit_data."
856
+ )
857
+
858
+ # Extract resource usage data if available (passed via kwargs from decorator)
859
+ kwargs_dict = kwargs or {}
860
+ resource_data = get_dict(kwargs_dict, "_resource_usage", {})
861
+
862
+ return ActionCompleteStepData(
863
+ **_base_data_dict(base_data),
864
+ action_executed=result.action_type,
865
+ dispatch_success=result.success,
866
+ handler_completed=result.handler != "Unknown",
867
+ follow_up_processing_pending=bool(result.follow_up_thought_id),
868
+ follow_up_thought_id=result.follow_up_thought_id,
869
+ execution_time_ms=result.execution_time_ms,
870
+ # Audit data from AuditEntryResult (REQUIRED fields)
871
+ audit_entry_id=result.audit_data.entry_id,
872
+ audit_sequence_number=result.audit_data.sequence_number,
873
+ audit_entry_hash=result.audit_data.entry_hash,
874
+ audit_signature=result.audit_data.signature,
875
+ # Resource usage (queried from telemetry by thought_id)
876
+ tokens_total=get_int(resource_data, "tokens_total", 0),
877
+ tokens_input=get_int(resource_data, "tokens_input", 0),
878
+ tokens_output=get_int(resource_data, "tokens_output", 0),
879
+ cost_cents=get_float(resource_data, "cost_cents", 0.0),
880
+ carbon_grams=get_float(resource_data, "carbon_grams", 0.0),
881
+ energy_mwh=get_float(resource_data, "energy_mwh", 0.0),
882
+ llm_calls=get_int(resource_data, "llm_calls", 0),
883
+ models_used=get_list(resource_data, "models_used", []),
884
+ )
885
+
886
+
887
+ def _create_round_complete_data(base_data: BaseStepData, args: Tuple[Any, ...]) -> RoundCompleteStepData:
888
+ """Create ROUND_COMPLETE specific typed data."""
889
+ if not args:
890
+ raise ValueError("ROUND_COMPLETE args is empty - completed thought count is required")
891
+
892
+ return RoundCompleteStepData(**_base_data_dict(base_data), round_status="completed", thoughts_processed=len(args))
893
+
894
+
895
+ def _create_step_result_schema(step: StepPoint, step_data: StepDataUnion) -> Any:
896
+ """Create appropriate step result schema based on step type."""
897
+ # Import here to avoid circular dependency
898
+ from ciris_engine.schemas.services.runtime_control import (
899
+ StepResultActionComplete,
900
+ StepResultConscienceExecution,
901
+ StepResultFinalizeAction,
902
+ StepResultGatherContext,
903
+ StepResultPerformAction,
904
+ StepResultPerformASPDMA,
905
+ StepResultPerformDMAs,
906
+ StepResultRecursiveASPDMA,
907
+ StepResultRecursiveConscience,
908
+ StepResultRoundComplete,
909
+ StepResultStartRound,
910
+ )
911
+
912
+ step_result_map = {
913
+ StepPoint.START_ROUND: StepResultStartRound,
914
+ StepPoint.GATHER_CONTEXT: StepResultGatherContext,
915
+ StepPoint.PERFORM_DMAS: StepResultPerformDMAs,
916
+ StepPoint.PERFORM_ASPDMA: StepResultPerformASPDMA,
917
+ StepPoint.CONSCIENCE_EXECUTION: StepResultConscienceExecution,
918
+ StepPoint.RECURSIVE_ASPDMA: StepResultRecursiveASPDMA,
919
+ StepPoint.RECURSIVE_CONSCIENCE: StepResultRecursiveConscience,
920
+ StepPoint.FINALIZE_ACTION: StepResultFinalizeAction,
921
+ StepPoint.PERFORM_ACTION: StepResultPerformAction,
922
+ StepPoint.ACTION_COMPLETE: StepResultActionComplete,
923
+ StepPoint.ROUND_COMPLETE: StepResultRoundComplete,
924
+ }
925
+
926
+ result_class = step_result_map.get(step)
927
+ if result_class:
928
+ if step == StepPoint.GATHER_CONTEXT:
929
+ logger.debug(f"Creating StepResultGatherContext with step_data type: {type(step_data)}, data: {step_data}")
930
+ return result_class(**step_data.model_dump())
931
+ return None
932
+
933
+
934
+ def _extract_timing_data(step_data: StepDataUnion) -> Tuple[Any, Any]:
935
+ """Extract and normalize timing data from typed step_data."""
936
+ from datetime import datetime, timezone
937
+
938
+ timestamp_str = step_data.timestamp if step_data.timestamp else datetime.now().isoformat()
939
+ # Ensure both timestamps have timezone info for consistent calculation
940
+ if timestamp_str.endswith("+00:00") or timestamp_str.endswith("Z"):
941
+ start_time = datetime.fromisoformat(timestamp_str.replace("Z", "+00:00"))
942
+ else:
943
+ start_time = datetime.fromisoformat(timestamp_str).replace(tzinfo=timezone.utc)
944
+ end_time = datetime.now(timezone.utc)
945
+
946
+ return start_time, end_time
947
+
948
+
949
+ def _build_step_result_data(
950
+ step: StepPoint,
951
+ step_data: StepDataUnion,
952
+ trace_context: TraceContext,
953
+ span_attributes: List[SpanAttribute],
954
+ ) -> StepResultData:
955
+ """Build the complete step result data structure."""
956
+ return StepResultData(
957
+ step_point=step.value,
958
+ success=step_data.success,
959
+ processing_time_ms=step_data.processing_time_ms,
960
+ thought_id=step_data.thought_id,
961
+ task_id=step_data.task_id or "",
962
+ step_data=step_data, # Use the typed step data object directly
963
+ # Enhanced trace data for OTLP compatibility
964
+ trace_context=trace_context,
965
+ span_attributes=span_attributes,
966
+ otlp_compatible=True,
967
+ )
968
+
969
+
970
+ async def _broadcast_step_result(step: StepPoint, step_data: StepDataUnion) -> None:
971
+ """Broadcast step result to global step result stream (DEPRECATED - use reasoning events)."""
972
+ # OLD BROADCASTING - TO BE REMOVED
973
+ # Keep for now to avoid breaking changes, but reasoning events are the future
974
+ pass
975
+
976
+
977
+ async def _broadcast_reasoning_event(
978
+ step: StepPoint, step_data: StepDataUnion, is_recursive: bool = False, thought_item: Any = None
979
+ ) -> None:
980
+ """
981
+ Broadcast simplified reasoning event for one of the 6 key steps.
982
+
983
+ CORRECT Step Point Mapping:
984
+ 0. START_ROUND → THOUGHT_START (thought + task metadata)
985
+ 1. GATHER_CONTEXT + PERFORM_DMAS → SNAPSHOT_AND_CONTEXT (snapshot + context)
986
+ 2. PERFORM_DMAS → DMA_RESULTS (Results of the 3 DMAs: CSDMA, DSDMA, PDMA)
987
+ 3. PERFORM_ASPDMA → ASPDMA_RESULT (result of ASPDMA action selection)
988
+ 4. CONSCIENCE_EXECUTION (+ RECURSIVE_CONSCIENCE) → CONSCIENCE_RESULT (result of 5 consciences, with is_recursive flag)
989
+ 5. ACTION_COMPLETE → ACTION_RESULT (execution + audit)
990
+ """
991
+ logger.debug(f"[BROADCAST DEBUG] _broadcast_reasoning_event called for step {step.value}")
992
+ try:
993
+ from ciris_engine.logic.infrastructure.step_streaming import reasoning_event_stream
994
+ from ciris_engine.schemas.streaming.reasoning_stream import create_reasoning_event
995
+
996
+ logger.debug("[BROADCAST DEBUG] Imports successful")
997
+
998
+ event = None
999
+ timestamp = step_data.timestamp or datetime.now().isoformat()
1000
+ logger.debug(f"[BROADCAST DEBUG] timestamp={timestamp}, step={step.value}")
1001
+
1002
+ # Map step points to reasoning events using helper functions
1003
+ if step == StepPoint.START_ROUND:
1004
+ # Event 0: THOUGHT_START
1005
+ event = _create_thought_start_event(step_data, timestamp, create_reasoning_event, thought_item)
1006
+
1007
+ elif step in (StepPoint.GATHER_CONTEXT, StepPoint.PERFORM_DMAS):
1008
+ # Event 1: SNAPSHOT_AND_CONTEXT (emitted at PERFORM_DMAS only)
1009
+ if step == StepPoint.PERFORM_DMAS:
1010
+ logger.debug("[BROADCAST DEBUG] Creating SNAPSHOT_AND_CONTEXT event")
1011
+ event = _create_snapshot_and_context_event(step_data, timestamp, create_reasoning_event, thought_item)
1012
+
1013
+ elif step == StepPoint.PERFORM_ASPDMA:
1014
+ # Event 2: DMA_RESULTS - get InitialDMAResults from step_data.dma_results (extracted from args)
1015
+ # step_data for PERFORM_ASPDMA contains dma_results from the previous PERFORM_DMAS step
1016
+ dma_results_for_event = getattr(step_data, "dma_results_obj", None)
1017
+ if dma_results_for_event:
1018
+ event = _create_dma_results_event(step_data, timestamp, dma_results_for_event, create_reasoning_event)
1019
+ else:
1020
+ logger.warning(f"No dma_results_obj found in step_data for PERFORM_ASPDMA step {step_data.thought_id}")
1021
+
1022
+ elif step in (StepPoint.CONSCIENCE_EXECUTION, StepPoint.RECURSIVE_CONSCIENCE):
1023
+ # Event 3: ASPDMA_RESULT
1024
+ is_recursive_step = step == StepPoint.RECURSIVE_CONSCIENCE
1025
+ event = _create_aspdma_result_event(step_data, timestamp, is_recursive_step, create_reasoning_event)
1026
+
1027
+ elif step == StepPoint.FINALIZE_ACTION:
1028
+ # Event 4: CONSCIENCE_RESULT
1029
+ event = _create_conscience_result_event(step_data, timestamp, create_reasoning_event)
1030
+
1031
+ elif step == StepPoint.ACTION_COMPLETE:
1032
+ # Event 5: ACTION_RESULT
1033
+ event = _create_action_result_event(step_data, timestamp, create_reasoning_event)
1034
+
1035
+ # Broadcast the event if we created one
1036
+ if event:
1037
+ logger.debug(
1038
+ f" Broadcasting reasoning event - type={event.event_type}, task_id={step_data.task_id}, thought_id={step_data.thought_id}"
1039
+ )
1040
+ await reasoning_event_stream.broadcast_reasoning_event(event)
1041
+ logger.debug(f" Broadcast complete - type={event.event_type}, task_id={step_data.task_id}")
1042
+ else:
1043
+ logger.debug(f" No event created for step {step.value}, task_id={step_data.task_id}")
1044
+
1045
+ except Exception as e:
1046
+ logger.warning(f"Error broadcasting reasoning event for {step.value}: {e}")
1047
+
1048
+
1049
+ # Public API functions for single-step control
1050
+
1051
+
1052
+ def enable_single_step_mode() -> None:
1053
+ """Enable single-step mode - thoughts will pause at step points."""
1054
+ global _single_step_mode
1055
+ _single_step_mode = True
1056
+ logger.info("Single-step mode enabled")
1057
+
1058
+
1059
+ def disable_single_step_mode() -> None:
1060
+ """Disable single-step mode - thoughts run normally."""
1061
+ global _single_step_mode
1062
+ _single_step_mode = False
1063
+ logger.info("Single-step mode disabled")
1064
+
1065
+
1066
+ def is_single_step_mode() -> bool:
1067
+ """Check if single-step mode is enabled."""
1068
+ return _single_step_mode
1069
+
1070
+
1071
+ async def execute_step(thought_id: str) -> StepExecutionResult:
1072
+ """
1073
+ Execute one step for a paused thought.
1074
+
1075
+ Args:
1076
+ thought_id: ID of the thought to advance one step
1077
+
1078
+ Returns:
1079
+ Status dict indicating success/failure
1080
+ """
1081
+ global _paused_thoughts
1082
+
1083
+ if thought_id not in _paused_thoughts:
1084
+ return StepExecutionResult(
1085
+ success=False,
1086
+ error=f"Thought {thought_id} is not paused or does not exist",
1087
+ thought_id=thought_id,
1088
+ )
1089
+
1090
+ try:
1091
+ # Resume the thought coroutine
1092
+ _paused_thoughts[thought_id].set()
1093
+
1094
+ return StepExecutionResult(
1095
+ success=True,
1096
+ thought_id=thought_id,
1097
+ message="Thought advanced one step",
1098
+ )
1099
+
1100
+ except Exception as e:
1101
+ logger.error(f"Error executing step for thought {thought_id}: {e}")
1102
+ return StepExecutionResult(
1103
+ success=False,
1104
+ error=str(e),
1105
+ thought_id=thought_id,
1106
+ )
1107
+
1108
+
1109
+ async def execute_all_steps() -> AllStepsExecutionResult:
1110
+ """
1111
+ Execute one step for all paused thoughts.
1112
+
1113
+ Returns:
1114
+ Status dict with count of thoughts advanced
1115
+ """
1116
+ global _paused_thoughts
1117
+
1118
+ if not _paused_thoughts:
1119
+ return AllStepsExecutionResult(
1120
+ success=True,
1121
+ thoughts_advanced=0,
1122
+ message="No thoughts currently paused",
1123
+ )
1124
+
1125
+ try:
1126
+ # Resume all paused thoughts
1127
+ for event in _paused_thoughts.values():
1128
+ event.set()
1129
+
1130
+ count = len(_paused_thoughts)
1131
+
1132
+ return AllStepsExecutionResult(
1133
+ success=True,
1134
+ thoughts_advanced=count,
1135
+ message=f"Advanced {count} thoughts one step",
1136
+ )
1137
+
1138
+ except Exception as e:
1139
+ logger.error(f"Error executing steps for all thoughts: {e}")
1140
+ return AllStepsExecutionResult(
1141
+ success=False,
1142
+ error=str(e),
1143
+ thoughts_advanced=0,
1144
+ )
1145
+
1146
+
1147
+ def get_paused_thoughts() -> Dict[str, str]:
1148
+ """
1149
+ Get list of currently paused thoughts.
1150
+
1151
+ Returns:
1152
+ Dict mapping thought_id to status
1153
+ """
1154
+ global _paused_thoughts
1155
+
1156
+ return dict.fromkeys(_paused_thoughts.keys(), "paused_awaiting_resume")
1157
+
1158
+
1159
+ # Enhanced trace data builders for OTLP compatibility
1160
+
1161
+
1162
+ def _build_trace_context_dict(
1163
+ thought_id: str, task_id: Optional[str], step: StepPoint, start_time: Any, end_time: Any
1164
+ ) -> TraceContext:
1165
+ """
1166
+ Build trace context compatible with OTLP format.
1167
+
1168
+ This ensures streaming and OTLP traces have consistent trace correlation data.
1169
+ """
1170
+ import hashlib
1171
+ import time
1172
+
1173
+ # Generate trace and span IDs using same logic as OTLP converter
1174
+ trace_base = f"{thought_id}_{task_id or 'no_task'}_{step.value}"
1175
+ trace_id = hashlib.sha256(trace_base.encode()).hexdigest()[:32].upper()
1176
+
1177
+ span_base = f"{trace_id}_{step.value}_{start_time.timestamp()}"
1178
+ span_id = hashlib.sha256(span_base.encode()).hexdigest()[:16].upper()
1179
+
1180
+ # Build parent span relationship - each step in the same thought is related
1181
+ parent_span_base = f"{thought_id}_pipeline_{task_id or 'no_task'}"
1182
+ parent_span_id = hashlib.sha256(parent_span_base.encode()).hexdigest()[:16].upper()
1183
+
1184
+ return TraceContext(
1185
+ trace_id=trace_id,
1186
+ span_id=span_id,
1187
+ parent_span_id=parent_span_id,
1188
+ span_name=f"h3ere.{step.value}",
1189
+ operation_name=f"H3ERE.{step.value}",
1190
+ start_time_ns=int(start_time.timestamp() * 1e9),
1191
+ end_time_ns=int(end_time.timestamp() * 1e9),
1192
+ duration_ns=int((end_time - start_time).total_seconds() * 1e9),
1193
+ span_kind="internal", # H3ERE pipeline steps are internal operations
1194
+ )
1195
+
1196
+
1197
+ def _extract_follow_up_thought_id(result: Any) -> Optional[str]:
1198
+ """
1199
+ Extract follow-up thought ID from ACTION_COMPLETE result.
1200
+
1201
+ According to the requirement: Anything but DEFER, REJECT, or TASK_COMPLETE
1202
+ should have a follow-up thought created.
1203
+
1204
+ Args:
1205
+ result: The ACTION_COMPLETE step result (dict or object)
1206
+
1207
+ Returns:
1208
+ Follow-up thought ID if available, None otherwise
1209
+ """
1210
+ # Terminal actions that don't create follow-ups
1211
+ TERMINAL_ACTIONS = {"DEFER", "REJECT", "TASK_COMPLETE"}
1212
+
1213
+ # Try to extract from dict format (primary path)
1214
+ if isinstance(result, dict):
1215
+ # Check action type FIRST to determine if follow-up should exist
1216
+ action_type = result.get("action_type", "").upper()
1217
+
1218
+ if action_type in TERMINAL_ACTIONS:
1219
+ # These actions should NOT have follow-ups, even if ID is present
1220
+ return None
1221
+
1222
+ # For non-terminal actions, extract the follow_up_thought_id
1223
+ return result.get("follow_up_thought_id")
1224
+
1225
+ # Try to extract from object format
1226
+ if hasattr(result, "follow_up_thought_id"):
1227
+ return str(result.follow_up_thought_id) if result.follow_up_thought_id else None
1228
+
1229
+ # Check for alternative attribute names
1230
+ if hasattr(result, "follow_up_id"):
1231
+ return str(result.follow_up_id) if result.follow_up_id else None
1232
+
1233
+ return None
1234
+
1235
+
1236
+ def _extract_lightweight_system_snapshot() -> SystemSnapshot:
1237
+ """
1238
+ Extract lightweight system snapshot for reasoning event context.
1239
+
1240
+ Returns a proper SystemSnapshot object with minimal fields populated.
1241
+ This is used for SSE streaming and must be a concrete typed object.
1242
+ """
1243
+ from datetime import timezone
1244
+
1245
+ # Create a minimal SystemSnapshot with current time
1246
+ snapshot = SystemSnapshot(
1247
+ current_time_utc=datetime.now(timezone.utc).isoformat(),
1248
+ )
1249
+
1250
+ return snapshot
1251
+
1252
+
1253
+ def _create_thought_start_event(
1254
+ step_data: StepDataUnion, timestamp: str, create_reasoning_event: Any, thought_item: Any = None
1255
+ ) -> Any:
1256
+ """Create THOUGHT_START reasoning event with thought and task metadata."""
1257
+ from ciris_engine.logic.persistence import get_task_by_id, get_thought_by_id
1258
+ from ciris_engine.schemas.services.runtime_control import ReasoningEvent
1259
+
1260
+ # Get occurrence_id from thought_item if available
1261
+ occurrence_id = getattr(thought_item, "agent_occurrence_id", "default") if thought_item else "default"
1262
+
1263
+ # Get full thought and task data from persistence
1264
+ thought = get_thought_by_id(step_data.thought_id, occurrence_id)
1265
+ task = get_task_by_id(step_data.task_id) if step_data.task_id else None
1266
+
1267
+ return create_reasoning_event(
1268
+ event_type=ReasoningEvent.THOUGHT_START,
1269
+ thought_id=step_data.thought_id,
1270
+ task_id=step_data.task_id or "",
1271
+ timestamp=timestamp,
1272
+ # Thought metadata
1273
+ thought_type=thought.thought_type.value if thought else "unknown",
1274
+ thought_content=thought.content if thought else "",
1275
+ thought_status=thought.status.value if thought else "unknown",
1276
+ round_number=thought.round_number if thought else 0,
1277
+ thought_depth=thought.thought_depth if thought else 0,
1278
+ parent_thought_id=thought.parent_thought_id if thought else None,
1279
+ # Task metadata
1280
+ task_description=task.description if task else "",
1281
+ task_priority=task.priority if task else 0,
1282
+ channel_id=task.channel_id if task else "",
1283
+ updated_info_available=task.updated_info_available if task else False,
1284
+ )
1285
+
1286
+
1287
+ def _create_snapshot_and_context_event(
1288
+ step_data: StepDataUnion, timestamp: str, create_reasoning_event: Any, thought_item: Any = None
1289
+ ) -> Any:
1290
+ """Create SNAPSHOT_AND_CONTEXT reasoning event with full system snapshot from thought context."""
1291
+ from ciris_engine.schemas.services.runtime_control import ReasoningEvent
1292
+
1293
+ # Extract full SystemSnapshot from thought_item.initial_context
1294
+ # Note: context string field removed - all data is in system_snapshot
1295
+ system_snapshot = None
1296
+ if thought_item and hasattr(thought_item, "initial_context"):
1297
+ initial_context = thought_item.initial_context
1298
+ if isinstance(initial_context, dict):
1299
+ # Extract system_snapshot from ProcessingThoughtContext dict
1300
+ system_snapshot = initial_context.get("system_snapshot")
1301
+ elif hasattr(initial_context, "system_snapshot"):
1302
+ # Extract from ProcessingThoughtContext object
1303
+ system_snapshot = initial_context.system_snapshot
1304
+
1305
+ # Fallback to minimal snapshot if we couldn't extract the full one
1306
+ if not system_snapshot:
1307
+ logger.warning("Could not extract full SystemSnapshot from thought_item, using minimal snapshot")
1308
+ system_snapshot = _extract_lightweight_system_snapshot()
1309
+
1310
+ return create_reasoning_event(
1311
+ event_type=ReasoningEvent.SNAPSHOT_AND_CONTEXT,
1312
+ thought_id=step_data.thought_id,
1313
+ task_id=step_data.task_id,
1314
+ timestamp=timestamp,
1315
+ system_snapshot=system_snapshot,
1316
+ )
1317
+
1318
+
1319
+ def _create_dma_results_event(
1320
+ step_data: StepDataUnion, timestamp: str, dma_results: Any, create_reasoning_event: Any
1321
+ ) -> Any:
1322
+ """
1323
+ Create DMA_RESULTS reasoning event from InitialDMAResults.
1324
+
1325
+ This event is broadcast at the START of PERFORM_ASPDMA step, using the
1326
+ result parameter which contains InitialDMAResults from PERFORM_DMAS.
1327
+ """
1328
+ from ciris_engine.schemas.services.runtime_control import ReasoningEvent
1329
+
1330
+ # Extract the 3 DMA results from InitialDMAResults object - pass concrete typed objects
1331
+ if not dma_results:
1332
+ raise ValueError(f"DMA results is None or empty: {dma_results}")
1333
+ if not hasattr(dma_results, "csdma"):
1334
+ raise ValueError(
1335
+ f"DMA results missing 'csdma' attribute. Type: {type(dma_results)}, attributes: {dir(dma_results)}"
1336
+ )
1337
+
1338
+ # All 3 DMA results are required (non-optional)
1339
+ if not dma_results.csdma:
1340
+ raise ValueError(f"CSDMA result is None: {dma_results.csdma}")
1341
+ if not dma_results.dsdma:
1342
+ raise ValueError(f"DSDMA result is None: {dma_results.dsdma}")
1343
+ if not dma_results.ethical_pdma:
1344
+ raise ValueError(f"Ethical PDMA result is None: {dma_results.ethical_pdma}")
1345
+
1346
+ # Extract prompts if available (for debugging/transparency)
1347
+ csdma_prompt = getattr(dma_results, "csdma_prompt", None)
1348
+ dsdma_prompt = getattr(dma_results, "dsdma_prompt", None)
1349
+ pdma_prompt = getattr(dma_results, "ethical_pdma_prompt", None)
1350
+
1351
+ return create_reasoning_event(
1352
+ event_type=ReasoningEvent.DMA_RESULTS,
1353
+ thought_id=step_data.thought_id,
1354
+ task_id=step_data.task_id,
1355
+ timestamp=timestamp,
1356
+ csdma=dma_results.csdma, # Pass CSDMAResult object directly
1357
+ dsdma=dma_results.dsdma, # Pass DSDMAResult object directly
1358
+ pdma=dma_results.ethical_pdma, # Pass EthicalDMAResult object directly
1359
+ csdma_prompt=csdma_prompt, # User prompt passed to CSDMA
1360
+ dsdma_prompt=dsdma_prompt, # User prompt passed to DSDMA
1361
+ pdma_prompt=pdma_prompt, # User prompt passed to PDMA
1362
+ )
1363
+
1364
+
1365
+ def _create_aspdma_result_event(
1366
+ step_data: StepDataUnion, timestamp: str, is_recursive: bool, create_reasoning_event: Any
1367
+ ) -> Any:
1368
+ """Create ASPDMA_RESULT reasoning event."""
1369
+ from ciris_engine.schemas.services.runtime_control import ReasoningEvent
1370
+
1371
+ # Extract ASPDMA prompt if available (from ConscienceExecutionStepData)
1372
+ aspdma_prompt = getattr(step_data, "aspdma_prompt", None)
1373
+
1374
+ return create_reasoning_event(
1375
+ event_type=ReasoningEvent.ASPDMA_RESULT,
1376
+ thought_id=step_data.thought_id,
1377
+ task_id=step_data.task_id,
1378
+ timestamp=timestamp,
1379
+ is_recursive=is_recursive,
1380
+ selected_action=getattr(step_data, "selected_action", ""),
1381
+ action_rationale=getattr(step_data, "action_rationale", ""),
1382
+ aspdma_prompt=aspdma_prompt, # User prompt passed to ASPDMA
1383
+ )
1384
+
1385
+
1386
+ def _create_conscience_result_event(step_data: StepDataUnion, timestamp: str, create_reasoning_event: Any) -> Any:
1387
+ """Create CONSCIENCE_RESULT reasoning event."""
1388
+ from ciris_engine.schemas.services.runtime_control import ReasoningEvent
1389
+
1390
+ return create_reasoning_event(
1391
+ event_type=ReasoningEvent.CONSCIENCE_RESULT,
1392
+ thought_id=step_data.thought_id,
1393
+ task_id=step_data.task_id,
1394
+ timestamp=timestamp,
1395
+ is_recursive=False, # FINALIZE_ACTION is never recursive
1396
+ conscience_passed=getattr(step_data, "conscience_passed", True),
1397
+ conscience_override_reason=getattr(step_data, "conscience_override_reason", None),
1398
+ epistemic_data=getattr(step_data, "epistemic_data", {}),
1399
+ final_action=getattr(step_data, "selected_action", ""),
1400
+ action_was_overridden=not getattr(step_data, "conscience_passed", True),
1401
+ updated_status_available=getattr(step_data, "updated_status_detected", None),
1402
+ )
1403
+
1404
+
1405
+ def _create_action_result_event(step_data: StepDataUnion, timestamp: str, create_reasoning_event: Any) -> Any:
1406
+ """Create ACTION_RESULT reasoning event with audit trail, resource usage, and follow-up data."""
1407
+ from ciris_engine.schemas.services.runtime_control import ReasoningEvent
1408
+
1409
+ # Extract follow_up_thought_id from step_data (already populated from dispatch_result)
1410
+ follow_up_thought_id = getattr(step_data, "follow_up_thought_id", None)
1411
+
1412
+ return create_reasoning_event(
1413
+ event_type=ReasoningEvent.ACTION_RESULT,
1414
+ thought_id=step_data.thought_id,
1415
+ task_id=step_data.task_id,
1416
+ timestamp=timestamp,
1417
+ action_executed=getattr(step_data, "action_executed", ""),
1418
+ execution_success=getattr(step_data, "dispatch_success", True),
1419
+ execution_time_ms=getattr(step_data, "execution_time_ms", 0.0),
1420
+ follow_up_thought_id=follow_up_thought_id,
1421
+ error=None,
1422
+ audit_entry_id=getattr(step_data, "audit_entry_id", None),
1423
+ audit_sequence_number=getattr(step_data, "audit_sequence_number", None),
1424
+ audit_entry_hash=getattr(step_data, "audit_entry_hash", None),
1425
+ audit_signature=getattr(step_data, "audit_signature", None),
1426
+ # Resource usage fields (queried from telemetry by thought_id)
1427
+ tokens_total=getattr(step_data, "tokens_total", 0),
1428
+ tokens_input=getattr(step_data, "tokens_input", 0),
1429
+ tokens_output=getattr(step_data, "tokens_output", 0),
1430
+ cost_cents=getattr(step_data, "cost_cents", 0.0),
1431
+ carbon_grams=getattr(step_data, "carbon_grams", 0.0),
1432
+ energy_mwh=getattr(step_data, "energy_mwh", 0.0),
1433
+ llm_calls=getattr(step_data, "llm_calls", 0),
1434
+ models_used=getattr(step_data, "models_used", []),
1435
+ )
1436
+
1437
+
1438
+ def _build_span_attributes_dict(step: StepPoint, step_result: Any, step_data: StepDataUnion) -> List[SpanAttribute]:
1439
+ """
1440
+ Build span attributes compatible with OTLP format.
1441
+
1442
+ This creates rich attribute data that's consistent between streaming and OTLP traces.
1443
+ """
1444
+ thought_id = step_data.thought_id
1445
+ task_id = step_data.task_id
1446
+
1447
+ # Start with core CIRIS attributes (matching OTLP format)
1448
+ attributes = [
1449
+ SpanAttribute(key="ciris.step_point", value={"stringValue": step.value}),
1450
+ SpanAttribute(key="ciris.thought_id", value={"stringValue": thought_id}),
1451
+ SpanAttribute(key="operation.name", value={"stringValue": f"H3ERE.{step.value}"}),
1452
+ SpanAttribute(key="service.name", value={"stringValue": "ciris-h3ere-pipeline"}),
1453
+ SpanAttribute(key="service.component", value={"stringValue": "thought_processor"}),
1454
+ SpanAttribute(key="span.success", value={"boolValue": step_data.success}),
1455
+ SpanAttribute(key="processing_time_ms", value={"doubleValue": step_data.processing_time_ms}),
1456
+ ]
1457
+
1458
+ # Add task_id if available - critical for correlation
1459
+ if task_id:
1460
+ attributes.append(SpanAttribute(key="ciris.task_id", value={"stringValue": str(task_id)}))
1461
+
1462
+ # Add step-specific attributes based on the typed step result
1463
+ if step_result and hasattr(step_result, "model_dump"):
1464
+ result_data = step_result.model_dump()
1465
+ _add_typed_step_attributes(attributes, step, result_data)
1466
+
1467
+ # Add error information if present
1468
+ error = step_data.error
1469
+ if error:
1470
+ attributes.extend(
1471
+ [
1472
+ SpanAttribute(key="error", value={"boolValue": True}),
1473
+ SpanAttribute(key="error.message", value={"stringValue": str(error)}),
1474
+ SpanAttribute(key="error.type", value={"stringValue": "ProcessingError"}),
1475
+ ]
1476
+ )
1477
+ else:
1478
+ attributes.append(SpanAttribute(key="error", value={"boolValue": False}))
1479
+
1480
+ return attributes
1481
+
1482
+
1483
+ def _add_gather_context_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1484
+ """Add attributes specific to GATHER_CONTEXT step."""
1485
+ if "context" in result_data and result_data["context"]:
1486
+ context_size = len(str(result_data["context"]))
1487
+ attributes.extend(
1488
+ [
1489
+ SpanAttribute(key="context.size_bytes", value={"intValue": context_size}),
1490
+ SpanAttribute(key="context.available", value={"boolValue": True}),
1491
+ ]
1492
+ )
1493
+
1494
+
1495
+ def _add_perform_dmas_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1496
+ """Add attributes specific to PERFORM_DMAS step."""
1497
+ if "dma_results" in result_data and result_data["dma_results"]:
1498
+ attributes.extend(
1499
+ [
1500
+ SpanAttribute(key="dma.results_available", value={"boolValue": True}),
1501
+ SpanAttribute(key="dma.results_size", value={"intValue": len(str(result_data["dma_results"]))}),
1502
+ ]
1503
+ )
1504
+ if "context" in result_data:
1505
+ attributes.append(SpanAttribute(key="dma.context_provided", value={"boolValue": bool(result_data["context"])}))
1506
+
1507
+
1508
+ def _add_perform_aspdma_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1509
+ """Add attributes specific to PERFORM_ASPDMA step."""
1510
+ if "selected_action" in result_data:
1511
+ attributes.append(
1512
+ SpanAttribute(key="action.selected", value={"stringValue": str(result_data["selected_action"])})
1513
+ )
1514
+ if "action_rationale" in result_data:
1515
+ attributes.append(
1516
+ SpanAttribute(key="action.has_rationale", value={"boolValue": bool(result_data["action_rationale"])})
1517
+ )
1518
+
1519
+
1520
+ def _add_conscience_execution_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1521
+ """Add attributes specific to CONSCIENCE_EXECUTION step."""
1522
+ if "conscience_passed" in result_data:
1523
+ attributes.append(SpanAttribute(key="conscience.passed", value={"boolValue": result_data["conscience_passed"]}))
1524
+ if "selected_action" in result_data:
1525
+ attributes.append(
1526
+ SpanAttribute(key="conscience.action", value={"stringValue": str(result_data["selected_action"])})
1527
+ )
1528
+
1529
+
1530
+ def _add_finalize_action_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1531
+ """Add attributes specific to FINALIZE_ACTION step."""
1532
+ if "selected_action" in result_data:
1533
+ attributes.append(
1534
+ SpanAttribute(key="finalized.action", value={"stringValue": str(result_data["selected_action"])})
1535
+ )
1536
+ if "selection_reasoning" in result_data:
1537
+ attributes.append(
1538
+ SpanAttribute(key="finalized.has_reasoning", value={"boolValue": bool(result_data["selection_reasoning"])})
1539
+ )
1540
+
1541
+
1542
+ def _add_perform_action_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1543
+ """Add attributes specific to PERFORM_ACTION step."""
1544
+ if "action_executed" in result_data:
1545
+ attributes.append(
1546
+ SpanAttribute(key="action.executed", value={"stringValue": str(result_data["action_executed"])})
1547
+ )
1548
+ if "dispatch_success" in result_data:
1549
+ attributes.append(
1550
+ SpanAttribute(key="action.dispatch_success", value={"boolValue": result_data["dispatch_success"]})
1551
+ )
1552
+
1553
+
1554
+ def _add_action_complete_attributes(attributes: List[SpanAttribute], result_data: JSONDict) -> None: # NOQA
1555
+ """Add attributes specific to ACTION_COMPLETE step."""
1556
+ if "handler_completed" in result_data:
1557
+ attributes.append(
1558
+ SpanAttribute(key="action.handler_completed", value={"boolValue": result_data["handler_completed"]})
1559
+ )
1560
+ if "execution_time_ms" in result_data:
1561
+ attributes.append(
1562
+ SpanAttribute(key="action.execution_time_ms", value={"doubleValue": result_data["execution_time_ms"]})
1563
+ )
1564
+
1565
+
1566
+ def _add_typed_step_attributes(attributes: List[SpanAttribute], step: StepPoint, result_data: JSONDict) -> None: # NOQA
1567
+ """Add step-specific attributes based on typed step result data."""
1568
+
1569
+ # Map step types to their handler functions
1570
+ step_attribute_handlers = {
1571
+ StepPoint.GATHER_CONTEXT: _add_gather_context_attributes,
1572
+ StepPoint.PERFORM_DMAS: _add_perform_dmas_attributes,
1573
+ StepPoint.PERFORM_ASPDMA: _add_perform_aspdma_attributes,
1574
+ StepPoint.CONSCIENCE_EXECUTION: _add_conscience_execution_attributes,
1575
+ StepPoint.FINALIZE_ACTION: _add_finalize_action_attributes,
1576
+ StepPoint.PERFORM_ACTION: _add_perform_action_attributes,
1577
+ StepPoint.ACTION_COMPLETE: _add_action_complete_attributes,
1578
+ }
1579
+
1580
+ # Call the appropriate handler function if one exists
1581
+ handler = step_attribute_handlers.get(step)
1582
+ if handler:
1583
+ handler(attributes, result_data)