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,381 @@
1
+ """A2ASpaceClient 的事件投影与持久化实现(纯移动自 ``ksadk.a2a.space_client``,行为不变)。
2
+
3
+ 以 mixin 形式被 :class:`A2ASpaceClient` 继承,依赖宿主提供 ``_event_adapter`` /
4
+ ``_event_dispatcher`` / ``_event_sink`` / ``_persisted_wire_events`` / ``_space_id`` /
5
+ ``_seq`` / ``_backend`` 及校验辅助方法。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import uuid
12
+ from collections.abc import Mapping
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ from a2a.types import TaskState
16
+ from google.protobuf.json_format import MessageToDict
17
+
18
+ from ksadk.a2a.control_plane import DiscoveredAgent
19
+ from ksadk.a2a.event_adapter import A2AEventAdapter
20
+ from ksadk.events.runtime_event import RuntimeEvent
21
+
22
+ if TYPE_CHECKING:
23
+ pass
24
+
25
+
26
+ def _utc_now() -> str:
27
+ from ksadk.a2a.space_client import _utc_now as _impl
28
+
29
+ return _impl()
30
+
31
+
32
+ def _canonical_proto(value: Any) -> dict[str, Any]:
33
+ from ksadk.a2a.space_client import _canonical_proto as _impl
34
+
35
+ return _impl(value)
36
+
37
+
38
+ def _present_message_field(value: Any, field_name: str) -> Any | None:
39
+ from ksadk.a2a.space_client import _present_message_field as _impl
40
+
41
+ return _impl(value, field_name)
42
+
43
+
44
+ class _SpaceClientEventMixin:
45
+ async def _project_stream_item(
46
+ self,
47
+ platform_task_id: str,
48
+ item: Any,
49
+ agent: DiscoveredAgent,
50
+ *,
51
+ wire_position: int,
52
+ operation_instance_id: str,
53
+ ) -> list[RuntimeEvent]:
54
+ runtime_events = self._stream_item_to_events(
55
+ item,
56
+ agent,
57
+ wire_position=wire_position,
58
+ invocation_id=platform_task_id,
59
+ )
60
+ platform_events = self._platform_events(
61
+ item,
62
+ platform_task_id,
63
+ operation_instance_id=operation_instance_id,
64
+ wire_position=wire_position,
65
+ )
66
+ if platform_events:
67
+ await self._event_dispatcher.enqueue(
68
+ platform_task_id=platform_task_id,
69
+ events=platform_events,
70
+ )
71
+ return await self._persist_events(runtime_events)
72
+
73
+ def _platform_events(
74
+ self,
75
+ item: Any,
76
+ platform_task_id: str,
77
+ *,
78
+ operation_instance_id: str,
79
+ wire_position: int,
80
+ ) -> list[dict[str, Any]]:
81
+ events: list[dict[str, Any]] = []
82
+
83
+ def append_event(
84
+ kind: str,
85
+ payload: dict[str, Any],
86
+ *,
87
+ status: str | None = None,
88
+ occurred_at: str | None = None,
89
+ ) -> None:
90
+ events.append(
91
+ self._platform_event(
92
+ kind,
93
+ payload,
94
+ platform_task_id,
95
+ operation_instance_id=operation_instance_id,
96
+ wire_position=wire_position,
97
+ event_ordinal=len(events),
98
+ status=status,
99
+ occurred_at=occurred_at,
100
+ )
101
+ )
102
+
103
+ task = _present_message_field(item, "task")
104
+ if task is None and hasattr(item, "status") and hasattr(item, "id"):
105
+ task = item
106
+ status_update = _present_message_field(item, "status_update")
107
+ artifact_update = _present_message_field(item, "artifact_update")
108
+ message = _present_message_field(item, "message")
109
+ if task is not None and getattr(task, "status", None) is not None:
110
+ payload = _canonical_proto(task.status)
111
+ state_name = TaskState.Name(task.status.state)
112
+ append_event(
113
+ "status",
114
+ payload,
115
+ status=state_name.removeprefix("TASK_STATE_").lower(),
116
+ occurred_at=str(payload.get("timestamp") or _utc_now()),
117
+ )
118
+ for artifact in getattr(task, "artifacts", None) or []:
119
+ append_event(
120
+ "artifact",
121
+ {
122
+ "Artifact": _canonical_proto(artifact),
123
+ "Append": False,
124
+ "LastChunk": True,
125
+ },
126
+ )
127
+ if status_update is not None and getattr(status_update, "status", None) is not None:
128
+ payload = _canonical_proto(status_update.status)
129
+ state_name = TaskState.Name(status_update.status.state)
130
+ append_event(
131
+ "status",
132
+ payload,
133
+ status=state_name.removeprefix("TASK_STATE_").lower(),
134
+ occurred_at=str(payload.get("timestamp") or _utc_now()),
135
+ )
136
+ if artifact_update is not None and getattr(artifact_update, "artifact", None) is not None:
137
+ append_event(
138
+ "artifact",
139
+ {
140
+ "Artifact": _canonical_proto(artifact_update.artifact),
141
+ "Append": bool(getattr(artifact_update, "append", False)),
142
+ "LastChunk": bool(getattr(artifact_update, "last_chunk", False)),
143
+ },
144
+ )
145
+ if message is not None:
146
+ payload = _canonical_proto(message)
147
+ append_event("message", payload)
148
+ append_event(
149
+ "status",
150
+ {"state": "TASK_STATE_COMPLETED", "message": payload},
151
+ status="completed",
152
+ )
153
+ return events
154
+
155
+ @staticmethod
156
+ def _platform_event(
157
+ kind: str,
158
+ payload: dict[str, Any],
159
+ platform_task_id: str,
160
+ *,
161
+ operation_instance_id: str,
162
+ wire_position: int,
163
+ event_ordinal: int,
164
+ status: str | None = None,
165
+ occurred_at: str | None = None,
166
+ ) -> dict[str, Any]:
167
+ source_id = hashlib.sha256(
168
+ (
169
+ f"{platform_task_id}:{operation_instance_id}:{wire_position}:{event_ordinal}:{kind}"
170
+ ).encode("utf-8")
171
+ ).hexdigest()
172
+ event: dict[str, Any] = {
173
+ "SourceEventId": source_id,
174
+ "EventKind": kind,
175
+ "Payload": payload,
176
+ "OccurredAt": occurred_at or _utc_now(),
177
+ }
178
+ if status:
179
+ event["Status"] = status
180
+ return event
181
+
182
+ async def flush_pending_events(self) -> int:
183
+ """Deliver all currently queued platform event batches or raise on failure."""
184
+
185
+ return await self._event_dispatcher.drain(raise_on_error=True)
186
+
187
+ def _next_seq(self) -> int:
188
+ self._seq += 1
189
+ return self._seq
190
+
191
+ def _event_ctx(
192
+ self,
193
+ agent: DiscoveredAgent,
194
+ invocation_id: str,
195
+ *,
196
+ event_id: str | None = None,
197
+ ) -> dict[str, Any]:
198
+ return {
199
+ "agent_id": agent.agent_id,
200
+ "user_id": "a2a_space",
201
+ "session_id": self._space_id,
202
+ "invocation_id": invocation_id,
203
+ "seq_id": self._next_seq(),
204
+ "event_id": event_id,
205
+ }
206
+
207
+ def task_to_event(self, task: Any, agent: DiscoveredAgent) -> RuntimeEvent:
208
+ return self._event_adapter.task_status_to_event(
209
+ task.status, **self._event_ctx(agent, invocation_id=str(task.id))
210
+ )
211
+
212
+ def _stream_item_to_events(
213
+ self,
214
+ item: Any,
215
+ agent: DiscoveredAgent,
216
+ *,
217
+ wire_position: int = 0,
218
+ invocation_id: str | None = None,
219
+ ) -> list[RuntimeEvent]:
220
+ events: list[RuntimeEvent] = []
221
+ task = _present_message_field(item, "task")
222
+ if task is None and hasattr(item, "status") and hasattr(item, "id"):
223
+ task = item
224
+ status_update = _present_message_field(item, "status_update")
225
+ artifact_update = _present_message_field(item, "artifact_update")
226
+ message = _present_message_field(item, "message")
227
+ resolved_invocation_id = invocation_id or str(
228
+ getattr(item, "task_id", None)
229
+ or getattr(task, "id", "")
230
+ or getattr(status_update, "task_id", "")
231
+ or getattr(artifact_update, "task_id", "")
232
+ or getattr(message, "task_id", "")
233
+ or ""
234
+ )
235
+
236
+ def ctx(kind: str, value: Any) -> dict[str, Any]:
237
+ metadata = getattr(value, "metadata", None)
238
+ native_event_id = ""
239
+ if metadata is not None:
240
+ if isinstance(metadata, Mapping):
241
+ metadata_dict = dict(metadata)
242
+ else:
243
+ try:
244
+ metadata_dict = MessageToDict(metadata, preserving_proto_field_name=True)
245
+ except (AttributeError, TypeError, ValueError):
246
+ metadata_dict = {}
247
+ native_event_id = str(
248
+ metadata_dict.get("event_id") or metadata_dict.get("ksadk_event_id") or ""
249
+ )
250
+ message_id = str(getattr(value, "message_id", "") or "")
251
+ artifact = getattr(value, "artifact", None)
252
+ artifact_id = str(
253
+ getattr(value, "artifact_id", "") or getattr(artifact, "artifact_id", "") or ""
254
+ )
255
+ source_id = native_event_id or message_id or artifact_id
256
+ event_id = uuid.uuid5(
257
+ uuid.NAMESPACE_URL,
258
+ f"ksadk:a2a:{resolved_invocation_id}:{wire_position}:{kind}:{source_id}",
259
+ ).hex
260
+ return self._event_ctx(agent, invocation_id=resolved_invocation_id, event_id=event_id)
261
+
262
+ if task is not None and getattr(task, "status", None) is not None:
263
+ task_status_message = _present_message_field(task.status, "message")
264
+ task_status_text = A2AEventAdapter._parts_text(
265
+ getattr(task_status_message, "parts", None)
266
+ )
267
+ task_is_terminal = task.status.state in {
268
+ TaskState.TASK_STATE_COMPLETED,
269
+ TaskState.TASK_STATE_FAILED,
270
+ TaskState.TASK_STATE_CANCELED,
271
+ TaskState.TASK_STATE_REJECTED,
272
+ }
273
+ if not task_is_terminal:
274
+ events.append(
275
+ self._event_adapter.task_status_to_event(
276
+ task.status,
277
+ **ctx("task", task),
278
+ )
279
+ )
280
+ if task_status_text:
281
+ events.append(
282
+ self._event_adapter.message_to_event(
283
+ task_status_text,
284
+ final=task_is_terminal,
285
+ **ctx("task-status-message", task_status_message),
286
+ )
287
+ )
288
+ if task_is_terminal:
289
+ events.append(
290
+ self._event_adapter.task_status_to_event(
291
+ task.status,
292
+ **ctx("task", task),
293
+ )
294
+ )
295
+ if status_update is not None and getattr(status_update, "status", None) is not None:
296
+ status_message = _present_message_field(status_update.status, "message")
297
+ text = A2AEventAdapter._parts_text(getattr(status_message, "parts", None))
298
+ terminal_states = {
299
+ TaskState.TASK_STATE_COMPLETED,
300
+ TaskState.TASK_STATE_FAILED,
301
+ TaskState.TASK_STATE_CANCELED,
302
+ TaskState.TASK_STATE_REJECTED,
303
+ }
304
+ is_terminal = status_update.status.state in terminal_states
305
+ if not is_terminal:
306
+ events.append(
307
+ self._event_adapter.task_status_to_event(
308
+ status_update.status, **ctx("status", status_update)
309
+ )
310
+ )
311
+ if text:
312
+ events.append(
313
+ self._event_adapter.message_to_event(
314
+ text,
315
+ final=is_terminal,
316
+ **ctx("status-message", status_message),
317
+ )
318
+ )
319
+ if is_terminal:
320
+ events.append(
321
+ self._event_adapter.task_status_to_event(
322
+ status_update.status, **ctx("status", status_update)
323
+ )
324
+ )
325
+ if artifact_update is not None and getattr(artifact_update, "artifact", None) is not None:
326
+ artifact = artifact_update.artifact
327
+ events.append(
328
+ self._event_adapter.artifact_to_event(artifact, **ctx("artifact", artifact_update))
329
+ )
330
+ artifact_text = A2AEventAdapter._parts_text(getattr(artifact, "parts", None))
331
+ if artifact_text and str(getattr(artifact, "name", "") or "") == "response":
332
+ events.append(
333
+ self._event_adapter.message_to_event(
334
+ artifact_text,
335
+ final=bool(getattr(artifact_update, "last_chunk", False)),
336
+ **ctx("artifact-text", artifact_update),
337
+ )
338
+ )
339
+ if message is not None:
340
+ text = A2AEventAdapter._parts_text(getattr(message, "parts", None))
341
+ if text:
342
+ events.append(
343
+ self._event_adapter.message_to_event(
344
+ text, final=True, **ctx("message", message)
345
+ )
346
+ )
347
+ return events
348
+
349
+ async def _persist_events(self, events: list[RuntimeEvent]) -> list[RuntimeEvent]:
350
+ existing_ids = set(self._persisted_wire_events)
351
+ if self._event_sink is not None:
352
+ list_events = getattr(self._event_sink, "list", None)
353
+ if callable(list_events) and events:
354
+ session_id = str(events[0].source.metadata.get("session_id") or self._space_id)
355
+ persisted_before = await list_events(session_id)
356
+ existing_ids.update(event.event_id for event in persisted_before)
357
+ fresh = [event for event in events if event.event_id not in existing_ids]
358
+ if not fresh:
359
+ return []
360
+ if self._event_sink is not None:
361
+ append = getattr(self._event_sink, "append", None)
362
+ if append is None:
363
+ raise TypeError("event_sink must provide async append(events)")
364
+ # RuntimeEventStore.append(session_id, events) requires session_id;
365
+ # fall back to single-arg call for non-canonical sinks.
366
+ session_id_for_persist = (
367
+ str(events[0].source.metadata.get("session_id") or self._space_id)
368
+ if events
369
+ else self._space_id
370
+ )
371
+ try:
372
+ persisted = await append(session_id_for_persist, fresh)
373
+ except TypeError:
374
+ persisted = await append(fresh)
375
+ if persisted is not None:
376
+ fresh = list(persisted)
377
+ self._persisted_wire_events.update(event.event_id for event in fresh)
378
+ return fresh
379
+
380
+
381
+ __all__ = ["_SpaceClientEventMixin"]
@@ -5,31 +5,37 @@
5
5
 
6
6
  方向:
7
7
  - ``task_status_to_event``:A2A TaskStatus/TaskState → RuntimeEvent(run.*)。
8
- - ``artifact_to_event``:A2A Artifact → RuntimeEvent(artifact.*)。
9
- - ``message_to_event``:A2A Message → RuntimeEvent(text.*)。
10
- - ``event_to_text_part``:RuntimeEvent(text.*)→ A2A ``Part``(用于出站)。
8
+ - ``artifact_to_event``:A2A Artifact → RuntimeEvent(item.*,item_kind="artifact")。
9
+ - ``message_to_event``:A2A Message → RuntimeEvent(item.*,item_kind="message")。
10
+ - ``event_to_text_part``:RuntimeEvent(item.*,item_kind="message")→ A2A ``Part``(用于出站)。
11
11
 
12
12
  wire 对象是 protobuf(``a2a_pb2``);文本用 ``Part(text=...)``。
13
13
  """
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ import time
17
18
  from typing import Any, Optional
