agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.0__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 (371) hide show
  1. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +36 -20
  2. agentengine_sdk_python-0.8.0.dist-info/RECORD +578 -0
  3. ksadk/a2a/__init__.py +178 -11
  4. ksadk/a2a/bootstrap.py +334 -0
  5. ksadk/a2a/card.py +120 -0
  6. ksadk/a2a/context_store.py +203 -0
  7. ksadk/a2a/control_plane.py +818 -0
  8. ksadk/a2a/credential.py +99 -0
  9. ksadk/a2a/event_adapter.py +149 -0
  10. ksadk/a2a/executor.py +406 -89
  11. ksadk/a2a/external_transport.py +516 -0
  12. ksadk/a2a/identity.py +304 -0
  13. ksadk/a2a/ids.py +22 -0
  14. ksadk/a2a/langgraph.py +285 -0
  15. ksadk/a2a/resume_store.py +201 -0
  16. ksadk/a2a/routes.py +105 -0
  17. ksadk/a2a/server.py +107 -60
  18. ksadk/a2a/space_client.py +1101 -0
  19. ksadk/a2a/task_adapter.py +423 -0
  20. ksadk/a2a/task_event_dispatcher.py +167 -0
  21. ksadk/a2a/task_event_outbox.py +326 -0
  22. ksadk/a2a/task_store.py +206 -0
  23. ksadk/a2ui/__init__.py +27 -0
  24. ksadk/a2ui/core.py +186 -0
  25. ksadk/a2ui/models.py +166 -0
  26. ksadk/a2ui/renderer.py +198 -0
  27. ksadk/agui/__init__.py +9 -0
  28. ksadk/agui/a2ui_projection.py +92 -0
  29. ksadk/agui/agent.py +857 -0
  30. ksadk/agui/config.py +86 -0
  31. ksadk/agui/routes.py +55 -0
  32. ksadk/api/client.py +233 -191
  33. ksadk/builders/__init__.py +2 -0
  34. ksadk/builders/base.py +16 -14
  35. ksadk/builders/code_builder.py +318 -236
  36. ksadk/builders/container_builder.py +187 -167
  37. ksadk/builders/framework_requirements.py +29 -11
  38. ksadk/builders/ks3_uploader.py +58 -27
  39. ksadk/builders/managed_runtime_builder.py +145 -0
  40. ksadk/builders/mcp_builder.py +91 -92
  41. ksadk/builders/requirements_utils.py +1 -5
  42. ksadk/cli/__init__.py +89 -171
  43. ksadk/cli/cmd_a2a.py +254 -70
  44. ksadk/cli/cmd_agent.py +19 -5
  45. ksadk/cli/cmd_build.py +158 -29
  46. ksadk/cli/cmd_completion.py +47 -35
  47. ksadk/cli/cmd_config.py +267 -198
  48. ksadk/cli/cmd_create.py +500 -720
  49. ksadk/cli/cmd_dashboard.py +120 -45
  50. ksadk/cli/cmd_deploy.py +117 -58
  51. ksadk/cli/cmd_destroy.py +44 -14
  52. ksadk/cli/cmd_files.py +63 -24
  53. ksadk/cli/cmd_hermes.py +168 -89
  54. ksadk/cli/cmd_invoke.py +184 -122
  55. ksadk/cli/cmd_launch.py +64 -28
  56. ksadk/cli/cmd_mcp.py +98 -64
  57. ksadk/cli/cmd_model.py +14 -5
  58. ksadk/cli/cmd_openclaw.py +483 -227
  59. ksadk/cli/cmd_replay.py +71 -0
  60. ksadk/cli/cmd_run.py +33 -10
  61. ksadk/cli/cmd_status.py +80 -31
  62. ksadk/cli/cmd_version.py +20 -13
  63. ksadk/cli/cmd_web.py +89 -13
  64. ksadk/cli/deploy_utils.py +20 -20
  65. ksadk/cli/dry_run.py +5 -3
  66. ksadk/cli/error_utils.py +37 -12
  67. ksadk/cli/global_options.py +1 -2
  68. ksadk/cli/local_runtime.py +1 -2
  69. ksadk/cli/model_catalog.py +6 -2
  70. ksadk/cli/network_options.py +34 -14
  71. ksadk/cli/resource_common.py +6 -2
  72. ksadk/cli/storage.py +0 -1
  73. ksadk/cli/ui.py +5 -3
  74. ksadk/cli/workflow_common.py +51 -17
  75. ksadk/codex/__init__.py +12 -0
  76. ksadk/codex/client.py +408 -0
  77. ksadk/codex/phase.py +143 -0
  78. ksadk/codex/runtime.py +449 -0
  79. ksadk/common/aicp_env.py +0 -1
  80. ksadk/common/auth.py +2 -2
  81. ksadk/common/constants.py +1 -3
  82. ksadk/common/llm_utils.py +17 -13
  83. ksadk/compat/__init__.py +5 -0
  84. ksadk/compat/adk_compat.py +200 -0
  85. ksadk/compat/copilotkit_a2ui.py +330 -0
  86. ksadk/configs/__init__.py +12 -12
  87. ksadk/configs/env_registry.py +500 -100
  88. ksadk/configs/global_config.py +2 -1
  89. ksadk/configs/settings.py +151 -124
  90. ksadk/conversations/__init__.py +7 -5
  91. ksadk/conversations/attachment_storage.py +16 -11
  92. ksadk/conversations/attachments.py +44 -36
  93. ksadk/conversations/compaction_pipeline.py +12 -12
  94. ksadk/conversations/compaction_prompt.py +9 -5
  95. ksadk/conversations/context.py +221 -6
  96. ksadk/conversations/message_projection.py +438 -51
  97. ksadk/conversations/model_context.py +12 -6
  98. ksadk/conversations/model_options.py +0 -1
  99. ksadk/conversations/normalize.py +20 -16
  100. ksadk/conversations/reasoning_markup.py +1 -1
  101. ksadk/conversations/runtime.py +339 -5255
  102. ksadk/conversations/runtime_compaction.py +333 -0
  103. ksadk/conversations/runtime_constants.py +27 -0
  104. ksadk/conversations/runtime_governance.py +185 -0
  105. ksadk/conversations/runtime_input.py +652 -0
  106. ksadk/conversations/runtime_invocation.py +395 -0
  107. ksadk/conversations/runtime_metadata.py +475 -0
  108. ksadk/conversations/runtime_observability.py +355 -0
  109. ksadk/conversations/runtime_payloads.py +272 -0
  110. ksadk/conversations/runtime_persistence.py +440 -0
  111. ksadk/conversations/runtime_preparation.py +418 -0
  112. ksadk/conversations/runtime_resume.py +816 -0
  113. ksadk/conversations/runtime_stream_events.py +902 -0
  114. ksadk/conversations/runtime_streaming.py +547 -0
  115. ksadk/conversations/semantic_summary.py +17 -5
  116. ksadk/conversations/session_title.py +6 -3
  117. ksadk/deployment/__init__.py +15 -16
  118. ksadk/deployment/agent_access.py +12 -23
  119. ksadk/deployment/base.py +51 -38
  120. ksadk/deployment/manager.py +63 -65
  121. ksadk/deployment/providers/serverless.py +309 -202
  122. ksadk/deployment/registry.py +38 -32
  123. ksadk/deployment/state.py +11 -11
  124. ksadk/deployment/ui_config.py +1 -1
  125. ksadk/detection/__init__.py +1 -1
  126. ksadk/detection/detector.py +146 -83
  127. ksadk/detection/mcp_detector.py +9 -6
  128. ksadk/events/__init__.py +25 -0
  129. ksadk/events/parser.py +191 -0
  130. ksadk/events/replay.py +37 -0
  131. ksadk/events/runtime_event.py +264 -0
  132. ksadk/events/store.py +317 -0
  133. ksadk/harness/__init__.py +34 -0
  134. ksadk/harness/app.py +278 -0
  135. ksadk/harness/config.py +181 -0
  136. ksadk/harness/reasoner.py +105 -0
  137. ksadk/harness/runner.py +211 -0
  138. ksadk/harness/sandbox.py +141 -0
  139. ksadk/harness/tools.py +222 -0
  140. ksadk/hermes_terminal.py +23 -12
  141. ksadk/identity/resolver.py +15 -9
  142. ksadk/ids.py +32 -0
  143. ksadk/knowledge_base/adk_tool.py +1 -1
  144. ksadk/knowledge_base/client.py +23 -29
  145. ksadk/managed_runtime.py +188 -0
  146. ksadk/markdown.py +5 -2
  147. ksadk/mcp_runtime/__init__.py +9 -6
  148. ksadk/memory/__init__.py +1 -1
  149. ksadk/memory/adk/__init__.py +2 -0
  150. ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
  151. ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
  152. ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
  153. ksadk/memory/adk/backends/sdk_ltm_backend.py +26 -33
  154. ksadk/memory/adk/long_term_memory.py +31 -35
  155. ksadk/memory/adk/resilient_session_service.py +4 -5
  156. ksadk/memory/adk/short_term_memory.py +12 -21
  157. ksadk/memory/adk_tool.py +3 -2
  158. ksadk/memory/backends/base.py +19 -19
  159. ksadk/memory/backends/memory.py +24 -25
  160. ksadk/memory/backends/redis.py +31 -30
  161. ksadk/memory/langchain_tool.py +2 -1
  162. ksadk/memory/manager.py +52 -47
  163. ksadk/memory/service.py +10 -8
  164. ksadk/model_policy.py +15 -7
  165. ksadk/model_proxy/__init__.py +51 -0
  166. ksadk/model_proxy/bootstrap.py +80 -0
  167. ksadk/model_proxy/cache.py +165 -0
  168. ksadk/model_proxy/config.py +45 -0
  169. ksadk/model_proxy/demo_webui.py +115 -0
  170. ksadk/model_proxy/detect.py +145 -0
  171. ksadk/model_proxy/gate.py +68 -0
  172. ksadk/model_proxy/namespace.py +173 -0
  173. ksadk/model_proxy/protocol_proxy.py +22 -0
  174. ksadk/model_proxy/server.py +300 -0
  175. ksadk/model_proxy/transform.py +691 -0
  176. ksadk/openclaw_gateway.py +29 -14
  177. ksadk/runners/adk_runner.py +345 -120
  178. ksadk/runners/base_runner.py +46 -29
  179. ksadk/runners/codex_runner.py +132 -0
  180. ksadk/runners/deepagents_runner.py +0 -1
  181. ksadk/runners/factory.py +17 -5
  182. ksadk/runners/langchain_runner.py +29 -742
  183. ksadk/runners/langgraph_runner.py +352 -90
  184. ksadk/runners/patch_langchain.py +16 -16
  185. ksadk/runners/remote_runner.py +134 -33
  186. ksadk/runners/usage_accumulator.py +1 -0
  187. ksadk/runners/utils/langfuse.py +3 -3
  188. ksadk/runners/utils/loader.py +7 -7
  189. ksadk/runtime/__init__.py +41 -0
  190. ksadk/runtime/adapter.py +345 -0
  191. ksadk/runtime/framework_adapters.py +124 -0
  192. ksadk/runtime/preprocessing.py +118 -0
  193. ksadk/runtime/runner_adapter.py +873 -0
  194. ksadk/runtime_context.py +18 -3
  195. ksadk/runtime_state.py +0 -1
  196. ksadk/sandbox/__init__.py +4 -1
  197. ksadk/sandbox/backends/__init__.py +4 -1
  198. ksadk/sandbox/backends/e2b.py +13 -5
  199. ksadk/sandbox/backends/local_process.py +11 -3
  200. ksadk/sandbox/base.py +10 -15
  201. ksadk/sandbox/factory.py +14 -4
  202. ksadk/sandbox/registry.py +57 -6
  203. ksadk/server/api_models.py +15 -5
  204. ksadk/server/app.py +455 -3885
  205. ksadk/server/composition.py +21 -0
  206. ksadk/server/factory.py +624 -0
  207. ksadk/server/routes/__init__.py +1 -0
  208. ksadk/server/routes/checkpoint_resolution.py +116 -0
  209. ksadk/server/routes/common.py +713 -0
  210. ksadk/server/routes/control.py +327 -0
  211. ksadk/server/routes/dependencies.py +98 -0
  212. ksadk/server/routes/misc.py +448 -0
  213. ksadk/server/routes/models.py +443 -0
  214. ksadk/server/routes/openai_compat.py +207 -0
  215. ksadk/server/routes/projection.py +795 -0
  216. ksadk/server/routes/routers.py +52 -0
  217. ksadk/server/routes/run.py +726 -0
  218. ksadk/server/routes/sessions.py +649 -0
  219. ksadk/server/routes/streaming.py +223 -0
  220. ksadk/server/routes/workspace.py +381 -0
  221. ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-Cjnqt-8W.js} +1 -1
  222. ksadk/server/static/assets/CodeBlock-BqyqZfuB.js +9 -0
  223. ksadk/server/static/assets/MathMessageMarkdown-BpH7jiFM.js +8 -0
  224. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +303 -0
  225. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +1 -0
  226. ksadk/server/static/assets/{arc-BA13sHc9.js → arc-CFKwSk_B.js} +1 -1
  227. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
  228. ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
  229. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
  230. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
  231. ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
  232. ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
  233. ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
  234. ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-BK8paA20.js} +1 -1
  235. ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
  236. ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
  237. ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
  238. ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D98vPd-E.js} +1 -1
  239. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +1 -0
  240. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +1 -0
  241. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +1 -0
  242. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
  243. ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
  244. ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
  245. ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
  246. ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
  247. ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
  248. ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
  249. ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-6CVKuTAe.js} +1 -1
  250. ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-BUHRxvDG.js} +1 -1
  251. ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-BZ9n9AjO.js} +1 -1
  252. ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BibcG1V9.js} +1 -1
  253. ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-Bs-jQcRX.js} +1 -1
  254. ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-C2xjE7cO.js} +1 -1
  255. ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-C7-3jInC.js} +1 -1
  256. ksadk/server/static/assets/{dist-D-xOD048.js → dist-C99THtIA.js} +1 -1
  257. ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-CGcp2ex8.js} +1 -1
  258. ksadk/server/static/assets/{dist-DyOkZmze.js → dist-CVQRZjPu.js} +1 -1
  259. ksadk/server/static/assets/{dist-BssVmjIo.js → dist-Cf23NY4L.js} +1 -1
  260. ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-CgF3fj15.js} +1 -1
  261. ksadk/server/static/assets/{dist-2hInLS_J.js → dist-Cwt7koer.js} +1 -1
  262. ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-D82mtD2s.js} +1 -1
  263. ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-DF06ORQo.js} +1 -1
  264. ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-DHn6nBzr.js} +1 -1
  265. ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-Djgl2wVZ.js} +1 -1
  266. ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-DlzCRy0S.js} +1 -1
  267. ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-DqNnNFrw.js} +1 -1
  268. ksadk/server/static/assets/{dist-D57wnGWd.js → dist-DyvYLMW9.js} +1 -1
  269. ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-eoW6tZXA.js} +1 -1
  270. ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-ivOya1LD.js} +1 -1
  271. ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
  272. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
  273. ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
  274. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-DpCoB2g9.js} +1 -1
  275. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +1 -0
  276. ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-9IKVFBVT.js} +1 -1
  277. ksadk/server/static/assets/index-QSwCHuB8.js +177 -0
  278. ksadk/server/static/assets/index-jOPmTOZH.css +2 -0
  279. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +1 -0
  280. ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
  281. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
  282. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
  283. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
  284. ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-DATssjp1.js} +1 -1
  285. ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-CvMBw9cA.js} +1 -1
  286. ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
  287. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-CSAQxEAe.js} +1 -1
  288. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +1 -0
  289. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +1 -0
  290. ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
  291. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
  292. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
  293. ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
  294. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
  295. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
  296. ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-DGpd9yFG.js} +1 -1
  297. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +1 -0
  298. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-jqoYs3jQ.js} +1 -1
  299. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +1 -0
  300. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +1 -0
  301. ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
  302. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
  303. ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
  304. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-SkiH8GsK.js} +1 -1
  305. ksadk/server/static/index.html +2 -2
  306. ksadk/server/terminal_sessions.py +111 -58
  307. ksadk/sessions/__init__.py +69 -19
  308. ksadk/sessions/base.py +31 -11
  309. ksadk/sessions/continuity.py +2 -3
  310. ksadk/sessions/in_memory.py +46 -2
  311. ksadk/sessions/local_service.py +148 -17
  312. ksadk/sessions/postgres_service.py +143 -25
  313. ksadk/sessions/resilient.py +36 -8
  314. ksadk/skills/models.py +17 -5
  315. ksadk/skills/package_store.py +5 -2
  316. ksadk/skills/runtime/agent.py +20 -5
  317. ksadk/skills/runtime/artifacts.py +1 -5
  318. ksadk/skills/runtime/backends/e2b.py +10 -4
  319. ksadk/skills/runtime/backends/local.py +15 -3
  320. ksadk/skills/runtime/base.py +1 -2
  321. ksadk/skills/runtime/executor.py +10 -3
  322. ksadk/skills/runtime/factory.py +4 -2
  323. ksadk/skills/runtime/loader.py +1 -2
  324. ksadk/skills/runtime/registry.py +15 -10
  325. ksadk/skills/runtime/request.py +3 -1
  326. ksadk/skills/service_client.py +38 -17
  327. ksadk/skills/tool_defs.py +15 -10
  328. ksadk/terminal_exec_policy.py +3 -4
  329. ksadk/tools/gateway.py +92 -15
  330. ksadk/tools/result_budget.py +12 -4
  331. ksadk/toolsets/__init__.py +134 -36
  332. ksadk/toolsets/platform.py +21 -5
  333. ksadk/toolsets/sandbox.py +82 -16
  334. ksadk/toolsets/skills.py +200 -39
  335. ksadk/toolsets/web.py +123 -26
  336. ksadk/toolsets/workspace.py +212 -101
  337. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  338. ksadk/tracing/exporters/langfuse_exporter.py +91 -76
  339. ksadk/tracing/setup.py +69 -53
  340. ksadk/tracing/span_utils.py +5 -2
  341. ksadk/tui/loop.py +78 -30
  342. ksadk/tui/stream_render.py +1 -0
  343. ksadk/ui_config.py +5 -3
  344. ksadk/version.py +1 -1
  345. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  346. agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
  347. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
  348. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
  349. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
  350. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
  351. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
  352. ksadk/server/static/assets/channel-CTuydARX.js +0 -1
  353. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
  354. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
  355. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
  356. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
  357. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
  358. ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
  359. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  360. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
  361. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
  362. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
  363. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
  364. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
  365. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
  366. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
  367. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
  368. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
  369. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
  370. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
  371. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
