agentengine-sdk-python 0.8.0__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 (494) hide show
  1. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
  2. agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
  3. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +2 -0
  5. ksadk/a2a/_space_client_events.py +381 -0
  6. ksadk/a2a/bootstrap.py +0 -2
  7. ksadk/a2a/card.py +6 -111
  8. ksadk/a2a/control_plane.py +239 -1
  9. ksadk/a2a/event_adapter.py +156 -64
  10. ksadk/a2a/executor.py +195 -172
  11. ksadk/a2a/routes.py +12 -5
  12. ksadk/a2a/server.py +1 -8
  13. ksadk/a2a/service_env.py +33 -0
  14. ksadk/a2a/space_client.py +43 -349
  15. ksadk/a2a_card.py +101 -0
  16. ksadk/a2ui/core.py +222 -53
  17. ksadk/agui/_agent_helpers.py +243 -0
  18. ksadk/agui/a2ui_projection.py +12 -5
  19. ksadk/agui/agent.py +474 -275
  20. ksadk/agui/config.py +11 -5
  21. ksadk/agui/routes.py +7 -15
  22. ksadk/api/client.py +530 -40
  23. ksadk/api/environment.py +27 -0
  24. ksadk/builders/code_builder.py +352 -53
  25. ksadk/builders/container_builder.py +71 -44
  26. ksadk/builders/framework_requirements.py +2 -1
  27. ksadk/builders/ks3_uploader.py +2 -2
  28. ksadk/builders/managed_runtime_builder.py +60 -28
  29. ksadk/cli/__init__.py +25 -0
  30. ksadk/cli/cmd_a2a.py +18 -31
  31. ksadk/cli/cmd_create.py +13 -26
  32. ksadk/cli/cmd_dashboard.py +15 -1
  33. ksadk/cli/cmd_deploy.py +28 -3
  34. ksadk/cli/cmd_eval.py +443 -0
  35. ksadk/cli/cmd_evalset.py +284 -0
  36. ksadk/cli/cmd_files.py +5 -1
  37. ksadk/cli/cmd_hermes.py +137 -163
  38. ksadk/cli/cmd_invoke.py +28 -38
  39. ksadk/cli/cmd_launch.py +12 -0
  40. ksadk/cli/cmd_managed_runtime.py +95 -0
  41. ksadk/cli/cmd_observe.py +85 -0
  42. ksadk/cli/cmd_openclaw.py +85 -479
  43. ksadk/cli/cmd_replay.py +28 -4
  44. ksadk/cli/cmd_run.py +29 -67
  45. ksadk/cli/cmd_studio.py +201 -0
  46. ksadk/cli/cmd_web.py +15 -6
  47. ksadk/cli/dry_run.py +2 -1
  48. ksadk/cli/env_options.py +83 -0
  49. ksadk/cli/global_options.py +3 -1
  50. ksadk/cli/hermes_env.py +151 -0
  51. ksadk/cli/invoke_payload.py +49 -0
  52. ksadk/cli/network_options.py +7 -5
  53. ksadk/cli/openclaw_env.py +458 -0
  54. ksadk/cli/runtime_bootstrap.py +51 -0
  55. ksadk/cli/ui.py +6 -0
  56. ksadk/cli/workflow_common.py +5 -5
  57. ksadk/codex/__init__.py +3 -3
  58. ksadk/codex/client.py +833 -49
  59. ksadk/codex/phase.py +1 -1
  60. ksadk/codex/runtime.py +720 -127
  61. ksadk/common/kop_client.py +232 -0
  62. ksadk/configs/__init__.py +1 -3
  63. ksadk/configs/env_registry.py +244 -45
  64. ksadk/configs/env_registry_pcm.py +181 -0
  65. ksadk/configs/env_var_spec.py +18 -0
  66. ksadk/configs/global_config.py +6 -1
  67. ksadk/configs/settings.py +5 -108
  68. ksadk/context_engine/__init__.py +98 -0
  69. ksadk/context_engine/assembler.py +176 -0
  70. ksadk/context_engine/baseline.py +419 -0
  71. ksadk/context_engine/cache_observability.py +228 -0
  72. ksadk/context_engine/capabilities.py +443 -0
  73. ksadk/context_engine/contributors.py +344 -0
  74. ksadk/context_engine/hosted_pipeline.py +417 -0
  75. ksadk/context_engine/models.py +117 -0
  76. ksadk/context_engine/planner.py +698 -0
  77. ksadk/context_engine/policies.py +319 -0
  78. ksadk/context_engine/projection.py +31 -0
  79. ksadk/context_engine/shadow_plan.py +266 -0
  80. ksadk/context_engine/tokenizer.py +164 -0
  81. ksadk/conversations/__init__.py +85 -94
  82. ksadk/conversations/context.py +126 -6
  83. ksadk/conversations/message_projection.py +292 -28
  84. ksadk/conversations/model_context.py +49 -3
  85. ksadk/conversations/runtime_compaction.py +207 -5
  86. ksadk/conversations/runtime_input.py +193 -3
  87. ksadk/conversations/runtime_invocation.py +81 -3
  88. ksadk/conversations/runtime_observability.py +157 -4
  89. ksadk/conversations/runtime_payloads.py +42 -0
  90. ksadk/conversations/runtime_preparation.py +280 -2
  91. ksadk/conversations/runtime_resume.py +71 -32
  92. ksadk/conversations/runtime_stream_events.py +94 -9
  93. ksadk/conversations/runtime_streaming.py +175 -22
  94. ksadk/conversations/semantic_summary.py +311 -1
  95. ksadk/conversations/session_lock.py +51 -0
  96. ksadk/deployment/env_forward.py +72 -0
  97. ksadk/deployment/managed_runtime.py +38 -0
  98. ksadk/deployment/manager.py +24 -8
  99. ksadk/deployment/providers/serverless.py +228 -92
  100. ksadk/evaluation/__init__.py +116 -0
  101. ksadk/evaluation/a2a_adapter.py +452 -0
  102. ksadk/evaluation/adapters.py +67 -0
  103. ksadk/evaluation/agent_eval_client.py +395 -0
  104. ksadk/evaluation/cloud_binding.py +80 -0
  105. ksadk/evaluation/cloud_converter.py +194 -0
  106. ksadk/evaluation/cloud_service.py +199 -0
  107. ksadk/evaluation/contracts.py +478 -0
  108. ksadk/evaluation/evalset.py +351 -0
  109. ksadk/evaluation/evaluators.py +627 -0
  110. ksadk/evaluation/evidence.py +258 -0
  111. ksadk/evaluation/executor.py +143 -0
  112. ksadk/evaluation/local_adapter.py +550 -0
  113. ksadk/evaluation/service_env.py +27 -0
  114. ksadk/evaluation/storage.py +68 -0
  115. ksadk/evaluation/studio_build_adapter.py +253 -0
  116. ksadk/evaluation/target.py +82 -0
  117. ksadk/events/__init__.py +13 -13
  118. ksadk/events/_v1_compat/__init__.py +1 -0
  119. ksadk/events/_v1_compat/models.py +299 -0
  120. ksadk/events/_v1_compat/parser.py +247 -0
  121. ksadk/events/_v1_compat/projection.py +753 -0
  122. ksadk/events/adapters/__init__.py +34 -0
  123. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  124. ksadk/events/adapters/_a2a_support.py +275 -0
  125. ksadk/events/adapters/_codex_interactions.py +375 -0
  126. ksadk/events/adapters/_codex_items.py +801 -0
  127. ksadk/events/adapters/_codex_validators.py +311 -0
  128. ksadk/events/adapters/_langgraph_support.py +785 -0
  129. ksadk/events/adapters/a2a.py +841 -0
  130. ksadk/events/adapters/adk.py +503 -0
  131. ksadk/events/adapters/codex.py +717 -0
  132. ksadk/events/adapters/langgraph.py +745 -0
  133. ksadk/events/canonical.py +440 -0
  134. ksadk/events/canonical_replay.py +497 -0
  135. ksadk/events/canonical_store.py +468 -0
  136. ksadk/events/cold_recovery.py +257 -0
  137. ksadk/events/content.py +89 -0
  138. ksadk/events/identity.py +86 -0
  139. ksadk/events/pipeline.py +455 -0
  140. ksadk/events/projections.py +66 -0
  141. ksadk/events/reducer.py +661 -0
  142. ksadk/events/replay.py +3 -36
  143. ksadk/events/runtime_event.py +20 -256
  144. ksadk/events/session_event.py +324 -0
  145. ksadk/events/store.py +3 -316
  146. ksadk/events/v1_compat.py +41 -0
  147. ksadk/harness/__init__.py +3 -2
  148. ksadk/harness/app.py +114 -123
  149. ksadk/harness/config.py +1 -1
  150. ksadk/harness/runtime.py +467 -0
  151. ksadk/hermes_terminal.py +5 -0
  152. ksadk/identity/resolver.py +4 -3
  153. ksadk/interaction/__init__.py +28 -0
  154. ksadk/interaction/contracts.py +136 -0
  155. ksadk/interaction/ledger.py +189 -0
  156. ksadk/interaction/provider.py +122 -0
  157. ksadk/interaction/providers/__init__.py +52 -0
  158. ksadk/interaction/providers/adk.py +40 -0
  159. ksadk/interaction/providers/codex.py +94 -0
  160. ksadk/interaction/providers/langgraph.py +58 -0
  161. ksadk/kernel/__init__.py +117 -0
  162. ksadk/kernel/authorization.py +258 -0
  163. ksadk/kernel/bootstrap.py +1074 -0
  164. ksadk/kernel/contract_fingerprints.py +61 -0
  165. ksadk/kernel/contracts.py +362 -0
  166. ksadk/kernel/control.py +219 -0
  167. ksadk/kernel/errors.py +79 -0
  168. ksadk/kernel/ingress.py +1102 -0
  169. ksadk/kernel/mapping.py +111 -0
  170. ksadk/kernel/memory_store.py +1133 -0
  171. ksadk/kernel/postgres_store.py +1756 -0
  172. ksadk/kernel/recovery.py +452 -0
  173. ksadk/kernel/runtime_identity.py +103 -0
  174. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  175. ksadk/kernel/sqlite_store.py +1410 -0
  176. ksadk/kernel/state.py +145 -0
  177. ksadk/kernel/store.py +232 -0
  178. ksadk/kernel/worker.py +953 -0
  179. ksadk/knowledge_base/client.py +22 -4
  180. ksadk/knowledge_base/service.py +32 -5
  181. ksadk/managed_a2a_card.py +160 -0
  182. ksadk/managed_runtime.py +16 -9
  183. ksadk/memory/__init__.py +61 -0
  184. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  185. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  186. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  187. ksadk/memory/adk/backends/sdk_ltm_backend.py +394 -5
  188. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  189. ksadk/memory/adk/long_term_memory.py +3 -2
  190. ksadk/memory/coordinator.py +461 -0
  191. ksadk/memory/events.py +202 -0
  192. ksadk/memory/extraction.py +228 -0
  193. ksadk/memory/ltm_backend_factory.py +16 -3
  194. ksadk/memory/models.py +316 -0
  195. ksadk/memory/policy.py +215 -0
  196. ksadk/memory/provider.py +47 -0
  197. ksadk/memory/provider_adapter.py +159 -0
  198. ksadk/memory/provider_resolver.py +71 -0
  199. ksadk/memory/providers/__init__.py +5 -0
  200. ksadk/memory/providers/local_sqlite.py +490 -0
  201. ksadk/memory/resolved_policy.py +145 -0
  202. ksadk/memory/service.py +198 -8
  203. ksadk/memory/tool.py +4 -0
  204. ksadk/model_proxy/bootstrap.py +16 -9
  205. ksadk/model_proxy/config.py +22 -1
  206. ksadk/model_proxy/detect.py +202 -9
  207. ksadk/model_proxy/namespace.py +67 -15
  208. ksadk/model_proxy/server.py +168 -6
  209. ksadk/model_proxy/transform.py +105 -3
  210. ksadk/observability/__init__.py +25 -0
  211. ksadk/observability/session_log.py +420 -0
  212. ksadk/observability/trajectory.py +105 -0
  213. ksadk/prompts/__init__.py +71 -0
  214. ksadk/prompts/compiler.py +215 -0
  215. ksadk/prompts/models.py +82 -0
  216. ksadk/prompts/projection.py +89 -0
  217. ksadk/prompts/resolved.py +137 -0
  218. ksadk/prompts/sources.py +233 -0
  219. ksadk/runners/_langgraph_runner_streams.py +822 -0
  220. ksadk/runners/adk_runner.py +14 -31
  221. ksadk/runners/base_runner.py +44 -3
  222. ksadk/runners/factory.py +3 -3
  223. ksadk/runners/langgraph_runner.py +252 -433
  224. ksadk/runners/utils/__init__.py +0 -10
  225. ksadk/runners/utils/loader.py +16 -0
  226. ksadk/runtime/__init__.py +67 -41
  227. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  228. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  229. ksadk/runtime/adapter.py +199 -16
  230. ksadk/runtime/conversation_execution.py +687 -0
  231. ksadk/runtime/executor.py +392 -0
  232. ksadk/runtime/factory.py +342 -0
  233. ksadk/runtime/framework_adapters.py +6 -12
  234. ksadk/runtime/hosted_finalizer.py +268 -0
  235. ksadk/runtime/launch.py +61 -0
  236. ksadk/runtime/preprocessing.py +49 -14
  237. ksadk/runtime/runner_adapter.py +330 -391
  238. ksadk/runtime/runner_loading.py +36 -0
  239. ksadk/runtime/usage.py +33 -0
  240. ksadk/sandbox/backends/e2b.py +36 -3
  241. ksadk/server/__init__.py +39 -4
  242. ksadk/server/app.py +18 -492
  243. ksadk/server/composition.py +36 -2
  244. ksadk/server/factory.py +210 -149
  245. ksadk/server/routes/common.py +15 -46
  246. ksadk/server/routes/control.py +13 -9
  247. ksadk/server/routes/kernel_ingress.py +258 -0
  248. ksadk/server/routes/misc.py +10 -33
  249. ksadk/server/routes/models.py +14 -6
  250. ksadk/server/routes/openai_compat.py +129 -27
  251. ksadk/server/routes/projection.py +84 -16
  252. ksadk/server/routes/run.py +347 -460
  253. ksadk/server/routes/sessions.py +37 -40
  254. ksadk/server/routes/streaming.py +52 -7
  255. ksadk/server/routes/workspace.py +54 -21
  256. ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  257. ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
  258. ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  259. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  260. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  261. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  262. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  263. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  264. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  265. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  266. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  267. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  268. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  269. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  270. ksadk/server/static/assets/{chunk-FMBD7UC4-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  271. ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  272. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  273. ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  274. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  275. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  276. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  277. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  278. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  279. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  280. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  281. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-CX3yotHq.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  282. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  283. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  284. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  285. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  286. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  287. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  288. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  289. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  290. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  291. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  292. ksadk/server/static/assets/{dist-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
  293. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  294. ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
  295. ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
  296. ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
  297. ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
  298. ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
  299. ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
  300. ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
  301. ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
  302. ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
  303. ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
  304. ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
  305. ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
  306. ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
  307. ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
  308. ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
  309. ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
  310. ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
  311. ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
  312. ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
  313. ksadk/server/static/assets/{dist-C99THtIA.js → dist-ngtN0DJB.js} +1 -1
  314. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  315. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  316. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  317. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  318. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  319. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  320. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  321. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  322. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  323. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  324. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  325. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  326. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  327. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  328. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  329. ksadk/server/static/assets/{linear-CvMBw9cA.js → linear-BHjG8b-J.js} +1 -1
  330. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  331. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-CSAQxEAe.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  332. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  333. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  334. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  335. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  336. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-CxIR4JXI.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  337. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  338. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  339. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  340. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  341. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  342. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  343. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  344. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  345. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  346. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  347. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  348. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  349. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  350. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  351. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-jqoYs3jQ.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  352. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  353. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  354. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  355. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  356. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  357. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  358. ksadk/server/static/index.html +2 -2
  359. ksadk/sessions/__init__.py +26 -9
  360. ksadk/sessions/_local_service_sync.py +688 -0
  361. ksadk/sessions/_local_tables.py +21 -0
  362. ksadk/sessions/_postgres_schema.py +305 -0
  363. ksadk/sessions/_postgres_tables.py +15 -0
  364. ksadk/sessions/base.py +80 -1
  365. ksadk/sessions/in_memory.py +53 -2
  366. ksadk/sessions/local_service.py +63 -604
  367. ksadk/sessions/postgres_service.py +58 -148
  368. ksadk/sessions/resilient.py +35 -1
  369. ksadk/skills/runtime/backends/e2b.py +1 -1
  370. ksadk/skills/service_client.py +13 -3
  371. ksadk/studio/__init__.py +5 -0
  372. ksadk/studio/agent_avatar_assets.py +120 -0
  373. ksadk/studio/agent_lifecycle.py +51 -0
  374. ksadk/studio/api.py +1598 -0
  375. ksadk/studio/api_catalog_routes.py +324 -0
  376. ksadk/studio/api_contracts.py +286 -0
  377. ksadk/studio/api_helpers.py +132 -0
  378. ksadk/studio/api_memory_routes.py +82 -0
  379. ksadk/studio/authoring.py +749 -0
  380. ksadk/studio/authoring_coordinator.py +1017 -0
  381. ksadk/studio/builder.py +397 -0
  382. ksadk/studio/capabilities.py +368 -0
  383. ksadk/studio/cloud.py +2099 -0
  384. ksadk/studio/codex_agent_service.py +694 -0
  385. ksadk/studio/codex_authoring.py +469 -0
  386. ksadk/studio/codex_builder.py +437 -0
  387. ksadk/studio/codex_manifest.py +307 -0
  388. ksadk/studio/codex_run.py +395 -0
  389. ksadk/studio/compiler.py +190 -0
  390. ksadk/studio/contracts.py +755 -0
  391. ksadk/studio/errors.py +47 -0
  392. ksadk/studio/event_store.py +214 -0
  393. ksadk/studio/framework_run.py +342 -0
  394. ksadk/studio/hosted_kernel.py +317 -0
  395. ksadk/studio/identifiers.py +33 -0
  396. ksadk/studio/manifest_resolver.py +131 -0
  397. ksadk/studio/mcp_runtime.py +229 -0
  398. ksadk/studio/model_client.py +629 -0
  399. ksadk/studio/model_profile_service.py +214 -0
  400. ksadk/studio/operations.py +275 -0
  401. ksadk/studio/otel_trace.py +1060 -0
  402. ksadk/studio/pagination.py +182 -0
  403. ksadk/studio/pcm_memory.py +85 -0
  404. ksadk/studio/python_tool_inspection.py +183 -0
  405. ksadk/studio/repository.py +327 -0
  406. ksadk/studio/resource_catalog.py +1260 -0
  407. ksadk/studio/run_service.py +1133 -0
  408. ksadk/studio/runtime_catalog.py +74 -0
  409. ksadk/studio/runtime_source.py +365 -0
  410. ksadk/studio/service.py +2249 -0
  411. ksadk/studio/shared_web.py +1004 -0
  412. ksadk/studio/skill_discovery.py +628 -0
  413. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  414. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  415. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  416. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  417. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  418. ksadk/studio/static/index.html +15 -0
  419. ksadk/studio/templates.py +722 -0
  420. ksadk/studio/validator.py +265 -0
  421. ksadk/studio/workspace.py +135 -0
  422. ksadk/tools/gateway.py +9 -0
  423. ksadk/toolsets/__init__.py +27 -1
  424. ksadk/toolsets/a2a.py +426 -0
  425. ksadk/tracing/__init__.py +19 -21
  426. ksadk/tracing/setup.py +317 -403
  427. ksadk/tracing/span_utils.py +0 -44
  428. ksadk/version.py +1 -1
  429. ksadk_runtime_common/memory_backend/registry.py +56 -56
  430. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  431. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  432. ksadk_runtime_common/workspace_files/router.py +8 -2
  433. agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
  434. ksadk/a2a/card_builder.py +0 -64
  435. ksadk/a2a/client.py +0 -309
  436. ksadk/events/parser.py +0 -191
  437. ksadk/harness/runner.py +0 -211
  438. ksadk/runners/codex_runner.py +0 -132
  439. ksadk/runners/utils/langfuse.py +0 -230
  440. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  441. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
  442. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
  443. ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
  444. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
  445. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
  446. ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
  447. ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
  448. ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
  449. ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
  450. ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
  451. ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
  452. ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
  453. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
  454. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
  455. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
  456. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  457. ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
  458. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  459. ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
  460. ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
  461. ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
  462. ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
  463. ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
  464. ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
  465. ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
  466. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
  467. ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
  468. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
  469. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
  470. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
  471. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  472. ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
  473. ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
  474. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
  475. ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
  476. ksadk/server/static/assets/katex-DATssjp1.js +0 -265
  477. ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
  478. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
  479. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
  480. ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
  481. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
  482. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
  483. ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
  484. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
  485. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
  486. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
  487. ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
  488. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
  489. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
  490. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
  491. ksadk/tracing/exporters/langfuse_exporter.py +0 -460
  492. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  493. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  494. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
ksadk/a2a/space_client.py CHANGED
@@ -7,7 +7,7 @@ import json
7
7
  import logging
8
8
  import os
9
9
  import uuid
10
- from collections.abc import AsyncIterator, Mapping
10
+ from collections.abc import AsyncIterator
11
11
  from contextlib import AsyncExitStack, asynccontextmanager
12
12
  from dataclasses import dataclass
13
13
  from datetime import datetime, timezone
@@ -27,17 +27,16 @@ from a2a.types import (
27
27
  SendMessageConfiguration,
28
28
  SendMessageRequest,
29
29
  SubscribeToTaskRequest,
30
- TaskState,
31
30
  )
32
31
  from google.protobuf.json_format import MessageToDict, ParseDict
33
32
 
33
+ from ksadk.a2a._space_client_events import _SpaceClientEventMixin
34
34
  from ksadk.a2a.control_plane import (
35
- ENV_A2A_CONTROL_PLANE_URL,
35
+ A2AAgentCardClient,
36
36
  A2AControlPlane,
37
37
  A2ARouteInterface,
38
38
  CredentialInjection,
39
39
  DiscoveredAgent,
40
- InternalA2AControlPlaneClient,
41
40
  PreparedA2AOperation,
42
41
  SpaceAgentPage,
43
42
  )
@@ -54,6 +53,7 @@ from ksadk.events.runtime_event import RuntimeEvent
54
53
 
55
54
  logger = logging.getLogger(__name__)
56
55
 
56
+ ENV_A2A_SPACE_ID = "KSADK_A2A_SPACE_ID"
57
57
  ENV_A2A_SPACE_IDS = "KSADK_A2A_SPACE_IDS"
58
58
  ENV_A2A_ENABLE_PUBLIC_EGRESS = "KSADK_A2A_ENABLE_PUBLIC_EGRESS"
59
59
 
@@ -63,6 +63,14 @@ MAX_A2A_MESSAGE_PARTS = 64
63
63
  MAX_A2A_MESSAGE_ID_LENGTH = 128
64
64
 
65
65
 
66
+ def _require_opaque_space_id(value: str, *, field_name: str) -> str:
67
+ """Validate a server-issued opaque Space ID without assuming a prefix."""
68
+ normalized = str(value or "").strip()
69
+ if not normalized or len(normalized) > 256 or any(char.isspace() for char in normalized):
70
+ raise ValueError(f"{field_name} must be a non-empty opaque resource ID")
71
+ return normalized
72
+
73
+
66
74
  @dataclass(frozen=True)
67
75
  class A2APlatformTask:
68
76
  """AgentEngine task locator with an optional latest remote A2A snapshot."""
@@ -96,7 +104,7 @@ def _present_message_field(value: Any, field_name: str) -> Any | None:
96
104
  return getattr(value, field_name, None)
97
105
 
98
106
 
99
- class A2ASpaceClient:
107
+ class A2ASpaceClient(_SpaceClientEventMixin):
100
108
  """Discovers Space members and performs permit-authorized A2A calls."""
101
109
 
102
110
  def __init__(
@@ -111,7 +119,7 @@ class A2ASpaceClient:
111
119
  event_outbox: A2ATaskEventOutbox | None = None,
112
120
  event_dispatcher: A2ATaskEventDispatcher | None = None,
113
121
  ) -> None:
114
- require_a2a_resource_id(space_id, "a2a-space-", field_name="space_id")
122
+ space_id = _require_opaque_space_id(space_id, field_name="space_id")
115
123
  if external_transport is not None and not isinstance(
116
124
  external_transport, A2AExternalTransport
117
125
  ):
@@ -148,19 +156,15 @@ class A2ASpaceClient:
148
156
  event_outbox: A2ATaskEventOutbox | None = None,
149
157
  event_dispatcher: A2ATaskEventDispatcher | None = None,
150
158
  ) -> "A2ASpaceClient":
151
- selected_space_id = str(space_id or "").strip()
159
+ selected_space_id = str(space_id or os.getenv(ENV_A2A_SPACE_ID) or "").strip()
152
160
  if selected_space_id:
153
- require_a2a_resource_id(
154
- selected_space_id,
155
- "a2a-space-",
156
- field_name="space_id",
157
- )
161
+ selected_space_id = _require_opaque_space_id(selected_space_id, field_name="space_id")
158
162
  else:
159
163
  raw_space_ids = str(os.getenv(ENV_A2A_SPACE_IDS) or "").strip()
160
164
  if not raw_space_ids:
161
165
  raise ValueError(
162
- f"missing {ENV_A2A_SPACE_IDS}; pass space_id or add the Runtime Agent "
163
- "to an A2A Space first"
166
+ f"missing {ENV_A2A_SPACE_ID} and {ENV_A2A_SPACE_IDS}; pass space_id "
167
+ "or add the Runtime Agent to an A2A Space first"
164
168
  )
165
169
  try:
166
170
  configured_space_ids = json.loads(raw_space_ids)
@@ -175,10 +179,8 @@ class A2ASpaceClient:
175
179
  if not isinstance(configured_space_id, str):
176
180
  raise ValueError(f"{ENV_A2A_SPACE_IDS}[{index}] must be an A2A Space ID string")
177
181
  normalized = configured_space_id.strip()
178
- require_a2a_resource_id(
179
- normalized,
180
- "a2a-space-",
181
- field_name=f"{ENV_A2A_SPACE_IDS}[{index}]",
182
+ normalized = _require_opaque_space_id(
183
+ normalized, field_name=f"{ENV_A2A_SPACE_IDS}[{index}]"
182
184
  )
183
185
  normalized_space_ids.append(normalized)
184
186
  if len(set(normalized_space_ids)) != len(normalized_space_ids):
@@ -189,11 +191,19 @@ class A2ASpaceClient:
189
191
  )
190
192
  selected_space_id = normalized_space_ids[0]
191
193
  if backend is None:
192
- control_plane_url = str(os.getenv(ENV_A2A_CONTROL_PLANE_URL) or "").strip()
193
- if not control_plane_url:
194
- raise ValueError(f"missing {ENV_A2A_CONTROL_PLANE_URL}")
195
- backend = InternalA2AControlPlaneClient(
196
- control_plane_url,
194
+ from ksadk.a2a.service_env import (
195
+ resolve_a2a_service_token,
196
+ resolve_a2a_service_url,
197
+ )
198
+
199
+ service_url = resolve_a2a_service_url()
200
+ if not service_url:
201
+ raise ValueError(
202
+ "A2A service url not configured: set KSADK_A2A_SERVICE_URL or AICP env"
203
+ )
204
+ backend = A2AAgentCardClient(
205
+ service_url,
206
+ service_token=resolve_a2a_service_token(),
197
207
  httpx_client=httpx_client,
198
208
  )
199
209
  if egress_enabled is None:
@@ -354,7 +364,9 @@ class A2ASpaceClient:
354
364
  async for response in client.send_message(request, context=context):
355
365
  response_task = _present_message_field(response, "task")
356
366
  if response_task is not None and str(getattr(response_task, "id", None) or ""):
357
- first_task = first_task or response_task
367
+ # 跟踪最新 task 状态:每个带 task 的 response 都更新 first_task,
368
+ # 使 send_message 返回的是最终状态(如 COMPLETED)而非首个 SUBMITTED。
369
+ first_task = response_task
358
370
  observed_task_id = str(response_task.id)
359
371
  observed_context_id = str(response_task.context_id or "") or None
360
372
  if remote_task_id is None:
@@ -464,9 +476,11 @@ class A2ASpaceClient:
464
476
 
465
477
  async def get_task(self, task_id: str) -> A2APlatformTask:
466
478
  require_a2a_resource_id(task_id, "a2a-task-", field_name="task_id")
479
+ cached_agent = self._agents_by_task.get(task_id)
467
480
  prepared = await self._backend.prepare_task_operation(
468
481
  platform_task_id=task_id,
469
482
  operation="get_task",
483
+ agent_id=getattr(cached_agent, "agent_id", None),
470
484
  )
471
485
  self._validate_prepared_ids(prepared)
472
486
  remote_task_ref = self._require_remote_task(prepared)
@@ -627,10 +641,12 @@ class A2ASpaceClient:
627
641
  headers: dict[str, str]
628
642
  async with AsyncExitStack() as exit_stack:
629
643
  if prepared.route.kind == "hosted_gateway":
644
+ token = self._backend.gateway_token()
630
645
  headers = {
631
- "Authorization": f"Bearer {self._backend.gateway_token()}",
632
646
  "X-AgentEngine-A2A-Permit": prepared.call_permit,
633
647
  }
648
+ if token:
649
+ headers["Authorization"] = f"Bearer {token}"
634
650
  http = self._httpx_client
635
651
  else:
636
652
  if prepared.route.kind == "external_public" and not self._egress_enabled:
@@ -670,6 +686,7 @@ class A2ASpaceClient:
670
686
  route_card = self._card_for_route(agent.agent_card, route)
671
687
  owned_http = None
672
688
  if http is None:
689
+ # 外部调用方需自行传入已配置 verify 的 httpx_client。
673
690
  owned_http = httpx.AsyncClient(trust_env=False)
674
691
  http = owned_http
675
692
  client = await create_client(
@@ -731,330 +748,6 @@ class A2ASpaceClient:
731
748
  observed_at=_utc_now(),
732
749
  )
733
750
 
734
- async def _project_stream_item(
735
- self,
736
- platform_task_id: str,
737
- item: Any,
738
- agent: DiscoveredAgent,
739
- *,
740
- wire_position: int,
741
- operation_instance_id: str,
742
- ) -> list[RuntimeEvent]:
743
- runtime_events = self._stream_item_to_events(
744
- item,
745
- agent,
746
- wire_position=wire_position,
747
- invocation_id=platform_task_id,
748
- )
749
- platform_events = self._platform_events(
750
- item,
751
- platform_task_id,
752
- operation_instance_id=operation_instance_id,
753
- wire_position=wire_position,
754
- )
755
- if platform_events:
756
- await self._event_dispatcher.enqueue(
757
- platform_task_id=platform_task_id,
758
- events=platform_events,
759
- )
760
- return await self._persist_events(runtime_events)
761
-
762
- def _platform_events(
763
- self,
764
- item: Any,
765
- platform_task_id: str,
766
- *,
767
- operation_instance_id: str,
768
- wire_position: int,
769
- ) -> list[dict[str, Any]]:
770
- events: list[dict[str, Any]] = []
771
-
772
- def append_event(
773
- kind: str,
774
- payload: dict[str, Any],
775
- *,
776
- status: str | None = None,
777
- occurred_at: str | None = None,
778
- ) -> None:
779
- events.append(
780
- self._platform_event(
781
- kind,
782
- payload,
783
- platform_task_id,
784
- operation_instance_id=operation_instance_id,
785
- wire_position=wire_position,
786
- event_ordinal=len(events),
787
- status=status,
788
- occurred_at=occurred_at,
789
- )
790
- )
791
-
792
- task = _present_message_field(item, "task")
793
- if task is None and hasattr(item, "status") and hasattr(item, "id"):
794
- task = item
795
- status_update = _present_message_field(item, "status_update")
796
- artifact_update = _present_message_field(item, "artifact_update")
797
- message = _present_message_field(item, "message")
798
- if task is not None and getattr(task, "status", None) is not None:
799
- payload = _canonical_proto(task.status)
800
- state_name = TaskState.Name(task.status.state)
801
- append_event(
802
- "status",
803
- payload,
804
- status=state_name.removeprefix("TASK_STATE_").lower(),
805
- occurred_at=str(payload.get("timestamp") or _utc_now()),
806
- )
807
- for artifact in getattr(task, "artifacts", None) or []:
808
- append_event(
809
- "artifact",
810
- {
811
- "Artifact": _canonical_proto(artifact),
812
- "Append": False,
813
- "LastChunk": True,
814
- },
815
- )
816
- if status_update is not None and getattr(status_update, "status", None) is not None:
817
- payload = _canonical_proto(status_update.status)
818
- state_name = TaskState.Name(status_update.status.state)
819
- append_event(
820
- "status",
821
- payload,
822
- status=state_name.removeprefix("TASK_STATE_").lower(),
823
- occurred_at=str(payload.get("timestamp") or _utc_now()),
824
- )
825
- if artifact_update is not None and getattr(artifact_update, "artifact", None) is not None:
826
- append_event(
827
- "artifact",
828
- {
829
- "Artifact": _canonical_proto(artifact_update.artifact),
830
- "Append": bool(getattr(artifact_update, "append", False)),
831
- "LastChunk": bool(getattr(artifact_update, "last_chunk", False)),
832
- },
833
- )
834
- if message is not None:
835
- payload = _canonical_proto(message)
836
- append_event("message", payload)
837
- append_event(
838
- "status",
839
- {"state": "TASK_STATE_COMPLETED", "message": payload},
840
- status="completed",
841
- )
842
- return events
843
-
844
- @staticmethod
845
- def _platform_event(
846
- kind: str,
847
- payload: dict[str, Any],
848
- platform_task_id: str,
849
- *,
850
- operation_instance_id: str,
851
- wire_position: int,
852
- event_ordinal: int,
853
- status: str | None = None,
854
- occurred_at: str | None = None,
855
- ) -> dict[str, Any]:
856
- source_id = hashlib.sha256(
857
- (
858
- f"{platform_task_id}:{operation_instance_id}:{wire_position}:{event_ordinal}:{kind}"
859
- ).encode("utf-8")
860
- ).hexdigest()
861
- event: dict[str, Any] = {
862
- "SourceEventId": source_id,
863
- "EventKind": kind,
864
- "Payload": payload,
865
- "OccurredAt": occurred_at or _utc_now(),
866
- }
867
- if status:
868
- event["Status"] = status
869
- return event
870
-
871
- async def flush_pending_events(self) -> int:
872
- """Deliver all currently queued platform event batches or raise on failure."""
873
-
874
- return await self._event_dispatcher.drain(raise_on_error=True)
875
-
876
- def _next_seq(self) -> int:
877
- self._seq += 1
878
- return self._seq
879
-
880
- def _event_ctx(
881
- self,
882
- agent: DiscoveredAgent,
883
- invocation_id: str,
884
- *,
885
- event_id: str | None = None,
886
- ) -> dict[str, Any]:
887
- return {
888
- "agent_id": agent.agent_id,
889
- "user_id": "a2a_space",
890
- "session_id": self._space_id,
891
- "invocation_id": invocation_id,
892
- "seq_id": self._next_seq(),
893
- "event_id": event_id,
894
- }
895
-
896
- def task_to_event(self, task: Any, agent: DiscoveredAgent) -> RuntimeEvent:
897
- return self._event_adapter.task_status_to_event(
898
- task.status, **self._event_ctx(agent, invocation_id=str(task.id))
899
- )
900
-
901
- def _stream_item_to_events(
902
- self,
903
- item: Any,
904
- agent: DiscoveredAgent,
905
- *,
906
- wire_position: int = 0,
907
- invocation_id: str | None = None,
908
- ) -> list[RuntimeEvent]:
909
- events: list[RuntimeEvent] = []
910
- task = _present_message_field(item, "task")
911
- if task is None and hasattr(item, "status") and hasattr(item, "id"):
912
- task = item
913
- status_update = _present_message_field(item, "status_update")
914
- artifact_update = _present_message_field(item, "artifact_update")
915
- message = _present_message_field(item, "message")
916
- resolved_invocation_id = invocation_id or str(
917
- getattr(item, "task_id", None)
918
- or getattr(task, "id", "")
919
- or getattr(status_update, "task_id", "")
920
- or getattr(artifact_update, "task_id", "")
921
- or getattr(message, "task_id", "")
922
- or ""
923
- )
924
-
925
- def ctx(kind: str, value: Any) -> dict[str, Any]:
926
- metadata = getattr(value, "metadata", None)
927
- native_event_id = ""
928
- if metadata is not None:
929
- if isinstance(metadata, Mapping):
930
- metadata_dict = dict(metadata)
931
- else:
932
- try:
933
- metadata_dict = MessageToDict(metadata, preserving_proto_field_name=True)
934
- except (AttributeError, TypeError, ValueError):
935
- metadata_dict = {}
936
- native_event_id = str(
937
- metadata_dict.get("event_id") or metadata_dict.get("ksadk_event_id") or ""
938
- )
939
- message_id = str(getattr(value, "message_id", "") or "")
940
- artifact = getattr(value, "artifact", None)
941
- artifact_id = str(
942
- getattr(value, "artifact_id", "") or getattr(artifact, "artifact_id", "") or ""
943
- )
944
- source_id = native_event_id or message_id or artifact_id
945
- event_id = uuid.uuid5(
946
- uuid.NAMESPACE_URL,
947
- f"ksadk:a2a:{resolved_invocation_id}:{wire_position}:{kind}:{source_id}",
948
- ).hex
949
- return self._event_ctx(agent, invocation_id=resolved_invocation_id, event_id=event_id)
950
-
951
- if task is not None and getattr(task, "status", None) is not None:
952
- task_status_message = _present_message_field(task.status, "message")
953
- task_status_text = A2AEventAdapter._parts_text(
954
- getattr(task_status_message, "parts", None)
955
- )
956
- task_is_terminal = task.status.state in {
957
- TaskState.TASK_STATE_COMPLETED,
958
- TaskState.TASK_STATE_FAILED,
959
- TaskState.TASK_STATE_CANCELED,
960
- TaskState.TASK_STATE_REJECTED,
961
- }
962
- if not task_is_terminal:
963
- events.append(
964
- self._event_adapter.task_status_to_event(
965
- task.status,
966
- **ctx("task", task),
967
- )
968
- )
969
- if task_status_text:
970
- events.append(
971
- self._event_adapter.message_to_event(
972
- task_status_text,
973
- final=task_is_terminal,
974
- **ctx("task-status-message", task_status_message),
975
- )
976
- )
977
- if task_is_terminal:
978
- events.append(
979
- self._event_adapter.task_status_to_event(
980
- task.status,
981
- **ctx("task", task),
982
- )
983
- )
984
- if status_update is not None and getattr(status_update, "status", None) is not None:
985
- status_message = _present_message_field(status_update.status, "message")
986
- text = A2AEventAdapter._parts_text(getattr(status_message, "parts", None))
987
- terminal_states = {
988
- TaskState.TASK_STATE_COMPLETED,
989
- TaskState.TASK_STATE_FAILED,
990
- TaskState.TASK_STATE_CANCELED,
991
- TaskState.TASK_STATE_REJECTED,
992
- }
993
- is_terminal = status_update.status.state in terminal_states
994
- if not is_terminal:
995
- events.append(
996
- self._event_adapter.task_status_to_event(
997
- status_update.status, **ctx("status", status_update)
998
- )
999
- )
1000
- if text:
1001
- events.append(
1002
- self._event_adapter.message_to_event(
1003
- text,
1004
- final=is_terminal,
1005
- **ctx("status-message", status_message),
1006
- )
1007
- )
1008
- if is_terminal:
1009
- events.append(
1010
- self._event_adapter.task_status_to_event(
1011
- status_update.status, **ctx("status", status_update)
1012
- )
1013
- )
1014
- if artifact_update is not None and getattr(artifact_update, "artifact", None) is not None:
1015
- artifact = artifact_update.artifact
1016
- events.append(
1017
- self._event_adapter.artifact_to_event(artifact, **ctx("artifact", artifact_update))
1018
- )
1019
- artifact_text = A2AEventAdapter._parts_text(getattr(artifact, "parts", None))
1020
- if artifact_text and str(getattr(artifact, "name", "") or "") == "response":
1021
- events.append(
1022
- self._event_adapter.message_to_event(
1023
- artifact_text,
1024
- final=bool(getattr(artifact_update, "last_chunk", False)),
1025
- **ctx("artifact-text", artifact_update),
1026
- )
1027
- )
1028
- if message is not None:
1029
- text = A2AEventAdapter._parts_text(getattr(message, "parts", None))
1030
- if text:
1031
- events.append(
1032
- self._event_adapter.message_to_event(
1033
- text, final=True, **ctx("message", message)
1034
- )
1035
- )
1036
- return events
1037
-
1038
- async def _persist_events(self, events: list[RuntimeEvent]) -> list[RuntimeEvent]:
1039
- existing_ids = set(self._persisted_wire_events)
1040
- if self._event_sink is not None:
1041
- list_events = getattr(self._event_sink, "list", None)
1042
- if callable(list_events) and events:
1043
- persisted_before = await list_events(events[0].session_id)
1044
- existing_ids.update(event.event_id for event in persisted_before)
1045
- fresh = [event for event in events if event.event_id not in existing_ids]
1046
- if not fresh:
1047
- return []
1048
- if self._event_sink is not None:
1049
- append = getattr(self._event_sink, "append", None)
1050
- if append is None:
1051
- raise TypeError("event_sink must provide async append(events)")
1052
- persisted = await append(fresh)
1053
- if persisted is not None:
1054
- fresh = list(persisted)
1055
- self._persisted_wire_events.update(event.event_id for event in fresh)
1056
- return fresh
1057
-
1058
751
  async def subscribe_events(self, task_id: str):
1059
752
  require_a2a_resource_id(task_id, "a2a-task-", field_name="task_id")
1060
753
  prepared = await self._backend.prepare_task_operation(
@@ -1095,6 +788,7 @@ __all__ = [
1095
788
  "A2ASpaceClient",
1096
789
  "DiscoveredAgent",
1097
790
  "ENV_A2A_ENABLE_PUBLIC_EGRESS",
791
+ "ENV_A2A_SPACE_ID",
1098
792
  "ENV_A2A_SPACE_IDS",
1099
793
  "ERR_PUBLIC_EGRESS_DISABLED",
1100
794
  "SpaceAgentPage",
ksadk/a2a_card.py ADDED
@@ -0,0 +1,101 @@
1
+ """Lightweight A2A AgentCard construction shared by discovery and data-plane code.
2
+
3
+ This module deliberately lives outside :mod:`ksadk.a2a`: importing that package
4
+ initializes the full v2 protocol stack, including optional database adapters.
5
+ Managed v1 discovery must be able to start with only the core FastAPI A2A
6
+ dependency installed.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from collections.abc import Sequence
12
+
13
+ from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill
14
+
15
+ A2A_PROTOCOL_VERSION = "1.0"
16
+ JSONRPC_PATH = "/a2a/jsonrpc"
17
+ REST_PATH_PREFIX = "/a2a/v1"
18
+
19
+ _DEFAULT_IO_MODES = ["text/plain"]
20
+
21
+
22
+ def build_agent_card(
23
+ *,
24
+ name: str,
25
+ base_url: str,
26
+ description: str = "",
27
+ version: str = "1.0.0",
28
+ skills: Sequence[str | AgentSkill] | None = None,
29
+ streaming: bool = True,
30
+ provider: dict[str, str] | None = None,
31
+ ) -> AgentCard:
32
+ """Build a wire-1.0 AgentCard with supported interfaces."""
33
+ base = base_url.rstrip("/")
34
+ supported_interfaces = [
35
+ AgentInterface(
36
+ url=f"{base}{JSONRPC_PATH}",
37
+ protocol_binding="JSONRPC",
38
+ protocol_version=A2A_PROTOCOL_VERSION,
39
+ ),
40
+ AgentInterface(
41
+ url=f"{base}{REST_PATH_PREFIX}",
42
+ protocol_binding="HTTP+JSON",
43
+ protocol_version=A2A_PROTOCOL_VERSION,
44
+ ),
45
+ ]
46
+
47
+ card_kwargs: dict = {
48
+ "name": name,
49
+ "description": description or f"{name} agent powered by ksadk",
50
+ "version": version,
51
+ "supported_interfaces": supported_interfaces,
52
+ "capabilities": AgentCapabilities(streaming=streaming, push_notifications=False),
53
+ "default_input_modes": list(_DEFAULT_IO_MODES),
54
+ "default_output_modes": list(_DEFAULT_IO_MODES),
55
+ "skills": _build_skills(skills),
56
+ }
57
+ if provider:
58
+ from a2a.types import AgentProvider
59
+
60
+ card_kwargs["provider"] = AgentProvider(
61
+ organization=provider.get("organization", ""),
62
+ url=provider.get("url", ""),
63
+ )
64
+ return AgentCard(**card_kwargs)
65
+
66
+
67
+ def _build_skills(skills: Sequence[str | AgentSkill] | None) -> list[AgentSkill]:
68
+ if not skills:
69
+ return [
70
+ AgentSkill(
71
+ id="general",
72
+ name="General",
73
+ description="General purpose agent powered by ksadk",
74
+ tags=["general"],
75
+ )
76
+ ]
77
+ result: list[AgentSkill] = []
78
+ for skill in skills:
79
+ if isinstance(skill, AgentSkill):
80
+ result.append(skill)
81
+ continue
82
+ if not isinstance(skill, str) or not skill.strip():
83
+ raise TypeError("AgentCard skills must be non-empty strings or AgentSkill objects")
84
+ skill_id = skill.strip()
85
+ result.append(
86
+ AgentSkill(
87
+ id=skill_id,
88
+ name=skill_id.replace("_", " ").title(),
89
+ description=f"Skill: {skill_id}",
90
+ tags=[skill_id],
91
+ )
92
+ )
93
+ return result
94
+
95
+
96
+ __all__ = [
97
+ "A2A_PROTOCOL_VERSION",
98
+ "JSONRPC_PATH",
99
+ "REST_PATH_PREFIX",
100
+ "build_agent_card",
101
+ ]