agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
  3. ksadk/a2a/_space_client_events.py +381 -0
  4. ksadk/a2a/event_adapter.py +156 -64
  5. ksadk/a2a/executor.py +179 -63
  6. ksadk/a2a/space_client.py +6 -333
  7. ksadk/a2ui/core.py +222 -53
  8. ksadk/agui/_agent_helpers.py +243 -0
  9. ksadk/agui/a2ui_projection.py +12 -5
  10. ksadk/agui/agent.py +443 -259
  11. ksadk/api/client.py +525 -27
  12. ksadk/builders/code_builder.py +284 -8
  13. ksadk/builders/container_builder.py +8 -1
  14. ksadk/builders/managed_runtime_builder.py +39 -35
  15. ksadk/cli/__init__.py +17 -0
  16. ksadk/cli/cmd_dashboard.py +15 -1
  17. ksadk/cli/cmd_deploy.py +10 -2
  18. ksadk/cli/cmd_eval.py +66 -9
  19. ksadk/cli/cmd_evalset.py +284 -0
  20. ksadk/cli/cmd_files.py +5 -1
  21. ksadk/cli/cmd_hermes.py +1 -126
  22. ksadk/cli/cmd_invoke.py +28 -38
  23. ksadk/cli/cmd_managed_runtime.py +95 -0
  24. ksadk/cli/cmd_observe.py +85 -0
  25. ksadk/cli/cmd_openclaw.py +1 -435
  26. ksadk/cli/cmd_replay.py +28 -4
  27. ksadk/cli/cmd_studio.py +99 -8
  28. ksadk/cli/cmd_web.py +10 -2
  29. ksadk/cli/hermes_env.py +151 -0
  30. ksadk/cli/invoke_payload.py +49 -0
  31. ksadk/cli/openclaw_env.py +458 -0
  32. ksadk/codex/client.py +180 -30
  33. ksadk/codex/runtime.py +428 -326
  34. ksadk/configs/env_registry.py +66 -12
  35. ksadk/configs/env_registry_pcm.py +181 -0
  36. ksadk/configs/env_var_spec.py +18 -0
  37. ksadk/configs/global_config.py +5 -0
  38. ksadk/context_engine/__init__.py +98 -0
  39. ksadk/context_engine/assembler.py +176 -0
  40. ksadk/context_engine/baseline.py +419 -0
  41. ksadk/context_engine/cache_observability.py +228 -0
  42. ksadk/context_engine/capabilities.py +443 -0
  43. ksadk/context_engine/contributors.py +344 -0
  44. ksadk/context_engine/hosted_pipeline.py +417 -0
  45. ksadk/context_engine/models.py +117 -0
  46. ksadk/context_engine/planner.py +698 -0
  47. ksadk/context_engine/policies.py +319 -0
  48. ksadk/context_engine/projection.py +31 -0
  49. ksadk/context_engine/shadow_plan.py +266 -0
  50. ksadk/context_engine/tokenizer.py +164 -0
  51. ksadk/conversations/context.py +126 -6
  52. ksadk/conversations/message_projection.py +292 -28
  53. ksadk/conversations/model_context.py +49 -3
  54. ksadk/conversations/runtime_compaction.py +207 -5
  55. ksadk/conversations/runtime_input.py +184 -2
  56. ksadk/conversations/runtime_invocation.py +81 -3
  57. ksadk/conversations/runtime_observability.py +141 -0
  58. ksadk/conversations/runtime_payloads.py +42 -0
  59. ksadk/conversations/runtime_preparation.py +272 -2
  60. ksadk/conversations/runtime_resume.py +20 -1
  61. ksadk/conversations/runtime_stream_events.py +94 -9
  62. ksadk/conversations/semantic_summary.py +311 -1
  63. ksadk/conversations/session_lock.py +51 -0
  64. ksadk/deployment/env_forward.py +72 -0
  65. ksadk/deployment/managed_runtime.py +5 -0
  66. ksadk/deployment/providers/serverless.py +143 -69
  67. ksadk/evaluation/__init__.py +32 -0
  68. ksadk/evaluation/a2a_adapter.py +9 -1
  69. ksadk/evaluation/adapters.py +18 -5
  70. ksadk/evaluation/agent_eval_client.py +395 -0
  71. ksadk/evaluation/cloud_binding.py +80 -0
  72. ksadk/evaluation/cloud_converter.py +194 -0
  73. ksadk/evaluation/cloud_service.py +199 -0
  74. ksadk/evaluation/contracts.py +73 -4
  75. ksadk/evaluation/evaluators.py +183 -17
  76. ksadk/evaluation/evidence.py +258 -0
  77. ksadk/evaluation/executor.py +31 -6
  78. ksadk/evaluation/local_adapter.py +550 -0
  79. ksadk/evaluation/service_env.py +27 -0
  80. ksadk/evaluation/studio_build_adapter.py +253 -0
  81. ksadk/evaluation/target.py +15 -6
  82. ksadk/events/__init__.py +13 -13
  83. ksadk/events/_v1_compat/__init__.py +1 -0
  84. ksadk/events/_v1_compat/models.py +299 -0
  85. ksadk/events/_v1_compat/parser.py +247 -0
  86. ksadk/events/_v1_compat/projection.py +753 -0
  87. ksadk/events/adapters/__init__.py +34 -0
  88. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  89. ksadk/events/adapters/_a2a_support.py +275 -0
  90. ksadk/events/adapters/_codex_interactions.py +375 -0
  91. ksadk/events/adapters/_codex_items.py +801 -0
  92. ksadk/events/adapters/_codex_validators.py +311 -0
  93. ksadk/events/adapters/_langgraph_support.py +785 -0
  94. ksadk/events/adapters/a2a.py +841 -0
  95. ksadk/events/adapters/adk.py +503 -0
  96. ksadk/events/adapters/codex.py +717 -0
  97. ksadk/events/adapters/langgraph.py +745 -0
  98. ksadk/events/canonical.py +440 -0
  99. ksadk/events/canonical_replay.py +497 -0
  100. ksadk/events/canonical_store.py +468 -0
  101. ksadk/events/cold_recovery.py +257 -0
  102. ksadk/events/content.py +89 -0
  103. ksadk/events/identity.py +86 -0
  104. ksadk/events/pipeline.py +455 -0
  105. ksadk/events/projections.py +66 -0
  106. ksadk/events/reducer.py +661 -0
  107. ksadk/events/replay.py +3 -36
  108. ksadk/events/runtime_event.py +20 -265
  109. ksadk/events/session_event.py +324 -0
  110. ksadk/events/store.py +3 -316
  111. ksadk/events/v1_compat.py +41 -0
  112. ksadk/harness/runtime.py +160 -57
  113. ksadk/identity/resolver.py +4 -3
  114. ksadk/interaction/__init__.py +28 -0
  115. ksadk/interaction/contracts.py +136 -0
  116. ksadk/interaction/ledger.py +189 -0
  117. ksadk/interaction/provider.py +122 -0
  118. ksadk/interaction/providers/__init__.py +52 -0
  119. ksadk/interaction/providers/adk.py +40 -0
  120. ksadk/interaction/providers/codex.py +94 -0
  121. ksadk/interaction/providers/langgraph.py +58 -0
  122. ksadk/kernel/__init__.py +117 -0
  123. ksadk/kernel/authorization.py +258 -0
  124. ksadk/kernel/bootstrap.py +1074 -0
  125. ksadk/kernel/contract_fingerprints.py +61 -0
  126. ksadk/kernel/contracts.py +362 -0
  127. ksadk/kernel/control.py +219 -0
  128. ksadk/kernel/errors.py +79 -0
  129. ksadk/kernel/ingress.py +1102 -0
  130. ksadk/kernel/mapping.py +111 -0
  131. ksadk/kernel/memory_store.py +1133 -0
  132. ksadk/kernel/postgres_store.py +1756 -0
  133. ksadk/kernel/recovery.py +452 -0
  134. ksadk/kernel/runtime_identity.py +103 -0
  135. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  136. ksadk/kernel/sqlite_store.py +1410 -0
  137. ksadk/kernel/state.py +145 -0
  138. ksadk/kernel/store.py +232 -0
  139. ksadk/kernel/worker.py +953 -0
  140. ksadk/knowledge_base/client.py +7 -0
  141. ksadk/knowledge_base/service.py +32 -5
  142. ksadk/memory/__init__.py +61 -0
  143. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  144. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  145. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  146. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  147. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  148. ksadk/memory/coordinator.py +461 -0
  149. ksadk/memory/events.py +202 -0
  150. ksadk/memory/extraction.py +228 -0
  151. ksadk/memory/ltm_backend_factory.py +16 -3
  152. ksadk/memory/models.py +316 -0
  153. ksadk/memory/policy.py +215 -0
  154. ksadk/memory/provider.py +47 -0
  155. ksadk/memory/provider_adapter.py +159 -0
  156. ksadk/memory/provider_resolver.py +71 -0
  157. ksadk/memory/providers/__init__.py +5 -0
  158. ksadk/memory/providers/local_sqlite.py +490 -0
  159. ksadk/memory/resolved_policy.py +145 -0
  160. ksadk/memory/service.py +188 -6
  161. ksadk/model_proxy/bootstrap.py +16 -9
  162. ksadk/model_proxy/detect.py +202 -9
  163. ksadk/model_proxy/namespace.py +39 -15
  164. ksadk/model_proxy/server.py +24 -5
  165. ksadk/model_proxy/transform.py +60 -2
  166. ksadk/observability/__init__.py +25 -0
  167. ksadk/observability/session_log.py +420 -0
  168. ksadk/observability/trajectory.py +105 -0
  169. ksadk/prompts/__init__.py +71 -0
  170. ksadk/prompts/compiler.py +215 -0
  171. ksadk/prompts/models.py +82 -0
  172. ksadk/prompts/projection.py +89 -0
  173. ksadk/prompts/resolved.py +137 -0
  174. ksadk/prompts/sources.py +233 -0
  175. ksadk/runners/_langgraph_runner_streams.py +822 -0
  176. ksadk/runners/adk_runner.py +5 -5
  177. ksadk/runners/base_runner.py +16 -0
  178. ksadk/runners/factory.py +1 -2
  179. ksadk/runners/langgraph_runner.py +198 -437
  180. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  181. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  182. ksadk/runtime/adapter.py +118 -2
  183. ksadk/runtime/conversation_execution.py +316 -182
  184. ksadk/runtime/executor.py +144 -3
  185. ksadk/runtime/factory.py +193 -7
  186. ksadk/runtime/hosted_finalizer.py +268 -0
  187. ksadk/runtime/launch.py +14 -1
  188. ksadk/runtime/preprocessing.py +25 -3
  189. ksadk/runtime/runner_adapter.py +288 -508
  190. ksadk/runtime/usage.py +33 -0
  191. ksadk/sandbox/backends/e2b.py +35 -2
  192. ksadk/server/composition.py +8 -0
  193. ksadk/server/factory.py +69 -6
  194. ksadk/server/routes/kernel_ingress.py +258 -0
  195. ksadk/server/routes/openai_compat.py +88 -8
  196. ksadk/server/routes/projection.py +35 -20
  197. ksadk/server/routes/run.py +94 -0
  198. ksadk/server/routes/sessions.py +2 -0
  199. ksadk/server/routes/streaming.py +5 -2
  200. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  201. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
  202. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  203. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  204. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  205. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  206. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  207. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  208. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  209. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  210. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  211. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  212. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  213. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  214. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  215. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  216. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  217. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  218. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  219. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  220. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  221. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  222. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  223. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  224. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  225. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  226. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  227. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  228. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  229. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  230. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  231. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  232. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  233. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  234. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  235. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  236. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
  237. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  238. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
  239. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
  240. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
  241. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
  242. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
  243. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
  244. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
  245. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
  246. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
  247. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
  248. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
  249. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
  250. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
  251. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
  252. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
  253. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
  254. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
  255. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
  256. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
  257. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-ngtN0DJB.js} +1 -1
  258. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  259. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  260. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  261. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  262. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  263. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  264. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  265. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  266. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  267. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  268. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  269. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  270. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  271. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  272. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  273. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-BHjG8b-J.js} +1 -1
  274. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  275. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  276. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  277. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  278. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  279. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  280. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  281. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  282. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  283. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  284. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  285. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  286. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  287. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  288. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  289. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  290. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  291. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  292. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  293. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  294. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  295. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  296. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  297. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  298. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  299. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  300. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  301. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  302. ksadk/server/static/index.html +2 -2
  303. ksadk/sessions/__init__.py +26 -9
  304. ksadk/sessions/_local_service_sync.py +688 -0
  305. ksadk/sessions/_local_tables.py +21 -0
  306. ksadk/sessions/_postgres_schema.py +305 -0
  307. ksadk/sessions/_postgres_tables.py +15 -0
  308. ksadk/sessions/base.py +80 -1
  309. ksadk/sessions/in_memory.py +53 -2
  310. ksadk/sessions/local_service.py +63 -604
  311. ksadk/sessions/postgres_service.py +58 -148
  312. ksadk/sessions/resilient.py +35 -1
  313. ksadk/studio/api.py +577 -25
  314. ksadk/studio/api_contracts.py +114 -5
  315. ksadk/studio/api_memory_routes.py +82 -0
  316. ksadk/studio/authoring.py +252 -27
  317. ksadk/studio/authoring_coordinator.py +799 -67
  318. ksadk/studio/builder.py +88 -11
  319. ksadk/studio/capabilities.py +17 -0
  320. ksadk/studio/cloud.py +1916 -95
  321. ksadk/studio/codex_agent_service.py +125 -14
  322. ksadk/studio/codex_authoring.py +469 -0
  323. ksadk/studio/codex_builder.py +138 -25
  324. ksadk/studio/codex_manifest.py +51 -22
  325. ksadk/studio/codex_run.py +46 -3
  326. ksadk/studio/compiler.py +1 -0
  327. ksadk/studio/contracts.py +114 -3
  328. ksadk/studio/event_store.py +25 -95
  329. ksadk/studio/framework_run.py +231 -3
  330. ksadk/studio/hosted_kernel.py +317 -0
  331. ksadk/studio/manifest_resolver.py +131 -0
  332. ksadk/studio/model_client.py +95 -9
  333. ksadk/studio/model_profile_service.py +1 -1
  334. ksadk/studio/operations.py +37 -5
  335. ksadk/studio/otel_trace.py +348 -42
  336. ksadk/studio/pcm_memory.py +85 -0
  337. ksadk/studio/repository.py +23 -2
  338. ksadk/studio/resource_catalog.py +43 -0
  339. ksadk/studio/run_service.py +563 -137
  340. ksadk/studio/runtime_source.py +42 -16
  341. ksadk/studio/service.py +1180 -72
  342. ksadk/studio/shared_web.py +32 -22
  343. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  344. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  345. ksadk/studio/static/index.html +2 -2
  346. ksadk/studio/templates.py +100 -8
  347. ksadk/studio/validator.py +19 -0
  348. ksadk/studio/workspace.py +30 -32
  349. ksadk/tracing/setup.py +304 -3
  350. ksadk/version.py +1 -1
  351. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  352. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  353. ksadk/events/parser.py +0 -191
  354. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  355. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  356. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  357. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  358. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  359. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  360. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  361. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  362. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  363. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  364. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  365. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  366. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  367. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  368. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  369. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  370. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  371. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  372. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  373. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  374. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  375. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  376. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  377. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  378. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  379. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  380. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  381. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  382. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  383. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  384. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  385. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  386. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  387. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  388. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  389. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  390. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  391. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  392. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  393. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  394. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  395. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  396. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  397. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  398. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  399. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  400. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  401. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  402. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  404. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  405. ksadk/studio/evaluation.py +0 -192
  406. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  407. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  408. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
  409. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  410. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  411. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
ksadk/api/client.py CHANGED
@@ -4,6 +4,7 @@ AgentEngine Server API 客户端
4
4
  支持 AWS V4 签名认证,用于通过 KOP 网关访问 AgentEngine Server。
5
5
  """
6
6
 
7
+ import asyncio
7
8
  import json
8
9
  import logging
9
10
  import mimetypes
@@ -14,7 +15,7 @@ import uuid
14
15
  from contextlib import contextmanager
15
16
  from dataclasses import dataclass
16
17
  from pathlib import Path
17
- from typing import Any, Callable, Dict, Iterator, Optional, Sequence
18
+ from typing import Any, AsyncIterator, Callable, Dict, Iterator, Optional, Sequence
18
19
  from urllib.parse import quote, unquote, urlparse, urlsplit
19
20
 
20
21
  import requests
@@ -36,6 +37,69 @@ class AttachmentContent:
36
37
  display_name: str
37
38
 
38
39
 
40
+ def _next_stream_chunk(iterator: Iterator[bytes]) -> bytes | None:
41
+ """Read one non-empty requests chunk without leaking StopIteration to asyncio."""
42
+
43
+ while True:
44
+ try:
45
+ chunk = next(iterator)
46
+ except StopIteration:
47
+ return None
48
+ if chunk:
49
+ return chunk
50
+
51
+
52
+ class AgentEngineSSEStream(AsyncIterator[bytes]):
53
+ """Async owner for one dedicated blocking requests SSE connection."""
54
+
55
+ def __init__(self, response: requests.Response, session: requests.Session) -> None:
56
+ self._response: requests.Response | None = response
57
+ self._session: requests.Session | None = session
58
+ # Read SSE as logical lines with the smallest requests read size. A
59
+ # fixed 8 KiB ``iter_content`` block makes short runs appear
60
+ # non-streaming, while ``chunk_size=None`` waits for EOF on urllib3.
61
+ # ``iter_lines`` performs the byte-at-a-time buffering inside the
62
+ # blocking worker and yields complete lines, avoiding one thread hop
63
+ # per byte. Re-add the delimiter so downstream SSE parsers keep their
64
+ # normal framing, including the blank line between events.
65
+ self._chunks = (line + b"\n" for line in response.iter_lines(chunk_size=1))
66
+ self._closed = False
67
+
68
+ def __aiter__(self) -> "AgentEngineSSEStream":
69
+ return self
70
+
71
+ async def __anext__(self) -> bytes:
72
+ if self._closed:
73
+ raise StopAsyncIteration
74
+ try:
75
+ chunk = await asyncio.to_thread(_next_stream_chunk, self._chunks)
76
+ except BaseException:
77
+ await self.aclose()
78
+ raise
79
+ if chunk is None:
80
+ await self.aclose()
81
+ raise StopAsyncIteration
82
+ return chunk
83
+
84
+ async def aclose(self) -> None:
85
+ if self._closed:
86
+ return
87
+ self._closed = True
88
+ response, session = self._response, self._session
89
+ self._response = None
90
+ self._session = None
91
+
92
+ def close_transport() -> None:
93
+ try:
94
+ if response is not None:
95
+ response.close()
96
+ finally:
97
+ if session is not None:
98
+ session.close()
99
+
100
+ await asyncio.to_thread(close_transport)
101
+
102
+
39
103
  class DryRunExit(Exception):
40
104
  """DryRun 模式退出异常。"""
41
105
 
@@ -127,7 +191,16 @@ class AgentEngineClient:
127
191
  logger.debug("AgentEngineClient: No credentials, signing disabled")
128
192
 
129
193
  self._session: Optional[requests.Session] = None
194
+ # The public client keeps synchronous ``requests`` transport for CLI
195
+ # compatibility. Async callers (notably Studio's FastAPI process)
196
+ # must not run that transport on the event-loop thread, and the shared
197
+ # requests.Session must not be used by several worker threads at once.
198
+ self._async_action_lock = asyncio.Lock()
130
199
  self._http_error_log_suppressors: list[HttpErrorLogSuppressor] = []
200
+ # A Server Action can be deployed before the external KOP publication
201
+ # finishes. Remember that result per client so an approval retry does
202
+ # not repeatedly hit the known-unpublished control-plane route.
203
+ self._unpublished_kop_actions: set[str] = set()
131
204
  # 反查身份的实例缓存(避免同会话重复调 IAM);None=未尝试,ResolvedIdentity|None=已反查
132
205
  self._resolved_identity: Any = None
133
206
  self._identity_resolve_attempted: bool = False
@@ -708,6 +781,17 @@ class AgentEngineClient:
708
781
  self._session.close()
709
782
  self._session = None
710
783
 
784
+ async def _action_async(
785
+ self,
786
+ action: str,
787
+ params: Optional[Dict[str, Any]] = None,
788
+ **kwargs: Any,
789
+ ) -> Dict[str, Any]:
790
+ """Run the legacy blocking Action transport without freezing an event loop."""
791
+
792
+ async with self._async_action_lock:
793
+ return await asyncio.to_thread(self._action, action, params, **kwargs)
794
+
711
795
  async def __aenter__(self):
712
796
  return self
713
797
 
@@ -912,6 +996,83 @@ class AgentEngineClient:
912
996
  )
913
997
  return AgentEngineAPIError(response.status_code, message)
914
998
 
999
+ @staticmethod
1000
+ def _is_unregistered_kop_action(error: AgentEngineAPIError, action: str) -> bool:
1001
+ """Return whether KOP rejected an otherwise valid Server Action.
1002
+
1003
+ Public Action publication is an infrastructure step independent of a
1004
+ Server rollout. During that window the per-Agent Gateway route is
1005
+ already authenticated and still forwards the exact same Action to
1006
+ Server admission, so callers can safely use it as the data-plane
1007
+ fallback instead of losing an approval response.
1008
+ """
1009
+
1010
+ message = str(error.message or "").strip().lower()
1011
+ return (
1012
+ error.code == 400
1013
+ and f"action {action.lower()}" in message
1014
+ and "not valid for this web service" in message
1015
+ )
1016
+
1017
+ def _runtime_action(
1018
+ self,
1019
+ *,
1020
+ access: Dict[str, Any],
1021
+ action: str,
1022
+ params: Dict[str, Any],
1023
+ ) -> Dict[str, Any]:
1024
+ endpoint = str(access.get("endpoint") or "").strip().rstrip("/")
1025
+ api_key = str(access.get("api_key") or "").strip()
1026
+ if not endpoint or not api_key:
1027
+ raise AgentEngineAPIError(404, "Agent runtime access is not ready")
1028
+ response = self._get_session().request(
1029
+ method="POST",
1030
+ url=f"{endpoint}/agentengine/api/v1/{action}",
1031
+ headers={"Authorization": f"Bearer {api_key}"},
1032
+ json=params,
1033
+ timeout=self.timeout,
1034
+ verify=self._ssl_verify_enabled(),
1035
+ )
1036
+ if response.status_code >= 400:
1037
+ raise self._workspace_runtime_error(response)
1038
+ try:
1039
+ result = response.json()
1040
+ except Exception as exc:
1041
+ raise AgentEngineAPIError(502, "Runtime Action returned invalid JSON") from exc
1042
+ if not isinstance(result, dict):
1043
+ raise AgentEngineAPIError(502, "Runtime Action returned a non-object payload")
1044
+ code = result.get("Code", 0)
1045
+ if code != 0:
1046
+ raise AgentEngineAPIError(
1047
+ code,
1048
+ str(result.get("Message") or "Unknown API error"),
1049
+ details={
1050
+ "request_id": result.get("RequestId"),
1051
+ "action": result.get("Action") or action,
1052
+ },
1053
+ )
1054
+ data = result.get("Data") if result.get("Data") is not None else result
1055
+ normalized = self._to_snake_case(data)
1056
+ if not isinstance(normalized, dict):
1057
+ raise AgentEngineAPIError(502, "Runtime Action returned non-object Data")
1058
+ return normalized
1059
+
1060
+ async def _runtime_action_for_agent(
1061
+ self,
1062
+ *,
1063
+ agent_id: str,
1064
+ action: str,
1065
+ params: Dict[str, Any],
1066
+ ) -> Dict[str, Any]:
1067
+ detail = await self.get_agent(agent_id, include_api_key=True)
1068
+ access = self._extract_runtime_access(detail)
1069
+ return await asyncio.to_thread(
1070
+ self._runtime_action,
1071
+ access=access,
1072
+ action=action,
1073
+ params=params,
1074
+ )
1075
+
915
1076
  @staticmethod
916
1077
  def _compact_params(params: Dict[str, Any] | None) -> Dict[str, Any]:
917
1078
  return {key: value for key, value in (params or {}).items() if value is not None}
@@ -1310,8 +1471,45 @@ class AgentEngineClient:
1310
1471
  payload[key] = text
1311
1472
  return payload
1312
1473
 
1474
+ @staticmethod
1475
+ def _managed_runtime_config_payload(data: Dict[str, Any]) -> Dict[str, Any]:
1476
+ """Build the public declaration accepted by Server Create/UpdateAgent.
1477
+
1478
+ ``runtime_config`` remains readable for older SDK callers, but it is a
1479
+ resolved read-model. New callers must send ``managed_runtime_config``
1480
+ so retries carry the complete YAML declaration Server needs to resolve
1481
+ a compatible immutable runtime image.
1482
+ """
1483
+ declaration = data.get("managed_runtime_config")
1484
+ if isinstance(declaration, dict):
1485
+ manifest = str(declaration.get("manifest") or "").strip()
1486
+ runtime_name = declaration.get("runtime_name")
1487
+ runtime_version = declaration.get("runtime_version")
1488
+ manifest_sha256 = declaration.get("manifest_sha256")
1489
+ else:
1490
+ legacy = data.get("runtime_config") or {}
1491
+ manifest = str(legacy.get("manifest") or "").strip()
1492
+ runtime_name = legacy.get("name")
1493
+ runtime_version = legacy.get("version")
1494
+ manifest_sha256 = legacy.get("manifest_sha256")
1495
+ if not manifest:
1496
+ raise ValueError("ManagedRuntime requires managed_runtime_config.manifest")
1497
+ payload: Dict[str, Any] = {
1498
+ "Manifest": manifest,
1499
+ "RuntimeName": runtime_name,
1500
+ "RuntimeVersion": runtime_version,
1501
+ }
1502
+ if manifest_sha256:
1503
+ payload["ManifestSHA256"] = manifest_sha256
1504
+ return payload
1505
+
1313
1506
  async def create_agent(self, data: Dict[str, Any]) -> Dict[str, Any]:
1314
- """创建 Agent (通过 CreateAgentProduct 走订单流程)"""
1507
+ """Create an Agent through the established order workflow.
1508
+
1509
+ The control plane invokes the existing ``CreateAgent`` callback after
1510
+ ``CreateAgentProduct``. Calling it a second time from Studio races
1511
+ that callback and can create an inconsistent lifecycle result.
1512
+ """
1315
1513
  framework = self._normalize_framework_name(data.get("framework"))
1316
1514
  params = {
1317
1515
  "Name": data.get("name"),
@@ -1357,7 +1555,7 @@ class AgentEngineClient:
1357
1555
  "IamRole": data.get("iam_role", "KsyunAgentEngineDefaultRole"),
1358
1556
  }
1359
1557
 
1360
- if params["DeploymentType"] in {"Code", "ManagedRuntime"}:
1558
+ if params["DeploymentType"] == "Code":
1361
1559
  ks3 = data.get("ks3", {})
1362
1560
  params["CodeConfig"] = {
1363
1561
  "Path": data.get("artifact_path", ""),
@@ -1365,14 +1563,11 @@ class AgentEngineClient:
1365
1563
  "SecretKey": ks3.get("secret_key"),
1366
1564
  "Region": self._normalize_payload_region(ks3.get("region", "cn-beijing-6")),
1367
1565
  "Bucket": ks3.get("bucket"),
1566
+ "Command": data.get("code_command"),
1567
+ "Checksum": data.get("code_checksum"),
1368
1568
  }
1369
- if params["DeploymentType"] == "ManagedRuntime":
1370
- runtime_config = data.get("runtime_config") or {}
1371
- params["RuntimeConfig"] = {
1372
- "Name": runtime_config.get("name"),
1373
- "Version": runtime_config.get("version"),
1374
- "ManifestSha256": runtime_config.get("manifest_sha256"),
1375
- }
1569
+ elif params["DeploymentType"] == "ManagedRuntime":
1570
+ params["ManagedRuntimeConfig"] = self._managed_runtime_config_payload(data)
1376
1571
  else:
1377
1572
  ic = data.get("image_credential", {}) or {}
1378
1573
  artifact = (data.get("artifact_path", "") or "").strip()
@@ -1387,8 +1582,18 @@ class AgentEngineClient:
1387
1582
  else:
1388
1583
  env_vars = []
1389
1584
 
1585
+ # Keep create and update semantics aligned. In particular, an
1586
+ # explicit ``--no-observability`` must not be silently rewritten to
1587
+ # true while the order is being created.
1588
+ observability = data.get("observability")
1589
+ if isinstance(observability, dict) and "langfuse_enabled" in observability:
1590
+ enable_observability = bool(observability.get("langfuse_enabled"))
1591
+ elif "enable_observability" in data:
1592
+ enable_observability = bool(data.get("enable_observability"))
1593
+ else:
1594
+ enable_observability = True
1390
1595
  advanced = {
1391
- "EnableObservability": True,
1596
+ "EnableObservability": enable_observability,
1392
1597
  "EnvironmentVariables": env_vars,
1393
1598
  }
1394
1599
  inbound_identity_auth = data.get("inbound_identity_auth")
@@ -1399,7 +1604,21 @@ class AgentEngineClient:
1399
1604
  advanced["ProjectId"] = project_id
1400
1605
  params["Advanced"] = advanced
1401
1606
 
1402
- return self._action("CreateAgentProduct", params)
1607
+ # ManagedRuntime is an already-paid, platform-owned YAML runtime. It
1608
+ # has no Code/Container order callback to materialize later, so use
1609
+ # the existing CreateAgent action to create its Agent/Runtime now.
1610
+ # Code and Container keep the established CreateAgentProduct flow.
1611
+ action = (
1612
+ "CreateAgent"
1613
+ if params["DeploymentType"] == "ManagedRuntime"
1614
+ else "CreateAgentProduct"
1615
+ )
1616
+ if action == "CreateAgent":
1617
+ # CreateAgent is also used as an order callback and therefore
1618
+ # requires an InstanceId. A declarative runtime has no order to
1619
+ # allocate one for us, so the SDK supplies a stable request UUID.
1620
+ params["InstanceId"] = str(data.get("instance_id") or uuid.uuid4())
1621
+ return self._action(action, params)
1403
1622
 
1404
1623
  async def get_agent(
1405
1624
  self,
@@ -1639,7 +1858,9 @@ class AgentEngineClient:
1639
1858
  if data.get("description"):
1640
1859
  params["Description"] = data["description"]
1641
1860
 
1642
- if data.get("artifact_path"):
1861
+ if artifact_type == "ManagedRuntime":
1862
+ params["ManagedRuntimeConfig"] = self._managed_runtime_config_payload(data)
1863
+ elif data.get("artifact_path"):
1643
1864
  artifact = (data.get("artifact_path", "") or "").strip()
1644
1865
  if (artifact_type or "").lower() == "container":
1645
1866
  ic = data.get("image_credential", {}) or {}
@@ -1655,14 +1876,9 @@ class AgentEngineClient:
1655
1876
  "SecretKey": ks3.get("secret_key"),
1656
1877
  "Region": self._normalize_payload_region(ks3.get("region", "cn-beijing-6")),
1657
1878
  "Bucket": ks3.get("bucket"),
1879
+ "Command": data.get("code_command"),
1880
+ "Checksum": data.get("code_checksum"),
1658
1881
  }
1659
- if artifact_type == "ManagedRuntime":
1660
- runtime_config = data.get("runtime_config") or {}
1661
- params["RuntimeConfig"] = {
1662
- "Name": runtime_config.get("name"),
1663
- "Version": runtime_config.get("version"),
1664
- "ManifestSha256": runtime_config.get("manifest_sha256"),
1665
- }
1666
1882
 
1667
1883
  if data.get("resources"):
1668
1884
  params["Resource"] = {
@@ -1729,26 +1945,137 @@ class AgentEngineClient:
1729
1945
  self, agent_id: str, user_id: Optional[str] = None, expires_hours: int = 24
1730
1946
  ) -> Dict[str, Any]:
1731
1947
  """创建会话"""
1732
- return self._action(
1948
+ return await self._action_async(
1733
1949
  "CreateSession", {"AgentId": agent_id, "UserId": user_id, "ExpiresHours": expires_hours}
1734
1950
  )
1735
1951
 
1736
1952
  async def get_session(self, session_id: str) -> Dict[str, Any]:
1737
1953
  """获取会话详情"""
1738
- return self._action("GetSession", {"Id": session_id})
1954
+ return await self._action_async("GetSession", {"Id": session_id})
1739
1955
 
1740
1956
  async def list_sessions(self, agent_id: str, page: int = 1, size: int = 20) -> Dict[str, Any]:
1741
1957
  """列出会话"""
1742
- return self._action("ListSessions", {"AgentId": agent_id, "Page": page, "PageSize": size})
1958
+ return await self._action_async(
1959
+ "ListSessions", {"AgentId": agent_id, "Page": page, "PageSize": size}
1960
+ )
1743
1961
 
1744
1962
  async def delete_session(self, session_id: str) -> bool:
1745
1963
  """删除会话"""
1746
1964
  try:
1747
- self._action("DeleteSession", {"Id": session_id})
1748
- return True
1965
+ result = await self._action_async("DeleteSession", {"Id": session_id})
1966
+ # Server may accept the request but retain the control-plane
1967
+ # record when runtime-side deletion is still pending. Do not
1968
+ # present that state as a completed delete to Studio callers.
1969
+ return bool(result.get("deleted"))
1749
1970
  except Exception:
1750
1971
  return False
1751
1972
 
1973
+ async def list_session_messages(
1974
+ self,
1975
+ *,
1976
+ agent_id: str,
1977
+ session_id: str,
1978
+ after_seq_id: int | None = None,
1979
+ before_seq_id: int | None = None,
1980
+ cursor_source: str | None = None,
1981
+ limit: int = 50,
1982
+ include_reasoning: bool = False,
1983
+ include_tool_events: bool = False,
1984
+ include_attachments: bool = True,
1985
+ ) -> Dict[str, Any]:
1986
+ """Read the Server-owned message projection for one cloud session.
1987
+
1988
+ This is intentionally an AgentEngine Action client method rather than
1989
+ a Hosted UI shortcut. Local Studio can retain AK/SK in its backend,
1990
+ call the same authenticated Server read path as the cloud console, and
1991
+ keep cursor ownership on the Server/Runtime boundary.
1992
+ """
1993
+
1994
+ params: Dict[str, Any] = {
1995
+ "AgentId": agent_id,
1996
+ "SessionId": session_id,
1997
+ "Limit": limit,
1998
+ "IncludeReasoning": include_reasoning,
1999
+ "IncludeToolEvents": include_tool_events,
2000
+ "IncludeAttachments": include_attachments,
2001
+ }
2002
+ if after_seq_id is not None:
2003
+ params["AfterSeqId"] = after_seq_id
2004
+ if before_seq_id is not None:
2005
+ params["BeforeSeqId"] = before_seq_id
2006
+ if cursor_source is not None:
2007
+ params["CursorSource"] = cursor_source
2008
+ return await self._action_async("ListSessionMessages", params)
2009
+
2010
+ async def list_session_events(
2011
+ self,
2012
+ *,
2013
+ agent_id: str,
2014
+ session_id: str,
2015
+ after_seq_id: int | None = None,
2016
+ limit: int = 100,
2017
+ ) -> Dict[str, Any]:
2018
+ """Read canonical cloud session events through the Server Action API."""
2019
+
2020
+ params: Dict[str, Any] = {
2021
+ "AgentId": agent_id,
2022
+ "SessionId": session_id,
2023
+ "Limit": limit,
2024
+ }
2025
+ if after_seq_id is not None:
2026
+ params["AfterSeqId"] = after_seq_id
2027
+ return await self._action_async("ListSessionEvents", params)
2028
+
2029
+ async def submit_interaction(
2030
+ self,
2031
+ *,
2032
+ agent_id: str,
2033
+ session_id: str,
2034
+ run_id: str,
2035
+ interaction_id: str,
2036
+ expected_revision: int,
2037
+ action: str,
2038
+ response: Dict[str, Any] | None = None,
2039
+ idempotency_key: str,
2040
+ ) -> Dict[str, Any]:
2041
+ """Submit one Interaction/v1 response via Server admission.
2042
+
2043
+ The caller supplies only public interaction fields. Tenant,
2044
+ principal, AgentInstance and permit remain Server-derived.
2045
+ """
2046
+
2047
+ params = {
2048
+ "AgentId": agent_id,
2049
+ "SessionId": session_id,
2050
+ "RunId": run_id,
2051
+ "InteractionId": interaction_id,
2052
+ "ExpectedRevision": expected_revision,
2053
+ # ``Action`` is reserved by the KOP envelope for the API operation
2054
+ # name. Keep the SDK argument ergonomic while using an
2055
+ # unambiguous public wire field.
2056
+ "InteractionAction": action,
2057
+ "Response": response or {},
2058
+ "IdempotencyKey": idempotency_key,
2059
+ }
2060
+ if "SubmitInteraction" not in self._unpublished_kop_actions:
2061
+ try:
2062
+ return await self._action_async("SubmitInteraction", params)
2063
+ except AgentEngineAPIError as exc:
2064
+ if not self._is_unregistered_kop_action(exc, "SubmitInteraction"):
2065
+ raise
2066
+ self._unpublished_kop_actions.add("SubmitInteraction")
2067
+ if "SubmitInteraction" in self._unpublished_kop_actions:
2068
+ # KOP publication can lag the Server/Gateway rollout. The
2069
+ # per-Agent endpoint is authenticated with the API key returned by
2070
+ # signed GetAgent and still traverses Gateway -> Server admission;
2071
+ # it never submits directly to Runtime.
2072
+ return await self._runtime_action_for_agent(
2073
+ agent_id=agent_id,
2074
+ action="SubmitInteraction",
2075
+ params=params,
2076
+ )
2077
+ raise AssertionError("unreachable SubmitInteraction transport state")
2078
+
1752
2079
  async def list_workspace_files(
1753
2080
  self,
1754
2081
  *,
@@ -2200,17 +2527,188 @@ class AgentEngineClient:
2200
2527
  # ===== Chat Actions =====
2201
2528
 
2202
2529
  async def chat(
2203
- self, agent_id: str, message: str, session_id: Optional[str] = None
2530
+ self,
2531
+ agent_id: str,
2532
+ message: Any,
2533
+ session_id: Optional[str] = None,
2534
+ *,
2535
+ model: Optional[str] = None,
2536
+ model_options: Optional[Dict[str, Any]] = None,
2537
+ tool_approval_mode: Optional[str] = None,
2538
+ collaboration_mode: Optional[str] = None,
2539
+ goal_objective: Optional[str] = None,
2204
2540
  ) -> Dict[str, Any]:
2205
2541
  """调用 Agent"""
2206
2542
  params = {
2207
2543
  "AgentId": agent_id,
2544
+ # The public KOP contract validates ApiFormat before forwarding the
2545
+ # request to Server. Keep this legacy string helper on the chat
2546
+ # completions shape instead of relying on Server's newer Responses
2547
+ # default, otherwise KOP rejects an otherwise valid request.
2548
+ "ApiFormat": "chat_completions",
2208
2549
  "Messages": [{"role": "user", "content": message}],
2209
2550
  "Stream": False,
2210
2551
  }
2211
2552
  if session_id:
2212
2553
  params["SessionId"] = session_id
2213
- return self._action("RunAgent", params)
2554
+ if model:
2555
+ params["Model"] = model
2556
+ if model_options:
2557
+ params["ModelOptions"] = dict(model_options)
2558
+ execution_metadata: Dict[str, Any] = {}
2559
+ if tool_approval_mode:
2560
+ execution_metadata["tool_approval_mode"] = tool_approval_mode
2561
+ if collaboration_mode:
2562
+ execution_metadata["collaboration_mode"] = collaboration_mode
2563
+ if goal_objective:
2564
+ execution_metadata["goal_objective"] = goal_objective
2565
+ if execution_metadata:
2566
+ params["Metadata"] = {"agentengine": execution_metadata}
2567
+ return await self._action_async("RunAgent", params)
2568
+
2569
+ def _open_chat_stream(self, params: Dict[str, Any]) -> AgentEngineSSEStream:
2570
+ """Open RunAgent SSE synchronously in a worker-owned requests session."""
2571
+
2572
+ path = "/agentengine/api/v1/RunAgent"
2573
+ _kop_mode, headers, full_url = self._build_action_request_target(path, "RunAgent")
2574
+ body_str = json.dumps(params, ensure_ascii=False)
2575
+ if self.dry_run:
2576
+ # Reuse the established dry-run contract, which raises DryRunExit
2577
+ # with the signed request rather than opening a socket.
2578
+ self._request("POST", path, params)
2579
+ raise AssertionError("dry-run request unexpectedly returned")
2580
+
2581
+ session = requests.Session()
2582
+ response: requests.Response | None = None
2583
+ retried_inner_endpoint = False
2584
+ try:
2585
+ while True:
2586
+ response = session.request(
2587
+ method="POST",
2588
+ url=full_url,
2589
+ data=body_str.encode("utf-8"),
2590
+ headers=headers,
2591
+ auth=self._auth.get_auth(),
2592
+ # A foreground Agent turn can legitimately spend minutes
2593
+ # reasoning before its next SSE chunk. Bound connection
2594
+ # establishment, not the lifetime of an admitted stream.
2595
+ timeout=(self.timeout, None),
2596
+ verify=self._ssl_verify_enabled(),
2597
+ stream=True,
2598
+ )
2599
+ content_type = str(response.headers.get("content-type") or "").lower()
2600
+ if response.status_code < 400 and "text/event-stream" in content_type:
2601
+ return AgentEngineSSEStream(response, session)
2602
+
2603
+ resp_text = response.text or ""
2604
+ details = self._extract_http_error_details(resp_text)
2605
+ details.setdefault("http_status", response.status_code)
2606
+ if response.status_code < 400:
2607
+ details["content_type"] = content_type or "<missing>"
2608
+ try:
2609
+ envelope = json.loads(resp_text)
2610
+ except (TypeError, ValueError):
2611
+ envelope = {}
2612
+ if not isinstance(envelope, dict):
2613
+ envelope = {}
2614
+ envelope_code = envelope.get("Code")
2615
+ error_code = (
2616
+ envelope_code
2617
+ if envelope_code not in {None, 0, "0"}
2618
+ else details.get("remote_error_code") or 502
2619
+ )
2620
+ message = (
2621
+ str(
2622
+ details.get("remote_error_message")
2623
+ or details.get("message")
2624
+ or ""
2625
+ ).strip()
2626
+ or "RunAgent stream did not return text/event-stream"
2627
+ )
2628
+ raise AgentEngineAPIError(
2629
+ error_code,
2630
+ message,
2631
+ details=details,
2632
+ )
2633
+ if not retried_inner_endpoint and self._can_retry_with_inner_aicp_endpoint(details):
2634
+ retried_inner_endpoint = True
2635
+ response.close()
2636
+ response = None
2637
+ self._switch_to_inner_aicp_endpoint()
2638
+ _kop_mode, headers, full_url = self._build_action_request_target(
2639
+ path, "RunAgent"
2640
+ )
2641
+ continue
2642
+
2643
+ self._log_http_error(
2644
+ method="POST",
2645
+ full_url=full_url,
2646
+ status_code=response.status_code,
2647
+ details=details,
2648
+ )
2649
+ message = (
2650
+ str(
2651
+ details.get("remote_error_message")
2652
+ or details.get("message")
2653
+ or ""
2654
+ ).strip()
2655
+ or resp_text
2656
+ )
2657
+ raise AgentEngineAPIError(
2658
+ response.status_code,
2659
+ message,
2660
+ details=details or None,
2661
+ )
2662
+ except BaseException:
2663
+ try:
2664
+ if response is not None:
2665
+ response.close()
2666
+ finally:
2667
+ session.close()
2668
+ raise
2669
+
2670
+ async def chat_stream(
2671
+ self,
2672
+ agent_id: str,
2673
+ message: Any,
2674
+ session_id: Optional[str] = None,
2675
+ *,
2676
+ model: Optional[str] = None,
2677
+ model_options: Optional[Dict[str, Any]] = None,
2678
+ tool_approval_mode: Optional[str] = None,
2679
+ collaboration_mode: Optional[str] = None,
2680
+ goal_objective: Optional[str] = None,
2681
+ ) -> AgentEngineSSEStream:
2682
+ """Open a signed foreground RunAgent SSE stream.
2683
+
2684
+ The upstream response is established before this method returns so an
2685
+ HTTP error remains a structured ``AgentEngineAPIError`` instead of a
2686
+ late exception after a downstream proxy has already emitted 200.
2687
+ """
2688
+
2689
+ params: Dict[str, Any] = {
2690
+ "AgentId": agent_id,
2691
+ "ApiFormat": "chat_completions",
2692
+ "Messages": [{"role": "user", "content": message}],
2693
+ "Stream": True,
2694
+ "Background": False,
2695
+ }
2696
+ if session_id:
2697
+ params["SessionId"] = session_id
2698
+ if model:
2699
+ params["Model"] = model
2700
+ if model_options:
2701
+ params["ModelOptions"] = dict(model_options)
2702
+ execution_metadata: Dict[str, Any] = {}
2703
+ if tool_approval_mode:
2704
+ execution_metadata["tool_approval_mode"] = tool_approval_mode
2705
+ if collaboration_mode:
2706
+ execution_metadata["collaboration_mode"] = collaboration_mode
2707
+ if goal_objective:
2708
+ execution_metadata["goal_objective"] = goal_objective
2709
+ if execution_metadata:
2710
+ params["Metadata"] = {"agentengine": execution_metadata}
2711
+ return await asyncio.to_thread(self._open_chat_stream, params)
2214
2712
 
2215
2713
  # ===== Version Actions =====
2216
2714