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
@@ -5,9 +5,6 @@ from typing import Any
5
5
  from urllib.parse import quote
6
6
 
7
7
  from ksadk.agui.a2ui_projection import project_a2ui_operations
8
- from ksadk.events.runtime_event import EventType
9
-
10
-
11
8
  def _event_metadata(event: Mapping[str, Any]) -> Mapping[str, Any]:
12
9
  metadata = event.get("Metadata")
13
10
  return metadata if isinstance(metadata, Mapping) else {}
@@ -20,7 +17,18 @@ def project_session_messages(
20
17
  include_tool_events: bool = False,
21
18
  include_attachments: bool = True,
22
19
  ) -> list[dict[str, Any]]:
23
- """Project persisted runtime events into the chat history contract."""
20
+ """Project persisted runtime events into the chat history contract.
21
+
22
+ 公开承诺字段(契约声明见 ``ksadk/events/projections.py``,执行形态为
23
+ ``tests/protocol/test_cross_projection_golden.py``):
24
+ - 每条消息含 ``Role``/``Content.text``/``SeqId``/``StartSeqId``;
25
+ - 开启 include_reasoning 时含 ``Reasoning``;开启 include_tool_events 时
26
+ 含 ``ToolEvents``(approval 项含 ``ApprovalRequestId``);
27
+ - A2UI 项以 ``Activities`` 携带(内含 ``surfaceId``)。
28
+
29
+ 内部不保证字段:分组实现细节、事件归并产生的中间键、未经开关开启的
30
+ 可选区块。
31
+ """
24
32
 
25
33
  agui_invocations = _agui_invocation_ids(events)
