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
ksadk/a2ui/core.py CHANGED
@@ -13,6 +13,7 @@ action ``a2ui.action``。均带 ``surface_id``(G0.2 必填键)。
13
13
  from __future__ import annotations
14
14
 
15
15
  import logging
16
+ import time
16
17
  import uuid
17
18
  from typing import Any, Optional
18
19
 
@@ -22,7 +23,21 @@ from ksadk.a2ui.models import (
22
23
  PendingInteraction,
23
24
  Surface,
24
25
  )
25
- from ksadk.events.runtime_event import EventType, RuntimeEvent
26
+ from ksadk.events.canonical import (
27
+ ContentSnapshot,
28
+ InteractionRequested,
29
+ ItemCompleted,
30
+ ItemStarted,
31
+ ItemUpdated,
32
+ RuntimeEvent,
33
+ SourceRef,
34
+ )
35
+ from ksadk.events.content import DataContent
36
+ from ksadk.events.identity import (
37
+ stable_event_id,
38
+ stable_item_id,
39
+ stable_scope_id,
40
+ )
26
41
  from ksadk.events.store import RuntimeEventStore
27
42
 
28
43
  logger = logging.getLogger(__name__)
@@ -33,6 +48,9 @@ class A2UICore:
33
48
 
34
49
  所有 A2UI 事件经 :class:`RuntimeEventStore` 持久化(**不另开通道、不经 A2A 绕过**),
35
50
  供 session 级订阅 / replay / 审计消费。
51
+
52
+ Canonical 映射:surface = ``item_kind=data`` + ``source.protocol="a2ui"``;
53
+ user action / input request = ``InteractionRequested``。
36
54
  """
37
55
 
38
56
  def __init__(
@@ -43,6 +61,9 @@ class A2UICore:
43
61
  user_id: str,
44
62
  session_id: str,
45
63
  catalog: dict[str, frozenset[str]] = BASIC_CATALOG,
64
+ interaction_ledger: Any | None = None,
65
+ interaction_guard: Any | None = None,
66
+ tenant_id: str = "default",
46
67
  ) -> None:
47
68
  self._store = store
48
69
  self._agent_id = agent_id
@@ -51,25 +72,59 @@ class A2UICore:
51
72
  self._catalog = catalog
52
73
  self._seq = 0
53
74
  self._seen_surfaces: set[str] = set()
75
+ # InteractionLedger 存在时它是 pending interaction 的唯一权威
76
+ # (Phase 1 Task 5 Step 6);本地 dict 只作无 ledger 的降级路径。
77
+ self._ledger = interaction_ledger
78
+ self._guard = interaction_guard
79
+ self._tenant_id = tenant_id
54
80
  self._pending: dict[str, PendingInteraction] = {}
55
81
 
56
- # ---- 内部:产出并持久化一个 A2UI RuntimeEvent ----
82
+ # ---- 内部:canonical 身份/信封 ----
57
83
 
58
- async def _emit(
59
- self, event_type: str, invocation_id: str, payload: dict[str, Any]
60
- ) -> RuntimeEvent:
61
- self._seq += 1
62
- event = RuntimeEvent.create(
63
- event_type,
64
- agent_id=self._agent_id,
65
- user_id=self._user_id,
66
- session_id=self._session_id,
67
- invocation_id=invocation_id,
68
- seq_id=self._seq,
69
- payload=payload,
84
+ def _scope_id(self, invocation_id: str) -> str:
85
+ return stable_scope_id("ksadk", self._session_id, invocation_id)
86
+
87
+ def _surface_item_id(self, invocation_id: str, surface_id: str) -> str:
88
+ return stable_item_id("ksadk", self._session_id, invocation_id, "a2ui", surface_id)
89
+
90
+ def _source(self, invocation_id: str, surface_id: str) -> SourceRef:
91
+ return SourceRef(
92
+ framework="ksadk",
93
+ protocol="a2ui",
94
+ native_run_id=invocation_id,
95
+ metadata={
96
+ "agent_id": self._agent_id,
97
+ "user_id": self._user_id,
98
+ "session_id": self._session_id,
99
+ "invocation_id": invocation_id,
100
+ "surface_id": surface_id,
101
+ },
70
102
  )
71
- # 经 RuntimeEvent 持久化(A7 store)——canonical,不绕过。
72
- await self._store.append_one(event)
103
+
104
+ def _envelope(
105
+ self,
106
+ invocation_id: str,
107
+ item_id: str,
108
+ event_type: str,
109
+ part_id: str,
110
+ surface_id: str = "",
111
+ ) -> dict[str, Any]:
112
+ self._seq += 1
113
+ return {
114
+ "schema_version": 2,
115
+ "event_id": stable_event_id(
116
+ "ksadk", self._scope_id(invocation_id), item_id, event_type, part_id,
117
+ invocation_id, self._seq,
118
+ ),
119
+ "seq": self._seq,
120
+ "timestamp": time.time(),
121
+ "run_id": invocation_id,
122
+ "scope_id": self._scope_id(invocation_id),
123
+ "source": self._source(invocation_id, surface_id or item_id.split(":")[-1]),
124
+ }
125
+
126
+ async def _append(self, event: RuntimeEvent) -> RuntimeEvent:
127
+ await self._store.append_one(self._session_id, event)
73
128
  return event
74
129
 
75
130
  # ---- 三种交互 ----
@@ -81,24 +136,31 @@ class A2UICore:
81
136
  invocation_id: str,
82
137
  origin: str = "local",
83
138
  ) -> str:
84
- """展示 surface(不阻塞)。首显发 surface.begin,重复显发 surface.update。"""
139
+ """展示 surface(不阻塞)。首显发 item.started,重复显发 item.updated。"""
85
140
  surface.validate(self._catalog)
86
- event_type = (
87
- EventType.A2UI_SURFACE_BEGIN
88
- if surface.surface_id not in self._seen_surfaces
89
- else EventType.A2UI_SURFACE_UPDATE
90
- )
141
+ item_id = self._surface_item_id(invocation_id, surface.surface_id)
142
+ part_id = "a2ui-surface"
143
+ surface_data = surface.to_dict()
144
+ is_new = surface.surface_id not in self._seen_surfaces
91
145
  self._seen_surfaces.add(surface.surface_id)
92
- await self._emit(
93
- event_type,
94
- invocation_id,
95
- {
96
- "surface_id": surface.surface_id,
97
- "catalog_id": surface.catalog_id,
98
- "surface": surface.to_dict(),
99
- "origin": origin,
100
- },
101
- )
146
+ if is_new:
147
+ event = ItemStarted(
148
+ **self._envelope(invocation_id, item_id, "item.started", part_id, surface_id=surface.surface_id),
149
+ item_id=item_id,
150
+ item_kind="data",
151
+ initial=ContentSnapshot(
152
+ parts=(DataContent(part_id=part_id, data=surface_data),)
153
+ ),
154
+ )
155
+ else:
156
+ event = ItemUpdated(
157
+ **self._envelope(invocation_id, item_id, "item.updated", part_id, surface_id=surface.surface_id),
158
+ item_id=item_id,
159
+ item_kind="data",
160
+ op="replace",
161
+ update=DataContent(part_id=part_id, data=surface_data),
162
+ )
163
+ await self._append(event)
102
164
  return surface.surface_id
103
165
 
104
166
  async def request_ui_input(
@@ -117,23 +179,77 @@ class A2UICore:
117
179
  """
118
180
  # 先展示(确保 surface 已渲染),再请求输入。
119
181
  await self.display_ui(surface, invocation_id=invocation_id, origin=origin)
182
+ interaction_id = f"int_{uuid.uuid4().hex[:12]}"
183
+ if self._ledger is not None and self._guard is not None:
184
+ # Phase 1 Task 5 Step 6:durable ledger 是 pending interaction 的
185
+ # 唯一权威;持久化身份与 interaction.requested 事实由 ledger 落盘。
186
+ from datetime import datetime, timezone
187
+
188
+ from ksadk.interaction.contracts import InteractionRecord
189
+
190
+ record = InteractionRecord(
191
+ interaction_id=interaction_id,
192
+ tenant_id=self._tenant_id,
193
+ agent_instance_id=self._agent_id,
194
+ session_id=self._session_id,
195
+ run_id=invocation_id,
196
+ kind="structured_input",
197
+ request_schema=dict(schema),
198
+ created_at=datetime.now(timezone.utc).isoformat(),
199
+ )
200
+ stored = await self._ledger.request(record, guard=self._guard)
201
+ interaction = PendingInteraction(
202
+ interaction_id=stored.interaction_id,
203
+ surface_id=surface.surface_id,
204
+ kind=kind,
205
+ input_schema=dict(schema),
206
+ status=stored.status,
207
+ )
208
+ self._pending[interaction.interaction_id] = interaction
209
+ # canonical A2UI wire 事实照常产出(durable 权威在 ledger)。
210
+ item_id = stable_item_id(
211
+ "ksadk", self._session_id, invocation_id,
212
+ "a2ui-interaction", interaction.interaction_id,
213
+ )
214
+ from ksadk.events.canonical import StructuredInputRequest
215
+
216
+ request = StructuredInputRequest(prompt=None, schema=dict(schema))
217
+ event = InteractionRequested(
218
+ **self._envelope(
219
+ invocation_id, item_id, "interaction.requested", "a2ui-interaction"
220
+ ),
221
+ interaction_id=interaction.interaction_id,
222
+ interaction_kind="structured_input",
223
+ request=request,
224
+ )
225
+ event.source.metadata["surface_id"] = surface.surface_id
226
+ event.source.metadata["kind"] = kind
227
+ await self._append(event)
228
+ return interaction
120
229
  interaction = PendingInteraction(
121
- interaction_id=f"int_{uuid.uuid4().hex[:12]}",
230
+ interaction_id=interaction_id,
122
231
  surface_id=surface.surface_id,
123
232
  kind=kind,
124
233
  input_schema=dict(schema),
125
234
  )
126
235
  self._pending[interaction.interaction_id] = interaction
