agentengine-sdk-python 0.6.9__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 (384) hide show
  1. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +41 -23
  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 +252 -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 +533 -726
  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 +173 -90
  54. ksadk/cli/cmd_invoke.py +388 -159
  55. ksadk/cli/cmd_launch.py +64 -28
  56. ksadk/cli/cmd_mcp.py +103 -64
  57. ksadk/cli/cmd_model.py +14 -5
  58. ksadk/cli/cmd_openclaw.py +488 -228
  59. ksadk/cli/cmd_replay.py +71 -0
  60. ksadk/cli/cmd_run.py +44 -14
  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 +38 -16
  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 +501 -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 +656 -0
  97. ksadk/conversations/model_context.py +22 -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 -5187
  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 +52 -39
  120. ksadk/deployment/manager.py +63 -65
  121. ksadk/deployment/providers/serverless.py +326 -209
  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 +267 -0
  156. ksadk/memory/adk/short_term_memory.py +33 -27
  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 +1248 -164
  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 -530
  183. ksadk/runners/langgraph_runner.py +490 -95
  184. ksadk/runners/patch_langchain.py +16 -16
  185. ksadk/runners/remote_runner.py +264 -38
  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 -3743
  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-C0meuOdi.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-bj2rZnP5.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-2u1ltDIj.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
  229. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-D6fvdK20.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
  230. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-BK82L5n5.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
  231. ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
  232. ksadk/server/static/assets/{chunk-2J33WTMH-DLVdkeyQ.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
  233. ksadk/server/static/assets/{chunk-4BX2VUAB-BbwsYcbW.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
  234. ksadk/server/static/assets/{chunk-55IACEB6-DOairxzw.js → chunk-55IACEB6-BK8paA20.js} +1 -1
  235. ksadk/server/static/assets/{chunk-727SXJPM-hCO487gs.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
  236. ksadk/server/static/assets/{chunk-AQP2D5EJ-XU8vDOuG.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
  237. ksadk/server/static/assets/{chunk-FMBD7UC4-PrapyfMu.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
  238. ksadk/server/static/assets/{chunk-ND2GUHAM-CboKhTZ3.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-_N8bJ-EU.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
  243. ksadk/server/static/assets/{dagre-BM42HDAG-FoDlo5J2.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
  244. ksadk/server/static/assets/{diagram-2AECGRRQ-BBp6ebBw.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
  245. ksadk/server/static/assets/{diagram-5GNKFQAL-CqOvG1PR.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
  246. ksadk/server/static/assets/{diagram-KO2AKTUF-O9T3t6ba.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
  247. ksadk/server/static/assets/{diagram-LMA3HP47-CGG8ekBO.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
  248. ksadk/server/static/assets/{diagram-OG6HWLK6-4BmH1EEg.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
  249. ksadk/server/static/assets/{dist-CiZHB6ZW.js → dist-6CVKuTAe.js} +1 -1
  250. ksadk/server/static/assets/{dist-BMKM66B4.js → dist-BUHRxvDG.js} +1 -1
  251. ksadk/server/static/assets/{dist-CZ6C3x8B.js → dist-BZ9n9AjO.js} +1 -1
  252. ksadk/server/static/assets/{dist-DbaH3p5h.js → dist-BibcG1V9.js} +1 -1
  253. ksadk/server/static/assets/{dist-BVzcWa6D.js → dist-Bs-jQcRX.js} +1 -1
  254. ksadk/server/static/assets/{dist-D99wf6_X.js → dist-C2xjE7cO.js} +1 -1
  255. ksadk/server/static/assets/{dist-DLMjL01k.js → dist-C7-3jInC.js} +1 -1
  256. ksadk/server/static/assets/{dist-DI-oVAXw.js → dist-C99THtIA.js} +1 -1
  257. ksadk/server/static/assets/{dist-BkJjNih3.js → dist-CGcp2ex8.js} +1 -1
  258. ksadk/server/static/assets/{dist-D5JGcxBx.js → dist-CVQRZjPu.js} +1 -1
  259. ksadk/server/static/assets/{dist-CWiTDN_V.js → dist-Cf23NY4L.js} +1 -1
  260. ksadk/server/static/assets/{dist-DLeM1OCK.js → dist-CgF3fj15.js} +1 -1
  261. ksadk/server/static/assets/{dist-BmuTWcm7.js → dist-Cwt7koer.js} +1 -1
  262. ksadk/server/static/assets/{dist-C2DKRFVK.js → dist-D82mtD2s.js} +1 -1
  263. ksadk/server/static/assets/{dist-B67uF2uK.js → dist-DF06ORQo.js} +1 -1
  264. ksadk/server/static/assets/{dist-Cwhk4lwI.js → dist-DHn6nBzr.js} +1 -1
  265. ksadk/server/static/assets/{dist-S4klkK5W.js → dist-Djgl2wVZ.js} +1 -1
  266. ksadk/server/static/assets/{dist-DCpZrjaK.js → dist-DlzCRy0S.js} +1 -1
  267. ksadk/server/static/assets/{dist-Cp1_jKwf.js → dist-DqNnNFrw.js} +1 -1
  268. ksadk/server/static/assets/{dist-6kSZvCZh.js → dist-DyvYLMW9.js} +1 -1
  269. ksadk/server/static/assets/{dist-DM0rEQPk.js → dist-eoW6tZXA.js} +1 -1
  270. ksadk/server/static/assets/{dist-Bk1l05Ni.js → dist-ivOya1LD.js} +1 -1
  271. ksadk/server/static/assets/{erDiagram-TEJ5UH35-oJhaci7S.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-DtTmUan-.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
  274. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BSsb_eij.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-BR5s6Pws.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-DYPc5cvh.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
  281. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-MoBdALDg.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
  282. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-DgLiQT8l.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
  283. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-CsFx112F.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
  284. ksadk/server/static/assets/{katex-DRsiwpM2.js → katex-DATssjp1.js} +1 -1
  285. ksadk/server/static/assets/{linear-TNRQ5Orv.js → linear-CvMBw9cA.js} +1 -1
  286. ksadk/server/static/assets/{mermaid-parser.core-D2eMVOgo.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
  287. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-BtByYFhL.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-DPnuCB8c.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
  291. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-miFpCPv4.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-mjB_yYkW.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
  294. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-D7hSlZZZ.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
  295. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-D9Cx6hC3.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
  296. ksadk/server/static/assets/{stateDiagram-AJRCARHV-D_zrg47o.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-CwSec0Wa.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-agCVobiF.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-TmrlhWNt.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
  304. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-DV71V-ah.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 +86 -40
  308. ksadk/sessions/base.py +31 -11
  309. ksadk/sessions/continuity.py +28 -5
  310. ksadk/sessions/in_memory.py +46 -2
  311. ksadk/sessions/local_service.py +148 -17
  312. ksadk/sessions/postgres_service.py +216 -35
  313. ksadk/sessions/resilience.py +52 -0
  314. ksadk/sessions/resilient.py +388 -0
  315. ksadk/skills/models.py +17 -5
  316. ksadk/skills/package_store.py +5 -2
  317. ksadk/skills/runtime/agent.py +20 -5
  318. ksadk/skills/runtime/artifacts.py +1 -5
  319. ksadk/skills/runtime/backends/e2b.py +10 -4
  320. ksadk/skills/runtime/backends/local.py +15 -3
  321. ksadk/skills/runtime/base.py +1 -2
  322. ksadk/skills/runtime/executor.py +10 -3
  323. ksadk/skills/runtime/factory.py +4 -2
  324. ksadk/skills/runtime/loader.py +1 -2
  325. ksadk/skills/runtime/registry.py +15 -10
  326. ksadk/skills/runtime/request.py +3 -1
  327. ksadk/skills/service_client.py +38 -17
  328. ksadk/skills/tool_defs.py +15 -10
  329. ksadk/terminal_exec_policy.py +3 -4
  330. ksadk/tools/gateway.py +92 -15
  331. ksadk/tools/result_budget.py +12 -4
  332. ksadk/toolsets/__init__.py +136 -36
  333. ksadk/toolsets/platform.py +21 -5
  334. ksadk/toolsets/sandbox.py +82 -16
  335. ksadk/toolsets/skills.py +200 -39
  336. ksadk/toolsets/web.py +123 -26
  337. ksadk/toolsets/workspace.py +264 -114
  338. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  339. ksadk/tracing/exporters/langfuse_exporter.py +91 -76
  340. ksadk/tracing/setup.py +132 -53
  341. ksadk/tracing/span_utils.py +5 -2
  342. ksadk/tui/__init__.py +22 -7
  343. ksadk/tui/loop.py +1925 -0
  344. ksadk/tui/stream_render.py +69 -0
  345. ksadk/ui_config.py +5 -3
  346. ksadk/version.py +1 -1
  347. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  348. agentengine_sdk_python-0.6.9.dist-info/RECORD +0 -487
  349. ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +0 -9
  350. ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +0 -8
  351. ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +0 -303
  352. ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +0 -1
  353. ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +0 -1
  354. ksadk/server/static/assets/channel-BSSOwFIb.js +0 -1
  355. ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +0 -1
  356. ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +0 -1
  357. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +0 -1
  358. ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +0 -1
  359. ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +0 -1
  360. ksadk/server/static/assets/index-BH7-pC0B.js +0 -165
  361. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  362. ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +0 -1
  363. ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +0 -1
  364. ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +0 -1
  365. ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +0 -1
  366. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +0 -1
  367. ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +0 -1
  368. ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +0 -1
  369. ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +0 -1
  370. ksadk/tui/app.py +0 -400
  371. ksadk/tui/clipboard.py +0 -100
  372. ksadk/tui/widgets/__init__.py +0 -22
  373. ksadk/tui/widgets/assistant.py +0 -89
  374. ksadk/tui/widgets/base.py +0 -54
  375. ksadk/tui/widgets/chat_input.py +0 -246
  376. ksadk/tui/widgets/history.py +0 -156
  377. ksadk/tui/widgets/system.py +0 -87
  378. ksadk/tui/widgets/thinking.py +0 -110
  379. ksadk/tui/widgets/tool_call.py +0 -161
  380. ksadk/tui/widgets/user.py +0 -37
  381. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
  382. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
  383. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
  384. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,326 @@
1
+ """Durable local outbox for AgentEngine A2A task event batches."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import hashlib
7
+ import json
8
+ import os
9
+ import sqlite3
10
+ from abc import ABC, abstractmethod
11
+ from dataclasses import dataclass
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ ENV_A2A_EVENT_OUTBOX_PATH = "KSADK_A2A_EVENT_OUTBOX_PATH"
16
+ DEFAULT_A2A_EVENT_OUTBOX_PATH = ".agentengine/a2a_event_outbox.sqlite3"
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class A2ATaskEventBatch:
21
+ sequence: int
22
+ batch_id: str
23
+ platform_task_id: str
24
+ events: list[dict[str, Any]]
25
+ attempt_count: int = 0
26
+
27
+
28
+ class A2ATaskEventOutbox(ABC):
29
+ """Persists task-sink batches until AgentEngine acknowledges them."""
30
+
31
+ @abstractmethod
32
+ async def initialize(self) -> None:
33
+ raise NotImplementedError
34
+
35
+ @abstractmethod
36
+ async def ensure_writable(self) -> None:
37
+ raise NotImplementedError
38
+
39
+ @abstractmethod
40
+ async def enqueue(
41
+ self,
42
+ *,
43
+ platform_task_id: str,
44
+ events: list[dict[str, Any]],
45
+ ) -> str:
46
+ raise NotImplementedError
47
+
48
+ @abstractmethod
49
+ async def pending(self, *, limit: int = 100) -> list[A2ATaskEventBatch]:
50
+ raise NotImplementedError
51
+
52
+ @abstractmethod
53
+ async def acknowledge(self, batch_id: str) -> None:
54
+ raise NotImplementedError
55
+
56
+ @abstractmethod
57
+ async def record_failure(self, batch_id: str, error: str) -> None:
58
+ raise NotImplementedError
59
+
60
+
61
+ def _serialize_events(events: list[dict[str, Any]]) -> str:
62
+ return json.dumps(events, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
63
+
64
+
65
+ def _batch_id(platform_task_id: str, events_json: str) -> str:
66
+ digest = hashlib.sha256(f"{platform_task_id}:{events_json}".encode("utf-8")).hexdigest()
67
+ return f"a2a-event-batch-{digest}"
68
+
69
+
70
+ class InMemoryA2ATaskEventOutbox(A2ATaskEventOutbox):
71
+ """Test/local adapter; production Runtime deployments should use SQLite."""
72
+
73
+ def __init__(self) -> None:
74
+ self._batches: dict[str, A2ATaskEventBatch] = {}
75
+ self._lock = asyncio.Lock()
76
+ self._next_sequence = 0
77
+
78
+ async def initialize(self) -> None:
79
+ return None
80
+
81
+ async def ensure_writable(self) -> None:
82
+ return None
83
+
84
+ async def enqueue(
85
+ self,
86
+ *,
87
+ platform_task_id: str,
88
+ events: list[dict[str, Any]],
89
+ ) -> str:
90
+ events_json = _serialize_events(events)
91
+ batch_id = _batch_id(platform_task_id, events_json)
92
+ async with self._lock:
93
+ if batch_id not in self._batches:
94
+ self._next_sequence += 1
95
+ self._batches[batch_id] = A2ATaskEventBatch(
96
+ sequence=self._next_sequence,
97
+ batch_id=batch_id,
98
+ platform_task_id=platform_task_id,
99
+ events=json.loads(events_json),
100
+ )
101
+ return batch_id
102
+
103
+ async def pending(self, *, limit: int = 100) -> list[A2ATaskEventBatch]:
104
+ async with self._lock:
105
+ return sorted(self._batches.values(), key=lambda batch: batch.sequence)[:limit]
106
+
107
+ async def acknowledge(self, batch_id: str) -> None:
108
+ async with self._lock:
109
+ self._batches.pop(batch_id, None)
110
+
111
+ async def record_failure(self, batch_id: str, error: str) -> None:
112
+ async with self._lock:
113
+ batch = self._batches.get(batch_id)
114
+ if batch is not None:
115
+ self._batches[batch_id] = A2ATaskEventBatch(
116
+ sequence=batch.sequence,
117
+ batch_id=batch.batch_id,
118
+ platform_task_id=batch.platform_task_id,
119
+ events=batch.events,
120
+ attempt_count=batch.attempt_count + 1,
121
+ )
122
+
123
+
124
+ class SQLiteA2ATaskEventOutbox(A2ATaskEventOutbox):
125
+ """SQLite adapter with stable batch IDs and crash-safe acknowledgement."""
126
+
127
+ def __init__(self, path: str | os.PathLike[str] | None = None) -> None:
128
+ configured = path or os.getenv(ENV_A2A_EVENT_OUTBOX_PATH) or DEFAULT_A2A_EVENT_OUTBOX_PATH
129
+ self._path = Path(configured).expanduser()
130
+ self._initialized = False
131
+ self._init_lock = asyncio.Lock()
132
+
133
+ @property
134
+ def path(self) -> Path:
135
+ return self._path
136
+
137
+ async def initialize(self) -> None:
138
+ if self._initialized:
139
+ return
140
+ async with self._init_lock:
141
+ if self._initialized:
142
+ return
143
+ await asyncio.to_thread(self._initialize_sync)
144
+ self._initialized = True
145
+
146
+ def _initialize_sync(self) -> None:
147
+ self._path.parent.mkdir(parents=True, exist_ok=True)
148
+ connection = sqlite3.connect(self._path, timeout=5)
149
+ try:
150
+ connection.execute("PRAGMA journal_mode=WAL")
151
+ connection.execute("PRAGMA synchronous=FULL")
152
+ connection.execute(
153
+ """
154
+ CREATE TABLE IF NOT EXISTS a2a_task_event_outbox (
155
+ sequence INTEGER NOT NULL,
156
+ batch_id TEXT PRIMARY KEY,
157
+ platform_task_id TEXT NOT NULL,
158
+ events_json TEXT NOT NULL,
159
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
160
+ attempt_count INTEGER NOT NULL DEFAULT 0,
161
+ last_error TEXT
162
+ )
163
+ """
164
+ )
165
+ columns = {
166
+ str(row[1])
167
+ for row in connection.execute("PRAGMA table_info(a2a_task_event_outbox)").fetchall()
168
+ }
169
+ if "sequence" not in columns:
170
+ connection.execute("ALTER TABLE a2a_task_event_outbox ADD COLUMN sequence INTEGER")
171
+ connection.execute(
172
+ "UPDATE a2a_task_event_outbox SET sequence = rowid WHERE sequence IS NULL"
173
+ )
174
+ connection.execute(
175
+ """
176
+ CREATE TABLE IF NOT EXISTS a2a_task_event_outbox_sequence (
177
+ sequence INTEGER PRIMARY KEY AUTOINCREMENT
178
+ )
179
+ """
180
+ )
181
+ connection.execute(
182
+ """
183
+ INSERT OR IGNORE INTO a2a_task_event_outbox_sequence(sequence)
184
+ SELECT sequence FROM a2a_task_event_outbox
185
+ """
186
+ )
187
+ connection.execute(
188
+ """
189
+ CREATE INDEX IF NOT EXISTS ix_a2a_task_event_outbox_created
190
+ ON a2a_task_event_outbox(sequence)
191
+ """
192
+ )
193
+ connection.commit()
194
+ finally:
195
+ connection.close()
196
+ os.chmod(self._path, 0o600)
197
+
198
+ async def enqueue(
199
+ self,
200
+ *,
201
+ platform_task_id: str,
202
+ events: list[dict[str, Any]],
203
+ ) -> str:
204
+ await self.initialize()
205
+ events_json = _serialize_events(events)
206
+ batch_id = _batch_id(platform_task_id, events_json)
207
+ await asyncio.to_thread(
208
+ self._enqueue_sync,
209
+ batch_id,
210
+ platform_task_id,
211
+ events_json,
212
+ )
213
+ return batch_id
214
+
215
+ async def ensure_writable(self) -> None:
216
+ await self.initialize()
217
+ await asyncio.to_thread(self._ensure_writable_sync)
218
+
219
+ async def pending(self, *, limit: int = 100) -> list[A2ATaskEventBatch]:
220
+ await self.initialize()
221
+ rows = await asyncio.to_thread(self._pending_sync, limit)
222
+ return [
223
+ A2ATaskEventBatch(
224
+ sequence=int(row[0]),
225
+ batch_id=str(row[1]),
226
+ platform_task_id=str(row[2]),
227
+ events=list(json.loads(str(row[3]))),
228
+ attempt_count=int(row[4]),
229
+ )
230
+ for row in rows
231
+ ]
232
+
233
+ async def acknowledge(self, batch_id: str) -> None:
234
+ await self.initialize()
235
+ await asyncio.to_thread(
236
+ self._execute,
237
+ "DELETE FROM a2a_task_event_outbox WHERE batch_id = ?",
238
+ (batch_id,),
239
+ )
240
+
241
+ async def record_failure(self, batch_id: str, error: str) -> None:
242
+ await self.initialize()
243
+ await asyncio.to_thread(
244
+ self._execute,
245
+ """
246
+ UPDATE a2a_task_event_outbox
247
+ SET attempt_count = attempt_count + 1, last_error = ?
248
+ WHERE batch_id = ?
249
+ """,
250
+ (error[:512], batch_id),
251
+ )
252
+
253
+ def _execute(self, statement: str, params: tuple[Any, ...]) -> None:
254
+ connection = sqlite3.connect(self._path, timeout=5)
255
+ try:
256
+ connection.execute("PRAGMA synchronous=FULL")
257
+ connection.execute(statement, params)
258
+ connection.commit()
259
+ finally:
260
+ connection.close()
261
+
262
+ def _enqueue_sync(self, batch_id: str, platform_task_id: str, events_json: str) -> None:
263
+ connection = sqlite3.connect(self._path, timeout=5, isolation_level=None)
264
+ try:
265
+ connection.execute("PRAGMA synchronous=FULL")
266
+ connection.execute("BEGIN IMMEDIATE")
267
+ existing = connection.execute(
268
+ "SELECT 1 FROM a2a_task_event_outbox WHERE batch_id = ?",
269
+ (batch_id,),
270
+ ).fetchone()
271
+ if existing is None:
272
+ cursor = connection.execute(
273
+ "INSERT INTO a2a_task_event_outbox_sequence DEFAULT VALUES"
274
+ )
275
+ if cursor.lastrowid is None:
276
+ raise RuntimeError("SQLite did not return an outbox sequence")
277
+ sequence = int(cursor.lastrowid)
278
+ connection.execute(
279
+ """
280
+ INSERT INTO a2a_task_event_outbox(
281
+ sequence, batch_id, platform_task_id, events_json
282
+ ) VALUES (?, ?, ?, ?)
283
+ """,
284
+ (sequence, batch_id, platform_task_id, events_json),
285
+ )
286
+ connection.execute("COMMIT")
287
+ except BaseException:
288
+ connection.rollback()
289
+ raise
290
+ finally:
291
+ connection.close()
292
+
293
+ def _ensure_writable_sync(self) -> None:
294
+ connection = sqlite3.connect(self._path, timeout=5, isolation_level=None)
295
+ try:
296
+ connection.execute("BEGIN IMMEDIATE")
297
+ connection.execute("ROLLBACK")
298
+ finally:
299
+ connection.close()
300
+
301
+ def _pending_sync(self, limit: int) -> list[tuple[Any, ...]]:
302
+ connection = sqlite3.connect(self._path, timeout=5)
303
+ try:
304
+ return list(
305
+ connection.execute(
306
+ """
307
+ SELECT sequence, batch_id, platform_task_id, events_json, attempt_count
308
+ FROM a2a_task_event_outbox
309
+ ORDER BY sequence
310
+ LIMIT ?
311
+ """,
312
+ (limit,),
313
+ ).fetchall()
314
+ )
315
+ finally:
316
+ connection.close()
317
+
318
+
319
+ __all__ = [
320
+ "A2ATaskEventBatch",
321
+ "A2ATaskEventOutbox",
322
+ "DEFAULT_A2A_EVENT_OUTBOX_PATH",
323
+ "ENV_A2A_EVENT_OUTBOX_PATH",
324
+ "InMemoryA2ATaskEventOutbox",
325
+ "SQLiteA2ATaskEventOutbox",
326
+ ]
@@ -0,0 +1,206 @@
1
+ """A2A durable TaskStore (goal-05)。
2
+
3
+ 契约(§4.6):托管被调 task 使用 SDK ``DatabaseTaskStore``,表名隔离为
4
+ ``ksadk_a2a_tasks``,owner resolver 必须包含 account/runtime identity。
5
+ **不用 InMemoryTaskStore**——7/31 重启恢复发布门禁依赖 durable store。
6
+
7
+ 注意:TaskStore 只持久化**协议 Task**,不等于 runner checkpoint;两者必须共同成功
8
+ 才能声明 durable async(§7.2)。SQLite 只用于快速单测;进程崩溃恢复门禁必须使用
9
+ 真实 PostgreSQL 和独立 OS 进程。
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import warnings
15
+ from threading import Lock
16
+ from typing import Any, Callable, Mapping, Optional, Sequence
17
+
18
+ from a2a.server import models as _sdk_models
19
+ from a2a.server.context import ServerCallContext
20
+ from a2a.server.routes.common import DefaultServerCallContextBuilder
21
+ from a2a.server.tasks import DatabaseTaskStore
22
+ from sqlalchemy.exc import SAWarning
23
+ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
24
+ from starlette.requests import Request
25
+
26
+ from ksadk.a2a.identity import A2AIngressIdentity, A2ATrustedIdentityResolver
27
+
28
+ #: 契约 §4.6 规定的隔离表名。
29
+ A2A_TASK_TABLE = "ksadk_a2a_tasks"
30
+
31
+ DEFAULT_ACCOUNT_HEADERS = ("x-ksc-account-id", "x-account-id")
32
+ DEFAULT_RUNTIME_HEADERS = ("x-auth-agent-id", "x-ksc-agent-id", "x-runtime-id")
33
+
34
+
35
+ # a2a-sdk 1.1.0 dynamically declares a new ORM model for every custom-table
36
+ # store. Repeating the same table in one process raises an SQLAlchemy duplicate
37
+ # table error. Cache only KsADK's model instead of monkeypatching the SDK module.
38
+ _task_model_cache: dict[str, type[Any]] = {}
39
+ _task_model_lock = Lock()
40
+
41
+
42
+ def _task_model(table_name: str) -> type[Any]:
43
+ with _task_model_lock:
44
+ model = _task_model_cache.get(table_name)
45
+ if model is None:
46
+ with warnings.catch_warnings():
47
+ warnings.filterwarnings(
48
+ "ignore",
49
+ message=(
50
+ "This declarative base already contains a class with the same class name"
51
+ ),
52
+ category=SAWarning,
53
+ )
54
+ model = _sdk_models.create_task_model(table_name)
55
+ _task_model_cache[table_name] = model
56
+ return model
57
+
58
+
59
+ class _KsADKDatabaseTaskStore(DatabaseTaskStore):
60
+ """DatabaseTaskStore with a process-local, non-global custom-table model."""
61
+
62
+ def __init__(
63
+ self,
64
+ *,
65
+ engine: AsyncEngine,
66
+ create_table: bool,
67
+ table_name: str,
68
+ owner_resolver: Callable[[ServerCallContext], str],
69
+ ) -> None:
70
+ super().__init__(
71
+ engine=engine,
72
+ create_table=create_table,
73
+ owner_resolver=owner_resolver,
74
+ )
75
+ self.task_model = _task_model(table_name)
76
+
77
+
78
+ def _first(state: dict[str, Any], *keys: str) -> Optional[str]:
79
+ for key in keys:
80
+ value = state.get(key)
81
+ if value:
82
+ return str(value)
83
+ return None
84
+
85
+
86
+ def default_owner_resolver(context: ServerCallContext) -> str:
87
+ """默认 owner resolver:组合 account + runtime identity(契约 §4.6 要求两者)。
88
+
89
+ owner 形如 ``"{account}/{runtime}"``:account 取 ``account_id``/``tenant_id``,
90
+ runtime 取 ``runtime_id``/``agent_id``。**同一 account 下不同 runtime 形成独立任务
91
+ 权限域**(不会共用);只凑齐一侧时用一侧;两侧都缺时退回 ``user``/``anonymous``。
92
+ 生产环境应由鉴权/STS 在 context.state 注入这些键;本地无鉴权时退回匿名。
93
+ """
94
+ state = getattr(context, "state", None) or {}
95
+ verified_identity = state.get(A2ATrustedIdentityResolver.state_key)
96
+ if isinstance(verified_identity, A2AIngressIdentity):
97
+ return verified_identity.owner_key()
98
+ account = _first(state, "account_id", "tenant_id")
99
+ runtime = _first(state, "runtime_id", "agent_id")
100
+ parts = [part for part in (account, runtime) if part]
101
+ if parts:
102
+ return "/".join(parts)
103
+ return _first(state, "user") or "anonymous"
104
+
105
+
106
+ class A2AOwnerContextBuilder(DefaultServerCallContextBuilder):
107
+ """Build A2A call contexts from platform-authenticated HTTP identity.
108
+
109
+ The SDK default stores headers only under ``state['headers']`` while the
110
+ task store intentionally reads normalized top-level identity fields. This
111
+ builder is shared by JSON-RPC and REST so both transports enforce the same
112
+ account/runtime owner boundary. Deployments must strip/replace these
113
+ platform headers at the public edge; message metadata is never trusted.
114
+ """
115
+
116
+ def __init__(
117
+ self,
118
+ *,
119
+ account_headers: Sequence[str] = DEFAULT_ACCOUNT_HEADERS,
120
+ runtime_headers: Sequence[str] = DEFAULT_RUNTIME_HEADERS,
121
+ identity_resolver: A2ATrustedIdentityResolver | None = None,
122
+ allow_unverified_identity: bool = True,
123
+ ) -> None:
124
+ self._account_headers = tuple(header.lower() for header in account_headers)
125
+ self._runtime_headers = tuple(header.lower() for header in runtime_headers)
126
+ self._identity_resolver = identity_resolver
127
+ self._allow_unverified_identity = allow_unverified_identity
128
+
129
+ @staticmethod
130
+ def _header(headers: Mapping[str, Any], names: Sequence[str]) -> str | None:
131
+ for name in names:
132
+ value = str(headers.get(name) or "").strip()
133
+ if value:
134
+ return value
135
+ return None
136
+
137
+ def build(self, request: Request) -> ServerCallContext:
138
+ context = super().build(request)
139
+ state = dict(context.state or {})
140
+ headers = {str(key).lower(): value for key, value in request.headers.items()}
141
+ scope_state = request.scope.get("state")
142
+ trusted_state = dict(scope_state) if isinstance(scope_state, Mapping) else {}
143
+ if self._identity_resolver is not None:
144
+ identity = self._identity_resolver.resolve(request)
145
+ state[A2ATrustedIdentityResolver.state_key] = identity
146
+ state["account_id"] = identity.account_id
147
+ state["tenant_id"] = identity.tenant_id
148
+ state["caller_principal_type"] = identity.caller_principal_type
149
+ state["caller_principal_id"] = identity.caller_principal_id
150
+ elif not self._allow_unverified_identity:
151
+ raise PermissionError("verified Gateway identity is required for inbound A2A")
152
+ else:
153
+ account = _first(trusted_state, "account_id", "tenant_id") or self._header(
154
+ headers, self._account_headers
155
+ )
156
+ runtime = _first(trusted_state, "runtime_id", "agent_id") or self._header(
157
+ headers, self._runtime_headers
158
+ )
159
+ if account:
160
+ state["account_id"] = account
161
+ if runtime:
162
+ state["runtime_id"] = runtime
163
+ context.state = state
164
+ context.tenant = default_owner_resolver(context)
165
+ return context
166
+
167
+
168
+ def build_a2a_task_store(
169
+ dsn: str | None = None,
170
+ *,
171
+ engine: Optional[AsyncEngine] = None,
172
+ table_name: str = A2A_TASK_TABLE,
173
+ owner_resolver: Optional[Callable[[ServerCallContext], str]] = None,
174
+ create_table: bool = True,
175
+ ) -> DatabaseTaskStore:
176
+ """构建 durable ``DatabaseTaskStore``。
177
+
178
+ 参数:
179
+ dsn: 数据库 DSN(如 ``sqlite+aiosqlite:///path.db`` 或
180
+ ``postgresql+asyncpg://...``)。与 ``engine`` 二选一。
181
+ engine: 已存在的 SQLAlchemy AsyncEngine(优先于 dsn)。
182
+ table_name: 隔离表名,默认 ``ksadk_a2a_tasks``。
183
+ owner_resolver: owner 解析器,默认 :func:`default_owner_resolver`。
184
+ create_table: 是否在 initialize 时建表(测试/本地默认 True;生产可 False
185
+ 由迁移管理)。
186
+ """
187
+ if engine is None:
188
+ if not dsn:
189
+ raise ValueError("build_a2a_task_store 需要 dsn 或 engine 之一")
190
+ engine = create_async_engine(dsn)
191
+ return _KsADKDatabaseTaskStore(
192
+ engine=engine,
193
+ create_table=create_table,
194
+ table_name=table_name,
195
+ owner_resolver=owner_resolver or default_owner_resolver,
196
+ )
197
+
198
+
199
+ __all__ = [
200
+ "A2A_TASK_TABLE",
201
+ "A2AOwnerContextBuilder",
202
+ "DEFAULT_ACCOUNT_HEADERS",
203
+ "DEFAULT_RUNTIME_HEADERS",
204
+ "build_a2a_task_store",
205
+ "default_owner_resolver",
206
+ ]
ksadk/a2ui/__init__.py ADDED
@@ -0,0 +1,27 @@
1
+ """A2UI(Agent 驱动 UI)— canonical:docs/A2UI-agent驱动UI技术方案.md。"""
2
+
3
+ from ksadk.a2ui.core import A2UICore
4
+ from ksadk.a2ui.models import (
5
+ BASIC_CATALOG,
6
+ BASIC_CATALOG_ID,
7
+ A2UIValidationError,
8
+ ActionReceipt,
9
+ Component,
10
+ PendingInteraction,
11
+ Surface,
12
+ )
13
+ from ksadk.a2ui.renderer import A2UIRenderer, RenderedNode, submit_a2ui_action
14
+
15
+ __all__ = [
16
+ "A2UICore",
17
+ "A2UIRenderer",
18
+ "RenderedNode",
19
+ "submit_a2ui_action",
20
+ "A2UIValidationError",
21
+ "ActionReceipt",
22
+ "BASIC_CATALOG",
23
+ "BASIC_CATALOG_ID",
24
+ "Component",
25
+ "PendingInteraction",
26
+ "Surface",
27
+ ]