26
34
  normalized = [
@@ -59,7 +67,10 @@ def _project_event_group(
59
67
  for event in events
60
68
  if event.get("EventType") == "reasoning" and _event_text(event)
61
69
  ]
62
- tool_events = (
70
+ # Split tool events: approval-only events before first assistant_message
71
+ # vs all tool events. When approval events precede a text completion, they
72
+ # get their own assistant message placeholder.
73
+ all_tool_events = (
63
74
  _project_tool_events(events, approval_responses=approval_responses)
64
75
  if include_tool_events
65
76
  else []
@@ -71,6 +82,27 @@ def _project_event_group(
71
82
  streamed_text = ""
72
83
  start_seq_id = min((int(event.get("SeqId") or 0) for event in events), default=0)
73
84
 
85
+ # Check if there are approval events before the first assistant_message.
86
+ # When approval events precede a text completion, they get their own
87
+ # assistant message placeholder with empty text.
88
+ has_assistant_message = any(
89
+ str(e.get("EventType") or "") == "assistant_message" for e in events
90
+ )
91
+ pre_assistant_tool_events: list[dict[str, Any]] = []
92
+ post_assistant_tool_events: list[dict[str, Any]] = []
93
+ if has_assistant_message and all_tool_events:
94
+ # Split: approval events go to pre_assistant, tool_call/tool_result
95
+ # go to post_assistant.
96
+ for te in all_tool_events:
97
+ if te.get("Type") == "approval":
98
+ pre_assistant_tool_events.append(te)
99
+ else:
100
+ post_assistant_tool_events.append(te)
101
+ else:
102
+ post_assistant_tool_events = list(all_tool_events)
103
+
104
+ has_pre_assistant_approvals = bool(pre_assistant_tool_events)
105
+
74
106
  for event in events:
75
107
  event_type = str(event.get("EventType") or "")
76
108
  if event_type == "user_message":
@@ -81,13 +113,31 @@ def _project_event_group(
81
113
  message["Attachments"] = attachments
82
114
  projected.append(message)
83
115
  elif event_type == "assistant_message":
116
+ # If there are approval events that preceded this assistant_message,
117
+ # emit a placeholder assistant message for them first.
118
+ if has_pre_assistant_approvals and not assistant_seen:
119
+ anchor = next(
120
+ (e for e in events
121
+ if str(e.get("EventType") or "") == "approval_request"),
122
+ events[0],
123
+ )
124
+ placeholder = _base_message(anchor, "assistant", content="")
125
+ if include_tool_events and pre_assistant_tool_events:
126
+ placeholder["ToolEvents"] = pre_assistant_tool_events
127
+ projected.append(placeholder)
128
+ assistant_seen = True
129
+ # Don't add tool_events/reasoning to the next message — they
130
+ # belong to the placeholder.
84
131
  message = _base_message(event, "assistant")
132
+ # Attach reasoning to the first non-placeholder assistant message.
133
+ # When has_pre_assistant_approvals is True, the placeholder was
134
+ # already emitted, so this is the real assistant message.
85
135
  if include_reasoning and reasoning:
86
136
  message["Reasoning"] = reasoning
87
- if tool_events:
88
- message["ToolEvents"] = tool_events
137
+ if include_tool_events and post_assistant_tool_events:
138
+ message["ToolEvents"] = post_assistant_tool_events
89
139
  if include_reasoning:
90
- blocks = _project_interleaved_blocks(events, tool_events=tool_events)
140
+ blocks = _project_interleaved_blocks(events, tool_events=post_assistant_tool_events)
91
141
  if blocks:
92
142
  message["Blocks"] = blocks
93
143
  projected.append(message)
@@ -98,7 +148,7 @@ def _project_event_group(
98
148
  streamed_text += _event_text(event)
99
149
 
100
150
  if not assistant_seen and (
101
- latest_snapshot is not None or streamed_text or reasoning or tool_events or activities
151
+ latest_snapshot is not None or streamed_text or reasoning or all_tool_events or activities
102
152
  ):
103
153
  anchor = next(
104
154
  (
@@ -111,9 +161,9 @@ def _project_event_group(
111
161
  "approval_request",
112
162
  "tool_call",
113
163
  "reasoning",
114
- EventType.A2UI_SURFACE_BEGIN,
115
- EventType.A2UI_SURFACE_UPDATE,
116
- EventType.A2UI_SURFACE_END,
164
+ "a2ui.surface.begin",
165
+ "a2ui.surface.update",
166
+ "a2ui.surface.end",
117
167
  }
118
168
  ),
119
169
  events[-1],
@@ -127,10 +177,10 @@ def _project_event_group(
127
177
  )
128
178
  if include_reasoning and reasoning:
129
179
  message["Reasoning"] = reasoning
130
- if tool_events:
131
- message["ToolEvents"] = tool_events
180
+ if all_tool_events:
181
+ message["ToolEvents"] = all_tool_events
132
182
  if include_reasoning:
133
- blocks = _project_interleaved_blocks(events, tool_events=tool_events)
183
+ blocks = _project_interleaved_blocks(events, tool_events=all_tool_events)
134
184
  if blocks:
135
185
  message["Blocks"] = blocks
136
186
  projected.append(message)
@@ -462,9 +512,9 @@ def _project_a2ui_activities(events: Sequence[Mapping[str, Any]]) -> list[dict[s
462
512
  for event in events:
463
513
  event_type = str(event.get("EventType") or "")
464
514
  if event_type not in {
465
- EventType.A2UI_SURFACE_BEGIN,
466
- EventType.A2UI_SURFACE_UPDATE,
467
- EventType.A2UI_SURFACE_END,
515
+ "a2ui.surface.begin",
516
+ "a2ui.surface.update",
517
+ "a2ui.surface.end",
468
518
  }:
469
519
  continue
470
520
  content = event.get("Content")
@@ -492,7 +542,7 @@ def _agui_invocation_ids(events: Sequence[Mapping[str, Any]]) -> set[str]:
492
542
  """Locate AG-UI runs so history written before ``payload.protocol`` remains usable."""
493
543
  invocation_ids: set[str] = set()
494
544
  for event in events:
495
- if str(event.get("EventType") or "") != EventType.RUN_STARTED:
545
+ if str(event.get("EventType") or "") != "run.started":
496
546
  continue
497
547
  if not _event_metadata(event).get("ksadk_runtime_event"):
498
548
  continue
@@ -505,16 +555,230 @@ def _agui_invocation_ids(events: Sequence[Mapping[str, Any]]) -> set[str]:
505
555
  return invocation_ids
506
556
 
507
557
 
558
+ _CANONICAL_EVENT_TYPE_MAP = {
559
+ "run.started": "run.started",
560
+ "run.completed": "run.completed",
561
+ "run.failed": "run.failed",
562
+ "run.canceled": "run.canceled",
563
+ "run.interrupted": "run.interrupted",
564
+ "item.started": "item.started",
565
+ "item.updated": "item.updated",
566
+ "item.completed": "item.completed",
567
+ "interaction.requested": "approval.requested",
568
+ }
569
+
570
+
571
+ def _normalize_canonical_event(
572
+ event: Mapping[str, Any],
573
+ content: Mapping[str, Any],
574
+ metadata: Mapping[str, Any],
575
+ ) -> Mapping[str, Any]:
576
+ """Project a canonical v2 SessionEvent into the legacy v1 wire shape."""
577
+ runtime_event = content.get("runtime_event")
578
+ if not isinstance(runtime_event, Mapping):
579
+ return event
580
+ event_type = str(runtime_event.get("event_type") or "")
581
+ item_kind = str(runtime_event.get("item_kind") or "")
582
+ raw_source = runtime_event.get("source") or {}
583
+ source = raw_source if isinstance(raw_source, Mapping) else {}
584
+ normalized = dict(event)
585
+ normalized_metadata = dict(metadata)
586
+
587
+ if event_type == "run.started":
588
+ source_metadata = source.get("metadata") if isinstance(source, Mapping) else None
589
+ if isinstance(source_metadata, Mapping) and source_metadata.get("source") == "ag-ui":
590
+ normalized["EventType"] = "user_message"
591
+ normalized["Content"] = {"text": _input_text(source_metadata.get("input"))}
592
+ normalized["Author"] = "user"
593
+ normalized["Metadata"] = normalized_metadata
594
+ return normalized
595
+ normalized["EventType"] = "run.started"
596
+ normalized["Content"] = {"status": runtime_event.get("status", "running")}
597
+ elif event_type == "run.completed":
598
+ normalized["EventType"] = "run.completed"
599
+ normalized["Content"] = {"status": "completed"}
600
+ elif event_type == "run.failed":
601
+ normalized["EventType"] = "run.failed"
602
+ error = runtime_event.get("error") or {}
603
+ normalized["Content"] = {"status": "failed", "error": error.get("message", "")}
604
+ elif event_type == "run.canceled":
605
+ normalized["EventType"] = "run.canceled"
606
+ normalized["Content"] = {"status": "canceled"}
607
+ elif event_type == "run.interrupted":
608
+ normalized["EventType"] = "run.interrupted"
609
+ normalized["Content"] = {"status": "interrupted"}
610
+ elif event_type == "item.started":
611
+ if item_kind == "tool_call":
612
+ initial = runtime_event.get("initial") or {}
613
+ parts = initial.get("parts") if isinstance(initial, Mapping) else None
614
+ part = parts[0] if isinstance(parts, list) and parts else {}
615
+ call_id = part.get("call_id", "")
616
+ name = part.get("name", "")
617
+ args = part.get("arguments", {})
618
+ normalized["EventType"] = "tool_call"
619
+ normalized["Content"] = {"call_id": call_id, "name": name, "args": args}
620
+ normalized_metadata.update({"call_id": call_id, "tool_name": name, "tool_args": args})
621
+ elif item_kind == "data" and source.get("protocol") == "a2ui":
622
+ surface_id = str(source.get("metadata", {}).get("surface_id") or "")
623
+ initial = runtime_event.get("initial") or {}
624
+ parts = initial.get("parts") if isinstance(initial, Mapping) else []
625
+ data: Any = {}
626
+ for part in (parts or []):
627
+ if isinstance(part, Mapping) and part.get("content_type") == "data":
628
+ data = part.get("data")
629
+ break
630
+ if isinstance(data, list):
631
+ normalized["Content"] = {"surface_id": surface_id, "components": data}
632
+ elif isinstance(data, Mapping):
633
+ normalized["Content"] = data
634
+ else:
635
+ normalized["Content"] = {"surface_id": surface_id}
636
+ normalized["EventType"] = "a2ui.surface.begin"
637
+ else:
638
+ return event
639
+ elif event_type == "item.completed":
640
+ if item_kind == "message":
641
+ snapshot = runtime_event.get("snapshot") or {}
642
+ parts = snapshot.get("parts") if isinstance(snapshot, Mapping) else None
643
+ text = ""
644
+ if isinstance(parts, list):
645
+ for part in parts:
646
+ if isinstance(part, Mapping) and part.get("content_type") == "text":
647
+ text = part.get("text", "")
648
+ break
649
+ if not text:
650
+ return event
651
+ normalized["EventType"] = "assistant_message"
652
+ normalized["Content"] = {"role": "model", "parts": [{"text": text}]}
653
+ normalized["Author"] = "assistant"
654
+ elif item_kind == "tool_call":
655
+ return event
656
+ elif item_kind == "tool_result":
657
+ snapshot = runtime_event.get("snapshot") or {}
658
+ parts = snapshot.get("parts") if isinstance(snapshot, Mapping) else None
659
+ part = parts[0] if isinstance(parts, list) and parts else {}
660
+ call_id = part.get("call_id", "")
661
+ result = part.get("result", "")
662
+ normalized["EventType"] = "tool_result"
663
+ normalized["Content"] = {"call_id": call_id, "name": "", "result": result}
664
+ normalized_metadata.update({"call_id": call_id, "tool_output": result})
665
+ elif item_kind == "data" and source.get("protocol") == "a2ui":
666
+ surface_id = str(source.get("metadata", {}).get("surface_id") or "")
667
+ normalized["EventType"] = "a2ui.surface.end"
668
+ normalized["Content"] = {"surface_id": surface_id}
669
+ else:
670
+ return event
671
+ elif event_type == "item.updated":
672
+ if item_kind == "message":
673
+ update = runtime_event.get("update") or {}
674
+ text = update.get("text", "") if isinstance(update, Mapping) else ""
675
+ normalized["EventType"] = "assistant_stream_delta"
676
+ normalized["Content"] = {"role": "model", "parts": [{"text": text}]}
677
+ elif item_kind == "reasoning":
678
+ update = runtime_event.get("update") or {}
679
+ text = update.get("text", "") if isinstance(update, Mapping) else ""
680
+ normalized["EventType"] = "reasoning"
681
+ normalized["Content"] = {"role": "model", "parts": [{"text": text}]}
682
+ elif item_kind == "data" and source.get("protocol") == "a2ui":
683
+ surface_id = str(source.get("metadata", {}).get("surface_id") or "")
684
+ update = runtime_event.get("update") or {}
685
+ update_data = update.get("data") if isinstance(update, Mapping) else None
686
+ if isinstance(update_data, list):
687
+ normalized["Content"] = {"surface_id": surface_id, "components": update_data}
688
+ elif isinstance(update_data, Mapping):
689
+ normalized["Content"] = update_data
690
+ else:
691
+ normalized["Content"] = {"surface_id": surface_id}
692
+ normalized["EventType"] = "a2ui.surface.update"
693
+ else:
694
+ return event
695
+ elif event_type == "interaction.requested":
696
+ interaction_kind = str(runtime_event.get("interaction_kind") or "approval")
697
+ request = runtime_event.get("request") or {}
698
+ if not isinstance(request, Mapping):
699
+ request = {}
700
+ if interaction_kind == "approval":
701
+ interaction_id = str(runtime_event.get("interaction_id") or "")
702
+ call_id = str(request.get("call_id") or "")
703
+ kind = str(request.get("kind") or "approval")
704
+ detail = request.get("detail")
705
+ if not isinstance(detail, Mapping):
706
+ detail = {}
707
+ normalized["EventType"] = "approval_request"
708
+ normalized["Content"] = {"detail": detail}
709
+ normalized_metadata["interrupt_info"] = {
710
+ "approval_request_id": interaction_id or call_id,
711
+ "id": interaction_id or call_id,
712
+ "tool_name": detail.get("tool_name") or kind,
713
+ "arguments": detail.get("arguments") or detail.get("args"),
714
+ "approval_level": detail.get("approval_level"),
715
+ "approval_message": detail.get("message"),
716
+ }
717
+ # Preserve ag-ui protocol tag from source metadata.
718
+ source = runtime_event.get("source") or {}
719
+ source_metadata = source.get("metadata") if isinstance(source, Mapping) else None
720
+ if isinstance(source_metadata, Mapping) and source_metadata.get("protocol") == "ag-ui":
721
+ normalized_metadata["protocol"] = "ag-ui"
722
+ else:
723
+ # structured_input: project as approval_request but with
724
+ # structured input schema in detail.
725
+ interaction_id = str(runtime_event.get("interaction_id") or "")
726
+ normalized["EventType"] = "approval_request"
727
+ normalized["Content"] = {"detail": request}
728
+ normalized_metadata["interrupt_info"] = {
729
+ "approval_request_id": interaction_id,
730
+ "id": interaction_id,
731
+ "tool_name": "structured_input",
732
+ "arguments": None,
733
+ }
734
+ elif event_type == "interaction.resolved":
735
+ interaction_kind = str(runtime_event.get("interaction_kind") or "")
736
+ response = runtime_event.get("response") or {}
737
+ if not isinstance(response, Mapping):
738
+ response = {}
739
+ response_type = str(response.get("response_type") or "")
740
+ interaction_id = str(runtime_event.get("interaction_id") or "")
741
+ if response_type == "approval":
742
+ decision = str(response.get("decision") or "")
743
+ normalized["EventType"] = "approval_response"
744
+ normalized["Content"] = {"detail": response}
745
+ normalized_metadata["resume_input"] = {
746
+ "approval_request_id": interaction_id,
747
+ "approve": decision in ("approved", "approve", True),
748
+ "decision": decision,
749
+ }
750
+ source = runtime_event.get("source") or {}
751
+ source_metadata = source.get("metadata") if isinstance(source, Mapping) else None
752
+ if isinstance(source_metadata, Mapping) and source_metadata.get("protocol") == "ag-ui":
753
+ normalized_metadata["protocol"] = "ag-ui"
754
+ else:
755
+ normalized["EventType"] = "approval_response"
756
+ normalized["Content"] = {"detail": response}
757
+ normalized_metadata["resume_input"] = {
758
+ "approval_request_id": interaction_id,
759
+ "approve": True,
760
+ "decision": "approved",
761
+ }
762
+ else:
763
+ return event
764
+
765
+ normalized["Metadata"] = normalized_metadata
766
+ return normalized
767
+
768
+
508
769
  def _normalize_runtime_event(
509
770
  event: Mapping[str, Any],
510
771
  *,
511
772
  agui_invocations: set[str],
512
773
  ) -> Mapping[str, Any]:
513
774
  metadata = _event_metadata(event)
514
- if not metadata.get("ksadk_runtime_event"):
775
+ is_canonical = metadata.get("ksadk_canonical_runtime_event")
776
+ if not metadata.get("ksadk_runtime_event") and not is_canonical:
515
777
  return event
516
778
  raw_content = event.get("Content")
517
779
  content = raw_content if isinstance(raw_content, Mapping) else {}
780
+ if is_canonical:
781
+ return _normalize_canonical_event(event, content, metadata)
518
782
  payload = content.get("payload")
519
783
  payload = payload if isinstance(payload, Mapping) else {}
520
784
  event_type = str(event.get("EventType") or "")
@@ -522,17 +786,17 @@ def _normalize_runtime_event(
522
786
  normalized["Content"] = dict(payload)
523
787
  normalized_metadata = dict(metadata)
524
788
 
525
- if event_type == EventType.RUN_STARTED and payload.get("source") == "ag-ui":
789
+ if event_type == "run.started" and payload.get("source") == "ag-ui":
526
790
  normalized["EventType"] = "user_message"
527
791
  normalized["Content"] = {"text": _input_text(payload.get("input"))}
528
792
  normalized["Author"] = "user"
529
- elif event_type == EventType.TEXT_COMPLETED:
793
+ elif event_type == "text.completed":
530
794
  normalized["EventType"] = "assistant_message"
531
- elif event_type == EventType.TEXT_DELTA:
795
+ elif event_type == "text.delta":
532
796
  normalized["EventType"] = "assistant_stream_delta"
533
- elif event_type in {EventType.REASONING_DELTA, EventType.REASONING_COMPLETED}:
797
+ elif event_type in {"reasoning.delta", "reasoning.completed"}:
534
798
  normalized["EventType"] = "reasoning"
535
- elif event_type == EventType.TOOL_CALL_BEGIN:
799
+ elif event_type == "tool.call.begin":
536
800
  normalized["EventType"] = "tool_call"
537
801
  normalized_metadata.update(
538
802
  {
@@ -541,7 +805,7 @@ def _normalize_runtime_event(
541
805
  "tool_args": payload.get("args"),
542
806
  }
543
807
  )
544
- elif event_type == EventType.TOOL_CALL_END:
808
+ elif event_type == "tool.call.end":
545
809
  normalized["EventType"] = "tool_result"
546
810
  normalized_metadata.update(
547
811
  {
@@ -550,7 +814,7 @@ def _normalize_runtime_event(
550
814
  "tool_output": payload.get("result", payload.get("error")),
551
815
  }
552
816
  )
553
- elif event_type == EventType.APPROVAL_REQUESTED:
817
+ elif event_type == "approval.requested":
554
818
  detail = payload.get("detail")
555
819
  detail = detail if isinstance(detail, Mapping) else {}
556
820
  approval_request = detail.get("approval_requests")
@@ -593,7 +857,7 @@ def _normalize_runtime_event(
593
857
  )
594
858
  if is_agui_approval:
595
859
  normalized_metadata["protocol"] = "ag-ui"
596
- elif event_type == EventType.APPROVAL_RESOLVED:
860
+ elif event_type == "approval.resolved":
597
861
  decision = payload.get("decision")
598
862
  normalized["EventType"] = "approval_response"
599
863
  normalized_metadata["resume_input"] = {
@@ -156,7 +156,7 @@ def estimate_text_tokens(text: str) -> int:
156
156
  """轻量 token 估算。
157
157
 
158
158
  当前先做一层比 `len/4` 更稳的启发式:
159
- - CJK 字符按 1 token 估算,避免中文场景长期卡在 0% / 1%
159
+ - CJK 字符按约 1.5 token 估算,降低中文场景的系统性低估
160
160
  - 其他字符继续按 4 chars ~= 1 token 估算
161
161
 
162
162
  这仍然不是真实 tokenizer,但比纯英文口径更接近本地中文使用体验。
@@ -176,10 +176,10 @@ def estimate_text_tokens(text: str) -> int:
176
176
  or 0x4E00 <= codepoint <= 0x9FFF
177
177
  or 0xF900 <= codepoint <= 0xFAFF
178
178
  ):
179
- cjk_tokens += 1
179
+ cjk_tokens += 1.5 # tiktoken cl100k_base: CJK ~1.5 tokens/char
180
180
  else:
181
181
  ascii_chars += 1
182
- return max(1, cjk_tokens + math.ceil(ascii_chars / 4))
182
+ return max(1, int(cjk_tokens) + math.ceil(ascii_chars / 4))
183
183
 
184
184
 
185
185
  def get_context_window_tokens(model_metadata: Mapping[str, Any] | None = None) -> int:
@@ -226,6 +226,52 @@ def get_auto_compact_threshold_percentage(model_metadata: Mapping[str, Any] | No
226
226
  return max(0, min(100, int(round((threshold_tokens / context_window) * 100))))
227
227
 
228
228
 
229
+ # --- PR D1:双阈值(仅 ksadk_hosted 路径使用) ---
230
+ # soft_limit:proactive 整理触发线(默认 50% effective window)。
231
+ # hard_limit:proactive 强制压缩触发线(≈ 现单阈值,默认 ~84%),尽量在 PTL 之前止血。
232
+ # 非 ksadk_hosted 路径仍用 get_auto_compact_threshold_tokens 单阈值,行为不变。
233
+ KSADK_COMPACT_SOFT_LIMIT_PCT_DEFAULT = 50
234
+ KSADK_COMPACT_HARD_LIMIT_PCT_DEFAULT = 85
235
+
236
+
237
+ def _compact_limit_pct_env(name: str, default: int) -> int:
238
+ import os
239
+
240
+ raw = os.environ.get(name)
241
+ if raw is None or str(raw).strip() == "":
242
+ return default
243
+ try:
244
+ return max(1, min(100, int(raw)))
245
+ except ValueError:
246
+ return default
247
+
248
+
249
+ def get_auto_compact_soft_limit_tokens(model_metadata: Mapping[str, Any] | None = None) -> int:
250
+ """soft_limit:proactive 整理触发线(默认 effective window 的 50%)。
251
+
252
+ 百分比可由 env ``KSADK_COMPACT_SOFT_LIMIT_PCT`` 覆盖(1..100)。
253
+ """
254
+ pct = _compact_limit_pct_env(
255
+ "KSADK_COMPACT_SOFT_LIMIT_PCT", KSADK_COMPACT_SOFT_LIMIT_PCT_DEFAULT
256
+ )
257
+ effective = get_effective_context_window_tokens(model_metadata)
258
+ return max(1, math.floor(effective * pct / 100))
259
+
260
+
261
+ def get_auto_compact_hard_limit_tokens(model_metadata: Mapping[str, Any] | None = None) -> int:
262
+ """hard_limit:proactive 强制压缩触发线(≈ 现单阈值算法,reserve+buffer)。
263
+
264
+ 默认复用 ``get_auto_compact_threshold_tokens``(~84%)。可由 env
265
+ ``KSADK_COMPACT_HARD_LIMIT_PCT`` 覆盖为按百分比计算(1..100);未设则用现阈值算法,
266
+ 保证与 PTL/非门控路径的既有 hard 边界一致。
267
+ """
268
+ pct_env = _compact_limit_pct_env("KSADK_COMPACT_HARD_LIMIT_PCT", 0) # 0 = 未设,走现算法
269
+ if pct_env:
270
+ effective = get_effective_context_window_tokens(model_metadata)
271
+ return max(1, math.floor(effective * pct_env / 100))
272
+ return get_auto_compact_threshold_tokens(model_metadata)
273
+
274
+
229
275
  def normalize_model_metadata(raw_model: Mapping[str, Any] | str | None) -> dict[str, Any]:
230
276
  """把模型目录统一规范成稳定 shape。
231
277