agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.2__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 (411) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
  3. ksadk/a2a/_space_client_events.py +381 -0
  4. ksadk/a2a/event_adapter.py +156 -64
  5. ksadk/a2a/executor.py +179 -63
  6. ksadk/a2a/space_client.py +6 -333
  7. ksadk/a2ui/core.py +222 -53
  8. ksadk/agui/_agent_helpers.py +243 -0
  9. ksadk/agui/a2ui_projection.py +12 -5
  10. ksadk/agui/agent.py +443 -259
  11. ksadk/api/client.py +525 -27
  12. ksadk/builders/code_builder.py +284 -8
  13. ksadk/builders/container_builder.py +8 -1
  14. ksadk/builders/managed_runtime_builder.py +39 -35
  15. ksadk/cli/__init__.py +17 -0
  16. ksadk/cli/cmd_dashboard.py +15 -1
  17. ksadk/cli/cmd_deploy.py +10 -2
  18. ksadk/cli/cmd_eval.py +66 -9
  19. ksadk/cli/cmd_evalset.py +284 -0
  20. ksadk/cli/cmd_files.py +5 -1
  21. ksadk/cli/cmd_hermes.py +1 -126
  22. ksadk/cli/cmd_invoke.py +28 -38
  23. ksadk/cli/cmd_managed_runtime.py +95 -0
  24. ksadk/cli/cmd_observe.py +85 -0
  25. ksadk/cli/cmd_openclaw.py +1 -435
  26. ksadk/cli/cmd_replay.py +28 -4
  27. ksadk/cli/cmd_studio.py +99 -8
  28. ksadk/cli/cmd_web.py +10 -2
  29. ksadk/cli/hermes_env.py +151 -0
  30. ksadk/cli/invoke_payload.py +49 -0
  31. ksadk/cli/openclaw_env.py +458 -0
  32. ksadk/codex/client.py +180 -30
  33. ksadk/codex/runtime.py +428 -326
  34. ksadk/configs/env_registry.py +66 -12
  35. ksadk/configs/env_registry_pcm.py +181 -0
  36. ksadk/configs/env_var_spec.py +18 -0
  37. ksadk/configs/global_config.py +5 -0
  38. ksadk/context_engine/__init__.py +98 -0
  39. ksadk/context_engine/assembler.py +176 -0
  40. ksadk/context_engine/baseline.py +419 -0
  41. ksadk/context_engine/cache_observability.py +228 -0
  42. ksadk/context_engine/capabilities.py +443 -0
  43. ksadk/context_engine/contributors.py +344 -0
  44. ksadk/context_engine/hosted_pipeline.py +417 -0
  45. ksadk/context_engine/models.py +117 -0
  46. ksadk/context_engine/planner.py +698 -0
  47. ksadk/context_engine/policies.py +319 -0
  48. ksadk/context_engine/projection.py +31 -0
  49. ksadk/context_engine/shadow_plan.py +266 -0
  50. ksadk/context_engine/tokenizer.py +164 -0
  51. ksadk/conversations/context.py +126 -6
  52. ksadk/conversations/message_projection.py +292 -28
  53. ksadk/conversations/model_context.py +49 -3
  54. ksadk/conversations/runtime_compaction.py +207 -5
  55. ksadk/conversations/runtime_input.py +184 -2
  56. ksadk/conversations/runtime_invocation.py +81 -3
  57. ksadk/conversations/runtime_observability.py +141 -0
  58. ksadk/conversations/runtime_payloads.py +42 -0
  59. ksadk/conversations/runtime_preparation.py +272 -2
  60. ksadk/conversations/runtime_resume.py +20 -1
  61. ksadk/conversations/runtime_stream_events.py +94 -9
  62. ksadk/conversations/semantic_summary.py +311 -1
  63. ksadk/conversations/session_lock.py +51 -0
  64. ksadk/deployment/env_forward.py +72 -0
  65. ksadk/deployment/managed_runtime.py +5 -0
  66. ksadk/deployment/providers/serverless.py +143 -69
  67. ksadk/evaluation/__init__.py +32 -0
  68. ksadk/evaluation/a2a_adapter.py +9 -1
  69. ksadk/evaluation/adapters.py +18 -5
  70. ksadk/evaluation/agent_eval_client.py +395 -0
  71. ksadk/evaluation/cloud_binding.py +80 -0
  72. ksadk/evaluation/cloud_converter.py +194 -0
  73. ksadk/evaluation/cloud_service.py +199 -0
  74. ksadk/evaluation/contracts.py +73 -4
  75. ksadk/evaluation/evaluators.py +183 -17
  76. ksadk/evaluation/evidence.py +258 -0
  77. ksadk/evaluation/executor.py +31 -6
  78. ksadk/evaluation/local_adapter.py +550 -0
  79. ksadk/evaluation/service_env.py +27 -0
  80. ksadk/evaluation/studio_build_adapter.py +253 -0
  81. ksadk/evaluation/target.py +15 -6
  82. ksadk/events/__init__.py +13 -13
  83. ksadk/events/_v1_compat/__init__.py +1 -0
  84. ksadk/events/_v1_compat/models.py +299 -0
  85. ksadk/events/_v1_compat/parser.py +247 -0
  86. ksadk/events/_v1_compat/projection.py +753 -0
  87. ksadk/events/adapters/__init__.py +34 -0
  88. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  89. ksadk/events/adapters/_a2a_support.py +275 -0
  90. ksadk/events/adapters/_codex_interactions.py +375 -0
  91. ksadk/events/adapters/_codex_items.py +801 -0
  92. ksadk/events/adapters/_codex_validators.py +311 -0
  93. ksadk/events/adapters/_langgraph_support.py +785 -0
  94. ksadk/events/adapters/a2a.py +841 -0
  95. ksadk/events/adapters/adk.py +503 -0
  96. ksadk/events/adapters/codex.py +717 -0
  97. ksadk/events/adapters/langgraph.py +745 -0
  98. ksadk/events/canonical.py +440 -0
  99. ksadk/events/canonical_replay.py +497 -0
  100. ksadk/events/canonical_store.py +468 -0
  101. ksadk/events/cold_recovery.py +257 -0
  102. ksadk/events/content.py +89 -0
  103. ksadk/events/identity.py +86 -0
  104. ksadk/events/pipeline.py +455 -0
  105. ksadk/events/projections.py +66 -0
  106. ksadk/events/reducer.py +661 -0
  107. ksadk/events/replay.py +3 -36
  108. ksadk/events/runtime_event.py +20 -265
  109. ksadk/events/session_event.py +324 -0
  110. ksadk/events/store.py +3 -316
  111. ksadk/events/v1_compat.py +41 -0
  112. ksadk/harness/runtime.py +160 -57
  113. ksadk/identity/resolver.py +4 -3
  114. ksadk/interaction/__init__.py +28 -0
  115. ksadk/interaction/contracts.py +136 -0
  116. ksadk/interaction/ledger.py +189 -0
  117. ksadk/interaction/provider.py +122 -0
  118. ksadk/interaction/providers/__init__.py +52 -0
  119. ksadk/interaction/providers/adk.py +40 -0
  120. ksadk/interaction/providers/codex.py +94 -0
  121. ksadk/interaction/providers/langgraph.py +58 -0
  122. ksadk/kernel/__init__.py +117 -0
  123. ksadk/kernel/authorization.py +258 -0
  124. ksadk/kernel/bootstrap.py +1074 -0
  125. ksadk/kernel/contract_fingerprints.py +61 -0
  126. ksadk/kernel/contracts.py +362 -0
  127. ksadk/kernel/control.py +219 -0
  128. ksadk/kernel/errors.py +79 -0
  129. ksadk/kernel/ingress.py +1102 -0
  130. ksadk/kernel/mapping.py +111 -0
  131. ksadk/kernel/memory_store.py +1133 -0
  132. ksadk/kernel/postgres_store.py +1756 -0
  133. ksadk/kernel/recovery.py +452 -0
  134. ksadk/kernel/runtime_identity.py +103 -0
  135. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  136. ksadk/kernel/sqlite_store.py +1410 -0
  137. ksadk/kernel/state.py +145 -0
  138. ksadk/kernel/store.py +232 -0
  139. ksadk/kernel/worker.py +953 -0
  140. ksadk/knowledge_base/client.py +7 -0
  141. ksadk/knowledge_base/service.py +32 -5
  142. ksadk/memory/__init__.py +61 -0
  143. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  144. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  145. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  146. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  147. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  148. ksadk/memory/coordinator.py +461 -0
  149. ksadk/memory/events.py +202 -0
  150. ksadk/memory/extraction.py +228 -0
  151. ksadk/memory/ltm_backend_factory.py +16 -3
  152. ksadk/memory/models.py +316 -0
  153. ksadk/memory/policy.py +215 -0
  154. ksadk/memory/provider.py +47 -0
  155. ksadk/memory/provider_adapter.py +159 -0
  156. ksadk/memory/provider_resolver.py +71 -0
  157. ksadk/memory/providers/__init__.py +5 -0
  158. ksadk/memory/providers/local_sqlite.py +490 -0
  159. ksadk/memory/resolved_policy.py +145 -0
  160. ksadk/memory/service.py +188 -6
  161. ksadk/model_proxy/bootstrap.py +16 -9
  162. ksadk/model_proxy/detect.py +202 -9
  163. ksadk/model_proxy/namespace.py +39 -15
  164. ksadk/model_proxy/server.py +24 -5
  165. ksadk/model_proxy/transform.py +60 -2
  166. ksadk/observability/__init__.py +25 -0
  167. ksadk/observability/session_log.py +420 -0
  168. ksadk/observability/trajectory.py +105 -0
  169. ksadk/prompts/__init__.py +71 -0
  170. ksadk/prompts/compiler.py +215 -0
  171. ksadk/prompts/models.py +82 -0
  172. ksadk/prompts/projection.py +89 -0
  173. ksadk/prompts/resolved.py +137 -0
  174. ksadk/prompts/sources.py +233 -0
  175. ksadk/runners/_langgraph_runner_streams.py +822 -0
  176. ksadk/runners/adk_runner.py +5 -5
  177. ksadk/runners/base_runner.py +16 -0
  178. ksadk/runners/factory.py +1 -2
  179. ksadk/runners/langgraph_runner.py +198 -437
  180. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  181. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  182. ksadk/runtime/adapter.py +118 -2
  183. ksadk/runtime/conversation_execution.py +316 -182
  184. ksadk/runtime/executor.py +144 -3
  185. ksadk/runtime/factory.py +193 -7
  186. ksadk/runtime/hosted_finalizer.py +268 -0
  187. ksadk/runtime/launch.py +14 -1
  188. ksadk/runtime/preprocessing.py +25 -3
  189. ksadk/runtime/runner_adapter.py +288 -508
  190. ksadk/runtime/usage.py +33 -0
  191. ksadk/sandbox/backends/e2b.py +35 -2
  192. ksadk/server/composition.py +8 -0
  193. ksadk/server/factory.py +69 -6
  194. ksadk/server/routes/kernel_ingress.py +258 -0
  195. ksadk/server/routes/openai_compat.py +88 -8
  196. ksadk/server/routes/projection.py +35 -20
  197. ksadk/server/routes/run.py +94 -0
  198. ksadk/server/routes/sessions.py +2 -0
  199. ksadk/server/routes/streaming.py +5 -2
  200. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  201. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
  202. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  203. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  204. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  205. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  206. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  207. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  208. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  209. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  210. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  211. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  212. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  213. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  214. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  215. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  216. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  217. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  218. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  219. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  220. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  221. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  222. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  223. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  224. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  225. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  226. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  227. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  228. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  229. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  230. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  231. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  232. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  233. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  234. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  235. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  236. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
  237. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  238. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
  239. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
  240. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
  241. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
  242. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
  243. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
  244. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
  245. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
  246. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
  247. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
  248. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
  249. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
  250. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
  251. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
  252. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
  253. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
  254. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
  255. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
  256. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
  257. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-ngtN0DJB.js} +1 -1
  258. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  259. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  260. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  261. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  262. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  263. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  264. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  265. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  266. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  267. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  268. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  269. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  270. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  271. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  272. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  273. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-BHjG8b-J.js} +1 -1
  274. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  275. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  276. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  277. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  278. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  279. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  280. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  281. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  282. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  283. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  284. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  285. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  286. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  287. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  288. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  289. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  290. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  291. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  292. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  293. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  294. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  295. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  296. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  297. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  298. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  299. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  300. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  301. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  302. ksadk/server/static/index.html +2 -2
  303. ksadk/sessions/__init__.py +26 -9
  304. ksadk/sessions/_local_service_sync.py +688 -0
  305. ksadk/sessions/_local_tables.py +21 -0
  306. ksadk/sessions/_postgres_schema.py +305 -0
  307. ksadk/sessions/_postgres_tables.py +15 -0
  308. ksadk/sessions/base.py +80 -1
  309. ksadk/sessions/in_memory.py +53 -2
  310. ksadk/sessions/local_service.py +63 -604
  311. ksadk/sessions/postgres_service.py +58 -148
  312. ksadk/sessions/resilient.py +35 -1
  313. ksadk/studio/api.py +577 -25
  314. ksadk/studio/api_contracts.py +114 -5
  315. ksadk/studio/api_memory_routes.py +82 -0
  316. ksadk/studio/authoring.py +252 -27
  317. ksadk/studio/authoring_coordinator.py +799 -67
  318. ksadk/studio/builder.py +88 -11
  319. ksadk/studio/capabilities.py +17 -0
  320. ksadk/studio/cloud.py +1916 -95
  321. ksadk/studio/codex_agent_service.py +125 -14
  322. ksadk/studio/codex_authoring.py +469 -0
  323. ksadk/studio/codex_builder.py +138 -25
  324. ksadk/studio/codex_manifest.py +51 -22
  325. ksadk/studio/codex_run.py +46 -3
  326. ksadk/studio/compiler.py +1 -0
  327. ksadk/studio/contracts.py +114 -3
  328. ksadk/studio/event_store.py +25 -95
  329. ksadk/studio/framework_run.py +231 -3
  330. ksadk/studio/hosted_kernel.py +317 -0
  331. ksadk/studio/manifest_resolver.py +131 -0
  332. ksadk/studio/model_client.py +95 -9
  333. ksadk/studio/model_profile_service.py +1 -1
  334. ksadk/studio/operations.py +37 -5
  335. ksadk/studio/otel_trace.py +348 -42
  336. ksadk/studio/pcm_memory.py +85 -0
  337. ksadk/studio/repository.py +23 -2
  338. ksadk/studio/resource_catalog.py +43 -0
  339. ksadk/studio/run_service.py +563 -137
  340. ksadk/studio/runtime_source.py +42 -16
  341. ksadk/studio/service.py +1180 -72
  342. ksadk/studio/shared_web.py +32 -22
  343. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  344. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  345. ksadk/studio/static/index.html +2 -2
  346. ksadk/studio/templates.py +100 -8
  347. ksadk/studio/validator.py +19 -0
  348. ksadk/studio/workspace.py +30 -32
  349. ksadk/tracing/setup.py +304 -3
  350. ksadk/version.py +1 -1
  351. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  352. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  353. ksadk/events/parser.py +0 -191
  354. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  355. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  356. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  357. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  358. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  359. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  360. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  361. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  362. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  363. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  364. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  365. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  366. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  367. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  368. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  369. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  370. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  371. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  372. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  373. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  374. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  375. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  376. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  377. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  378. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  379. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  380. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  381. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  382. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  383. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  384. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  385. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  386. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  387. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  388. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  389. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  390. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  391. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  392. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  393. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  394. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  395. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  396. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  397. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  398. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  399. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  400. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  401. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  402. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  404. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  405. ksadk/studio/evaluation.py +0 -192
  406. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  407. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  408. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
  409. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  410. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  411. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,275 @@