18
19
 
19
20
  from a2a.types import Part, TaskState, TaskStatus
20
21
 
21
- from ksadk.events.runtime_event import EventType, RuntimeEvent
22
-
23
- #: A2A TaskState → RuntimeEvent run.* 事件类型映射。
24
- _TASK_STATE_TO_RUN_EVENT = {
25
- TaskState.TASK_STATE_SUBMITTED: EventType.RUN_STARTED,
26
- TaskState.TASK_STATE_WORKING: EventType.RUN_PROGRESS,
27
- TaskState.TASK_STATE_COMPLETED: EventType.RUN_COMPLETED,
28
- TaskState.TASK_STATE_FAILED: EventType.RUN_FAILED,
29
- TaskState.TASK_STATE_CANCELED: EventType.RUN_CANCELED,
30
- TaskState.TASK_STATE_INPUT_REQUIRED: EventType.RUN_INTERRUPTED,
31
- TaskState.TASK_STATE_REJECTED: EventType.RUN_FAILED,
32
- }
22
+ from ksadk.events.canonical import (
23
+ ContentSnapshot,
24
+ ErrorInfo,
25
+ ItemCompleted,
26
+ ItemStarted,
27
+ ItemUpdated,
28
+ RunCanceled,
29
+ RunCompleted,
30
+ RunFailed,
31
+ RunInterrupted,
32
+ RunProgress,
33
+ RunStarted,
34
+ RuntimeEvent,
35
+ SourceRef,
36
+ )
37
+ from ksadk.events.content import TextContent
38
+ from ksadk.events.identity import stable_event_id, stable_item_id, stable_scope_id
33
39
 