ksadk/a2ui/core.py ADDED
@@ -0,0 +1,186 @@
1
+ """A2UICore — Agent-facing interface + RuntimeEvent 产出 (goal-13,canonical §5.1/§5.2)。
2
+
3
+ **硬约束(canonical §1 / H2 P0-C):A2UI 必须先进入 RuntimeEvent,不得以 A2A executor
4
+ 绕过**——本类的 ``display_ui`` / ``request_ui_input`` / ``submit_action`` 全部经 A7
5
+ ``RuntimeEventStore`` 产出并持久化 A2UI 事件(``a2ui.surface.*`` / ``a2ui.interaction`` /
6
+ ``a2ui.action``),由 session 级订阅承载(A2UI 依赖,可 run 后非阻塞 action 与回放)。
7
+
8
+ 冻结 schema 映射(G0.2 已冻结,不改):surface 首显 ``a2ui.surface.begin`` / 更新
9
+ ``a2ui.surface.update`` / 结束 ``a2ui.surface.end``;请求输入 ``a2ui.interaction``;
10
+ action ``a2ui.action``。均带 ``surface_id``(G0.2 必填键)。
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import logging
16
+ import uuid
17
+ from typing import Any, Optional
18
+
19
+ from ksadk.a2ui.models import (
20
+ BASIC_CATALOG,
21
+ ActionReceipt,
22
+ PendingInteraction,
23
+ Surface,
24
+ )
25
+ from ksadk.events.runtime_event import EventType, RuntimeEvent
26
+ from ksadk.events.store import RuntimeEventStore
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class A2UICore:
32
+ """A2UI Agent-facing interface:display / request_input / submit_action。
33
+
34
+ 所有 A2UI 事件经 :class:`RuntimeEventStore` 持久化(**不另开通道、不经 A2A 绕过**),
35
+ 供 session 级订阅 / replay / 审计消费。
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ store: RuntimeEventStore,
41
+ *,
42
+ agent_id: str,
43
+ user_id: str,
44
+ session_id: str,
45
+ catalog: dict[str, frozenset[str]] = BASIC_CATALOG,
46
+ ) -> None:
47
+ self._store = store
48
+ self._agent_id = agent_id
49
+ self._user_id = user_id
50
+ self._session_id = session_id
51
+ self._catalog = catalog
52
+ self._seq = 0
53
+ self._seen_surfaces: set[str] = set()
54
+ self._pending: dict[str, PendingInteraction] = {}
55
+
56
+ # ---- 内部:产出并持久化一个 A2UI RuntimeEvent ----
57
+
58
+ async def _emit(
59
+ self, event_type: str, invocation_id: str, payload: dict[str, Any]
60
+ ) -> RuntimeEvent:
61
+ self._seq += 1
62
+ event = RuntimeEvent.create(
63
+ event_type,
64
+ agent_id=self._agent_id,
65
+ user_id=self._user_id,
66
+ session_id=self._session_id,
67
+ invocation_id=invocation_id,
68
+ seq_id=self._seq,
69
+ payload=payload,
70
+ )
71
+ # 经 RuntimeEvent 持久化(A7 store)——canonical,不绕过。
72
+ await self._store.append_one(event)
73
+ return event
74
+
75
+ # ---- 三种交互 ----
76
+
77
+ async def display_ui(
78
+ self,
79
+ surface: Surface,
80
+ *,
81
+ invocation_id: str,
82
+ origin: str = "local",
83
+ ) -> str:
84
+ """展示 surface(不阻塞)。首显发 surface.begin,重复显发 surface.update。"""
85
+ surface.validate(self._catalog)
86
+ event_type = (
87
+ EventType.A2UI_SURFACE_BEGIN
88
+ if surface.surface_id not in self._seen_surfaces
89
+ else EventType.A2UI_SURFACE_UPDATE
90
+ )
91
+ self._seen_surfaces.add(surface.surface_id)
92
+ await self._emit(
93
+ event_type,
94
+ invocation_id,
95
+ {
96
+ "surface_id": surface.surface_id,
97
+ "catalog_id": surface.catalog_id,
98
+ "surface": surface.to_dict(),
99
+ "origin": origin,
100
+ },
101
+ )
102
+ return surface.surface_id
103
+
104
+ async def request_ui_input(
105
+ self,
106
+ surface: Surface,
107
+ *,
108
+ schema: dict[str, Any],
109
+ kind: str,
110
+ invocation_id: str,
111
+ origin: str = "local",
112
+ ) -> PendingInteraction:
113
+ """等待用户输入(input_required 语义):先展示 surface,再登记 pending interaction。
114
+
115
+ 返回的 :class:`PendingInteraction` 是一次等待输入的持久化身份;用户上行
116
+ ``SubmitA2UIAction`` 命中后 resume(由 RuntimeBridge/adapter 处理,不在本层)。
117
+ """
118
+ # 先展示(确保 surface 已渲染),再请求输入。
119
+ await self.display_ui(surface, invocation_id=invocation_id, origin=origin)
120
+ interaction = PendingInteraction(
121
+ interaction_id=f"int_{uuid.uuid4().hex[:12]}",
122
+ surface_id=surface.surface_id,
123
+ kind=kind,
124
+ input_schema=dict(schema),
125
+ )
126
+ self._pending[interaction.interaction_id] = interaction
127
+ await self._emit(
128
+ EventType.A2UI_INTERACTION,
129
+ invocation_id,
130
+ {
131
+ "surface_id": surface.surface_id,
132
+ "interaction_id": interaction.interaction_id,
133
+ "kind": kind,
134
+ "input_schema": dict(schema),
135
+ },
136
+ )
137
+ return interaction
138
+
139
+ async def submit_action(
140
+ self,
141
+ action: dict[str, Any],
142
+ *,
143
+ invocation_id: str,
144
+ origin: str = "local",
145
+ ) -> ActionReceipt:
146
+ """非阻塞 action(原 run 可已结束):登记 action.received,返回幂等回执。
147
+
148
+ ``action``: ``{"action_id","surface_id","name","actor"?,"component_id"?}``。
149
+ """
150
+ receipt = ActionReceipt(
151
+ action_id=str(action.get("action_id") or f"act_{uuid.uuid4().hex[:12]}"),
152
+ surface_id=str(action["surface_id"]),
153
+ name=str(action["name"]),
154
+ actor=str(action.get("actor") or "user"),
155
+ status="received",
156
+ )
157
+ await self._emit(
158
+ EventType.A2UI_ACTION,
159
+ invocation_id,
160
+ {
161
+ "surface_id": receipt.surface_id,
162
+ "action_id": receipt.action_id,
163
+ "name": receipt.name,
164
+ "actor": receipt.actor,
165
+ "component_id": action.get("component_id"),
166
+ "origin": origin,
167
+ },
168
+ )
169
+ return receipt
170
+
171
+ async def end_surface(self, surface_id: str, *, invocation_id: str) -> None:
172
+ """结束 surface(surface.end)。"""
173
+ await self._emit(
174
+ EventType.A2UI_SURFACE_END,
175
+ invocation_id,
176
+ {"surface_id": surface_id},
177
+ )
178
+ self._seen_surfaces.discard(surface_id)
179
+
180
+ # ---- 查询 ----
181
+
182
+ def pending_interaction(self, interaction_id: str) -> Optional[PendingInteraction]:
183
+ return self._pending.get(interaction_id)
184
+
185
+
186
+ __all__ = ["A2UICore"]
ksadk/a2ui/models.py ADDED
@@ -0,0 +1,166 @@
1
+ """A2UI 语义模型 + basic catalog (goal-13,canonical 见 docs/A2UI-agent驱动UI技术方案.md)。
2
+
3
+ 模型独立于 transport(RuntimeEvent 是 canonical;Responses/A2A 只是 adapter):
4
+
5
+ - ``Component`` / ``Surface``:声明式组件树 + 数据模型(props 是**数据**,不含可执行代码)。
6
+ - ``PendingInteraction``:一次 ``request_ui_input`` 的持久化身份(input_required 语义)。
7
+ - ``ActionReceipt``:一次 action 的幂等回执。
8
+ - ``BASIC_CATALOG``:Q3 MVP 渲染集(Card/Text/Form/Select/RadioGroup/CheckboxGroup/
9
+ ApprovalBar)。**未知组件类型安全降级**(渲染为占位,不执行任意代码),符合设计 §3.1/§3.2。
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import uuid
15
+ from dataclasses import dataclass, field
16
+ from typing import Any, Optional
17
+
18
+ #: pinned A2UI core 版本(goal-13 版本约束:a2ui-core==0.1.1,A2UI v1.0 Candidate)。
19
+ #: 校验期据此断言构建期 pinned 版本未漂移(Q4 治理:upstream commit + schema/catalog SHA)。
20
+ try:
21
+ from a2ui.core.version import __version__ as A2UI_CORE_VERSION
22
+ except ImportError: # pragma: no cover - a2ui-core 未安装时显式降级
23
+ A2UI_CORE_VERSION = "uninstalled"
24
+
25
+ # ---------------------------------------------------------------------------
26
+ # basic catalog(Q3 MVP 渲染集;未知类型安全降级)
27
+ # ---------------------------------------------------------------------------
28
+
29
+ #: 允许展示/交互的组件类型及其允许的 prop 键(白名单;props 是数据,不允许代码)。
30
+ BASIC_CATALOG: dict[str, frozenset[str]] = {
31
+ "Card": frozenset({"title", "body", "footer", "children"}),
32
+ "Text": frozenset({"text", "variant"}),
33
+ "Form": frozenset({"title", "fields", "submit_label"}),
34
+ "Select": frozenset({"label", "options", "value"}),
35
+ "RadioGroup": frozenset({"label", "options", "value"}),
36
+ "CheckboxGroup": frozenset({"label", "options", "value"}),
37
+ "ApprovalBar": frozenset({"tool_name", "summary", "approve_label", "deny_label"}),
38
+ }
39
+
40
+ #: catalog 标识(对应 pinned basic catalog;构建期校验 SHA 是后续治理项)。
41
+ BASIC_CATALOG_ID = "a2ui.org/catalogs/basic/v1.0"
42
+
43
+
44
+ class A2UIValidationError(ValueError):
45
+ """surface/component 校验失败(未知类型、非法 prop、结构错误)。"""
46
+
47
+
48
+ @dataclass
49
+ class Component:
50
+ """声明式组件(props 是数据,不可执行)。"""
51
+
52
+ component_id: str
53
+ type: str
54
+ props: dict[str, Any] = field(default_factory=dict)
55
+ children: list["Component"] = field(default_factory=list)
56
+
57
+ def validate(self, catalog: dict[str, frozenset[str]] = BASIC_CATALOG) -> None:
58
+ """校验组件类型已知 + prop 在白名单 + 无嵌套代码字段。未知类型 → 安全降级错误。"""
59
+ if self.type not in catalog:
60
+ raise A2UIValidationError(
61
+ f"未知组件类型 {self.type!r}(不在 basic catalog;安全降级,不渲染任意代码)"
62
+ )
63
+ allowed = catalog[self.type]
64
+ unknown_props = set(self.props.keys()) - allowed - {"children"}
65
+ if unknown_props:
66
+ raise A2UIValidationError(f"组件 {self.type} 含白名单外 prop: {sorted(unknown_props)}")
67
+ for key, value in self.props.items():
68
+ if callable(value):
69
+ raise A2UIValidationError(f"组件 {self.type} prop {key} 不可为可执行代码")
70
+ for child in self.children:
71
+ child.validate(catalog)
72
+
73
+ def to_dict(self) -> dict[str, Any]:
74
+ return {
75
+ "component_id": self.component_id,
76
+ "type": self.type,
77
+ "props": self.props,
78
+ "children": [c.to_dict() for c in self.children],
79
+ }
80
+
81
+ @classmethod
82
+ def from_dict(cls, data: dict[str, Any]) -> "Component":
83
+ """从 dict(a2ui.surface.* 事件 payload 中的组件)重建;供 renderer 反序列化。"""
84
+ return cls(
85
+ component_id=str(data.get("component_id") or ""),
86
+ type=str(data.get("type") or ""),
87
+ props=dict(data.get("props") or {}),
88
+ children=[cls.from_dict(c) for c in data.get("children") or []],
89
+ )
90
+
91
+
92
+ @dataclass
93
+ class Surface:
94
+ """一个 UI surface(组件树 + 数据模型)。"""
95
+
96
+ surface_id: str
97
+ components: list[Component] = field(default_factory=list)
98
+ data_model: dict[str, Any] = field(default_factory=dict)
99
+ catalog_id: str = BASIC_CATALOG_ID
100
+
101
+ @classmethod
102
+ def new(cls, components: list[Component], *, data_model: Optional[dict] = None) -> "Surface":
103
+ return cls(
104
+ surface_id=f"surf_{uuid.uuid4().hex[:12]}",
105
+ components=components,
106
+ data_model=data_model or {},
107
+ )
108
+
109
+ def validate(self, catalog: dict[str, frozenset[str]] = BASIC_CATALOG) -> None:
110
+ if not self.surface_id:
111
+ raise A2UIValidationError("surface_id 不能为空")
112
+ for component in self.components:
113
+ component.validate(catalog)
114
+
115
+ def to_dict(self) -> dict[str, Any]:
116
+ return {
117
+ "surface_id": self.surface_id,
118
+ "catalog_id": self.catalog_id,
119
+ "components": [c.to_dict() for c in self.components],
120
+ "data_model": self.data_model,
121
+ }
122
+
123
+ @classmethod
124
+ def from_dict(cls, data: dict[str, Any]) -> "Surface":
125
+ """从 dict(a2ui.surface.* 事件 payload["surface"])重建 Surface;供 renderer 反序列化。"""
126
+ return cls(
127
+ surface_id=str(data.get("surface_id") or ""),
128
+ components=[Component.from_dict(c) for c in data.get("components") or []],
129
+ data_model=dict(data.get("data_model") or {}),
130
+ catalog_id=str(data.get("catalog_id") or BASIC_CATALOG_ID),
131
+ )
132
+
133
+
134
+ @dataclass
135
+ class PendingInteraction:
136
+ """一次 request_ui_input 的持久化身份(input_required;命中后 resume)。"""
137
+
138
+ interaction_id: str
139
+ surface_id: str
140
+ kind: str # "form" | "select" | "approval" | ...
141
+ input_schema: dict[str, Any] = field(default_factory=dict)
142
+ status: str = "pending" # "pending" | "resolved" | "expired"
143
+
144
+
145
+ @dataclass
146
+ class ActionReceipt:
147
+ """一次 action 的幂等回执(审计用)。"""
148
+
149
+ action_id: str
150
+ surface_id: str
151
+ name: str
152
+ actor: str = "user"
153
+ status: str = "received" # "received" | "completed" | "failed"
154
+ response: Optional[dict[str, Any]] = None
155
+ error: Optional[str] = None
156
+
157
+
158
+ __all__ = [
159
+ "A2UIValidationError",
160
+ "ActionReceipt",
161
+ "BASIC_CATALOG",
162
+ "BASIC_CATALOG_ID",
163
+ "Component",
164
+ "PendingInteraction",
165
+ "Surface",
166
+ ]
ksadk/a2ui/renderer.py ADDED
@@ -0,0 +1,198 @@
1
+ """A2UI renderer registry + 流式渲染 + SubmitA2UIAction 回传 (goal-14,canonical §5.4)。
2
+
3
+ - **registry**:Card / Text / Form / Select / RadioGroup / CheckboxGroup / ApprovalBar 渲染;
4
+ **未知 catalog/组件类型安全降级**为 ``placeholder``,**不执行任何动态代码**(安全约束)。
5
+ - **Approval 是硬要求**(goal-18 预发演示的人机交互):``ApprovalBar`` 渲染为可交互审批卡,
6
+ 带 approve/deny 动作,经 :func:`submit_a2ui_action`(SubmitA2UIAction)回传到
7
+ :class:`~ksadk.a2ui.core.A2UICore.submit_action`,形成"渲染→人点选→回传→resume"闭环。
8
+ - **parser 复用 goal-12 共享实现,不在 renderer 复制**(停止条件):surface 状态经
9
+ goal-13 ``Surface.from_dict`` 从 a2ui.surface.* 事件重建,renderer 只负责渲染。
10
+ - **live/replay 状态一致**:同一 surface 事件流,live 渲染与 replay 渲染产物逐字节一致
11
+ (``to_json`` 确定性);交互记录(a2ui.action)也经 goal-12 replay 可回放。
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ from dataclasses import dataclass, field
18
+ from typing import Any, Callable, Optional
19
+
20
+ from ksadk.a2ui.models import BASIC_CATALOG, Component, Surface
21
+
22
+ # ---------------------------------------------------------------------------
23
+ # RenderedNode:渲染产物(确定性,可 to_json 供 conformance)
24
+ # ---------------------------------------------------------------------------
25
+
26
+
27
+ @dataclass
28
+ class RenderedNode:
29
+ """一个渲染节点(组件渲染结果;``actions`` 承载可交互动作,如审批卡的 approve/deny)。"""
30
+
31
+ type: str
32
+ props: dict[str, Any] = field(default_factory=dict)
33
+ children: list["RenderedNode"] = field(default_factory=list)
34
+ actions: list[dict[str, Any]] = field(default_factory=list)
35
+
36
+ def to_dict(self) -> dict[str, Any]:
37
+ return {
38
+ "type": self.type,
39
+ "props": self.props,
40
+ "actions": self.actions,
41
+ "children": [c.to_dict() for c in self.children],
42
+ }
43
+
44
+ def to_json(self) -> str:
45
+ return json.dumps(self.to_dict(), ensure_ascii=False, sort_keys=True, separators=(",", ":"))
46
+
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # 各类型 renderer(纯函数,无动态代码)
50
+ # ---------------------------------------------------------------------------
51
+
52
+
53
+ def _render_text(comp: Component, _r: "A2UIRenderer") -> RenderedNode:
54
+ return RenderedNode(
55
+ type="text",
56
+ props={"text": str(comp.props.get("text") or ""), "variant": comp.props.get("variant")},
57
+ )
58
+
59
+
60
+ def _render_card(comp: Component, r: "A2UIRenderer") -> RenderedNode:
61
+ return RenderedNode(
62
+ type="card",
63
+ props={
64
+ "title": comp.props.get("title"),
65
+ "body": comp.props.get("body"),
66
+ "footer": comp.props.get("footer"),
67
+ },
68
+ children=[r.render_component(c) for c in comp.children],
69
+ )
70
+
71
+
72
+ def _render_form(comp: Component, r: "A2UIRenderer") -> RenderedNode:
73
+ return RenderedNode(
74
+ type="form",
75
+ props={
76
+ "title": comp.props.get("title"),
77
+ "fields": comp.props.get("fields") or [],
78
+ "submit_label": comp.props.get("submit_label") or "提交",
79
+ },
80
+ actions=[{"name": "submit", "label": comp.props.get("submit_label") or "提交"}],
81
+ children=[r.render_component(c) for c in comp.children],
82
+ )
83
+
84
+
85
+ def _render_choice(kind: str) -> Callable[[Component, "A2UIRenderer"], RenderedNode]:
86
+ def _render(comp: Component, _r: "A2UIRenderer") -> RenderedNode:
87
+ return RenderedNode(
88
+ type=kind,
89
+ props={
90
+ "label": comp.props.get("label"),
91
+ "options": comp.props.get("options") or [],
92
+ "value": comp.props.get("value"),
93
+ },
94
+ actions=[{"name": "change", "label": comp.props.get("label")}],
95
+ )
96
+
97
+ return _render
98
+
99
+
100
+ def _render_approval(comp: Component, _r: "A2UIRenderer") -> RenderedNode:
101
+ """ApprovalBar → 可交互审批卡(approve/deny 动作;硬要求,goal-18 人机交互用)。"""
102
+ return RenderedNode(
103
+ type="approval",
104
+ props={
105
+ "tool_name": comp.props.get("tool_name"),
106
+ "summary": comp.props.get("summary"),
107
+ },
108
+ actions=[
109
+ {"name": "approve", "label": comp.props.get("approve_label") or "批准"},
110
+ {"name": "deny", "label": comp.props.get("deny_label") or "拒绝"},
111
+ ],
112
+ )
113
+
114
+
115
+ def _render_placeholder(comp: Component, _r: "A2UIRenderer") -> RenderedNode:
116
+ """未知类型安全降级:渲染为占位,**不执行任何动态代码**(props 不回显为可执行内容)。"""
117
+ return RenderedNode(
118
+ type="placeholder",
119
+ props={"reason": f"未知组件类型 {comp.type!r},已安全降级"},
120
+ )
121
+
122
+
123
+ # ---------------------------------------------------------------------------
124
+ # A2UIRenderer registry
125
+ # ---------------------------------------------------------------------------
126
+
127
+
128
+ class A2UIRenderer:
129
+ """A2UI renderer registry(类型 → renderer;未知类型安全降级,不执行动态代码)。"""
130
+
131
+ def __init__(self, catalog: dict[str, frozenset[str]] = BASIC_CATALOG) -> None:
132
+ self._catalog = catalog
133
+ self._renderers: dict[str, Callable[[Component, "A2UIRenderer"], RenderedNode]] = {
134
+ "Card": _render_card,
135
+ "Text": _render_text,
136
+ "Form": _render_form,
137
+ "Select": _render_choice("select"),
138
+ "RadioGroup": _render_choice("radio_group"),
139
+ "CheckboxGroup": _render_choice("checkbox_group"),
140
+ "ApprovalBar": _render_approval,
141
+ }
142
+
143
+ def register(
144
+ self, component_type: str, renderer: Callable[[Component, "A2UIRenderer"], RenderedNode]
145
+ ) -> None:
146
+ """注册自定义 renderer(扩展 catalog 用;renderer 必须是纯函数,不含动态代码)。"""
147
+ self._renderers[component_type] = renderer
148
+
149
+ def render_component(self, component: Component) -> RenderedNode:
150
+ renderer = self._renderers.get(component.type, _render_placeholder)
151
+ return renderer(component, self)
152
+
153
+ def render_surface(self, surface: Surface) -> RenderedNode:
154
+ """渲染一个 surface(流式:组件树递归渲染;产物确定性,供 live/replay conformance)。"""
155
+ return RenderedNode(
156
+ type="surface",
157
+ props={"surface_id": surface.surface_id, "catalog_id": surface.catalog_id},
158
+ children=[self.render_component(c) for c in surface.components],
159
+ )
160
+
161
+
162
+ # ---------------------------------------------------------------------------
163
+ # SubmitA2UIAction 回传(渲染 → 人点选 → 回传 → resume)
164
+ # ---------------------------------------------------------------------------
165
+
166
+
167
+ async def submit_a2ui_action(
168
+ core: Any,
169
+ *,
170
+ action_id: str,
171
+ surface_id: str,
172
+ name: str,
173
+ actor: str = "user",
174
+ component_id: Optional[str] = None,
175
+ invocation_id: str,
176
+ ) -> Any:
177
+ """SubmitA2UIAction:把用户对渲染卡(如审批卡 approve/deny)的点选回传到 A2UICore。
178
+
179
+ 与 :class:`~ksadk.a2ui.core.A2UICore.submit_action` 接口对齐(不在 renderer 侧自造语义):
180
+ 产出 ``a2ui.action`` 事件(经 RuntimeEvent 持久化),供 resume / 审计 / 回放。
181
+ """
182
+ return await core.submit_action(
183
+ {
184
+ "action_id": action_id,
185
+ "surface_id": surface_id,
186
+ "name": name,
187
+ "actor": actor,
188
+ "component_id": component_id,
189
+ },
190
+ invocation_id=invocation_id,
191
+ )
192
+
193
+
194
+ __all__ = [
195
+ "A2UIRenderer",
196
+ "RenderedNode",
197
+ "submit_a2ui_action",
198
+ ]
ksadk/agui/__init__.py ADDED
@@ -0,0 +1,9 @@
1
+ """Official AG-UI transport integration for KSADK runtimes."""
2
+
3
+ from ksadk.agui.config import (
4
+ AGUI_PROTOCOL_VERSION,
5
+ AGUIConfig,
6
+ agui_dependencies_available,
7
+ )
8
+
9
+ __all__ = ["AGUIConfig", "AGUI_PROTOCOL_VERSION", "agui_dependencies_available"]
@@ -0,0 +1,92 @@
1
+ """Project canonical A2UI RuntimeEvents into official AG-UI activity content."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from typing import Any
7
+
8
+ from ksadk.events.runtime_event import EventType
9
+
10
+
11
+ def project_a2ui_operations(event_type: str, payload: Mapping[str, Any]) -> list[dict[str, Any]]:
12
+ """Return A2UI v0.9 operations carried by an AG-UI activity event."""
13
+
14
+ explicit = payload.get("operations", payload.get("a2ui_operations"))
15
+ if isinstance(explicit, list):
16
+ return [dict(operation) for operation in explicit if isinstance(operation, Mapping)]
17
+
18
+ surface_id = str(payload.get("surface_id") or payload.get("surfaceId") or "")
19
+ if not surface_id:
20
+ return []
21
+ if event_type == EventType.A2UI_SURFACE_END:
22
+ return [{"version": "v0.9", "deleteSurface": {"surfaceId": surface_id}}]
23
+
24
+ surface = payload.get("surface")
25
+ surface_data = surface if isinstance(surface, Mapping) else payload
26
+ components = _flatten_components(surface_data.get("components"))
27
+ data_model = surface_data.get("data_model", surface_data.get("dataModel"))
28
+ operations: list[dict[str, Any]] = []
29
+ if event_type == EventType.A2UI_SURFACE_BEGIN:
30
+ catalog_id = str(
31
+ surface_data.get("catalog_id")
32
+ or surface_data.get("catalogId")
33
+ or payload.get("catalog_id")
34
+ or payload.get("catalogId")
35
+ or "https://a2ui.org/specification/v0_9/basic_catalog.json"
36
+ )
37
+ operations.append(
38
+ {
39
+ "version": "v0.9",
40
+ "createSurface": {"surfaceId": surface_id, "catalogId": catalog_id},
41
+ }
42
+ )
43
+ if components:
44
+ operations.append(
45
+ {
46
+ "version": "v0.9",
47
+ "updateComponents": {"surfaceId": surface_id, "components": components},
48
+ }
49
+ )
50
+ if data_model is not None:
51
+ operations.append(
52
+ {
53
+ "version": "v0.9",
54
+ "updateDataModel": {
55
+ "surfaceId": surface_id,
56
+ "path": "/",
57
+ "value": data_model,
58
+ },
59
+ }
60
+ )
61
+ return operations
62
+
63
+
64
+ def _flatten_components(raw: Any) -> list[dict[str, Any]]:
65
+ if not isinstance(raw, list):
66
+ return []
67
+ flattened: list[dict[str, Any]] = []
68
+
69
+ def visit(component: Any) -> str:
70
+ if not isinstance(component, Mapping):
71
+ return ""
72
+ component_id = str(component.get("id") or component.get("component_id") or "")
73
+ component_type = str(component.get("component") or component.get("type") or "")
74
+ if not component_id or not component_type:
75
+ return ""
76
+ children = [visit(child) for child in component.get("children") or []]
77
+ children = [child_id for child_id in children if child_id]
78
+ entry: dict[str, Any] = {"id": component_id, "component": component_type}
79
+ props = component.get("props")
80
+ if isinstance(props, Mapping):
81
+ entry.update(dict(props))
82
+ if children and "children" not in entry and "child" not in entry:
83
+ entry["children"] = children
84
+ flattened.append(entry)
85
+ return component_id
86
+
87
+ for item in raw:
88
+ visit(item)
89
+ return flattened
90
+
91
+
92
+ __all__ = ["project_a2ui_operations"]