1
+ """A2A adapter 的错误/上下文/状态 dataclass 与校验辅助(纯移动自 adapters.a2a,行为不变)。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import math
7
+ from collections.abc import Mapping
8
+ from dataclasses import dataclass, field
9
+ from typing import Any, Literal, Protocol, cast
10
+
11
+ from a2a.types import (
12
+ GetTaskRequest,
13
+ Task,
14
+ TaskState,
15
+ TaskStatus,
16
+ )
17
+ from google.protobuf.json_format import MessageToDict
18
+ from pydantic import JsonValue
19
+
20
+ from ksadk.events.canonical import (
21
+ OutputRef,
22
+ RuntimeEvent,
23
+ SourceRef,
24
+ )
25
+ from ksadk.events.content import (
26
+ ContentSnapshot,
27
+ ContentValue,
28
+ )
29
+ from ksadk.events.identity import (
30
+ stable_scope_id,
31
+ )
32
+
33
+ ReconciliationReason = Literal["terminal", "reconnect", "subscription_rebuild"]
34
+
35
+ _ACTIVE_STATES = frozenset({TaskState.TASK_STATE_SUBMITTED, TaskState.TASK_STATE_WORKING})
36
+ _INTERACTION_STATES = frozenset(
37
+ {TaskState.TASK_STATE_INPUT_REQUIRED, TaskState.TASK_STATE_AUTH_REQUIRED}
38
+ )
39
+ _TERMINAL_STATES = frozenset(
40
+ {
41
+ TaskState.TASK_STATE_COMPLETED,
42
+ TaskState.TASK_STATE_FAILED,
43
+ TaskState.TASK_STATE_CANCELED,
44
+ TaskState.TASK_STATE_REJECTED,
45
+ }
46
+ )
47
+
48
+
49
+ class A2AMappingError(ValueError):
50
+ """An A2A protobuf violates the native identity or content contract."""
51
+
52
+ def __init__(self, code: str, field_name: str, message: str) -> None:
53
+ super().__init__(message)
54
+ self.code = code
55
+ self.field_name = field_name
56
+ self.source = "a2a"
57
+
58
+
59
+ def _fail(code: str, field_name: str, message: str) -> None:
60
+ raise A2AMappingError(code, field_name, message)
61
+
62
+
63
+ @dataclass
64
+ class A2AAdapterContext:
65
+ """Runtime invocation facts and non-durable pre-store sequence placeholders."""
66
+
67
+ run_id: str
68
+ context_id: str
69
+ task_id: str | None
70
+ initial_seq: int = 0
71
+ _next_seq: int = field(init=False, repr=False)
72
+ _direct_message_id: str | None = field(default=None, init=False, repr=False)
73
+
74
+ def __post_init__(self) -> None:
75
+ self.run_id = _required_string(self.run_id, "runtime run_id")
76
+ self.context_id = _required_string(self.context_id, "context_id")
77
+ if self.task_id is not None:
78
+ self.task_id = _required_string(self.task_id, "task_id")
79
+ if self.initial_seq < 0:
80
+ raise ValueError("A2A initial_seq must be non-negative")
81
+ self._next_seq = self.initial_seq
82
+
83
+ @property
84
+ def scope_id(self) -> str:
85
+ if self.task_id is not None:
86
+ return stable_scope_id("a2a", self.context_id, self.task_id)
87
+ if self._direct_message_id is not None:
88
+ return stable_scope_id("a2a", self.context_id, "message", self._direct_message_id)
89
+ _fail(
90
+ "missing_native_identity",
91
+ "task_id/message_id",
92
+ "A2A scope requires a task_id or direct message_id",
93
+ )
94
+
95
+ @property
96
+ def native_run_id(self) -> str:
97
+ return _required_string(self.task_id or self._direct_message_id, "task_id/message_id")
98
+
99
+ def bind_direct_message(self, message_id: str) -> None:
100
+ native_message_id = _required_string(message_id, "message.message_id")
101
+ if self.task_id is not None:
102
+ return
103
+ if self._direct_message_id not in {None, native_message_id}:
104
+ _fail(
105
+ "direct_message_scope_collision",
106
+ "message.message_id",
107
+ "A2A direct response changed message scope",
108
+ )
109
+ self._direct_message_id = native_message_id
110
+
111
+ def allocate_placeholder_seq(self) -> int:
112
+ value = self._next_seq
113
+ self._next_seq += 1
114
+ return value
115
+
116
+ def peek_placeholder_seq(self) -> int:
117
+ """Return the next placeholder without consuming it."""
118
+
119
+ return self._next_seq
120
+
121
+
122
+ @dataclass(frozen=True)
123
+ class A2AReconciliationResult:
124
+ """Result of GetTask reconciliation.
125
+
126
+ ``consistent`` means the emitted projection matches the fetched Task.
127
+ ``terminal`` independently reports whether that Task was terminal.
128
+ """
129
+
130
+ events: tuple[RuntimeEvent, ...]
131
+ consistent: bool
132
+ terminal: bool
133
+ attempt_id: str
134
+ error: str | None = None
135
+
136
+
137
+ class _A2AClient(Protocol):
138
+ async def get_task(self, request: GetTaskRequest, **kwargs: Any) -> Task: ...
139
+
140
+
141
+ @dataclass
142
+ class _ArtifactState:
143
+ artifact_id: str
144
+ item_id: str
145
+ parts: dict[str, ContentValue] = field(default_factory=dict)
146
+ part_order: list[str] = field(default_factory=list)
147
+ closed: bool = False
148
+ present: bool = True
149
+
150
+ def snapshot(self) -> ContentSnapshot:
151
+ return ContentSnapshot(parts=tuple(self.parts[part_id] for part_id in self.part_order))
152
+
153
+
154
+ @dataclass(frozen=True)
155
+ class _MessageState:
156
+ signature: bytes
157
+
158
+
159
+ @dataclass(frozen=True)
160
+ class _Occurrence:
161
+ native_event_id: str | None
162
+ native_cursor: str | None
163
+ identity: str
164
+ provisional: bool
165
+ duplicate: bool = False
166
+
167
+
168
+ @dataclass
169
+ class _SnapshotScope:
170
+ """Shared plumbing for one GetTask snapshot projection pass."""
171
+
172
+ task: Task
173
+ context: A2AAdapterContext
174
+ source: SourceRef
175
+ timestamp: float
176
+ occurrence: _Occurrence
177
+ terminal: bool
178
+ reason: ReconciliationReason
179
+ attempt_id: str
180
+ events: list[RuntimeEvent] = field(default_factory=list)
181
+ _output_refs: list[OutputRef] = field(default_factory=list)
182
+ _output_ref_keys: set[tuple[str, str]] = field(default_factory=set)
183
+
184
+ def add_output_ref(self, item_id: str) -> None:
185
+ key = (self.context.scope_id, item_id)
186
+ if key not in self._output_ref_keys:
187
+ self._output_ref_keys.add(key)
188
+ self._output_refs.append(OutputRef(scope_id=self.context.scope_id, item_id=item_id))
189
+
190
+
191
+ def _proto_fingerprint(value: object) -> str:
192
+ serialize = getattr(value, "SerializeToString", None)
193
+ if not callable(serialize):
194
+ _fail(
195
+ "invalid_protobuf_payload",
196
+ "event",
197
+ "A2A occurrence payload must be a protobuf message",
198
+ )
199
+ payload = cast(bytes, serialize(deterministic=True))
200
+ return hashlib.sha256(payload).hexdigest()
201
+
202
+
203
+ def _validate_unique_parts(parts: tuple[ContentValue, ...], field_name: str) -> None:
204
+ seen: set[str] = set()
205
+ for part in parts:
206
+ if part.part_id in seen:
207
+ _fail(
208
+ "duplicate_part_id",
209
+ field_name,
210
+ f"A2A snapshot contains duplicate part_id {part.part_id!r}",
211
+ )
212
+ seen.add(part.part_id)
213
+
214
+
215
+ def _metadata(struct: Any) -> dict[str, JsonValue]:
216
+ if struct is None:
217
+ return {}
218
+ return cast(
219
+ dict[str, JsonValue],
220
+ MessageToDict(struct, preserving_proto_field_name=True),
221
+ )
222
+
223
+
224
+ def _optional_metadata_string(
225
+ metadata: Mapping[str, JsonValue],
226
+ *keys: str,
227
+ ) -> str | None:
228
+ for key in keys:
229
+ value = metadata.get(key)
230
+ if value is not None:
231
+ text = str(value).strip()
232
+ if text:
233
+ return text
234
+ return None
235
+
236
+
237
+ def _required_metadata_string(metadata: Mapping[str, JsonValue], key: str) -> str:
238
+ value = _optional_metadata_string(metadata, key)
239
+ if value is None:
240
+ _fail(
241
+ "missing_part_metadata",
242
+ f"part.metadata.{key}",
243
+ f"A2A typed part requires metadata {key!r}",
244
+ )
245
+ return value
246
+
247
+
248
+ def _required_string(value: object, field_name: str) -> str:
249
+ text = str(value or "").strip()
250
+ if not text:
251
+ _fail(
252
+ "missing_native_identity",
253
+ field_name,
254
+ f"A2A {field_name} must be non-empty",
255
+ )
256
+ return text
257
+
258
+
259
+ def _status_message_id(status: TaskStatus) -> str | None:
260
+ if status.HasField("message") and status.message.message_id:
261
+ return status.message.message_id
262
+ return None
263
+
264
+
265
+ def _parts_text(parts: Any) -> str:
266
+ return "".join(str(part.text) for part in parts if part.text)
267
+
268
+
269
+ def _timestamp(value: float) -> float:
270
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
271
+ _fail("invalid_timestamp", "timestamp", "timestamp must be finite")
272
+ result = float(value)
273
+ if not math.isfinite(result):
274
+ _fail("invalid_timestamp", "timestamp", "timestamp must be finite")
275
+ return result
@@ -0,0 +1,375 @@
1
+ """CodexEventAdapter 的交互(interaction/serverRequest)映射方法(纯移动自 codex,行为不变)。
2
+
3
+ 以 mixin 形式被 :class:`CodexEventAdapter` 继承。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from collections.abc import Mapping
9
+ from typing import Any, Callable, Literal
10
+
11
+ from pydantic import JsonValue
12
+
13
+ from ksadk.events.adapters._codex_items import (
14
+ _APPROVAL_KINDS,
15
+ _CONTROL_REQUEST_BUILDERS,
16
+ CodexAdapterContext,
17
+ _approval_response,
18
+ _elicitation_request,
19
+ _envelope,
20
+ _InteractionState,
21
+ _protocol_source,
22
+ _structured_response_data,
23
+ _thread_continuation_identity,
24
+ )
25
+ from ksadk.events.adapters._codex_validators import (
26
+ _fail,
27
+ _json_value,
28
+ _mapping,
29
+ _question_schema,
30
+ _request_id,
31
+ _required_string,
32
+ _required_text,
33
+ )
34
+ from ksadk.events.canonical import (
35
+ ApprovalRequest,
36
+ ApprovalResponse,
37
+ InteractionRequest,
38
+ InteractionRequested,
39
+ InteractionResolved,
40
+ InteractionResponse,
41
+ RunInterrupted,
42
+ RunProgress,
43
+ RuntimeEvent,
44
+ SourceRef,
45
+ StructuredInputRequest,
46
+ StructuredInputResponse,
47
+ )
48
+ from ksadk.events.identity import stable_item_id, stable_scope_id
49
+
50
+
51
+ class _CodexInteractionMixin:
52
+ def _map_control_interaction_request(
53
+ self,
54
+ *,
55
+ message: Mapping[str, Any],
56
+ method: str,
57
+ params: Mapping[str, Any],
58
+ context: CodexAdapterContext,
59
+ cursor: str,
60
+ timestamp: float,
61
+ ) -> tuple[RuntimeEvent, ...]:
62
+ """Map process-level v2 requests without inventing a turn interruption."""
63
+
64
+ request_id = _request_id(message.get("id"), "id")
65
+ if request_id in self._interactions:
66
+ _fail(
67
+ "interaction_already_pending",
68
+ "id",
69
+ f"Codex JSON-RPC request {request_id!r} is already pending",
70
+ )
71
+ thread_id = f"runtime:{context.run_id}"
72
+ turn_id = "control"
73
+ scope_id = stable_scope_id("codex", thread_id, turn_id)
74
+ interaction_id = stable_item_id("codex", scope_id, "interaction", method, request_id)
75
+ request = _CONTROL_REQUEST_BUILDERS[method](params)
76
+ state = _InteractionState(
77
+ request_id=request_id,
78
+ interaction_id=interaction_id,
79
+ interaction_kind="structured_input",
80
+ scope_id=scope_id,
81
+ thread_id=thread_id,
82
+ turn_id=turn_id,
83
+ native_item_id=request_id,
84
+ method=method,
85
+ interrupts_run=False,
86
+ )
87
+ self._interactions[request_id] = state
88
+ source = _protocol_source(
89
+ method=method,
90
+ cursor=cursor,
91
+ thread_id=thread_id,
92
+ turn_id=turn_id,
93
+ native_item_id=request_id,
94
+ native_event_id=request_id,
95
+ )
96
+ return (
97
+ InteractionRequested(
98
+ **_envelope(context, cursor, timestamp)(
99
+ scope_id, interaction_id, "interaction.requested", "structured_input", source
100
+ ),
101
+ interaction_id=interaction_id,
102
+ interaction_kind="structured_input",
103
+ request=request,
104
+ ),
105
+ )
106
+
107
+ def _map_server_request_resolved(
108
+ self,
109
+ *,
110
+ params: Mapping[str, Any],
111
+ context: CodexAdapterContext,
112
+ cursor: str,
113
+ timestamp: float,
114
+ ) -> tuple[RuntimeEvent, ...]:
115
+ """Close a request that Codex resolved outside its JSON-RPC response path."""
116
+
117
+ thread_id = _required_string(params.get("threadId"), "params.threadId")
118
+ request_id = _request_id(params.get("requestId"), "params.requestId")
119
+ state = self._interactions.get(request_id)
120
+ if state is None:
121
+ return self._map_known_notification(
122
+ method="serverRequest/resolved",
123
+ params=params,
124
+ context=context,
125
+ cursor=cursor,
126
+ timestamp=timestamp,
127
+ )
128
+ if state.thread_id != thread_id:
129
+ _fail(
130
+ "interaction_scope_mismatch",
131
+ "params.threadId",
132
+ "Codex serverRequest/resolved threadId does not match the pending request",
133
+ )
134
+ resolved = self._resolve_interaction(
135
+ state,
136
+ cursor=cursor,
137
+ timestamp=timestamp,
138
+ context=context,
139
+ source=_protocol_source(
140
+ method="serverRequest/resolved",
141
+ cursor=cursor,
142
+ thread_id=state.thread_id,
143
+ turn_id=state.turn_id,
144
+ native_item_id=state.native_item_id,
145
+ native_event_id=request_id,
146
+ ),
147
+ response=(
148
+ ApprovalResponse(
149
+ decision="canceled",
150
+ data={"source": "serverRequest/resolved", "requestId": request_id},
151
+ )
152
+ if state.interaction_kind == "approval"
153
+ else StructuredInputResponse(
154
+ data={"source": "serverRequest/resolved", "requestId": request_id}
155
+ )
156
+ ),
157
+ )
158
+ return (resolved,)
159
+
160
+ def _map_interaction_request(
161
+ self,
162
+ *,
163
+ message: Mapping[str, Any],
164
+ method: str,
165
+ params: Mapping[str, Any],
166
+ env: Callable[..., dict[str, Any]],
167
+ context: CodexAdapterContext,
168
+ cursor: str,
169
+ timestamp: float,
170
+ thread_id: str,
171
+ turn_id: str,
172
+ scope_id: str,
173
+ interrupts_run: bool,
174
+ ) -> tuple[RuntimeEvent, ...]:
175
+ request_id = _request_id(message.get("id"), "id")
176
+ if request_id in self._interactions:
177
+ _fail(
178
+ "interaction_already_pending",
179
+ "id",
180
+ f"Codex JSON-RPC request {request_id!r} is already pending",
181
+ )
182
+ if method == "item/tool/call":
183
+ native_item_id = _required_string(params.get("callId"), "params.callId")
184
+ elif method == "mcpServer/elicitation/request":
185
+ native_item_id = request_id
186
+ else:
187
+ native_item_id = _required_string(params.get("itemId"), "params.itemId")
188
+ native_interaction_id = params.get("approvalId") or request_id
189
+ native_interaction_id = _required_string(native_interaction_id, "params.approvalId")
190
+ interaction_id = stable_item_id(
191
+ "codex", scope_id, "interaction", method, native_interaction_id
192
+ )
193
+ kind: Literal["approval", "structured_input"]
194
+ request: InteractionRequest
195
+ question_ids: frozenset[str] = frozenset()
196
+ secret_question_ids: frozenset[str] = frozenset()
197
+ if method == "item/tool/requestUserInput":
198
+ kind = "structured_input"
199
+ prompt, schema, question_ids, secret_question_ids = _question_schema(
200
+ params.get("questions")
201
+ )
202
+ request = StructuredInputRequest(prompt=prompt, schema=schema)
203
+ elif method == "mcpServer/elicitation/request":
204
+ kind = "structured_input"
205
+ request = _elicitation_request(params)
206
+ else:
207
+ kind = "approval"
208
+ request = ApprovalRequest(
209
+ call_id=native_item_id,
210
+ kind=_APPROVAL_KINDS[method],
211
+ detail=_json_value(params),
212
+ )
213
+ state = _InteractionState(
214
+ request_id=request_id,
215
+ interaction_id=interaction_id,
216
+ interaction_kind=kind,
217
+ scope_id=scope_id,
218
+ thread_id=thread_id,
219
+ turn_id=turn_id,
220
+ native_item_id=native_item_id,
221
+ method=method,
222
+ interrupts_run=interrupts_run,
223
+ question_ids=question_ids,
224
+ secret_question_ids=secret_question_ids,
225
+ )
226
+ self._interactions[request_id] = state
227
+ source = _protocol_source(
228
+ method=method,
229
+ cursor=cursor,
230
+ thread_id=thread_id,
231
+ turn_id=turn_id,
232
+ native_item_id=native_item_id,
233
+ native_event_id=request_id,
234
+ )
235
+ requested = InteractionRequested(
236
+ **env(scope_id, interaction_id, "interaction.requested", kind, source),
237
+ interaction_id=interaction_id,
238
+ interaction_kind=kind,
239
+ request=request,
240
+ )
241
+ if not interrupts_run:
242
+ return (requested,)
243
+ return (
244
+ requested,
245
+ RunInterrupted(
246
+ **env(scope_id, turn_id, "run.interrupted", interaction_id, source),
247
+ status="interrupted",
248
+ reason="Codex requires user interaction",
249
+ interaction_id=interaction_id,
250
+ continuation_id=self._thread_continuations.setdefault(
251
+ thread_id, _thread_continuation_identity(thread_id)[1]
252
+ ),
253
+ ),
254
+ )
255
+
256
+ def _map_jsonrpc_response(
257
+ self,
258
+ message: Mapping[str, Any],
259
+ context: CodexAdapterContext,
260
+ cursor: str,
261
+ timestamp: float,
262
+ ) -> tuple[RuntimeEvent, ...]:
263
+ request_id = _request_id(message.get("id"), "id")
264
+ if request_id in self._resume_requests:
265
+ if "error" in message:
266
+ thread_id = self._resume_requests.pop(request_id)
267
+ self._pending_resume_by_thread.pop(thread_id, None)
268
+ _fail(
269
+ "thread_resume_failed",
270
+ "error",
271
+ "Codex thread/resume failed with a JSON-RPC error",
272
+ )
273
+ _mapping(message.get("result"), "result")
274
+ return ()
275
+ state = self._interactions.get(request_id)
276
+ if state is None:
277
+ _fail(
278
+ "unknown_jsonrpc_response",
279
+ "id",
280
+ f"Codex response has no pending request: {request_id}",
281
+ )
282
+ is_error_response = "error" in message
283
+ result: Mapping[str, Any] = {}
284
+ response: InteractionResponse
285
+ if is_error_response:
286
+ error = _mapping(message.get("error"), "error")
287
+ code = error.get("code")
288
+ if isinstance(code, bool) or not isinstance(code, int):
289
+ _fail(
290
+ "invalid_interaction_response",
291
+ "error.code",
292
+ "Codex JSON-RPC error.code must be an integer",
293
+ )
294
+ _required_text(error.get("message"), "error.message")
295
+ sanitized_error: dict[str, JsonValue] = {
296
+ "code": code,
297
+ "messagePresent": True,
298
+ "dataPresent": "data" in error,
299
+ }
300
+ if state.interaction_kind == "approval":
301
+ response = ApprovalResponse(
302
+ decision="canceled", data={"jsonrpcError": sanitized_error}
303
+ )
304
+ else:
305
+ response = StructuredInputResponse(data={"jsonrpcError": sanitized_error})
306
+ else:
307
+ result = _mapping(message.get("result"), "result")
308
+ if state.interaction_kind == "approval":
309
+ response = _approval_response(state.method, result)
310
+ else:
311
+ response = StructuredInputResponse(data=_structured_response_data(state, result))
312
+ source = _protocol_source(
313
+ method="jsonrpc/response",
314
+ cursor=cursor,
315
+ thread_id=state.thread_id,
316
+ turn_id=state.turn_id,
317
+ native_item_id=state.native_item_id,
318
+ native_event_id=request_id,
319
+ )
320
+ resolved = self._resolve_interaction(
321
+ state,
322
+ cursor=cursor,
323
+ timestamp=timestamp,
324
+ context=context,
325
+ source=source,
326
+ response=response,
327
+ )
328
+ if is_error_response:
329
+ return (resolved,)
330
+ resumes = (
331
+ isinstance(response, ApprovalResponse) and response.decision in {"approved", "rejected"}
332
+ ) or (
333
+ isinstance(response, StructuredInputResponse)
334
+ and (
335
+ state.method == "item/tool/requestUserInput"
336
+ or result.get("action") in {"accept", "decline"}
337
+ )
338
+ )
339
+ if not resumes or not state.interrupts_run:
340
+ return (resolved,)
341
+ return (
342
+ resolved,
343
+ RunProgress(
344
+ **_envelope(context, cursor, timestamp)(
345
+ state.scope_id, state.turn_id, "run.progress", state.interaction_id, source
346
+ ),
347
+ status="running",
348
+ message="Codex user interaction resolved; turn resumed",
349
+ ),
350
+ )
351
+
352
+ def _resolve_interaction(
353
+ self,
354
+ state: _InteractionState,
355
+ *,
356
+ cursor: str,
357
+ timestamp: float,
358
+ context: CodexAdapterContext,
359
+ source: SourceRef,
360
+ response: InteractionResponse,
361
+ ) -> InteractionResolved:
362
+ resolved = InteractionResolved(
363
+ **_envelope(context, cursor, timestamp)(
364
+ state.scope_id,
365
+ state.interaction_id,
366
+ "interaction.resolved",
367
+ state.interaction_kind,
368
+ source,
369
+ ),
370
+ interaction_id=state.interaction_id,
371
+ interaction_kind=state.interaction_kind,
372
+ response=response,
373
+ )
374
+ del self._interactions[state.request_id]
375
+ return resolved