34
40
 
35
41
  class A2AEventAdapter:
@@ -48,25 +54,57 @@ class A2AEventAdapter:
48
54
  seq_id: int,
49
55
  event_id: Optional[str] = None,
50
56
  ) -> RuntimeEvent:
51
- """A2A TaskStatus → RuntimeEvent(run.*)。"""
52
- event_type = _TASK_STATE_TO_RUN_EVENT.get(status.state, EventType.RUN_PROGRESS)
53
- state_name = TaskState.Name(status.state) if status.state is not None else "unknown"
54
- payload: dict[str, Any] = {"status": state_name}
55
- if event_type == EventType.RUN_CANCELED:
56
- payload["cancel_result"] = "interrupted_active_turn"
57
- elif event_type == EventType.RUN_FAILED:
58
- message = getattr(status, "message", None)
59
- payload["error"] = self._parts_text(getattr(message, "parts", None)) or state_name
60
- return RuntimeEvent.create(
61
- event_type,
62
- agent_id=agent_id,
63
- user_id=user_id,
64
- session_id=session_id,
65
- invocation_id=invocation_id,
66
- seq_id=seq_id,
67
- payload=payload,
68
- event_id=event_id,
57
+ """A2A TaskStatus → canonical RuntimeEvent(run.*)。"""
58
+ state = status.state
59
+ state_name = TaskState.Name(state) if state is not None else "unknown"
60
+ scope_id = stable_scope_id("a2a", session_id, invocation_id)
61
+ run_id = invocation_id
62
+ source = SourceRef(
63
+ framework="a2a",
64
+ native_run_id=invocation_id,
65
+ metadata={"agent_id": agent_id, "user_id": user_id, "status": state_name},
66
+ )
67
+ timestamp = time.time()
68
+ eid = event_id or stable_event_id(
69
+ "a2a", scope_id, run_id, "run", "run", invocation_id, seq_id
69
70
  )
71
+ common: dict[str, Any] = {
72
+ "schema_version": 2,
73
+ "event_id": eid,
74
+ "seq": seq_id,
75
+ "timestamp": timestamp,
76
+ "run_id": run_id,
77
+ "scope_id": scope_id,
78
+ "source": source,
79
+ }
80
+ if state == TaskState.TASK_STATE_SUBMITTED:
81
+ return RunStarted(**common, status="running")
82
+ if state == TaskState.TASK_STATE_WORKING:
83
+ return RunProgress(**common, status="running", message=state_name)
84
+ if state == TaskState.TASK_STATE_COMPLETED:
85
+ return RunCompleted(**common, status="completed", output_refs=())
86
+ if state in {TaskState.TASK_STATE_FAILED, TaskState.TASK_STATE_REJECTED}:
87
+ message = getattr(status, "message", None)
88
+ error_text = self._parts_text(getattr(message, "parts", None)) or state_name
89
+ return RunFailed(
90
+ **common,
91
+ status="failed",
92
+ error=ErrorInfo(
93
+ code=(
94
+ "a2a_task_rejected"
95
+ if state == TaskState.TASK_STATE_REJECTED
96
+ else "a2a_task_failed"
97
+ ),
98
+ message=error_text,
99
+ source="a2a",
100
+ scope_id=scope_id,
101
+ ),
102
+ )
103
+ if state == TaskState.TASK_STATE_CANCELED:
104
+ return RunCanceled(**common, status="canceled", reason="interrupted_active_turn")
105
+ if state == TaskState.TASK_STATE_INPUT_REQUIRED:
106
+ return RunInterrupted(**common, status="interrupted", reason=state_name)
107
+ return RunProgress(**common, status="running", message=state_name)
70
108
 
71
109
  def artifact_to_event(
72
110
  self,
@@ -79,23 +117,40 @@ class A2AEventAdapter:
79
117
  seq_id: int,
80
118
  event_id: Optional[str] = None,
81
119
  ) -> RuntimeEvent:
82
- """A2A Artifact → RuntimeEvent(artifact.*)。"""
120
+ """A2A Artifact → canonical RuntimeEvent(item.started,item_kind="artifact")。"""
121
+ artifact_id = str(getattr(artifact, "artifact_id", None) or "")
83
122
  name = getattr(artifact, "name", None) or "artifact"
84
123
  text = self._parts_text(getattr(artifact, "parts", None))
85
- return RuntimeEvent.create(
86
- EventType.ARTIFACT_CREATED,
87
- agent_id=agent_id,
88
- user_id=user_id,
89
- session_id=session_id,
90
- invocation_id=invocation_id,
91
- seq_id=seq_id,
92
- payload={
93
- "artifact_id": str(getattr(artifact, "artifact_id", None) or ""),
94
- "name": name,
95
- "version": 1,
96
- "text": text,
97
- },
98
- event_id=event_id,
124
+ scope_id = stable_scope_id("a2a", session_id, invocation_id)
125
+ item_id = stable_item_id(
126
+ "a2a", session_id, invocation_id, "artifact", artifact_id or name
127
+ )
128
+ source = SourceRef(
129
+ framework="a2a",
130
+ native_run_id=invocation_id,
131
+ native_item_id=artifact_id or None,
132
+ metadata={"agent_id": agent_id, "user_id": user_id, "artifact_name": name},
133
+ )
134
+ eid = event_id or stable_event_id(
135
+ "a2a", scope_id, item_id, "item.started", "artifact", invocation_id, seq_id
136
+ )
137
+ initial = (
138
+ ContentSnapshot(parts=(TextContent(part_id="text", text=text),))
139
+ if text
140
+ else None
141
+ )
142
+ return ItemStarted(
143
+ schema_version=2,
144
+ event_id=eid,
145
+ seq=seq_id,
146
+ timestamp=time.time(),
147
+ run_id=invocation_id,
148
+ scope_id=scope_id,
149
+ source=source,
150
+ item_id=item_id,
151
+ item_kind="artifact",
152
+ phase="final_answer",
153
+ initial=initial,
99
154
  )
100
155
 
101
156
  def message_to_event(
@@ -110,29 +165,66 @@ class A2AEventAdapter:
110
165
  seq_id: int,
111
166
  event_id: Optional[str] = None,
112
167
  ) -> RuntimeEvent:
113
- """A2A Message 文本 → RuntimeEvent(text.*,带相位)。"""
114
- return RuntimeEvent.create(
115
- EventType.TEXT_COMPLETED if final else EventType.TEXT_DELTA,
116
- agent_id=agent_id,
117
- user_id=user_id,
118
- session_id=session_id,
119
- invocation_id=invocation_id,
120
- seq_id=seq_id,
121
- phase="final_answer" if final else "commentary",
122
- payload={"text": text},
123
- event_id=event_id,
168
+ """A2A Message 文本 → canonical RuntimeEvent(item.*,item_kind="message")。"""
169
+ scope_id = stable_scope_id("a2a", session_id, invocation_id)
170
+ item_id = stable_item_id("a2a", session_id, invocation_id, "message", "response")
171
+ source = SourceRef(
172
+ framework="a2a",
173
+ native_run_id=invocation_id,
174
+ metadata={"agent_id": agent_id, "user_id": user_id},
175
+ )
176
+ timestamp = time.time()
177
+ if final:
178
+ eid = event_id or stable_event_id(
179
+ "a2a", scope_id, item_id, "item.completed", "snapshot", invocation_id, seq_id
180
+ )
181
+ return ItemCompleted(
182
+ schema_version=2,
183
+ event_id=eid,
184
+ seq=seq_id,
185
+ timestamp=timestamp,
186
+ run_id=invocation_id,
187
+ scope_id=scope_id,
188
+ source=source,
189
+ item_id=item_id,
190
+ item_kind="message",
191
+ snapshot=ContentSnapshot(
192
+ parts=(TextContent(part_id="text-0", text=text),)
193
+ ),
194
+ )
195
+ eid = event_id or stable_event_id(
196
+ "a2a", scope_id, item_id, "item.updated", "text-0", invocation_id, seq_id
197
+ )
198
+ return ItemUpdated(
199
+ schema_version=2,
200
+ event_id=eid,
201
+ seq=seq_id,
202
+ timestamp=timestamp,
203
+ run_id=invocation_id,
204
+ scope_id=scope_id,
205
+ source=source,
206
+ item_id=item_id,
207
+ item_kind="message",
208
+ op="append",
209
+ update=TextContent(part_id="text-0", text=text),
124
210
  )
125
211
 
126
212
  # ---- RuntimeEvent → A2A ----
127
213
 
128
214
  @staticmethod
129
215
  def event_to_text_part(event: RuntimeEvent) -> Optional[Part]:
130
- """RuntimeEvent(text.*)→ A2A ``Part``(用于出站 message/artifact)。"""
131
- event.validate_conformance()
132
- if event.event_type not in (EventType.TEXT_DELTA, EventType.TEXT_COMPLETED):
216
+ """RuntimeEvent(item.*,item_kind="message")→ A2A ``Part``(用于出站 message/artifact)。"""
217
+ if isinstance(event, ItemUpdated) and event.item_kind == "message":
218
+ if isinstance(event.update, TextContent):
219
+ text = event.update.text
220
+ return Part(text=text) if text else None
221
+ return None
222
+ if isinstance(event, ItemCompleted) and event.item_kind == "message":
223
+ if event.snapshot.parts and isinstance(event.snapshot.parts[0], TextContent):
224
+ text = event.snapshot.parts[0].text
225
+ return Part(text=text) if text else None
133
226
  return None
134
- text = str(event.payload.get("text") or "")
135
- return Part(text=text) if text else None
227
+ return None
136
228
 
137
229
  @staticmethod
138
230
  def _parts_text(parts: Any) -> str: