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/common/llm_utils.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """LLM Utilities"""
2
2
 
3
- import os
4
3
  import logging
4
+ import os
5
5
 
6
6
  logger = logging.getLogger(__name__)
7
7
 
@@ -10,28 +10,32 @@ PUBLIC_ENDPOINT = "https://kspmas.ksyun.com/v1/"
10
10
 
11
11
  # Internal Endpoint (Auto-injected by Platform)
12
12
  # Note: In most cases, we don't need to hardcode this because the platform injects it.
13
- # But for the purpose of "smart switching based on public URL", we might need to know what to switch TO,
13
+ # But for "smart switching based on public URL", we might need to know
14
+ # what to switch TO,
14
15
  # or simply rely on leaving it empty so the platform default takes over?
15
- #
16
+ #
16
17
  # According to user: "OPENAI_BASE_URL 不填会自动选择的" (If empty, it auto-selects).
17
- # So our strategy: If Public URL + Internal Env -> Unset OPENAI_BASE_URL (letting it fall back to platform default).
18
+ # Strategy: If Public URL + Internal Env -> Unset OPENAI_BASE_URL,
19
+ # letting it fall back to the platform default.
20
+
18
21
 
19
22
  def get_smart_openai_env() -> None:
20
23
  """Smartly configure OpenAI Environment Variables.
21
-
24
+
22
25
  If it detects that the code is running in a Ksyun Internal Environment (Serverless/KCE)
23
26
  AND the OPENAI_BASE_URL is set to the Public Endpoint, it will unset OPENAI_BASE_URL
24
27
  to allow the platform's automatic internal endpoint injection to take effect.
25
-
26
- This prevents network hangs caused by accessing public endpoints from internal-only environments.
28
+
29
+ This prevents network hangs caused by accessing public endpoints from
30
+ internal-only environments.
27
31
  """
28
32
  base_url = os.environ.get("OPENAI_BASE_URL", "").strip()
29
-
33
+
30
34
  # logic 1: Check if it is the Public Endpoint
31
35
  # Normalize by removing trailing slash for comparison
32
36
  normalized_url = base_url.rstrip("/")
33
37
  normalized_public = PUBLIC_ENDPOINT.rstrip("/")
34
-
38
+
35
39
  if normalized_url != normalized_public:
36
40
  return
37
41
 
@@ -41,11 +45,11 @@ def get_smart_openai_env() -> None:
41
45
  # - K_SERVICE (Injected by Knative/Serverless)
42
46
  # - KUBERNETES_SERVICE_HOST (Injected by K8s)
43
47
  is_internal = (
44
- "KSYUN_REGION" in os.environ
48
+ "KSYUN_REGION" in os.environ
45
49
  or "K_SERVICE" in os.environ
46
50
  or "KUBERNETES_SERVICE_HOST" in os.environ
47
51
  )
48
-
52
+
49
53
  if is_internal:
50
54
  logger.warning(
51
55
  f"Detected Public OPENAI_BASE_URL ({base_url}) in Internal Environment. "
@@ -55,7 +59,7 @@ def get_smart_openai_env() -> None:
55
59
  # Or explicitly set it to internal generic address if known?
56
60
  # User said: "OPENAI_BASE_URL 不填会自动选择". So we unset it.
57
61
  del os.environ["OPENAI_BASE_URL"]
58
-
62
+
59
63
  # Verify if successful removal
60
64
  if "OPENAI_BASE_URL" not in os.environ:
61
- logger.info("Successfully switched to Internal Endpoint mode.")
65
+ logger.info("Successfully switched to Internal Endpoint mode.")
@@ -0,0 +1,5 @@
1
+ """兼容层包 (goal-00)。"""
2
+
3
+ from ksadk.compat import adk_compat
4
+
5
+ __all__ = ["adk_compat", "copilotkit_a2ui"]
@@ -0,0 +1,200 @@
1
+ """Google ADK 多版本兼容层 (goal-00)。
2
+
3
+ ksadk 业务代码**不直接** ``import google.adk``;统一从本模块取符号。
4
+ ``google-adk`` 的版本差异只在兼容层内消化,业务代码对版本无感知。
5
+
6
+ 版本窗口
7
+ --------
8
+ 依赖约束 ``google-adk>=1.34.0,<3.0.0``:
9
+
10
+ - **1.34.x** 是最低支持锚点(不承诺 1.x 全系;1.0 缺 ``google.adk.apps`` 等,代价过大)。
11
+ - **2.x**(当前 2.5.x)是上界内最新主线。
12
+
13
+ 实测(2026-07-21, goal-00 探测,解包对比 1.34.3 vs 2.5.0):ksadk 用到的
14
+ 全部符号在两个版本**都存在**,差异仅为 2.x 的**向后兼容可选新增**:
15
+
16
+ - ``Runner.run_async`` 2.x 新增可选 ``yield_user_message``(默认 False)。
17
+ - ``RunConfig`` 2.x 新增若干可选字段(``http_options`` / ``telemetry`` /
18
+ ``model_input_context`` 等),均为可选,不传不影响。
19
+ - ``App.root_agent`` 2.x 变为可选(1.34 必填);ksadk 始终显式传,两版皆可。
20
+ - ``DatabaseSessionService`` 2.x 新增可选 ``db_engine``(``db_url`` 变可选);
21
+ ksadk 始终传 ``db_url``,两版皆可。
22
+ - ``McpToolset.header_provider`` 2.x 支持 awaitable;ksadk 未用该参数。
23
+
24
+ ksadk 现有调用**不依赖任何 2.x-only 参数**,因此 1.34 与 2.x 对 ksadk 能力对等,
25
+ 无需降级 shim。能力降级矩阵的完整文字版见
26
+ ``docs/adk-multi-version-compat.md``。
27
+
28
+ 使用 2.x-only 新能力的纪律
29
+ --------------------------
30
+ 若未来要用某个 2.x 才有的可选参数/符号,**必须**在本层用
31
+ :func:`adk_version_at_least` 判断后再下发,并对 1.34 做显式降级;不允许业务
32
+ 代码自行 ``import google.adk`` 探测。
33
+
34
+ 加载语义
35
+ --------
36
+ 本模块 import 自身**不触发** ``google.adk`` 导入(惰性,PEP 562
37
+ ``__getattr__``)。只有真正访问某个符号时才导入对应 ``google.adk`` 子模块;
38
+ 未安装 ``google-adk`` 时抛出带安装提示的 :class:`ImportError`,便于
39
+ ``memory/adk_tool`` 等调用方捕获并降级为原函数。
40
+ """
41
+
42
+ from __future__ import annotations
43
+
44
+ from importlib import import_module
45
+ from importlib.metadata import PackageNotFoundError
46
+ from importlib.metadata import version as _dist_version
47
+ from typing import TYPE_CHECKING, Any
48
+
49
+ if TYPE_CHECKING: # pragma: no cover - 仅供 mypy 静态检查,运行时不执行
50
+ pass
51
+
52
+ #: 导出符号名 -> 提供该符号的 google.adk 子模块路径。
53
+ #: 这是 ksadk 全部 google.adk 依赖的唯一登记表;新增依赖先在这里登记。
54
+ _LAZY_SYMBOLS: dict[str, str] = {
55
+ # agents
56
+ "Agent": "google.adk.agents",
57
+ "RunConfig": "google.adk.agents.run_config",
58
+ "StreamingMode": "google.adk.agents.run_config",
59
+ # apps
60
+ "App": "google.adk.apps",
61
+ "ResumabilityConfig": "google.adk.apps",
62
+ # events
63
+ "Event": "google.adk.events.event",
64
+ # memory
65
+ "BaseMemoryService": "google.adk.memory.base_memory_service",
66
+ "SearchMemoryResponse": "google.adk.memory.base_memory_service",
67
+ "MemoryEntry": "google.adk.memory.memory_entry",
68
+ # models
69
+ "LlmResponse": "google.adk.models",
70
+ "LiteLlm": "google.adk.models.lite_llm",
71
+ # runners
72
+ "Runner": "google.adk.runners",
73
+ # sessions
74
+ "BaseSessionService": "google.adk.sessions",
75
+ "InMemorySessionService": "google.adk.sessions",
76
+ "Session": "google.adk.sessions",
77
+ "DatabaseSessionService": "google.adk.sessions",
78
+ "InvocationContext": "google.adk.agents",
79
+ "ToolContext": "google.adk.tools",
80
+ "GetSessionConfig": "google.adk.sessions.base_session_service",
81
+ "ListSessionsResponse": "google.adk.sessions.base_session_service",
82
+ # tools
83
+ "FunctionTool": "google.adk.tools",
84
+ "load_memory": "google.adk.tools",
85
+ "McpTool": "google.adk.tools.mcp_tool.mcp_tool",
86
+ "McpToolset": "google.adk.tools.mcp_tool.mcp_toolset",
87
+ "CheckableMcpHttpClientFactory": "google.adk.tools.mcp_tool.mcp_session_manager",
88
+ "StreamableHTTPConnectionParams": "google.adk.tools.mcp_tool.mcp_session_manager",
89
+ }
90
+
91
+ #: 以模块形式导出的名字 -> 模块路径(如 genai types、需要 monkeypatch 的 lite_llm)。
92
+ _LAZY_MODULES: dict[str, str] = {
93
+ "genai_types": "google.genai.types",
94
+ }
95
+
96
+ _INSTALL_HINT = (
97
+ "google-adk 未安装或版本不在支持窗口 (>=1.34.0,<3.0.0)。" "安装: pip install 'ksadk[adk]'"
98
+ )
99
+
100
+ _ADK_NOT_FOUND = "google-adk 未安装"
101
+
102
+
103
+ def _raise_missing(name: str, exc: BaseException) -> None:
104
+ raise ImportError(f"无法导入 google.adk 符号 {name!r}。{_INSTALL_HINT}") from exc
105
+
106
+
107
+ def __getattr__(name: str) -> Any:
108
+ """PEP 562 惰性解析:首次访问符号时才导入对应 google.adk 子模块。"""
109
+ if name in _LAZY_SYMBOLS:
110
+ module_path = _LAZY_SYMBOLS[name]
111
+ try:
112
+ module = import_module(module_path)
113
+ except ImportError as exc:
114
+ _raise_missing(name, exc)
115
+ try:
116
+ value = getattr(module, name)
117
+ except AttributeError as exc:
118
+ raise ImportError(
119
+ f"google.adk 已安装但 {module_path} 缺少 {name!r};"
120
+ f"当前版本 {adk_version() or '未知'} 可能不在支持窗口 (>=1.34.0,<3.0.0)。"
121
+ ) from exc
122
+ # 注意: 刻意不缓存到 globals()。测试常 monkeypatch ``google.adk.*``
123
+ # 子模块符号(如把 Runner 换成 FakeRunner);若在此缓存,会把某次 patch
124
+ # 后的值泄漏给后续解析,造成跨测试污染。每次经 getattr 重新解析,
125
+ # 让既有 ``google.adk.*`` patch 点继续生效。开销可忽略(import_module
126
+ # 命中 sys.modules 缓存)。
127
+ return value
128
+ if name in _LAZY_MODULES:
129
+ module_path = _LAZY_MODULES[name]
130
+ try:
131
+ value = import_module(module_path)
132
+ except ImportError as exc:
133
+ _raise_missing(name, exc)
134
+ return value
135
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
136
+
137
+
138
+ def __dir__() -> list[str]:
139
+ return sorted(set(globals()) | set(_LAZY_SYMBOLS) | set(_LAZY_MODULES))
140
+
141
+
142
+ def is_adk_available() -> bool:
143
+ """google-adk 是否可导入(不关心版本)。"""
144
+ try:
145
+ import_module("google.adk")
146
+ except ImportError:
147
+ return False
148
+ return True
149
+
150
+
151
+ def adk_version() -> str | None:
152
+ """返回已安装的 google-adk 版本;未安装返回 None。"""
153
+ try:
154
+ return _dist_version("google-adk")
155
+ except PackageNotFoundError:
156
+ return None
157
+
158
+
159
+ def adk_version_at_least(min_version: str) -> bool:
160
+ """已安装 google-adk 版本是否 >= ``min_version``;未安装或无法解析返回 False。
161
+
162
+ 用于下发 2.x-only 能力前的版本门禁,例如::
163
+
164
+ if adk_version_at_least("2.0.0"):
165
+ kwargs["yield_user_message"] = True
166
+ """
167
+ ver = adk_version()
168
+ if ver is None:
169
+ return False
170
+ try:
171
+ from packaging.version import Version
172
+
173
+ return bool(Version(ver) >= Version(min_version))
174
+ except Exception:
175
+ return False
176
+
177
+
178
+ def lite_llm_module() -> Any:
179
+ """返回 ``google.adk.models.lite_llm`` 模块对象。
180
+
181
+ adk_runner 的 JSON 容错 patch 需要 MonkeyPatch 该模块内的
182
+ ``_message_to_generate_content_response``(私有函数),因此需要模块本身
183
+ 而非单个符号。未安装 litellm/google-adk 时抛 :class:`ImportError`。
184
+ """
185
+ try:
186
+ return import_module("google.adk.models.lite_llm")
187
+ except ImportError as exc:
188
+ _raise_missing("google.adk.models.lite_llm", exc)
189
+
190
+
191
+ __all__ = [
192
+ # 版本/能力探测
193
+ "is_adk_available",
194
+ "adk_version",
195
+ "adk_version_at_least",
196
+ "lite_llm_module",
197
+ # 惰性符号
198
+ *_LAZY_SYMBOLS.keys(),
199
+ *_LAZY_MODULES.keys(),
200
+ ]
@@ -0,0 +1,330 @@
1
+ """Compatibility bridge for the pinned CopilotKit and AG-UI A2UI packages.
2
+
3
+ The currently pinned public packages disagree on the A2UI factory signature.
4
+ More importantly, the released LangGraph adapter moves an async model invocation
5
+ to a worker thread and calls it with ``asyncio.run``. Async providers such as
6
+ ``ChatOpenAI`` retain event-loop-bound clients, so that path can wait forever.
7
+
8
+ This module keeps CopilotKit's middleware lifecycle and dynamic-tool dispatch,
9
+ but owns the small framework glue that invokes the A2UI sub-agent on the active
10
+ event loop. The A2UI wire format, prompt construction, and validation are still
11
+ provided by the official AG-UI toolkit.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import asyncio
17
+ import inspect
18
+ import logging
19
+ import os
20
+ from importlib import import_module
21
+ from typing import Any
22
+
23
+ try:
24
+ from copilotkit import CopilotKitMiddleware, copilotkit_lg_middleware
25
+ from langchain.tools import ToolRuntime, tool
26
+ from langchain_core.messages import SystemMessage
27
+ except ImportError as exc: # The module itself belongs to the optional AG-UI feature.
28
+ raise ImportError(
29
+ "CopilotKit A2UI requires ksadk[agui] with copilotkit and ag-ui-langgraph installed."
30
+ ) from exc
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+ _DEFAULT_GENERATION_TIMEOUT_SECONDS = 20.0
35
+
36
+ # The upstream toolkit's generic default prompt is intentionally exhaustive.
37
+ # It is also large enough to exceed the Hosted UI model gateway's reliable tool
38
+ # latency. This compact contract covers the v0.9 basic catalog used by ksadk-web
39
+ # while leaving applications free to pass their own guidelines explicitly.
40
+ _KSADK_HOSTED_UI_GUIDELINES = {
41
+ "generation_guidelines": """\
42
+ Return exactly one render_a2ui tool call. Use A2UI v0.9 flat components: every
43
+ component has an id and a component field. The root id is root. Use only Text,
44
+ Column, Row, Card, List, Button, ChoicePicker, Divider, TextField, CheckBox,
45
+ or Slider. Put properties directly on each component, never under type or
46
+ properties. Use child for one component id and children for an array of ids.
47
+ For example: [{\"id\":\"root\",\"component\":\"Card\",\"child\":\"content\"},
48
+ {\"id\":\"content\",\"component\":\"Column\",\"children\":[\"title\"]},
49
+ {\"id\":\"title\",\"component\":\"Text\",\"variant\":\"h2\",\"text\":\"Status\"}].
50
+ Use only facts present in the conversation and tool results. Do not return
51
+ Markdown or prose instead of the tool call.""",
52
+ "design_guidelines": """\
53
+ Create one compact, readable surface. Use hierarchy and spacing through Card,
54
+ Column, Row, Text, Divider, and ChoicePicker instead of decorative elements.
55
+ For status, summarize real values; for risks, show severity and owner; for
56
+ choices, use ChoicePicker with a bound data value.""",
57
+ }
58
+
59
+
60
+ def _a2ui_toolkit_dependencies() -> tuple[Any, ...]:
61
+ """Resolve the optional toolkit, which currently publishes no type metadata."""
62
+ try:
63
+ toolkit = import_module("ag_ui_a2ui_toolkit")
64
+ except ImportError as exc:
65
+ raise ImportError(
66
+ "CopilotKit A2UI requires ksadk[agui] with ag-ui-a2ui-toolkit installed."
67
+ ) from exc
68
+ names = (
69
+ "RENDER_A2UI_TOOL_DEF",
70
+ "resolve_a2ui_tool_params",
71
+ "prepare_a2ui_request",
72
+ "build_a2ui_envelope",
73
+ "validate_a2ui_components",
74
+ "augment_prompt_with_validation_errors",
75
+ "wrap_error_envelope",
76
+ "MAX_A2UI_ATTEMPTS",
77
+ )
78
+ values = tuple(getattr(toolkit, name, None) for name in names)
79
+ if any(value is None for value in values):
80
+ raise RuntimeError("ag-ui-a2ui-toolkit is missing a required A2UI integration symbol")
81
+ return values
82
+
83
+
84
+ (
85
+ _RENDER_A2UI_TOOL_DEF,
86
+ _resolve_a2ui_tool_params,
87
+ _prepare_a2ui_request,
88
+ _build_a2ui_envelope,
89
+ _validate_a2ui_components,
90
+ _augment_prompt_with_validation_errors,
91
+ _wrap_error_envelope,
92
+ _MAX_A2UI_ATTEMPTS,
93
+ ) = _a2ui_toolkit_dependencies()
94
+
95
+
96
+ def _generation_timeout_seconds() -> float:
97
+ """Read the operator-owned A2UI deadline, with a conservative default."""
98
+ raw = os.getenv("KSADK_A2UI_GENERATION_TIMEOUT_SECONDS", "").strip()
99
+ if not raw:
100
+ return _DEFAULT_GENERATION_TIMEOUT_SECONDS
101
+ try:
102
+ return max(1.0, min(float(raw), 120.0))
103
+ except ValueError:
104
+ return _DEFAULT_GENERATION_TIMEOUT_SECONDS
105
+
106
+
107
+ def _tool_call_args(response: Any) -> dict[str, Any] | None:
108
+ for call in getattr(response, "tool_calls", None) or []:
109
+ if not isinstance(call, dict):
110
+ continue
111
+ if call.get("name") != _RENDER_A2UI_TOOL_DEF["function"]["name"]:
112
+ continue
113
+ args = call.get("args")
114
+ return args if isinstance(args, dict) else {}
115
+ return None
116
+
117
+
118
+ async def _invoke_a2ui_subagent(
119
+ model_with_tool: Any,
120
+ *,
121
+ prompt: str,
122
+ messages: list[Any],
123
+ timeout_seconds: float,
124
+ ) -> dict[str, Any] | None:
125
+ """Ask the structured-output model on the same loop as the parent run."""
126
+
127
+ async def invoke() -> Any:
128
+ ainvoke = getattr(model_with_tool, "ainvoke", None)
129
+ if callable(ainvoke):
130
+ result = ainvoke([SystemMessage(content=prompt), *messages])
131
+ return await result if inspect.isawaitable(result) else result
132
+ invoke_sync = getattr(model_with_tool, "invoke", None)
133
+ if not callable(invoke_sync):
134
+ raise TypeError("A2UI model must expose ainvoke() or invoke()")
135
+ return await asyncio.to_thread(invoke_sync, [SystemMessage(content=prompt), *messages])
136
+
137
+ response = await asyncio.wait_for(invoke(), timeout=timeout_seconds)
138
+ return _tool_call_args(response)
139
+
140
+
141
+ def _attempt_callback(callback: Any, record: dict[str, Any]) -> None:
142
+ if not callable(callback):
143
+ return
144
+ try:
145
+ callback(record)
146
+ except Exception:
147
+ # Diagnostics must not prevent a usable UI surface from being returned.
148
+ logger.debug("A2UI attempt callback failed", exc_info=True)
149
+
150
+
151
+ async def _generate_a2ui_envelope(
152
+ *,
153
+ config: dict[str, Any],
154
+ state: dict[str, Any],
155
+ messages: list[Any],
156
+ intent: str,
157
+ target_surface_id: str | None,
158
+ changes: str | None,
159
+ ) -> str:
160
+ """Run the official validate/retry contract without crossing event loops."""
161
+
162
+ prep = _prepare_a2ui_request(
163
+ intent=intent,
164
+ target_surface_id=target_surface_id,
165
+ changes=changes,
166
+ messages=messages,
167
+ state=state,
168
+ guidelines=config["guidelines"],
169
+ )
170
+ if prep.get("error"):
171
+ return str(_wrap_error_envelope(prep["error"]))
172
+
173
+ model = config["model"]
174
+ model_with_tool = model.bind_tools(
175
+ [_RENDER_A2UI_TOOL_DEF],
176
+ tool_choice=_RENDER_A2UI_TOOL_DEF["function"]["name"],
177
+ )
178
+ recovery = config.get("recovery") or {}
179
+ max_attempts = recovery.get("maxAttempts", _MAX_A2UI_ATTEMPTS)
180
+ try:
181
+ max_attempts = max(1, min(int(max_attempts), 5))
182
+ except (TypeError, ValueError):
183
+ max_attempts = _MAX_A2UI_ATTEMPTS
184
+
185
+ timeout_seconds = _generation_timeout_seconds()
186
+ last_errors: list[dict[str, str]] = []
187
+ attempts: list[dict[str, Any]] = []
188
+ for attempt in range(1, max_attempts + 1):
189
+ prompt = _augment_prompt_with_validation_errors(prep["prompt"], last_errors)
190
+ try:
191
+ args = await _invoke_a2ui_subagent(
192
+ model_with_tool,
193
+ prompt=prompt,
194
+ messages=messages,
195
+ timeout_seconds=timeout_seconds,
196
+ )
197
+ except asyncio.TimeoutError:
198
+ record: dict[str, Any] = {
199
+ "attempt": attempt,
200
+ "ok": False,
201
+ "errors": [
202
+ {
203
+ "code": "a2ui_generation_timeout",
204
+ "path": "model",
205
+ "message": f"A2UI generation exceeded {timeout_seconds:g} seconds",
206
+ }
207
+ ],
208
+ }
209
+ attempts.append(record)
210
+ _attempt_callback(config.get("on_a2ui_attempt"), record)
211
+ # Retrying an already-cancelled request usually piles up more work;
212
+ # return a visible error instead of leaving the chat in limbo.
213
+ return str(_wrap_error_envelope(record["errors"][0]["message"]))
214
+ except Exception as exc:
215
+ record = {
216
+ "attempt": attempt,
217
+ "ok": False,
218
+ "errors": [
219
+ {
220
+ "code": "a2ui_generation_error",
221
+ "path": "model",
222
+ "message": str(exc) or type(exc).__name__,
223
+ }
224
+ ],
225
+ }
226
+ attempts.append(record)
227
+ _attempt_callback(config.get("on_a2ui_attempt"), record)
228
+ return str(_wrap_error_envelope(record["errors"][0]["message"]))
229
+
230
+ if not args:
231
+ record = {
232
+ "attempt": attempt,
233
+ "ok": False,
234
+ "errors": [
235
+ {
236
+ "code": "empty_components",
237
+ "path": "components",
238
+ "message": "Sub-agent did not call render_a2ui",
239
+ }
240
+ ],
241
+ }
242
+ else:
243
+ components = args.get("components")
244
+ data = args.get("data")
245
+ validation = _validate_a2ui_components(
246
+ components=components if isinstance(components, list) else [],
247
+ data=data if isinstance(data, dict) else {},
248
+ catalog=config.get("catalog"),
249
+ )
250
+ record = {
251
+ "attempt": attempt,
252
+ "ok": bool(validation["valid"]),
253
+ "errors": list(validation["errors"]),
254
+ }
255
+ attempts.append(record)
256
+ _attempt_callback(config.get("on_a2ui_attempt"), record)
257
+ if record["ok"]:
258
+ return str(
259
+ _build_a2ui_envelope(
260
+ args=args,
261
+ is_update=prep["is_update"],
262
+ target_surface_id=target_surface_id,
263
+ prior=prep["prior"],
264
+ default_surface_id=config["default_surface_id"],
265
+ default_catalog_id=config["default_catalog_id"],
266
+ )
267
+ )
268
+ last_errors = record["errors"]
269
+
270
+ return str(
271
+ _wrap_error_envelope(f"Failed to generate valid A2UI after {max_attempts} attempt(s)")
272
+ )
273
+
274
+
275
+ def build_ksadk_a2ui_tool(params: dict[str, Any]) -> Any:
276
+ """Build the dynamic LangChain A2UI tool used by the CopilotKit shim."""
277
+
278
+ resolved_params = dict(params)
279
+ resolved_params.setdefault("guidelines", _KSADK_HOSTED_UI_GUIDELINES)
280
+ config = _resolve_a2ui_tool_params(resolved_params)
281
+
282
+ @tool(config["tool_name"], description=config["tool_description"])
283
+ async def generate_a2ui(
284
+ runtime: ToolRuntime[Any],
285
+ intent: str = "create",
286
+ target_surface_id: str | None = None,
287
+ changes: str | None = None,
288
+ ) -> str:
289
+ state = runtime.state if isinstance(runtime.state, dict) else {}
290
+ messages = list(state.get("messages") or [])[:-1]
291
+ return await _generate_a2ui_envelope(
292
+ config=config,
293
+ state=state,
294
+ messages=messages,
295
+ intent=intent,
296
+ target_surface_id=target_surface_id,
297
+ changes=changes,
298
+ )
299
+
300
+ return generate_a2ui
301
+
302
+
303
+ class KsadkCopilotKitMiddleware(CopilotKitMiddleware):
304
+ """Official lifecycle middleware with KSADK's safe A2UI tool executor."""
305
+
306
+ def _maybe_build_a2ui_tool(self, request: Any) -> Any | None:
307
+ state = request.state or {}
308
+ if not self._a2ui_inject_decision(state):
309
+ return None
310
+
311
+ resolved = self._resolve_a2ui_catalog(state)
312
+ _component_schema, catalog_id = resolved if resolved else (None, None)
313
+ params: dict[str, Any] = {"model": request.model}
314
+ if catalog_id:
315
+ params["default_catalog_id"] = catalog_id
316
+
317
+ tool = build_ksadk_a2ui_tool(params)
318
+ existing_names = {getattr(item, "name", None) for item in (request.tools or [])}
319
+ if tool.name in existing_names:
320
+ return None
321
+
322
+ thread_key = (
323
+ copilotkit_lg_middleware._current_thread_id()
324
+ or copilotkit_lg_middleware._DEFAULT_THREAD_KEY
325
+ )
326
+ copilotkit_lg_middleware._a2ui_tools_by_thread[thread_key] = tool
327
+ return tool
328
+
329
+
330
+ __all__ = ["KsadkCopilotKitMiddleware", "build_ksadk_a2ui_tool"]
ksadk/configs/__init__.py CHANGED
@@ -5,7 +5,7 @@ AgentEngine 统一配置管理
5
5
 
6
6
  使用方式:
7
7
  from ksadk.configs import settings
8
-
8
+
9
9
  环境变量优先级 (举例):
10
10
  Model: OPENAI_API_KEY > LLM_API_KEY > MODEL_API_KEY
11
11
  Langfuse: LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_HOST
@@ -17,24 +17,24 @@ AgentEngine 统一配置管理
17
17
  """
18
18
 
19
19
  from ksadk.configs.settings import (
20
- # 全局配置入口
21
- settings,
22
- Settings,
23
- # 各配置类
24
- ModelConfig,
25
- LangfuseConfig,
20
+ DEFAULT_MODEL_NAME,
21
+ KSPMAS_INTERNAL_HOST,
22
+ KSPMAS_INTERNAL_URL,
23
+ KSPMAS_PUBLIC_URL,
26
24
  AgentConfig,
27
- KingsoftCloudConfig,
28
25
  CodeModeConfig,
26
+ KingsoftCloudConfig,
27
+ LangfuseConfig,
28
+ # 各配置类
29
+ ModelConfig,
29
30
  OTelConfig,
31
+ Settings,
30
32
  # 通用网络检测工具
31
33
  check_endpoint_reachable,
32
34
  # KSPMAS 服务
33
35
  get_kspmas_api_base,
34
- KSPMAS_INTERNAL_HOST,
35
- KSPMAS_INTERNAL_URL,
36
- KSPMAS_PUBLIC_URL,
37
- DEFAULT_MODEL_NAME,
36
+ # 全局配置入口
37
+ settings,
38
38
  setup_environment,
39
39
  )
40
40