agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.3__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 (476) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/METADATA +25 -12
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/RECORD +421 -232
  3. ksadk/_build_provenance.json +1 -0
  4. ksadk/a2a/_space_client_events.py +381 -0
  5. ksadk/a2a/event_adapter.py +156 -64
  6. ksadk/a2a/executor.py +179 -63
  7. ksadk/a2a/space_client.py +6 -333
  8. ksadk/a2ui/core.py +222 -53
  9. ksadk/agui/_agent_helpers.py +247 -0
  10. ksadk/agui/a2ui_projection.py +12 -5
  11. ksadk/agui/agent.py +443 -259
  12. ksadk/api/client.py +528 -27
  13. ksadk/builders/code_builder.py +284 -8
  14. ksadk/builders/container_builder.py +8 -1
  15. ksadk/builders/managed_runtime_builder.py +42 -35
  16. ksadk/cli/__init__.py +23 -0
  17. ksadk/cli/cmd_dashboard.py +15 -1
  18. ksadk/cli/cmd_deploy.py +10 -2
  19. ksadk/cli/cmd_eval.py +66 -9
  20. ksadk/cli/cmd_evalset.py +284 -0
  21. ksadk/cli/cmd_files.py +5 -1
  22. ksadk/cli/cmd_hermes.py +1 -126
  23. ksadk/cli/cmd_invoke.py +28 -38
  24. ksadk/cli/cmd_managed_runtime.py +95 -0
  25. ksadk/cli/cmd_observe.py +85 -0
  26. ksadk/cli/cmd_openclaw.py +1 -435
  27. ksadk/cli/cmd_plugin.py +657 -0
  28. ksadk/cli/cmd_replay.py +28 -4
  29. ksadk/cli/cmd_studio.py +99 -8
  30. ksadk/cli/cmd_web.py +10 -2
  31. ksadk/cli/hermes_env.py +151 -0
  32. ksadk/cli/invoke_payload.py +49 -0
  33. ksadk/cli/openclaw_env.py +458 -0
  34. ksadk/codex/client.py +180 -30
  35. ksadk/codex/runtime.py +475 -331
  36. ksadk/configs/env_registry.py +94 -12
  37. ksadk/configs/env_registry_pcm.py +181 -0
  38. ksadk/configs/env_var_spec.py +18 -0
  39. ksadk/configs/global_config.py +5 -0
  40. ksadk/configs/settings.py +9 -0
  41. ksadk/context_engine/__init__.py +98 -0
  42. ksadk/context_engine/assembler.py +176 -0
  43. ksadk/context_engine/baseline.py +419 -0
  44. ksadk/context_engine/cache_observability.py +228 -0
  45. ksadk/context_engine/capabilities.py +443 -0
  46. ksadk/context_engine/contributors.py +409 -0
  47. ksadk/context_engine/hosted_pipeline.py +417 -0
  48. ksadk/context_engine/models.py +117 -0
  49. ksadk/context_engine/planner.py +698 -0
  50. ksadk/context_engine/policies.py +319 -0
  51. ksadk/context_engine/projection.py +31 -0
  52. ksadk/context_engine/shadow_plan.py +266 -0
  53. ksadk/context_engine/tokenizer.py +164 -0
  54. ksadk/conversations/__init__.py +19 -0
  55. ksadk/conversations/context.py +230 -30
  56. ksadk/conversations/contracts.py +266 -0
  57. ksadk/conversations/message_projection.py +308 -26
  58. ksadk/conversations/model_context.py +49 -3
  59. ksadk/conversations/projector.py +616 -0
  60. ksadk/conversations/reducer.py +98 -0
  61. ksadk/conversations/runtime_compaction.py +207 -5
  62. ksadk/conversations/runtime_input.py +184 -2
  63. ksadk/conversations/runtime_invocation.py +81 -3
  64. ksadk/conversations/runtime_observability.py +141 -0
  65. ksadk/conversations/runtime_payloads.py +42 -0
  66. ksadk/conversations/runtime_preparation.py +272 -2
  67. ksadk/conversations/runtime_resume.py +20 -1
  68. ksadk/conversations/runtime_stream_events.py +94 -9
  69. ksadk/conversations/semantic_summary.py +311 -1
  70. ksadk/conversations/session_lock.py +51 -0
  71. ksadk/deployment/env_forward.py +72 -0
  72. ksadk/deployment/managed_runtime.py +5 -0
  73. ksadk/deployment/providers/serverless.py +143 -69
  74. ksadk/evaluation/__init__.py +32 -0
  75. ksadk/evaluation/a2a_adapter.py +9 -1
  76. ksadk/evaluation/adapters.py +18 -5
  77. ksadk/evaluation/agent_eval_client.py +395 -0
  78. ksadk/evaluation/cloud_binding.py +80 -0
  79. ksadk/evaluation/cloud_converter.py +194 -0
  80. ksadk/evaluation/cloud_service.py +199 -0
  81. ksadk/evaluation/contracts.py +73 -4
  82. ksadk/evaluation/evaluators.py +183 -17
  83. ksadk/evaluation/evidence.py +258 -0
  84. ksadk/evaluation/executor.py +31 -6
  85. ksadk/evaluation/local_adapter.py +550 -0
  86. ksadk/evaluation/service_env.py +27 -0
  87. ksadk/evaluation/studio_build_adapter.py +253 -0
  88. ksadk/evaluation/target.py +15 -6
  89. ksadk/events/__init__.py +13 -13
  90. ksadk/events/_v1_compat/__init__.py +1 -0
  91. ksadk/events/_v1_compat/models.py +299 -0
  92. ksadk/events/_v1_compat/parser.py +247 -0
  93. ksadk/events/_v1_compat/projection.py +755 -0
  94. ksadk/events/adapters/__init__.py +34 -0
  95. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  96. ksadk/events/adapters/_a2a_support.py +275 -0
  97. ksadk/events/adapters/_codex_interactions.py +375 -0
  98. ksadk/events/adapters/_codex_items.py +801 -0
  99. ksadk/events/adapters/_codex_validators.py +311 -0
  100. ksadk/events/adapters/_langgraph_support.py +785 -0
  101. ksadk/events/adapters/a2a.py +841 -0
  102. ksadk/events/adapters/adk.py +503 -0
  103. ksadk/events/adapters/codex.py +907 -0
  104. ksadk/events/adapters/langgraph.py +745 -0
  105. ksadk/events/canonical.py +440 -0
  106. ksadk/events/canonical_replay.py +497 -0
  107. ksadk/events/canonical_store.py +468 -0
  108. ksadk/events/cold_recovery.py +257 -0
  109. ksadk/events/content.py +89 -0
  110. ksadk/events/identity.py +86 -0
  111. ksadk/events/pipeline.py +455 -0
  112. ksadk/events/projections.py +66 -0
  113. ksadk/events/reducer.py +661 -0
  114. ksadk/events/replay.py +3 -36
  115. ksadk/events/runtime_event.py +20 -265
  116. ksadk/events/session_event.py +324 -0
  117. ksadk/events/store.py +3 -316
  118. ksadk/events/v1_compat.py +41 -0
  119. ksadk/harness/__init__.py +45 -35
  120. ksadk/harness/runtime.py +220 -58
  121. ksadk/identity/resolver.py +4 -3
  122. ksadk/interaction/__init__.py +28 -0
  123. ksadk/interaction/contracts.py +136 -0
  124. ksadk/interaction/ledger.py +189 -0
  125. ksadk/interaction/provider.py +122 -0
  126. ksadk/interaction/providers/__init__.py +52 -0
  127. ksadk/interaction/providers/adk.py +40 -0
  128. ksadk/interaction/providers/codex.py +94 -0
  129. ksadk/interaction/providers/langgraph.py +58 -0
  130. ksadk/kernel/__init__.py +117 -0
  131. ksadk/kernel/authorization.py +258 -0
  132. ksadk/kernel/bootstrap.py +1074 -0
  133. ksadk/kernel/contract_fingerprints.py +62 -0
  134. ksadk/kernel/contracts.py +370 -0
  135. ksadk/kernel/control.py +220 -0
  136. ksadk/kernel/errors.py +79 -0
  137. ksadk/kernel/ingress.py +1123 -0
  138. ksadk/kernel/mapping.py +111 -0
  139. ksadk/kernel/memory_store.py +1134 -0
  140. ksadk/kernel/postgres_store.py +1757 -0
  141. ksadk/kernel/recovery.py +452 -0
  142. ksadk/kernel/runtime_identity.py +103 -0
  143. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  144. ksadk/kernel/sqlite_store.py +1411 -0
  145. ksadk/kernel/state.py +145 -0
  146. ksadk/kernel/store.py +232 -0
  147. ksadk/kernel/worker.py +964 -0
  148. ksadk/knowledge_base/client.py +7 -0
  149. ksadk/knowledge_base/service.py +32 -5
  150. ksadk/memory/__init__.py +61 -0
  151. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  152. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  153. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  154. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  155. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  156. ksadk/memory/coordinator.py +461 -0
  157. ksadk/memory/events.py +202 -0
  158. ksadk/memory/extraction.py +228 -0
  159. ksadk/memory/ltm_backend_factory.py +16 -3
  160. ksadk/memory/models.py +316 -0
  161. ksadk/memory/policy.py +215 -0
  162. ksadk/memory/provider.py +47 -0
  163. ksadk/memory/provider_adapter.py +159 -0
  164. ksadk/memory/provider_resolver.py +71 -0
  165. ksadk/memory/providers/__init__.py +5 -0
  166. ksadk/memory/providers/local_sqlite.py +497 -0
  167. ksadk/memory/resolved_policy.py +145 -0
  168. ksadk/memory/service.py +188 -6
  169. ksadk/model_proxy/bootstrap.py +16 -9
  170. ksadk/model_proxy/detect.py +202 -9
  171. ksadk/model_proxy/namespace.py +39 -15
  172. ksadk/model_proxy/server.py +24 -5
  173. ksadk/model_proxy/transform.py +60 -2
  174. ksadk/observability/__init__.py +25 -0
  175. ksadk/observability/session_log.py +420 -0
  176. ksadk/observability/trajectory.py +105 -0
  177. ksadk/plugins/__init__.py +167 -0
  178. ksadk/plugins/bridges/__init__.py +45 -0
  179. ksadk/plugins/bridges/codex.py +552 -0
  180. ksadk/plugins/bridges/dsh.py +1116 -0
  181. ksadk/plugins/builtins.py +747 -0
  182. ksadk/plugins/bundle.py +246 -0
  183. ksadk/plugins/bundle_security.py +167 -0
  184. ksadk/plugins/composition.py +529 -0
  185. ksadk/plugins/context_contributor.py +437 -0
  186. ksadk/plugins/contracts.py +451 -0
  187. ksadk/plugins/dsh_toolchain.py +935 -0
  188. ksadk/plugins/ecosystem_bridge.py +1105 -0
  189. ksadk/plugins/ecosystem_probe.py +191 -0
  190. ksadk/plugins/host.py +724 -0
  191. ksadk/plugins/providers/__init__.py +85 -0
  192. ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
  193. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
  194. ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
  195. ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
  196. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
  197. ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
  198. ksadk/plugins/providers/codex.py +722 -0
  199. ksadk/plugins/providers/codex_dsh.py +83 -0
  200. ksadk/plugins/providers/dsh.py +951 -0
  201. ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
  202. ksadk/plugins/providers/harness.py +627 -0
  203. ksadk/plugins/providers/harness_dsh.py +91 -0
  204. ksadk/plugins/providers/legacy.py +215 -0
  205. ksadk/plugins/providers/legacy_catalog.py +100 -0
  206. ksadk/plugins/providers/shipped_dsh.py +370 -0
  207. ksadk/plugins/resolver.py +331 -0
  208. ksadk/plugins/subagent_providers/__init__.py +12 -0
  209. ksadk/plugins/subagent_providers/codex.py +443 -0
  210. ksadk/plugins/subagents.py +333 -0
  211. ksadk/prompts/__init__.py +71 -0
  212. ksadk/prompts/compiler.py +215 -0
  213. ksadk/prompts/models.py +82 -0
  214. ksadk/prompts/projection.py +89 -0
  215. ksadk/prompts/resolved.py +137 -0
  216. ksadk/prompts/sources.py +233 -0
  217. ksadk/runners/_langgraph_runner_streams.py +822 -0
  218. ksadk/runners/adk_runner.py +5 -5
  219. ksadk/runners/base_runner.py +16 -0
  220. ksadk/runners/factory.py +1 -2
  221. ksadk/runners/langgraph_runner.py +198 -437
  222. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  223. ksadk/runtime/_runner_adapter/stream_mapping.py +797 -0
  224. ksadk/runtime/adapter.py +119 -2
  225. ksadk/runtime/conversation_execution.py +316 -182
  226. ksadk/runtime/executor.py +144 -3
  227. ksadk/runtime/factory.py +268 -8
  228. ksadk/runtime/framework_adapters.py +18 -0
  229. ksadk/runtime/hosted_finalizer.py +268 -0
  230. ksadk/runtime/launch.py +14 -1
  231. ksadk/runtime/preprocessing.py +25 -3
  232. ksadk/runtime/runner_adapter.py +293 -508
  233. ksadk/runtime/usage.py +33 -0
  234. ksadk/sandbox/__init__.py +2 -1
  235. ksadk/sandbox/backends/e2b.py +35 -2
  236. ksadk/sandbox/factory.py +72 -0
  237. ksadk/scheduler/__init__.py +18 -0
  238. ksadk/scheduler/calendar.py +102 -0
  239. ksadk/scheduler/contracts.py +254 -0
  240. ksadk/scheduler/dispatcher.py +129 -0
  241. ksadk/scheduler/engine.py +416 -0
  242. ksadk/scheduler/sqlite_store.py +563 -0
  243. ksadk/server/composition.py +8 -0
  244. ksadk/server/factory.py +69 -6
  245. ksadk/server/routes/kernel_ingress.py +258 -0
  246. ksadk/server/routes/openai_compat.py +88 -8
  247. ksadk/server/routes/projection.py +35 -20
  248. ksadk/server/routes/run.py +94 -0
  249. ksadk/server/routes/sessions.py +2 -0
  250. ksadk/server/routes/streaming.py +5 -2
  251. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-10GPXIJ6.js} +1 -1
  252. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-BXk1l-G1.js} +4 -4
  253. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  254. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-D9uB55Oh.js} +4 -4
  255. ksadk/server/static/assets/MermaidBlock--OEYoXIJ.js +312 -0
  256. ksadk/server/static/assets/NativeTerminalPanel-DrEe1syq.js +1 -0
  257. ksadk/server/static/assets/abnfDiagram-VCTEODGH-eeTFJLvo.js +1 -0
  258. ksadk/server/static/assets/arc-S3ZNbIAd.js +1 -0
  259. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +1 -0
  260. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-CRjgEJDX.js +36 -0
  261. ksadk/server/static/assets/blockDiagram-NRAW4CY4-C7bsBoNH.js +129 -0
  262. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-BX3c33Ob.js +38 -0
  263. ksadk/server/static/assets/channel-s354Yo6o.js +1 -0
  264. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +1 -0
  265. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-bZ7ws-8m.js} +1 -1
  266. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-D2r0pvhY.js} +1 -1
  267. ksadk/server/static/assets/chunk-G27WJ6UU-CZwF3oUP.js +231 -0
  268. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-DigFYCML.js} +1 -1
  269. ksadk/server/static/assets/chunk-LCL6LL3I-CnorGV5q.js +206 -0
  270. ksadk/server/static/assets/chunk-POPQ4Y6H-CexntQA-.js +1 -0
  271. ksadk/server/static/assets/chunk-RHFEMEQ7-CHTC7UxA.js +168 -0
  272. ksadk/server/static/assets/chunk-SVP7TREG-BC1EWt_-.js +88 -0
  273. ksadk/server/static/assets/chunk-XXDRQBXY-BTG24xN0.js +1 -0
  274. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +1 -0
  275. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +1 -0
  276. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-CkonRdAS.js} +1 -1
  277. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +1 -0
  278. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-DEOCBe15.js +62 -0
  279. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  280. ksadk/server/static/assets/dagre-3AP2YEHR-DBThPuLa.js +4 -0
  281. ksadk/server/static/assets/dagre-ClTPrTht.js +1 -0
  282. ksadk/server/static/assets/diagram-S7CK7UJ4-DsZHrnpJ.js +30 -0
  283. ksadk/server/static/assets/diagram-UQ7AKVKN-BJR4nhVr.js +41 -0
  284. ksadk/server/static/assets/diagram-VSXAHHWV-xzcERX0a.js +3 -0
  285. ksadk/server/static/assets/diagram-VX7I27RA-tn2xM1xu.js +24 -0
  286. ksadk/server/static/assets/diagram-Z3DM3KII-BZPGBkw5.js +24 -0
  287. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-4zN1_tq5.js} +1 -1
  288. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-8VWI-2bZ.js} +1 -1
  289. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-B-46q3Hk.js} +1 -1
  290. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-B0gdk4rl.js} +1 -1
  291. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-B1oWRmrH.js} +1 -1
  292. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-BI1qQH4n.js} +1 -1
  293. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-BJLUwH6W.js} +1 -1
  294. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Bbwqa8TG.js} +1 -1
  295. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-Btyo4vX4.js} +1 -1
  296. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-C71CsujO.js} +1 -1
  297. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-CXpH_Rdd.js} +1 -1
  298. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-Cq4OL6nO.js} +1 -1
  299. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-D1V3f1B4.js} +1 -1
  300. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-DJmCPRVB.js} +1 -1
  301. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DQAB0qn_.js} +2 -2
  302. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DUwKa_l6.js} +1 -1
  303. ksadk/server/static/assets/dist-DdRBIceA.js +1 -0
  304. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-DfGFrb0v.js} +1 -1
  305. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-DjhwGUgZ.js} +1 -1
  306. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-DyqV4fL4.js} +1 -1
  307. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-M67Hwu0n.js} +1 -1
  308. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-u8tVH5Ak.js} +1 -1
  309. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-DVfMsLge.js +1 -0
  310. ksadk/server/static/assets/erDiagram-SSCWMZ5O-CWEZSYaw.js +99 -0
  311. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +1 -0
  312. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +1 -0
  313. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-TWIxoyYL.js +292 -0
  314. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +1 -0
  315. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-DDh2hd2S.js +106 -0
  316. ksadk/server/static/assets/index-B2k_urY8.js +241 -0
  317. ksadk/server/static/assets/index-ILPt6IWF.css +2 -0
  318. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +1 -0
  319. ksadk/server/static/assets/infoDiagram-RXCK75RN-CgoyWiDR.js +2 -0
  320. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-CyRIu_om.js} +6 -6
  321. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DN5JXHzN.js} +6 -6
  322. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-CNP3ui66.js} +10 -10
  323. ksadk/server/static/assets/katex-DWEzQy1d.js +257 -0
  324. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-C-qHp7d2.js} +1 -1
  325. ksadk/server/static/assets/mermaid-parser.core-Cl-K943T.js +166 -0
  326. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-D5DB5mYm.js} +29 -29
  327. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +1 -0
  328. ksadk/server/static/assets/pegDiagram-XKGWAZYB-BQVc9ia_.js +1 -0
  329. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +1 -0
  330. ksadk/server/static/assets/pieDiagram-E7YTZNPT-B6UCAvtY.js +39 -0
  331. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-mIr2d3eb.js} +6 -6
  332. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +1 -0
  333. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +1 -0
  334. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +1 -0
  335. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +1 -0
  336. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +1 -0
  337. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-Dt3FFDmK.js +1 -0
  338. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-Cz_vQtgF.js +84 -0
  339. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-wlO1TsH5.js} +7 -7
  340. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-CHRbElYq.js} +10 -10
  341. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-DXX54iyO.js +1 -0
  342. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-Dp_lw9II.js +1 -0
  343. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +1 -0
  344. ksadk/server/static/assets/swimlanes-XN3QIQJK-D8O5UlLG.js +1 -0
  345. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +8 -0
  346. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-8mfKcxvG.js} +7 -7
  347. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +1 -0
  348. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +1 -0
  349. ksadk/server/static/assets/vennDiagram-4TSXK5OY-EnNl0DE7.js +34 -0
  350. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +1 -0
  351. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DBu5fbYr.js +78 -0
  352. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-BSVXs4IY.js +7 -0
  353. ksadk/server/static/index.html +2 -2
  354. ksadk/sessions/__init__.py +26 -9
  355. ksadk/sessions/_local_service_sync.py +688 -0
  356. ksadk/sessions/_local_tables.py +21 -0
  357. ksadk/sessions/_postgres_schema.py +305 -0
  358. ksadk/sessions/_postgres_tables.py +15 -0
  359. ksadk/sessions/base.py +80 -1
  360. ksadk/sessions/in_memory.py +53 -2
  361. ksadk/sessions/local_service.py +63 -604
  362. ksadk/sessions/postgres_service.py +58 -148
  363. ksadk/sessions/resilient.py +35 -1
  364. ksadk/skills/service_client.py +48 -0
  365. ksadk/studio/agent_lifecycle.py +26 -20
  366. ksadk/studio/api.py +1063 -69
  367. ksadk/studio/api_catalog_routes.py +5 -0
  368. ksadk/studio/api_contracts.py +148 -6
  369. ksadk/studio/api_memory_routes.py +82 -0
  370. ksadk/studio/api_plugin_routes.py +480 -0
  371. ksadk/studio/attachment_store.py +187 -0
  372. ksadk/studio/authoring.py +259 -28
  373. ksadk/studio/authoring_coordinator.py +809 -67
  374. ksadk/studio/builder.py +197 -40
  375. ksadk/studio/capabilities.py +17 -0
  376. ksadk/studio/cloud.py +1920 -95
  377. ksadk/studio/codex_agent_service.py +137 -15
  378. ksadk/studio/codex_authoring.py +469 -0
  379. ksadk/studio/codex_builder.py +177 -25
  380. ksadk/studio/codex_manifest.py +71 -22
  381. ksadk/studio/codex_run.py +59 -4
  382. ksadk/studio/compatibility_report.py +445 -0
  383. ksadk/studio/compiler.py +7 -1
  384. ksadk/studio/contracts.py +234 -4
  385. ksadk/studio/dsh_provider_registration.py +768 -0
  386. ksadk/studio/event_store.py +79 -101
  387. ksadk/studio/framework_run.py +264 -3
  388. ksadk/studio/hosted_kernel.py +317 -0
  389. ksadk/studio/manifest_resolver.py +131 -0
  390. ksadk/studio/model_client.py +95 -9
  391. ksadk/studio/model_profile_service.py +1 -1
  392. ksadk/studio/operations.py +47 -5
  393. ksadk/studio/otel_trace.py +348 -42
  394. ksadk/studio/pcm_memory.py +85 -0
  395. ksadk/studio/plugin_composition.py +301 -0
  396. ksadk/studio/plugin_kernel_adapter.py +128 -0
  397. ksadk/studio/plugin_runtime.py +652 -0
  398. ksadk/studio/repository.py +23 -2
  399. ksadk/studio/resource_catalog.py +49 -1
  400. ksadk/studio/run_service.py +1266 -202
  401. ksadk/studio/runtime_source.py +51 -17
  402. ksadk/studio/scheduler_runtime.py +374 -0
  403. ksadk/studio/scheduler_service.py +211 -0
  404. ksadk/studio/service.py +1815 -117
  405. ksadk/studio/shared_web.py +199 -50
  406. ksadk/studio/soul.py +52 -0
  407. ksadk/studio/static/assets/index-DXs1Eq4M.css +1 -0
  408. ksadk/studio/static/assets/index-DeDqwTsD.js +283 -0
  409. ksadk/studio/static/index.html +2 -2
  410. ksadk/studio/templates.py +100 -8
  411. ksadk/studio/validator.py +20 -1
  412. ksadk/studio/workspace.py +31 -32
  413. ksadk/tracing/setup.py +304 -3
  414. ksadk/version.py +1 -1
  415. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  416. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  417. ksadk_runtime_common/workspace_files/path_utils.py +41 -0
  418. ksadk/events/parser.py +0 -191
  419. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  420. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  421. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  422. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  423. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  424. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  425. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  426. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  427. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  428. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  429. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  430. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  431. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  432. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  433. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  434. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  435. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  436. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  437. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  438. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  439. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  440. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  441. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  442. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  443. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  444. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  445. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  446. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  447. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  448. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  449. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  450. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  451. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  452. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  453. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  454. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  455. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  456. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  457. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  458. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  459. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  460. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  461. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  462. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  463. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  464. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  465. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  466. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  467. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  468. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  469. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  470. ksadk/studio/evaluation.py +0 -192
  471. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  472. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  473. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/WHEEL +0 -0
  474. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/entry_points.txt +0 -0
  475. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/licenses/LICENSE +0 -0
  476. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1 @@
1
+ {"schemaVersion":1,"sourceCommit":"320b7f324966bd3aa8557a65cf592716699edb8c","sourceTree":"clean","version":"0.8.3"}
@@ -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: