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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
  2. agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
  3. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +2 -0
  5. ksadk/a2a/_space_client_events.py +381 -0
  6. ksadk/a2a/bootstrap.py +0 -2
  7. ksadk/a2a/card.py +6 -111
  8. ksadk/a2a/control_plane.py +239 -1
  9. ksadk/a2a/event_adapter.py +156 -64
  10. ksadk/a2a/executor.py +195 -172
  11. ksadk/a2a/routes.py +12 -5
  12. ksadk/a2a/server.py +1 -8
  13. ksadk/a2a/service_env.py +33 -0
  14. ksadk/a2a/space_client.py +43 -349
  15. ksadk/a2a_card.py +101 -0
  16. ksadk/a2ui/core.py +222 -53
  17. ksadk/agui/_agent_helpers.py +243 -0
  18. ksadk/agui/a2ui_projection.py +12 -5
  19. ksadk/agui/agent.py +474 -275
  20. ksadk/agui/config.py +11 -5
  21. ksadk/agui/routes.py +7 -15
  22. ksadk/api/client.py +530 -40
  23. ksadk/api/environment.py +27 -0
  24. ksadk/builders/code_builder.py +352 -53
  25. ksadk/builders/container_builder.py +71 -44
  26. ksadk/builders/framework_requirements.py +2 -1
  27. ksadk/builders/ks3_uploader.py +2 -2
  28. ksadk/builders/managed_runtime_builder.py +60 -28
  29. ksadk/cli/__init__.py +25 -0
  30. ksadk/cli/cmd_a2a.py +18 -31
  31. ksadk/cli/cmd_create.py +13 -26
  32. ksadk/cli/cmd_dashboard.py +15 -1
  33. ksadk/cli/cmd_deploy.py +28 -3
  34. ksadk/cli/cmd_eval.py +443 -0
  35. ksadk/cli/cmd_evalset.py +284 -0
  36. ksadk/cli/cmd_files.py +5 -1
  37. ksadk/cli/cmd_hermes.py +137 -163
  38. ksadk/cli/cmd_invoke.py +28 -38
  39. ksadk/cli/cmd_launch.py +12 -0
  40. ksadk/cli/cmd_managed_runtime.py +95 -0
  41. ksadk/cli/cmd_observe.py +85 -0
  42. ksadk/cli/cmd_openclaw.py +85 -479
  43. ksadk/cli/cmd_replay.py +28 -4
  44. ksadk/cli/cmd_run.py +29 -67
  45. ksadk/cli/cmd_studio.py +201 -0
  46. ksadk/cli/cmd_web.py +15 -6
  47. ksadk/cli/dry_run.py +2 -1
  48. ksadk/cli/env_options.py +83 -0
  49. ksadk/cli/global_options.py +3 -1
  50. ksadk/cli/hermes_env.py +151 -0
  51. ksadk/cli/invoke_payload.py +49 -0
  52. ksadk/cli/network_options.py +7 -5
  53. ksadk/cli/openclaw_env.py +458 -0
  54. ksadk/cli/runtime_bootstrap.py +51 -0
  55. ksadk/cli/ui.py +6 -0
  56. ksadk/cli/workflow_common.py +5 -5
  57. ksadk/codex/__init__.py +3 -3
  58. ksadk/codex/client.py +833 -49
  59. ksadk/codex/phase.py +1 -1
  60. ksadk/codex/runtime.py +720 -127
  61. ksadk/common/kop_client.py +232 -0
  62. ksadk/configs/__init__.py +1 -3
  63. ksadk/configs/env_registry.py +244 -45
  64. ksadk/configs/env_registry_pcm.py +181 -0
  65. ksadk/configs/env_var_spec.py +18 -0
  66. ksadk/configs/global_config.py +6 -1
  67. ksadk/configs/settings.py +5 -108
  68. ksadk/context_engine/__init__.py +98 -0
  69. ksadk/context_engine/assembler.py +176 -0
  70. ksadk/context_engine/baseline.py +419 -0
  71. ksadk/context_engine/cache_observability.py +228 -0
  72. ksadk/context_engine/capabilities.py +443 -0
  73. ksadk/context_engine/contributors.py +344 -0
  74. ksadk/context_engine/hosted_pipeline.py +417 -0
  75. ksadk/context_engine/models.py +117 -0
  76. ksadk/context_engine/planner.py +698 -0
  77. ksadk/context_engine/policies.py +319 -0
  78. ksadk/context_engine/projection.py +31 -0
  79. ksadk/context_engine/shadow_plan.py +266 -0
  80. ksadk/context_engine/tokenizer.py +164 -0
  81. ksadk/conversations/__init__.py +85 -94
  82. ksadk/conversations/context.py +126 -6
  83. ksadk/conversations/message_projection.py +292 -28
  84. ksadk/conversations/model_context.py +49 -3
  85. ksadk/conversations/runtime_compaction.py +207 -5
  86. ksadk/conversations/runtime_input.py +193 -3
  87. ksadk/conversations/runtime_invocation.py +81 -3
  88. ksadk/conversations/runtime_observability.py +157 -4
  89. ksadk/conversations/runtime_payloads.py +42 -0
  90. ksadk/conversations/runtime_preparation.py +280 -2
  91. ksadk/conversations/runtime_resume.py +71 -32
  92. ksadk/conversations/runtime_stream_events.py +94 -9
  93. ksadk/conversations/runtime_streaming.py +175 -22
  94. ksadk/conversations/semantic_summary.py +311 -1
  95. ksadk/conversations/session_lock.py +51 -0
  96. ksadk/deployment/env_forward.py +72 -0
  97. ksadk/deployment/managed_runtime.py +38 -0
  98. ksadk/deployment/manager.py +24 -8
  99. ksadk/deployment/providers/serverless.py +228 -92
  100. ksadk/evaluation/__init__.py +116 -0
  101. ksadk/evaluation/a2a_adapter.py +452 -0
  102. ksadk/evaluation/adapters.py +67 -0
  103. ksadk/evaluation/agent_eval_client.py +395 -0
  104. ksadk/evaluation/cloud_binding.py +80 -0
  105. ksadk/evaluation/cloud_converter.py +194 -0
  106. ksadk/evaluation/cloud_service.py +199 -0
  107. ksadk/evaluation/contracts.py +478 -0
  108. ksadk/evaluation/evalset.py +351 -0
  109. ksadk/evaluation/evaluators.py +627 -0
  110. ksadk/evaluation/evidence.py +258 -0
  111. ksadk/evaluation/executor.py +143 -0
  112. ksadk/evaluation/local_adapter.py +550 -0
  113. ksadk/evaluation/service_env.py +27 -0
  114. ksadk/evaluation/storage.py +68 -0
  115. ksadk/evaluation/studio_build_adapter.py +253 -0
  116. ksadk/evaluation/target.py +82 -0
  117. ksadk/events/__init__.py +13 -13
  118. ksadk/events/_v1_compat/__init__.py +1 -0
  119. ksadk/events/_v1_compat/models.py +299 -0
  120. ksadk/events/_v1_compat/parser.py +247 -0
  121. ksadk/events/_v1_compat/projection.py +753 -0
  122. ksadk/events/adapters/__init__.py +34 -0
  123. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  124. ksadk/events/adapters/_a2a_support.py +275 -0
  125. ksadk/events/adapters/_codex_interactions.py +375 -0
  126. ksadk/events/adapters/_codex_items.py +801 -0
  127. ksadk/events/adapters/_codex_validators.py +311 -0
  128. ksadk/events/adapters/_langgraph_support.py +785 -0
  129. ksadk/events/adapters/a2a.py +841 -0
  130. ksadk/events/adapters/adk.py +503 -0
  131. ksadk/events/adapters/codex.py +717 -0
  132. ksadk/events/adapters/langgraph.py +745 -0
  133. ksadk/events/canonical.py +440 -0
  134. ksadk/events/canonical_replay.py +497 -0
  135. ksadk/events/canonical_store.py +468 -0
  136. ksadk/events/cold_recovery.py +257 -0
  137. ksadk/events/content.py +89 -0
  138. ksadk/events/identity.py +86 -0
  139. ksadk/events/pipeline.py +455 -0
  140. ksadk/events/projections.py +66 -0
  141. ksadk/events/reducer.py +661 -0
  142. ksadk/events/replay.py +3 -36
  143. ksadk/events/runtime_event.py +20 -256
  144. ksadk/events/session_event.py +324 -0
  145. ksadk/events/store.py +3 -316
  146. ksadk/events/v1_compat.py +41 -0
  147. ksadk/harness/__init__.py +3 -2
  148. ksadk/harness/app.py +114 -123
  149. ksadk/harness/config.py +1 -1
  150. ksadk/harness/runtime.py +467 -0
  151. ksadk/hermes_terminal.py +5 -0
  152. ksadk/identity/resolver.py +4 -3
  153. ksadk/interaction/__init__.py +28 -0
  154. ksadk/interaction/contracts.py +136 -0
  155. ksadk/interaction/ledger.py +189 -0
  156. ksadk/interaction/provider.py +122 -0
  157. ksadk/interaction/providers/__init__.py +52 -0
  158. ksadk/interaction/providers/adk.py +40 -0
  159. ksadk/interaction/providers/codex.py +94 -0
  160. ksadk/interaction/providers/langgraph.py +58 -0
  161. ksadk/kernel/__init__.py +117 -0
  162. ksadk/kernel/authorization.py +258 -0
  163. ksadk/kernel/bootstrap.py +1074 -0
  164. ksadk/kernel/contract_fingerprints.py +61 -0
  165. ksadk/kernel/contracts.py +362 -0
  166. ksadk/kernel/control.py +219 -0
  167. ksadk/kernel/errors.py +79 -0
  168. ksadk/kernel/ingress.py +1102 -0
  169. ksadk/kernel/mapping.py +111 -0
  170. ksadk/kernel/memory_store.py +1133 -0
  171. ksadk/kernel/postgres_store.py +1756 -0
  172. ksadk/kernel/recovery.py +452 -0
  173. ksadk/kernel/runtime_identity.py +103 -0
  174. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  175. ksadk/kernel/sqlite_store.py +1410 -0
  176. ksadk/kernel/state.py +145 -0
  177. ksadk/kernel/store.py +232 -0
  178. ksadk/kernel/worker.py +953 -0
  179. ksadk/knowledge_base/client.py +22 -4
  180. ksadk/knowledge_base/service.py +32 -5
  181. ksadk/managed_a2a_card.py +160 -0
  182. ksadk/managed_runtime.py +16 -9
  183. ksadk/memory/__init__.py +61 -0
  184. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  185. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  186. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  187. ksadk/memory/adk/backends/sdk_ltm_backend.py +394 -5
  188. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  189. ksadk/memory/adk/long_term_memory.py +3 -2
  190. ksadk/memory/coordinator.py +461 -0
  191. ksadk/memory/events.py +202 -0
  192. ksadk/memory/extraction.py +228 -0
  193. ksadk/memory/ltm_backend_factory.py +16 -3
  194. ksadk/memory/models.py +316 -0
  195. ksadk/memory/policy.py +215 -0
  196. ksadk/memory/provider.py +47 -0
  197. ksadk/memory/provider_adapter.py +159 -0
  198. ksadk/memory/provider_resolver.py +71 -0
  199. ksadk/memory/providers/__init__.py +5 -0
  200. ksadk/memory/providers/local_sqlite.py +490 -0
  201. ksadk/memory/resolved_policy.py +145 -0
  202. ksadk/memory/service.py +198 -8
  203. ksadk/memory/tool.py +4 -0
  204. ksadk/model_proxy/bootstrap.py +16 -9
  205. ksadk/model_proxy/config.py +22 -1
  206. ksadk/model_proxy/detect.py +202 -9
  207. ksadk/model_proxy/namespace.py +67 -15
  208. ksadk/model_proxy/server.py +168 -6
  209. ksadk/model_proxy/transform.py +105 -3
  210. ksadk/observability/__init__.py +25 -0
  211. ksadk/observability/session_log.py +420 -0
  212. ksadk/observability/trajectory.py +105 -0
  213. ksadk/prompts/__init__.py +71 -0
  214. ksadk/prompts/compiler.py +215 -0
  215. ksadk/prompts/models.py +82 -0
  216. ksadk/prompts/projection.py +89 -0
  217. ksadk/prompts/resolved.py +137 -0
  218. ksadk/prompts/sources.py +233 -0
  219. ksadk/runners/_langgraph_runner_streams.py +822 -0
  220. ksadk/runners/adk_runner.py +14 -31
  221. ksadk/runners/base_runner.py +44 -3
  222. ksadk/runners/factory.py +3 -3
  223. ksadk/runners/langgraph_runner.py +252 -433
  224. ksadk/runners/utils/__init__.py +0 -10
  225. ksadk/runners/utils/loader.py +16 -0
  226. ksadk/runtime/__init__.py +67 -41
  227. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  228. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  229. ksadk/runtime/adapter.py +199 -16
  230. ksadk/runtime/conversation_execution.py +687 -0
  231. ksadk/runtime/executor.py +392 -0
  232. ksadk/runtime/factory.py +342 -0
  233. ksadk/runtime/framework_adapters.py +6 -12
  234. ksadk/runtime/hosted_finalizer.py +268 -0
  235. ksadk/runtime/launch.py +61 -0
  236. ksadk/runtime/preprocessing.py +49 -14
  237. ksadk/runtime/runner_adapter.py +330 -391
  238. ksadk/runtime/runner_loading.py +36 -0
  239. ksadk/runtime/usage.py +33 -0
  240. ksadk/sandbox/backends/e2b.py +36 -3
  241. ksadk/server/__init__.py +39 -4
  242. ksadk/server/app.py +18 -492
  243. ksadk/server/composition.py +36 -2
  244. ksadk/server/factory.py +210 -149
  245. ksadk/server/routes/common.py +15 -46
  246. ksadk/server/routes/control.py +13 -9
  247. ksadk/server/routes/kernel_ingress.py +258 -0
  248. ksadk/server/routes/misc.py +10 -33
  249. ksadk/server/routes/models.py +14 -6
  250. ksadk/server/routes/openai_compat.py +129 -27
  251. ksadk/server/routes/projection.py +84 -16
  252. ksadk/server/routes/run.py +347 -460
  253. ksadk/server/routes/sessions.py +37 -40
  254. ksadk/server/routes/streaming.py +52 -7
  255. ksadk/server/routes/workspace.py +54 -21
  256. ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  257. ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
  258. ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  259. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  260. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  261. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  262. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  263. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  264. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  265. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  266. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  267. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  268. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  269. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  270. ksadk/server/static/assets/{chunk-FMBD7UC4-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  271. ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  272. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  273. ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  274. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  275. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  276. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  277. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  278. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  279. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  280. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  281. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-CX3yotHq.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  282. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  283. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  284. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  285. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  286. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  287. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  288. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  289. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  290. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  291. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  292. ksadk/server/static/assets/{dist-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
  293. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  294. ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
  295. ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
  296. ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
  297. ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
  298. ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
  299. ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
  300. ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
  301. ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
  302. ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
  303. ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
  304. ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
  305. ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
  306. ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
  307. ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
  308. ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
  309. ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
  310. ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
  311. ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
  312. ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
  313. ksadk/server/static/assets/{dist-C99THtIA.js → dist-ngtN0DJB.js} +1 -1
  314. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  315. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  316. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  317. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  318. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  319. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  320. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  321. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  322. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  323. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  324. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  325. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  326. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  327. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  328. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  329. ksadk/server/static/assets/{linear-CvMBw9cA.js → linear-BHjG8b-J.js} +1 -1
  330. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  331. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-CSAQxEAe.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  332. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  333. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  334. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  335. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  336. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-CxIR4JXI.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  337. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  338. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  339. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  340. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  341. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  342. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  343. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  344. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  345. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  346. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  347. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  348. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  349. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  350. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  351. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-jqoYs3jQ.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  352. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  353. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  354. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  355. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  356. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  357. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  358. ksadk/server/static/index.html +2 -2
  359. ksadk/sessions/__init__.py +26 -9
  360. ksadk/sessions/_local_service_sync.py +688 -0
  361. ksadk/sessions/_local_tables.py +21 -0
  362. ksadk/sessions/_postgres_schema.py +305 -0
  363. ksadk/sessions/_postgres_tables.py +15 -0
  364. ksadk/sessions/base.py +80 -1
  365. ksadk/sessions/in_memory.py +53 -2
  366. ksadk/sessions/local_service.py +63 -604
  367. ksadk/sessions/postgres_service.py +58 -148
  368. ksadk/sessions/resilient.py +35 -1
  369. ksadk/skills/runtime/backends/e2b.py +1 -1
  370. ksadk/skills/service_client.py +13 -3
  371. ksadk/studio/__init__.py +5 -0
  372. ksadk/studio/agent_avatar_assets.py +120 -0
  373. ksadk/studio/agent_lifecycle.py +51 -0
  374. ksadk/studio/api.py +1598 -0
  375. ksadk/studio/api_catalog_routes.py +324 -0
  376. ksadk/studio/api_contracts.py +286 -0
  377. ksadk/studio/api_helpers.py +132 -0
  378. ksadk/studio/api_memory_routes.py +82 -0
  379. ksadk/studio/authoring.py +749 -0
  380. ksadk/studio/authoring_coordinator.py +1017 -0
  381. ksadk/studio/builder.py +397 -0
  382. ksadk/studio/capabilities.py +368 -0
  383. ksadk/studio/cloud.py +2099 -0
  384. ksadk/studio/codex_agent_service.py +694 -0
  385. ksadk/studio/codex_authoring.py +469 -0
  386. ksadk/studio/codex_builder.py +437 -0
  387. ksadk/studio/codex_manifest.py +307 -0
  388. ksadk/studio/codex_run.py +395 -0
  389. ksadk/studio/compiler.py +190 -0
  390. ksadk/studio/contracts.py +755 -0
  391. ksadk/studio/errors.py +47 -0
  392. ksadk/studio/event_store.py +214 -0
  393. ksadk/studio/framework_run.py +342 -0
  394. ksadk/studio/hosted_kernel.py +317 -0
  395. ksadk/studio/identifiers.py +33 -0
  396. ksadk/studio/manifest_resolver.py +131 -0
  397. ksadk/studio/mcp_runtime.py +229 -0
  398. ksadk/studio/model_client.py +629 -0
  399. ksadk/studio/model_profile_service.py +214 -0
  400. ksadk/studio/operations.py +275 -0
  401. ksadk/studio/otel_trace.py +1060 -0
  402. ksadk/studio/pagination.py +182 -0
  403. ksadk/studio/pcm_memory.py +85 -0
  404. ksadk/studio/python_tool_inspection.py +183 -0
  405. ksadk/studio/repository.py +327 -0
  406. ksadk/studio/resource_catalog.py +1260 -0
  407. ksadk/studio/run_service.py +1133 -0
  408. ksadk/studio/runtime_catalog.py +74 -0
  409. ksadk/studio/runtime_source.py +365 -0
  410. ksadk/studio/service.py +2249 -0
  411. ksadk/studio/shared_web.py +1004 -0
  412. ksadk/studio/skill_discovery.py +628 -0
  413. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  414. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  415. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  416. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  417. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  418. ksadk/studio/static/index.html +15 -0
  419. ksadk/studio/templates.py +722 -0
  420. ksadk/studio/validator.py +265 -0
  421. ksadk/studio/workspace.py +135 -0
  422. ksadk/tools/gateway.py +9 -0
  423. ksadk/toolsets/__init__.py +27 -1
  424. ksadk/toolsets/a2a.py +426 -0
  425. ksadk/tracing/__init__.py +19 -21
  426. ksadk/tracing/setup.py +317 -403
  427. ksadk/tracing/span_utils.py +0 -44
  428. ksadk/version.py +1 -1
  429. ksadk_runtime_common/memory_backend/registry.py +56 -56
  430. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  431. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  432. ksadk_runtime_common/workspace_files/router.py +8 -2
  433. agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
  434. ksadk/a2a/card_builder.py +0 -64
  435. ksadk/a2a/client.py +0 -309
  436. ksadk/events/parser.py +0 -191
  437. ksadk/harness/runner.py +0 -211
  438. ksadk/runners/codex_runner.py +0 -132
  439. ksadk/runners/utils/langfuse.py +0 -230
  440. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  441. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
  442. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
  443. ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
  444. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
  445. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
  446. ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
  447. ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
  448. ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
  449. ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
  450. ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
  451. ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
  452. ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
  453. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
  454. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
  455. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
  456. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  457. ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
  458. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  459. ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
  460. ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
  461. ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
  462. ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
  463. ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
  464. ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
  465. ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
  466. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
  467. ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
  468. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
  469. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
  470. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
  471. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  472. ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
  473. ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
  474. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
  475. ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
  476. ksadk/server/static/assets/katex-DATssjp1.js +0 -265
  477. ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
  478. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
  479. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
  480. ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
  481. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
  482. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
  483. ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
  484. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
  485. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
  486. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
  487. ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
  488. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
  489. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
  490. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
  491. ksadk/tracing/exporters/langfuse_exporter.py +0 -460
  492. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  493. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  494. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,822 @@
1
+ """LangGraphRunner 的 stream / stream_canonical_events 实现(纯移动自 langgraph_runner,行为不变)。
2
+
3
+ 以 mixin 形式被 :class:`LangGraphRunner` 继承。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import inspect
9
+ import time
10
+ import uuid
11
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, Mapping
12
+
13
+ from langgraph.types import Command
14
+
15
+ from ksadk.conversations.reasoning_markup import ReasoningMarkupParser, strip_reasoning_markup
16
+ from ksadk.events.runtime_event import RuntimeEvent
17
+ from ksadk.runners.usage_accumulator import accumulate_usage
18
+
19
+ if TYPE_CHECKING:
20
+ pass
21
+
22
+
23
+ class _LangGraphStreamMixin:
24
+ async def stream(self, input_data: Dict[str, Any]) -> AsyncIterator[Dict[str, Any]]:
25
+ """流式调用 LangGraph 图"""
26
+ payload = dict(input_data)
27
+ payload.pop("_ksadk_force_graph_invoke", None)
28
+ session_id = payload.pop("session_id", None) or str(uuid.uuid4())[:8]
29
+ history = payload.pop("history", [])
30
+ is_resume = payload.pop("resume", False)
31
+ is_checkpoint_resume = bool(payload.pop("checkpoint_resume", False))
32
+ resume_payload_provided = bool(payload.pop("resume_payload_provided", False))
33
+ resume_interrupt_id = str(payload.pop("resume_interrupt_id", "") or "")
34
+ resume_value = payload.get("input")
35
+ is_gateway_approval_resume = bool(
36
+ is_resume and self._is_gateway_approval_semantic_resume(resume_value)
37
+ )
38
+ if is_gateway_approval_resume:
39
+ # See ``invoke``: the graph did not suspend at a native interrupt,
40
+ # so use the durable transcript to run the post-tool answer turn.
41
+ payload["input"] = self._gateway_approval_follow_up_input()
42
+ resume_value = payload["input"]
43
+ checkpoint_ref = self._extract_langgraph_checkpoint_ref(payload)
44
+ native_context = self.build_native_context(payload.get("platform_context"))
45
+ invoke_payload = dict(payload)
46
+ invoke_payload["session_id"] = session_id
47
+ if history:
48
+ invoke_payload["history"] = history
49
+ if is_resume and not is_gateway_approval_resume:
50
+ invoke_payload["resume"] = True
51
+ if is_checkpoint_resume:
52
+ invoke_payload["checkpoint_resume"] = True
53
+ invoke_payload["resume_payload_provided"] = resume_payload_provided
54
+ invoke_payload["resume_interrupt_id"] = resume_interrupt_id
55
+
56
+ config = self._get_config(session_id)
57
+ if is_checkpoint_resume:
58
+ config = self._apply_checkpoint_resume_config(
59
+ config,
60
+ session_id=session_id,
61
+ checkpoint_ref=checkpoint_ref,
62
+ )
63
+
64
+ if is_checkpoint_resume:
65
+ state = resume_value
66
+ elif is_resume and not is_gateway_approval_resume:
67
+ # Keep the interrupt value intact for ``Command(resume=...)``;
68
+ # prepare-state hooks only shape fresh user turns.
69
+ state = resume_value
70
+ elif self._has_prepare_state_hook():
71
+ state = self._prepare_state_with_hook(
72
+ payload,
73
+ session_id,
74
+ history,
75
+ is_resume=is_gateway_approval_resume,
76
+ )
77
+ else:
78
+ state = self._to_state(payload, history)
79
+
80
+ accumulated_text = ""
81
+ accumulated_reasoning = ""
82
+ inline_reasoning_parser = ReasoningMarkupParser()
83
+ emitted_non_text_event = False
84
+ final_output_text = ""
85
+ final_output_usage: dict[str, Any] = {}
86
+ final_output_last_usage: dict[str, Any] = {}
87
+ model_run_usages: dict[str, dict[str, Any]] = {}
88
+ model_run_order: list[str] = []
89
+ stream_usage_run_keys: set[str] = set()
90
+ latest_stream_usage: dict[str, Any] = {}
91
+ model_started_at: dict[str, float] = {}
92
+ model_step_indexes: dict[str, int] = {}
93
+ first_token_seen: set[str] = set()
94
+ next_step_index = 0
95
+
96
+ def model_run_key(
97
+ event: Mapping[str, Any],
98
+ *,
99
+ fallback_key: str | None = None,
100
+ ) -> str:
101
+ raw_run_id = event.get("run_id")
102
+ return (
103
+ str(raw_run_id)
104
+ if raw_run_id
105
+ else fallback_key or f"model-event-{len(model_run_order)}"
106
+ )
107
+
108
+ def record_model_usage(
109
+ event: Mapping[str, Any],
110
+ usage: dict[str, Any],
111
+ *,
112
+ fallback_key: str | None = None,
113
+ ) -> None:
114
+ if not usage:
115
+ return
116
+ run_key = model_run_key(event, fallback_key=fallback_key)
117
+ if run_key not in model_run_usages:
118
+ model_run_order.append(run_key)
119
+ model_run_usages[run_key] = dict(usage)
120
+
121
+ def accumulated_model_usage() -> dict[str, Any]:
122
+ if len(model_run_order) == 1:
123
+ return dict(model_run_usages.get(model_run_order[0]) or {})
124
+ usage: dict[str, Any] = {}
125
+ for run_key in model_run_order:
126
+ usage = accumulate_usage(usage, model_run_usages.get(run_key) or {})
127
+ return usage
128
+
129
+ def latest_model_usage() -> dict[str, Any]:
130
+ for run_key in reversed(model_run_order):
131
+ usage = model_run_usages.get(run_key)
132
+ if usage:
133
+ return dict(usage)
134
+ return {}
135
+
136
+ if is_checkpoint_resume and callable(getattr(self._agent, "astream", None)):
137
+ try:
138
+ async for chunk in self._stream_checkpoint_resume_updates(
139
+ stream_input=self._checkpoint_resume_input(
140
+ state,
141
+ payload_provided=resume_payload_provided,
142
+ interrupt_id=resume_interrupt_id,
143
+ ),
144
+ config=config,
145
+ context=native_context,
146
+ ):
147
+ yield chunk
148
+ return
149
+ except Exception as e:
150
+ yield {
151
+ "type": "error",
152
+ "message": str(e) or "LangGraph checkpoint resume failed",
153
+ "checkpoint_id": str(checkpoint_ref.get("checkpoint_id") or ""),
154
+ "exception_type": type(e).__name__,
155
+ }
156
+ return
157
+
158
+ if not hasattr(self._agent, "astream_events"):
159
+ result = await self.invoke(invoke_payload)
160
+ final_chunk = {"output": result.get("output", ""), "type": "final"}
161
+ usage = self._extract_usage(result)
162
+ if usage:
163
+ final_chunk["usage"] = usage
164
+ last_usage = self._extract_last_usage(result)
165
+ if last_usage:
166
+ final_chunk.setdefault("metadata", {})["last_usage"] = last_usage
167
+ yield final_chunk
168
+ return
169
+
170
+ try:
171
+ stream_input = (
172
+ self._checkpoint_resume_input(
173
+ state,
174
+ payload_provided=resume_payload_provided,
175
+ interrupt_id=resume_interrupt_id,
176
+ )
177
+ if is_checkpoint_resume
178
+ else (
179
+ Command(resume=state) if is_resume and not is_gateway_approval_resume else state
180
+ )
181
+ )
182
+ # stream_mode 含 "custom" 才会产生 on_custom_stream 事件(custom writer);
183
+ # 保留默认 "values" 以兼容既有 on_chain_end/graph_update 消费。
184
+ stream_kwargs = {"version": "v2", "config": config}
185
+ if self._callable_accepts_keyword(self._agent.astream_events, "stream_mode"):
186
+ stream_kwargs["stream_mode"] = ["values", "custom"]
187
+ if native_context and self._callable_accepts_keyword(
188
+ self._agent.astream_events, "context"
189
+ ):
190
+ stream_kwargs["context"] = native_context
191
+ async for event in self._agent.astream_events(stream_input, **stream_kwargs):
192
+ event_kind = event.get("event", "")
193
+
194
+ if event_kind == "on_chat_model_start":
195
+ model_call_id = str(event.get("run_id") or "")
196
+ if model_call_id:
197
+ next_step_index += 1
198
+ step_id = f"step_{model_call_id}"
199
+ model_started_at[model_call_id] = time.monotonic()
200
+ model_step_indexes[model_call_id] = next_step_index
201
+ yield {
202
+ "type": "step_start",
203
+ "step_id": step_id,
204
+ "step_index": next_step_index,
205
+ }
206
+ yield {
207
+ "type": "model_call_begin",
208
+ "step_id": step_id,
209
+ "model_call_id": model_call_id,
210
+ "model": str(event.get("name") or "chat-model"),
211
+ }
212
+
213
+ elif event_kind == "on_chat_model_stream":
214
+ chunk = event.get("data", {}).get("chunk")
215
+ if not chunk:
216
+ continue
217
+ model_call_id = str(event.get("run_id") or "")
218
+ if (
219
+ model_call_id in model_started_at
220
+ and model_call_id not in first_token_seen
221
+ ):
222
+ reasoning_content = getattr(chunk, "reasoning_content", None)
223
+ if not reasoning_content and hasattr(chunk, "additional_kwargs"):
224
+ reasoning_content = chunk.additional_kwargs.get(
225
+ "reasoning_content"
226
+ )
227
+ if getattr(chunk, "content", None) or reasoning_content:
228
+ first_token_seen.add(model_call_id)
229
+ yield {
230
+ "type": "model_call_first_token",
231
+ "step_id": f"step_{model_call_id}",
232
+ "model_call_id": model_call_id,
233
+ "ttft_ms": int(
234
+ (time.monotonic() - model_started_at[model_call_id])
235
+ * 1000
236
+ ),
237
+ }
238
+ chunk_usage = self._extract_usage(chunk)
239
+ if chunk_usage:
240
+ # Some LangChain providers attach cumulative usage to
241
+ # every stream chunk, and LangChain may then sum those
242
+ # cumulative snapshots into an inflated
243
+ # on_chat_model_end usage. For a concrete model run,
244
+ # keep the latest stream snapshot and ignore the later
245
+ # end usage for that same run_id.
246
+ latest_stream_usage = dict(chunk_usage)
247
+ if event.get("run_id"):
248
+ run_key = model_run_key(event)
249
+ stream_usage_run_keys.add(run_key)
250
+ record_model_usage(event, latest_stream_usage)
251
+
252
+ # 推理内容
253
+ reasoning = getattr(chunk, "reasoning_content", None)
254
+ if not reasoning and hasattr(chunk, "additional_kwargs"):
255
+ reasoning = chunk.additional_kwargs.get("reasoning_content")
256
+
257
+ if reasoning:
258
+ accumulated_reasoning += reasoning
259
+ yield {"delta": reasoning, "type": "thinking"}
260
+
261
+ # 常规内容
262
+ if hasattr(chunk, "content") and chunk.content:
263
+ content = self._filter_tool_tags(chunk.content)
264
+ if isinstance(content, str):
265
+ if accumulated_reasoning and content.startswith(accumulated_reasoning):
266
+ content = content[len(accumulated_reasoning) :]
267
+ elif reasoning and content.startswith(reasoning):
268
+ content = content[len(reasoning) :]
269
+ if content:
270
+ for part in inline_reasoning_parser.feed(content):
271
+ if not part.text:
272
+ continue
273
+ if part.kind == "thinking":
274
+ accumulated_reasoning += part.text
275
+ yield {"delta": part.text, "type": "thinking"}
276
+ else:
277
+ accumulated_text += part.text
278
+ yield {"delta": part.text, "type": "text"}
279
+
280
+ elif event_kind == "on_chat_model_end":
281
+ data = event.get("data") or {}
282
+ output = data.get("output") if isinstance(data, Mapping) else None
283
+ usage = self._extract_usage(output) or self._extract_usage(data)
284
+ last_usage = self._extract_last_usage(output) or self._extract_last_usage(data)
285
+ run_key = model_run_key(event)
286
+ if run_key not in stream_usage_run_keys:
287
+ record_model_usage(event, last_usage or usage)
288
+ model_call_id = str(event.get("run_id") or "")
289
+ started_at = model_started_at.pop(model_call_id, None)
290
+ step_index = model_step_indexes.pop(model_call_id, None)
291
+ if started_at is not None and step_index is not None:
292
+ duration_ms = int((time.monotonic() - started_at) * 1000)
293
+ step_id = f"step_{model_call_id}"
294
+ yield {
295
+ "type": "model_call_end",
296
+ "step_id": step_id,
297
+ "model_call_id": model_call_id,
298
+ "status": "completed",
299
+ "duration_ms": duration_ms,
300
+ }
301
+ yield {
302
+ "type": "step_end",
303
+ "step_id": step_id,
304
+ "step_index": step_index,
305
+ "status": "completed",
306
+ "duration_ms": duration_ms,
307
+ }
308
+
309
+ elif event_kind == "on_chain_stream":
310
+ # node 内 get_stream_writer() 写入的自定义数据,经 stream_mode 含
311
+ # "custom" 时,astream_events 包成 on_chain_stream,chunk 为
312
+ # (mode, value) tuple:("custom", value) 是 writer 透传内容,
313
+ # ("values", state) 是 state 快照(忽略,终态走 on_chain_end)。
314
+ # 编排方常用 custom writer 把"调远端 agent/子图"的流式增量透传出来。
315
+ chunk = event.get("data", {}).get("chunk")
316
+ if not (isinstance(chunk, tuple) and len(chunk) == 2 and chunk[0] == "custom"):
317
+ continue
318
+ data = chunk[1]
319
+ if isinstance(data, str):
320
+ accumulated_text += data
321
+ yield {"delta": data, "type": "text"}
322
+ continue
323
+ if isinstance(data, Mapping):
324
+ custom_type = str(data.get("type") or "text")
325
+ if custom_type in ("tool_call", "tool_result"):
326
+ # 结构化工具事件:透传完整 payload(tool_name/tool_args/
327
+ # tool_output 等),不计入正文,供 UI 渲染工具卡片。
328
+ out = {"type": custom_type}
329
+ out.update({k: v for k, v in data.items() if k != "type"})
330
+ yield out
331
+ continue
332
+ custom_delta = ""
333
+ for key in ("delta", "text", "content", "output", "data"):
334
+ value = data.get(key)
335
+ if isinstance(value, str) and value:
336
+ custom_delta = value
337
+ break
338
+ if not custom_delta:
339
+ continue
340
+ replace = bool(data.get("replace"))
341
+ if custom_type == "thinking":
342
+ accumulated_reasoning = (
343
+ custom_delta if replace else accumulated_reasoning + custom_delta
344
+ )
345
+ else:
346
+ accumulated_text = (
347
+ custom_delta if replace else accumulated_text + custom_delta
348
+ )
349
+ custom_event: dict[str, Any] = {
350
+ "delta": custom_delta,
351
+ "type": custom_type,
352
+ }
353
+ if replace:
354
+ custom_event["replace"] = True
355
+ yield custom_event
356
+ continue
357
+ if data is not None:
358
+ accumulated_text += str(data)
359
+ yield {"delta": str(data), "type": "text"}
360
+
361
+ elif event_kind == "on_tool_start":
362
+ emitted_non_text_event = True
363
+ yield {
364
+ "type": "tool_call",
365
+ "tool_name": event.get("name", "unknown"),
366
+ "tool_args": event.get("data", {}).get("input", {}),
367
+ "run_id": event.get("run_id"),
368
+ }
369
+
370
+ elif event_kind == "on_tool_end":
371
+ emitted_non_text_event = True
372
+ tool_output = event.get("data", {}).get("output", "")
373
+ # LangGraph returns a ToolMessage here for normal tools.
374
+ # Preserve its content instead of serializing the repr,
375
+ # otherwise structured output such as A2UI envelopes becomes
376
+ # unparsable. Keep the callback run_id below: it is paired
377
+ # with the preceding ``on_tool_start`` event on this stream.
378
+ normalized_output = getattr(tool_output, "content", tool_output)
379
+ if isinstance(tool_output, Mapping) and "content" in tool_output:
380
+ normalized_output = tool_output["content"]
381
+ yield {
382
+ "type": "tool_result",
383
+ "tool_name": event.get("name", "unknown"),
384
+ "tool_args": event.get("data", {}).get("input", {}),
385
+ "tool_output": normalized_output,
386
+ "run_id": event.get("run_id"),
387
+ }
388
+
389
+ elif event_kind == "on_chain_end":
390
+ output = event.get("data", {}).get("output", {})
391
+ if isinstance(output, dict) and "__interrupt__" in output:
392
+ emitted_non_text_event = True
393
+ yield {
394
+ "type": "interrupt",
395
+ "interrupt_info": output["__interrupt__"],
396
+ "session_id": session_id,
397
+ }
398
+ return
399
+ extracted_output = self._extract_output(output)
400
+ if extracted_output:
401
+ final_output_text = strip_reasoning_markup(str(extracted_output))
402
+ final_output_usage = self._extract_usage(output)
403
+ final_output_last_usage = self._extract_last_usage(output)
404
+
405
+ except Exception as e:
406
+ if "Interrupt" in type(e).__name__:
407
+ yield {
408
+ "type": "interrupt",
409
+ "interrupt_info": self._get_interrupt_info(self._agent.get_state(config)),
410
+ "session_id": session_id,
411
+ }
412
+ return
413
+ raise
414
+
415
+ # goal-18(ksadk-web 人机交互):图因审批门(HITL)在流式中静默暂停时,
416
+ # 这里把审批详情(action_requests)作为 approval 事件冒出,供 UI 渲染审批卡。
417
+ # 此前流式路径只在 checkpoint 标 resumable,UI 拿不到"该批哪个工具/什么参数/允许哪些决定"。
418
+ # 注:get_state 在部分 agent 上是 async,统一按 awaitable 处理;取不到则跳过,不破坏事件流。
419
+ pending_approval = None
420
+ try:
421
+ _get_state = getattr(self._agent, "aget_state", None) or getattr(
422
+ self._agent, "get_state", None
423
+ )
424
+ if _get_state is not None:
425
+ _maybe_state = _get_state(config)
426
+ if inspect.isawaitable(_maybe_state):
427
+ _maybe_state = await _maybe_state
428
+ pending_approval = self._get_interrupt_info(_maybe_state)
429
+ except Exception:
430
+ pending_approval = None
431
+ if pending_approval:
432
+ yield {
433
+ "type": "approval",
434
+ "interrupt_info": pending_approval,
435
+ "session_id": session_id,
436
+ }
437
+ metadata = await self._latest_checkpoint_metadata(config)
438
+ if metadata:
439
+ yield {"type": "checkpoint", "metadata": metadata}
440
+ return
441
+
442
+ for part in inline_reasoning_parser.flush():
443
+ if not part.text:
444
+ continue
445
+ if part.kind == "thinking":
446
+ accumulated_reasoning += part.text
447
+ yield {"delta": part.text, "type": "thinking"}
448
+ else:
449
+ accumulated_text += part.text
450
+ yield {"delta": part.text, "type": "text"}
451
+
452
+ if not accumulated_text:
453
+ if final_output_text:
454
+ final_chunk = {"output": final_output_text, "type": "final"}
455
+ usage = accumulated_model_usage() or final_output_usage or latest_stream_usage
456
+ last_usage = (
457
+ latest_model_usage() or final_output_last_usage or latest_stream_usage or usage
458
+ )
459
+ if usage:
460
+ final_chunk["usage"] = usage
461
+ if last_usage:
462
+ final_chunk.setdefault("metadata", {})["last_usage"] = last_usage
463
+ yield final_chunk
464
+ elif not emitted_non_text_event:
465
+ result = await self.invoke({**invoke_payload, "_ksadk_force_graph_invoke": True})
466
+ fallback_chunk: dict[str, Any] = {
467
+ "output": result.get("output", ""),
468
+ "type": "final",
469
+ }
470
+ usage = self._extract_usage(result)
471
+ if usage:
472
+ fallback_chunk["usage"] = usage
473
+ last_usage = self._extract_last_usage(result)
474
+ if last_usage:
475
+ fallback_chunk.setdefault("metadata", {})["last_usage"] = last_usage
476
+ yield fallback_chunk
477
+ checkpoint_metadata = result.get("metadata") if isinstance(result, dict) else None
478
+ if isinstance(checkpoint_metadata, dict) and checkpoint_metadata.get("agentengine"):
479
+ yield {"type": "checkpoint", "metadata": checkpoint_metadata}
480
+ return
481
+ else:
482
+ final_chunk = {"output": accumulated_text, "type": "final"}
483
+ state_usage = await self._latest_state_usage(config)
484
+ usage = (
485
+ accumulated_model_usage()
486
+ or state_usage
487
+ or final_output_usage
488
+ or latest_stream_usage
489
+ )
490
+ if usage:
491
+ final_chunk["usage"] = usage
492
+ last_usage = (
493
+ latest_model_usage()
494
+ or state_usage
495
+ or final_output_last_usage
496
+ or latest_stream_usage
497
+ or usage
498
+ )
499
+ final_chunk.setdefault("metadata", {})["last_usage"] = last_usage
500
+ yield final_chunk
501
+
502
+ metadata = await self._latest_checkpoint_metadata(config)
503
+ if metadata:
504
+ yield {"type": "checkpoint", "metadata": metadata}
505
+
506
+ async def stream_canonical_events(
507
+ self, input_data: Dict[str, Any]
508
+ ) -> AsyncIterator[RuntimeEvent]:
509
+ """Emit canonical RuntimeEvent (schema_version=2) for a LangGraph run.
510
+
511
+ Emits RunStarted/RunCompleted/RunFailed lifecycle events and uses
512
+ LangGraphEventAdapter to map item.* events from the v3
513
+ AsyncGraphRunStream. The old ``stream`` method (dict path) is
514
+ retained for backward compatibility; runner_adapter prefers this
515
+ canonical path when present.
516
+ """
517
+
518
+ import time as _time
519
+
520
+ from ksadk.events.adapters.langgraph import (
521
+ LangGraphAdapterContext,
522
+ LangGraphEventAdapter,
523
+ LangGraphMappingError,
524
+ )
525
+ from ksadk.events.canonical import (
526
+ ContinuationCreated,
527
+ ErrorInfo,
528
+ OutputRef,
529
+ RunCompleted,
530
+ RunFailed,
531
+ RunInterrupted,
532
+ RunStarted,
533
+ SourceRef,
534
+ )
535
+ from ksadk.events.identity import stable_event_id, stable_item_id, stable_scope_id
536
+ from ksadk.events.reducer import StreamReducer
537
+
538
+ # --- parse input (mirrors stream()) ---
539
+ payload = dict(input_data)
540
+ run_id = str(
541
+ payload.pop("run_id", None) or payload.pop("invocation_id", None) or ""
542
+ ).strip()
543
+ if not run_id:
544
+ raise ValueError(
545
+ "LangGraph canonical stream requires an explicit run_id or invocation_id"
546
+ )
547
+ payload.pop("_ksadk_force_graph_invoke", None)
548
+ session_id = payload.pop("session_id", None) or str(uuid.uuid4())[:8]
549
+ history = payload.pop("history", [])
550
+ is_resume = payload.pop("resume", False)
551
+ is_checkpoint_resume = bool(payload.pop("checkpoint_resume", False))
552
+ resume_payload_provided = bool(payload.pop("resume_payload_provided", False))
553
+ resume_interrupt_id = str(payload.pop("resume_interrupt_id", "") or "")
554
+ resume_value = payload.get("input")
555
+ checkpoint_ref = self._extract_langgraph_checkpoint_ref(payload)
556
+ native_context = self.build_native_context(payload.get("platform_context"))
557
+
558
+ config = self._get_config(session_id)
559
+ if is_checkpoint_resume:
560
+ config = self._apply_checkpoint_resume_config(
561
+ config,
562
+ session_id=session_id,
563
+ checkpoint_ref=checkpoint_ref,
564
+ )
565
+
566
+ # --- build state (same logic as stream()) ---
567
+ if is_checkpoint_resume:
568
+ state = resume_value
569
+ elif is_resume:
570
+ state = resume_value
571
+ elif self._has_prepare_state_hook():
572
+ state = self._prepare_state_with_hook(payload, session_id, history)
573
+ else:
574
+ state = self._to_state(payload, history)
575
+
576
+ stream_input = (
577
+ self._checkpoint_resume_input(
578
+ state,
579
+ payload_provided=resume_payload_provided,
580
+ interrupt_id=resume_interrupt_id,
581
+ )
582
+ if is_checkpoint_resume
583
+ else (Command(resume=state) if is_resume else state)
584
+ )
585
+
586
+ # --- identity ---
587
+ run_scope_id = stable_scope_id("langgraph", run_id, "$run")
588
+ run_item_id = stable_item_id("langgraph", run_id, "$run")
589
+
590
+ source_metadata: dict[str, Any] = {}
591
+ if session_id:
592
+ source_metadata["session_id"] = session_id
593
+ invocation_id = str(input_data.get("invocation_id") or "").strip()
594
+ if invocation_id:
595
+ source_metadata["invocation_id"] = invocation_id
596
+ agent_id = str(input_data.get("agent_id") or "").strip()
597
+ if agent_id:
598
+ source_metadata["agent_id"] = agent_id
599
+ user_id = str(input_data.get("user_id") or "").strip()
600
+ if user_id:
601
+ source_metadata["user_id"] = user_id
602
+
603
+ run_source = SourceRef(
604
+ framework="langgraph",
605
+ native_run_id=run_id,
606
+ metadata=source_metadata,
607
+ )
608
+
609
+ started_at = _time.time()
610
+ yield RunStarted(
611
+ schema_version=2,
612
+ event_id=stable_event_id(
613
+ "langgraph",
614
+ run_scope_id,
615
+ run_item_id,
616
+ "run.started",
617
+ "run",
618
+ run_id,
619
+ 0,
620
+ ),
621
+ seq=0,
622
+ timestamp=started_at,
623
+ run_id=run_id,
624
+ scope_id=run_scope_id,
625
+ source=run_source,
626
+ status="running",
627
+ )
628
+
629
+ # --- check astream_events availability ---
630
+ if not hasattr(self._agent, "astream_events"):
631
+ terminal_source = SourceRef(
632
+ framework="langgraph",
633
+ native_run_id=run_id,
634
+ metadata={**source_metadata, "fallback": "no_astream_events"},
635
+ )
636
+ yield RunCompleted(
637
+ schema_version=2,
638
+ event_id=stable_event_id(
639
+ "langgraph",
640
+ run_scope_id,
641
+ run_item_id,
642
+ "run.completed",
643
+ "run",
644
+ run_id,
645
+ 0,
646
+ ),
647
+ seq=1,
648
+ timestamp=_time.time(),
649
+ run_id=run_id,
650
+ scope_id=run_scope_id,
651
+ source=terminal_source,
652
+ status="completed",
653
+ output_refs=(),
654
+ )
655
+ return
656
+
657
+ # --- build adapter context ---
658
+ adapter_checkpoint_ref: dict[str, Any] | None = None
659
+ if checkpoint_ref:
660
+ adapter_checkpoint_ref = dict(checkpoint_ref)
661
+ adapter_checkpoint_ref.setdefault("checkpoint_ns", "")
662
+
663
+ adapter_context = LangGraphAdapterContext(
664
+ run_id=run_id,
665
+ graph_run_id=run_id,
666
+ initial_seq=1,
667
+ checkpoint_ref=adapter_checkpoint_ref,
668
+ )
669
+ adapter = LangGraphEventAdapter()
670
+ reducer = StreamReducer()
671
+
672
+ # --- build stream kwargs (v3 rejects stream_mode/subgraphs) ---
673
+ stream_kwargs: dict[str, Any] = {"version": "v3", "config": config}
674
+ if native_context and self._callable_accepts_keyword(self._agent.astream_events, "context"):
675
+ stream_kwargs["context"] = native_context
676
+
677
+ was_interrupted = False
678
+ last_timestamp = started_at
679
+
680
+ try:
681
+ run_stream = await self._agent.astream_events(stream_input, **stream_kwargs)
682
+ async for event in adapter.stream_run(run_stream, adapter_context):
683
+ if isinstance(event, RunInterrupted):
684
+ was_interrupted = True
685
+ # Extract checkpoint from graph state and emit
686
+ # ContinuationCreated BEFORE RunInterrupted so downstream
687
+ # consumers (agui agent) can resolve the resumable
688
+ # checkpoint_id before processing the terminal interrupt.
689
+ try:
690
+ ckpt_state = self._agent.get_state(config)
691
+ ckpt_config = getattr(ckpt_state, "config", {}) or {}
692
+ ckpt_id = str(
693
+ (ckpt_config.get("configurable") or {}).get("checkpoint_id", "") or ""
694
+ )
695
+ if ckpt_id:
696
+ ckpt_ref = {
697
+ "thread_id": str(
698
+ (ckpt_config.get("configurable") or {}).get(
699
+ "thread_id", session_id
700
+ )
701
+ ),
702
+ "checkpoint_ns": "",
703
+ "checkpoint_id": ckpt_id,
704
+ }
705
+ continuation_id = stable_item_id(
706
+ "langgraph",
707
+ run_scope_id,
708
+ "continuation",
709
+ "graph-checkpoint",
710
+ ckpt_ref["thread_id"],
711
+ "checkpoint-ns:",
712
+ ckpt_id,
713
+ )
714
+ cont_event = ContinuationCreated(
715
+ schema_version=2,
716
+ event_id=stable_event_id(
717
+ "langgraph",
718
+ run_scope_id,
719
+ continuation_id,
720
+ "continuation.created",
721
+ "checkpoint",
722
+ run_id,
723
+ 0,
724
+ ),
725
+ seq=adapter_context.allocate_placeholder_seq(),
726
+ timestamp=last_timestamp,
727
+ run_id=run_id,
728
+ scope_id=run_scope_id,
729
+ source=SourceRef(
730
+ framework="langgraph",
731
+ native_run_id=run_id,
732
+ metadata={"checkpoint": True},
733
+ ),
734
+ continuation_id=continuation_id,
735
+ continuation_kind="graph_checkpoint",
736
+ resumable=True,
737
+ ref=ckpt_ref,
738
+ )
739
+ reducer.apply(cont_event)
740
+ yield cont_event
741
+ except Exception:
742
+ pass
743
+ reducer.apply(event)
744
+ last_timestamp = float(getattr(event, "timestamp", 0.0) or last_timestamp)
745
+ yield event
746
+ return
747
+ reducer.apply(event)
748
+ last_timestamp = float(getattr(event, "timestamp", 0.0) or last_timestamp)
749
+ yield event
750
+ except Exception as exc:
751
+ error_source = SourceRef(
752
+ framework="langgraph",
753
+ native_run_id=run_id,
754
+ metadata={"error_type": type(exc).__name__},
755
+ )
756
+ error_code = exc.code if isinstance(exc, LangGraphMappingError) else "langgraph_failed"
757
+ yield RunFailed(
758
+ schema_version=2,
759
+ event_id=stable_event_id(
760
+ "langgraph",
761
+ run_scope_id,
762
+ run_item_id,
763
+ "run.failed",
764
+ "run",
765
+ run_id,
766
+ 0,
767
+ ),
768
+ seq=adapter_context.allocate_placeholder_seq(),
769
+ timestamp=_time.time(),
770
+ run_id=run_id,
771
+ scope_id=run_scope_id,
772
+ source=error_source,
773
+ status="failed",
774
+ error=ErrorInfo(
775
+ code=error_code,
776
+ message=str(exc) or type(exc).__name__,
777
+ source="langgraph",
778
+ scope_id=run_scope_id,
779
+ ),
780
+ )
781
+ return
782
+
783
+ # --- emit RunCompleted (skip if RunInterrupted was terminal) ---
784
+ if was_interrupted:
785
+ return
786
+
787
+ projection = reducer.snapshot()
788
+ output_refs = tuple(
789
+ OutputRef(scope_id=item.scope_id, item_id=item.item_id)
790
+ for item in projection.items
791
+ if item.status == "completed"
792
+ and item.item_kind == "message"
793
+ and item.phase == "final_answer"
794
+ )
795
+
796
+ terminal_source = SourceRef(
797
+ framework="langgraph",
798
+ native_run_id=run_id,
799
+ metadata=dict(source_metadata),
800
+ )
801
+ yield RunCompleted(
802
+ schema_version=2,
803
+ event_id=stable_event_id(
804
+ "langgraph",
805
+ run_scope_id,
806
+ run_item_id,
807
+ "run.completed",
808
+ "run",
809
+ run_id,
810
+ 0,
811
+ ),
812
+ seq=adapter_context.allocate_placeholder_seq(),
813
+ timestamp=last_timestamp,
814
+ run_id=run_id,
815
+ scope_id=run_scope_id,
816
+ source=terminal_source,
817
+ status="completed",
818
+ output_refs=output_refs,
819
+ )
820
+
821
+
822
+ __all__ = ["_LangGraphStreamMixin"]