127
- await self._emit(
128
- EventType.A2UI_INTERACTION,
129
- invocation_id,
130
- {
131
- "surface_id": surface.surface_id,
132
- "interaction_id": interaction.interaction_id,
133
- "kind": kind,
134
- "input_schema": dict(schema),
135
- },
236
+ item_id = stable_item_id(
237
+ "ksadk", self._session_id, invocation_id, "a2ui-interaction", interaction.interaction_id
136
238
  )
239
+ from ksadk.events.canonical import StructuredInputRequest
240
+
241
+ request = StructuredInputRequest(prompt=None, schema=dict(schema))
242
+ event = InteractionRequested(
243
+ **self._envelope(
244
+ invocation_id, item_id, "interaction.requested", "a2ui-interaction"
245
+ ),
246
+ interaction_id=interaction.interaction_id,
247
+ interaction_kind="structured_input",
248
+ request=request,
249
+ )
250
+ event.source.metadata["surface_id"] = surface.surface_id
251
+ event.source.metadata["kind"] = kind
252
+ await self._append(event)
137
253
  return interaction
138
254
 
139
255
  async def submit_action(
@@ -145,7 +261,10 @@ class A2UICore:
145
261
  ) -> ActionReceipt:
146
262
  """非阻塞 action(原 run 可已结束):登记 action.received,返回幂等回执。
147
263
 
148
- ``action``: ``{"action_id","surface_id","name","actor"?,"component_id"?}``。
264
+ ``action``: ``{"action_id","surface_id","name","actor"?,"component_id"?}``;
265
+ 携带 ``interaction_id`` 且配置了 InteractionLedger 时,对原 ID 建
266
+ InteractionSubmission 走 durable resolve,不再发第二个
267
+ InteractionRequested(Phase 1 Task 5 Step 6)。
149
268
  """
150
269
  receipt = ActionReceipt(
151
270
  action_id=str(action.get("action_id") or f"act_{uuid.uuid4().hex[:12]}"),
@@ -154,33 +273,83 @@ class A2UICore:
154
273
  actor=str(action.get("actor") or "user"),
155
274
  status="received",
156
275
  )
157
- await self._emit(
158
- EventType.A2UI_ACTION,
159
- invocation_id,
160
- {
161
- "surface_id": receipt.surface_id,
276
+ if (
277
+ self._ledger is not None
278
+ and self._guard is not None
279
+ and action.get("interaction_id")
280
+ ):
281
+ # durable 路径:对原 interaction 建 submission(first-wins),
282
+ # 不再产出第二个 interaction.requested 事实。
283
+ from ksadk.interaction.contracts import InteractionSubmission
284
+
285
+ submission = InteractionSubmission(
286
+ interaction_id=str(action["interaction_id"]),
287
+ expected_revision=int(action.get("expected_revision") or 1),
288
+ action="submit",
289
+ response=dict(action),
290
+ idempotency_key=f"a2ui-action:{receipt.action_id}",
291
+ )
292
+ resolved = await self._ledger.resolve(submission, guard=self._guard)
293
+ receipt.status = resolved.status
294
+ pending = self._pending.get(submission.interaction_id)
295
+ if pending is not None:
296
+ pending.status = resolved.status
297
+ return receipt
298
+ item_id = stable_item_id(
299
+ "ksadk", self._session_id, invocation_id, "a2ui-action", receipt.action_id
300
+ )
301
+ from ksadk.events.canonical import ApprovalRequest
302
+
303
+ request = ApprovalRequest(
304
+ call_id=None,
305
+ kind="a2ui_action",
306
+ detail={
162
307
  "action_id": receipt.action_id,
308
+ "surface_id": receipt.surface_id,
163
309
  "name": receipt.name,
164
310
  "actor": receipt.actor,
165
311
  "component_id": action.get("component_id"),
166
312
  "origin": origin,
167
313
  },
168
314
  )
315
+ event = InteractionRequested(
316
+ **self._envelope(
317
+ invocation_id, item_id, "interaction.requested", "a2ui-action"
318
+ ),
319
+ interaction_id=receipt.action_id,
320
+ interaction_kind="approval",
321
+ request=request,
322
+ )
323
+ await self._append(event)
169
324
  return receipt
170
325
 
171
326
  async def end_surface(self, surface_id: str, *, invocation_id: str) -> None:
172
- """结束 surface(surface.end)。"""
173
- await self._emit(
174
- EventType.A2UI_SURFACE_END,
175
- invocation_id,
176
- {"surface_id": surface_id},
327
+ """结束 surface(item.completed)。"""
328
+ item_id = self._surface_item_id(invocation_id, surface_id)
329
+ event = ItemCompleted(
330
+ **self._envelope(invocation_id, item_id, "item.completed", "a2ui-surface", surface_id=surface_id),
331
+ item_id=item_id,
332
+ item_kind="data",
333
+ snapshot=ContentSnapshot(parts=()),
177
334
  )
335
+ await self._append(event)
178
336
  self._seen_surfaces.discard(surface_id)
179
337
 
180
338
  # ---- 查询 ----
181
339
 
182
340
  def pending_interaction(self, interaction_id: str) -> Optional[PendingInteraction]:
341
+ """查询 pending interaction。
342
+
343
+ 配置了 ledger 时,durable 台账是权威;本地缓存条目由
344
+ request_ui_input / submit_action 随 durable 事实同步更新。
345
+ """
183
346
  return self._pending.get(interaction_id)
184
347
 
348
+ async def pending_interaction_record(self, interaction_id: str):
349
+ """durable 视角:从 InteractionLedger 读取 InteractionRecord。"""
350
+ if self._ledger is None:
351
+ return None
352
+ return await self._ledger.get(interaction_id)
353
+
185
354
 
186
355
  __all__ = ["A2UICore"]
@@ -0,0 +1,243 @@
1
+ """KsadkAGUIAgent 的静态辅助函数(纯移动自 ``ksadk.agui.agent``,行为不变)。
2
+
3
+ 类内保留同名 staticmethod 委托,对外 ``KsadkAGUIAgent._x`` 调用面不变。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ from typing import TYPE_CHECKING, Any, Mapping
10
+
11
+ from ag_ui.core import Interrupt, RunAgentInput
12
+
13
+ from ksadk.agui.a2ui_projection import project_a2ui_operations
14
+ from ksadk.events.canonical import (
15
+ ContentSnapshot,
16
+ InteractionRequested,
17
+ ItemCompleted,
18
+ ItemStarted,
19
+ ItemUpdated,
20
+ )
21
+ from ksadk.events.content import DataContent, TextContent
22
+ from ksadk.runtime.adapter import RunHandle
23
+
24
+ if TYPE_CHECKING:
25
+ from ksadk.agui.agent import _ThreadRun
26
+
27
+
28
+ def approval_decision_for_audit(status: str, payload: Any) -> str:
29
+ """Persist a stable decision value while accepting official AG-UI envelopes."""
30
+
31
+ if status != "resolved":
32
+ return "rejected"
33
+ if payload is True:
34
+ return "approved"
35
+ if isinstance(payload, Mapping):
36
+ for key in ("approve", "approved"):
37
+ if key in payload:
38
+ return "approved" if bool(payload[key]) else "rejected"
39
+ for key in ("decision", "type"):
40
+ if key in payload:
41
+ return approval_decision_for_audit(status, payload[key])
42
+ return "rejected"
43
+ if isinstance(payload, str) and payload.strip().lower() in {"approve", "approved"}:
44
+ return "approved"
45
+ return "rejected"
46
+
47
+
48
+ def durable_handle(handle: RunHandle) -> dict[str, Any]:
49
+ allowed = {
50
+ "agent_id",
51
+ "user_id",
52
+ "checkpoint_id",
53
+ "known_checkpoint_ids",
54
+ "pending_approval_ids",
55
+ "framework_ref",
56
+ "thread_id",
57
+ "checkpoint_ns",
58
+ "resume_thread_id",
59
+ }
60
+ native_ref = {key: value for key, value in handle.native_ref.items() if key in allowed}
61
+ return {
62
+ "run_id": handle.run_id,
63
+ "session_id": handle.session_id,
64
+ "runtime_type": handle.runtime_type,
65
+ "native_ref": json_safe(native_ref),
66
+ }
67
+
68
+
69
+ def interrupt_from_payload(payload: Mapping[str, Any]) -> Interrupt:
70
+ interrupt_id = str(payload.get("approval_id") or payload.get("call_id") or "")
71
+ raw_detail = payload.get("detail")
72
+ detail = raw_detail if isinstance(raw_detail, dict) else {}
73
+ return Interrupt(
74
+ id=interrupt_id,
75
+ reason=str(detail.get("reason") or payload.get("kind") or "approval"),
76
+ message=approval_message(detail, payload),
77
+ tool_call_id=str(payload.get("call_id") or "") or None,
78
+ response_schema=detail.get("response_schema"),
79
+ metadata=approval_metadata(detail, payload),
80
+ )
81
+
82
+
83
+ def interrupt_from_interaction(event: InteractionRequested) -> Interrupt:
84
+ detail = event.request.detail if isinstance(event.request.detail, dict) else {}
85
+ payload = {
86
+ "approval_id": event.interaction_id,
87
+ "call_id": event.request.call_id or "",
88
+ "kind": event.request.kind,
89
+ "detail": detail,
90
+ }
91
+ return interrupt_from_payload(payload)
92
+
93
+
94
+ def extract_text(snapshot: ContentSnapshot | None) -> str:
95
+ if snapshot is None:
96
+ return ""
97
+ for part in snapshot.parts:
98
+ if isinstance(part, TextContent):
99
+ return part.text
100
+ return ""
101
+
102
+
103
+ def first_part(snapshot: ContentSnapshot | None) -> Any:
104
+ if snapshot is None or not snapshot.parts:
105
+ return None
106
+ return snapshot.parts[0]
107
+
108
+
109
+ def a2ui_operations(
110
+ event: ItemStarted | ItemUpdated | ItemCompleted,
111
+ surface_id: str,
112
+ ) -> list[dict[str, Any]]:
113
+ if isinstance(event, ItemStarted):
114
+ part = first_part(event.initial)
115
+ if isinstance(part, DataContent):
116
+ if isinstance(part.data, list):
117
+ return [dict(op) for op in part.data if isinstance(op, Mapping)]
118
+ if isinstance(part.data, Mapping):
119
+ # Surface data dict (surface_id, catalog_id, components, etc.)
120
+ # Use project_a2ui_operations to extract canonical operations.
121
+ return project_a2ui_operations("a2ui.surface.begin", dict(part.data))
122
+ return []
123
+ if isinstance(event, ItemUpdated):
124
+ if isinstance(event.update, DataContent):
125
+ if isinstance(event.update.data, list):
126
+ return [dict(op) for op in event.update.data if isinstance(op, Mapping)]
127
+ if isinstance(event.update.data, Mapping):
128
+ return project_a2ui_operations("a2ui.surface.update", dict(event.update.data))
129
+ return []
130
+ # ItemCompleted (end): produce deleteSurface to preserve AG-UI wire
131
+ if surface_id:
132
+ return [{"version": "v0.9", "deleteSurface": {"surfaceId": surface_id}}]
133
+ return []
134
+
135
+
136
+ def duplicate_run(input: RunAgentInput) -> "_ThreadRun":
137
+ from ksadk.agui.agent import _ThreadRun
138
+
139
+ return _ThreadRun(
140
+ handle=RunHandle(
141
+ run_id=input.run_id,
142
+ session_id=input.thread_id,
143
+ runtime_type="ag-ui-duplicate",
144
+ )
145
+ )
146
+
147
+
148
+ def json_safe(value: Any) -> Any:
149
+ return json.loads(json.dumps(value, ensure_ascii=False, default=str))
150
+
151
+
152
+ def latest_user_input(input: RunAgentInput) -> Any:
153
+ for message in reversed(input.messages):
154
+ if getattr(message, "role", None) == "user":
155
+ return getattr(message, "content", "")
156
+ return ""
157
+
158
+
159
+ def input_text(value: Any) -> str:
160
+ if isinstance(value, str):
161
+ return value.strip()
162
+ if isinstance(value, Mapping):
163
+ return str(value.get("text") or value.get("content") or "").strip()
164
+ return str(value or "").strip()
165
+
166
+
167
+ def approval_action(detail: Mapping[str, Any]) -> Mapping[str, Any]:
168
+ nested_request = detail.get("approval_requests")
169
+ actions = (
170
+ nested_request.get("action_requests")
171
+ if isinstance(nested_request, Mapping)
172
+ else detail.get("action_requests")
173
+ )
174
+ if isinstance(actions, list):
175
+ for action in actions:
176
+ if isinstance(action, Mapping):
177
+ return action
178
+ return {}
179
+
180
+
181
+ def approval_metadata(
182
+ detail: Mapping[str, Any],
183
+ payload: Mapping[str, Any],
184
+ ) -> dict[str, Any]:
185
+ action = approval_action(detail)
186
+ arguments = (
187
+ action.get("args")
188
+ or action.get("arguments")
189
+ or detail.get("arguments")
190
+ or detail.get("args")
191
+ or payload.get("args")
192
+ )
193
+ metadata: dict[str, Any] = {
194
+ "tool_name": str(
195
+ action.get("name")
196
+ or detail.get("tool_name")
197
+ or payload.get("name")
198
+ or payload.get("kind")
199
+ or "approval"
200
+ ),
201
+ "arguments": arguments if arguments is not None else {},
202
+ }
203
+ approval_level = (
204
+ action.get("approval_level")
205
+ or detail.get("approval_level")
206
+ or payload.get("approval_level")
207
+ )
208
+ if approval_level:
209
+ metadata["approval_level"] = str(approval_level)
210
+ return metadata
211
+
212
+
213
+ def approval_message(detail: Mapping[str, Any], payload: Mapping[str, Any]) -> str:
214
+ action = approval_action(detail)
215
+ return str(
216
+ action.get("description")
217
+ or detail.get("message")
218
+ or payload.get("message")
219
+ or "Approval required"
220
+ )
221
+
222
+
223
+ def resume_fingerprint(status: str, payload: Any) -> Any:
224
+ return json.dumps([status, payload], sort_keys=True, ensure_ascii=False, default=str)
225
+
226
+
227
+ __all__ = [
228
+ "a2ui_operations",
229
+ "approval_action",
230
+ "approval_decision_for_audit",
231
+ "approval_message",
232
+ "approval_metadata",
233
+ "durable_handle",
234
+ "duplicate_run",
235
+ "extract_text",
236
+ "first_part",
237
+ "input_text",
238
+ "interrupt_from_interaction",
239
+ "interrupt_from_payload",
240
+ "json_safe",
241
+ "latest_user_input",
242
+ "resume_fingerprint",
243
+ ]
@@ -5,11 +5,18 @@ from __future__ import annotations
5
5
  from collections.abc import Mapping
6
6
  from typing import Any
7
7
 
8
- from ksadk.events.runtime_event import EventType
9
-
10
8
 
11
9
  def project_a2ui_operations(event_type: str, payload: Mapping[str, Any]) -> list[dict[str, Any]]:
12
- """Return A2UI v0.9 operations carried by an AG-UI activity event."""
10
+ """Return A2UI v0.9 operations carried by an AG-UI activity event.
11
+
12
+ 公开承诺字段(契约声明见 ``ksadk/events/projections.py``):
13
+ - 操作列表,每条形如 ``{"version": "v0.9", createSurface|updateComponents|
14
+ updateDataModel|deleteSurface: {...}}``,内层必含 ``surfaceId``;
15
+ - 无 surface 信息时返回空列表。
16
+
17
+ 内部不保证字段:操作的构造来源(显式 operations vs 从 surface 推导)、
18
+ catalogId 缺省值之外的字段顺序与附加键。
19
+ """
13
20
 
14
21
  explicit = payload.get("operations", payload.get("a2ui_operations"))
15
22
  if isinstance(explicit, list):
@@ -18,7 +25,7 @@ def project_a2ui_operations(event_type: str, payload: Mapping[str, Any]) -> list
18
25
  surface_id = str(payload.get("surface_id") or payload.get("surfaceId") or "")
19
26
  if not surface_id:
20
27
  return []
21
- if event_type == EventType.A2UI_SURFACE_END:
28
+ if event_type == "a2ui.surface.end":
22
29
  return [{"version": "v0.9", "deleteSurface": {"surfaceId": surface_id}}]
23
30
 
24
31
  surface = payload.get("surface")
@@ -26,7 +33,7 @@ def project_a2ui_operations(event_type: str, payload: Mapping[str, Any]) -> list
26
33
  components = _flatten_components(surface_data.get("components"))
27
34
  data_model = surface_data.get("data_model", surface_data.get("dataModel"))
28
35
  operations: list[dict[str, Any]] = []
29
- if event_type == EventType.A2UI_SURFACE_BEGIN:
36
+ if event_type == "a2ui.surface.begin":
30
37
  catalog_id = str(
31
38
  surface_data.get("catalog_id")
32
39
  or surface_data.get("catalogId")