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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
  2. agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
  3. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +2 -0
  5. ksadk/a2a/_space_client_events.py +381 -0
  6. ksadk/a2a/bootstrap.py +0 -2
  7. ksadk/a2a/card.py +6 -111
  8. ksadk/a2a/control_plane.py +239 -1
  9. ksadk/a2a/event_adapter.py +156 -64
  10. ksadk/a2a/executor.py +195 -172
  11. ksadk/a2a/routes.py +12 -5
  12. ksadk/a2a/server.py +1 -8
  13. ksadk/a2a/service_env.py +33 -0
  14. ksadk/a2a/space_client.py +43 -349
  15. ksadk/a2a_card.py +101 -0
  16. ksadk/a2ui/core.py +222 -53
  17. ksadk/agui/_agent_helpers.py +243 -0
  18. ksadk/agui/a2ui_projection.py +12 -5
  19. ksadk/agui/agent.py +474 -275
  20. ksadk/agui/config.py +11 -5
  21. ksadk/agui/routes.py +7 -15
  22. ksadk/api/client.py +530 -40
  23. ksadk/api/environment.py +27 -0
  24. ksadk/builders/code_builder.py +352 -53
  25. ksadk/builders/container_builder.py +71 -44
  26. ksadk/builders/framework_requirements.py +2 -1
  27. ksadk/builders/ks3_uploader.py +2 -2
  28. ksadk/builders/managed_runtime_builder.py +60 -28
  29. ksadk/cli/__init__.py +25 -0
  30. ksadk/cli/cmd_a2a.py +18 -31
  31. ksadk/cli/cmd_create.py +13 -26
  32. ksadk/cli/cmd_dashboard.py +15 -1
  33. ksadk/cli/cmd_deploy.py +28 -3
  34. ksadk/cli/cmd_eval.py +443 -0
  35. ksadk/cli/cmd_evalset.py +284 -0
  36. ksadk/cli/cmd_files.py +5 -1
  37. ksadk/cli/cmd_hermes.py +137 -163
  38. ksadk/cli/cmd_invoke.py +28 -38
  39. ksadk/cli/cmd_launch.py +12 -0
  40. ksadk/cli/cmd_managed_runtime.py +95 -0
  41. ksadk/cli/cmd_observe.py +85 -0
  42. ksadk/cli/cmd_openclaw.py +85 -479
  43. ksadk/cli/cmd_replay.py +28 -4
  44. ksadk/cli/cmd_run.py +29 -67
  45. ksadk/cli/cmd_studio.py +201 -0
  46. ksadk/cli/cmd_web.py +15 -6
  47. ksadk/cli/dry_run.py +2 -1
  48. ksadk/cli/env_options.py +83 -0
  49. ksadk/cli/global_options.py +3 -1
  50. ksadk/cli/hermes_env.py +151 -0
  51. ksadk/cli/invoke_payload.py +49 -0
  52. ksadk/cli/network_options.py +7 -5
  53. ksadk/cli/openclaw_env.py +458 -0
  54. ksadk/cli/runtime_bootstrap.py +51 -0
  55. ksadk/cli/ui.py +6 -0
  56. ksadk/cli/workflow_common.py +5 -5
  57. ksadk/codex/__init__.py +3 -3
  58. ksadk/codex/client.py +833 -49
  59. ksadk/codex/phase.py +1 -1
  60. ksadk/codex/runtime.py +720 -127
  61. ksadk/common/kop_client.py +232 -0
  62. ksadk/configs/__init__.py +1 -3
  63. ksadk/configs/env_registry.py +244 -45
  64. ksadk/configs/env_registry_pcm.py +181 -0
  65. ksadk/configs/env_var_spec.py +18 -0
  66. ksadk/configs/global_config.py +6 -1
  67. ksadk/configs/settings.py +5 -108
  68. ksadk/context_engine/__init__.py +98 -0
  69. ksadk/context_engine/assembler.py +176 -0
  70. ksadk/context_engine/baseline.py +419 -0
  71. ksadk/context_engine/cache_observability.py +228 -0
  72. ksadk/context_engine/capabilities.py +443 -0
  73. ksadk/context_engine/contributors.py +344 -0
  74. ksadk/context_engine/hosted_pipeline.py +417 -0
  75. ksadk/context_engine/models.py +117 -0
  76. ksadk/context_engine/planner.py +698 -0
  77. ksadk/context_engine/policies.py +319 -0
  78. ksadk/context_engine/projection.py +31 -0
  79. ksadk/context_engine/shadow_plan.py +266 -0
  80. ksadk/context_engine/tokenizer.py +164 -0
  81. ksadk/conversations/__init__.py +85 -94
  82. ksadk/conversations/context.py +126 -6
  83. ksadk/conversations/message_projection.py +292 -28
  84. ksadk/conversations/model_context.py +49 -3
  85. ksadk/conversations/runtime_compaction.py +207 -5
  86. ksadk/conversations/runtime_input.py +193 -3
  87. ksadk/conversations/runtime_invocation.py +81 -3
  88. ksadk/conversations/runtime_observability.py +157 -4
  89. ksadk/conversations/runtime_payloads.py +42 -0
  90. ksadk/conversations/runtime_preparation.py +280 -2
  91. ksadk/conversations/runtime_resume.py +71 -32
  92. ksadk/conversations/runtime_stream_events.py +94 -9
  93. ksadk/conversations/runtime_streaming.py +175 -22
  94. ksadk/conversations/semantic_summary.py +311 -1
  95. ksadk/conversations/session_lock.py +51 -0
  96. ksadk/deployment/env_forward.py +72 -0
  97. ksadk/deployment/managed_runtime.py +38 -0
  98. ksadk/deployment/manager.py +24 -8
  99. ksadk/deployment/providers/serverless.py +228 -92
  100. ksadk/evaluation/__init__.py +116 -0
  101. ksadk/evaluation/a2a_adapter.py +452 -0
  102. ksadk/evaluation/adapters.py +67 -0
  103. ksadk/evaluation/agent_eval_client.py +395 -0
  104. ksadk/evaluation/cloud_binding.py +80 -0
  105. ksadk/evaluation/cloud_converter.py +194 -0
  106. ksadk/evaluation/cloud_service.py +199 -0
  107. ksadk/evaluation/contracts.py +478 -0
  108. ksadk/evaluation/evalset.py +351 -0
  109. ksadk/evaluation/evaluators.py +627 -0
  110. ksadk/evaluation/evidence.py +258 -0
  111. ksadk/evaluation/executor.py +143 -0
  112. ksadk/evaluation/local_adapter.py +550 -0
  113. ksadk/evaluation/service_env.py +27 -0
  114. ksadk/evaluation/storage.py +68 -0
  115. ksadk/evaluation/studio_build_adapter.py +253 -0
  116. ksadk/evaluation/target.py +82 -0
  117. ksadk/events/__init__.py +13 -13
  118. ksadk/events/_v1_compat/__init__.py +1 -0
  119. ksadk/events/_v1_compat/models.py +299 -0
  120. ksadk/events/_v1_compat/parser.py +247 -0
  121. ksadk/events/_v1_compat/projection.py +753 -0
  122. ksadk/events/adapters/__init__.py +34 -0
  123. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  124. ksadk/events/adapters/_a2a_support.py +275 -0
  125. ksadk/events/adapters/_codex_interactions.py +375 -0
  126. ksadk/events/adapters/_codex_items.py +801 -0
  127. ksadk/events/adapters/_codex_validators.py +311 -0
  128. ksadk/events/adapters/_langgraph_support.py +785 -0
  129. ksadk/events/adapters/a2a.py +841 -0
  130. ksadk/events/adapters/adk.py +503 -0
  131. ksadk/events/adapters/codex.py +717 -0
  132. ksadk/events/adapters/langgraph.py +745 -0
  133. ksadk/events/canonical.py +440 -0
  134. ksadk/events/canonical_replay.py +497 -0
  135. ksadk/events/canonical_store.py +468 -0
  136. ksadk/events/cold_recovery.py +257 -0
  137. ksadk/events/content.py +89 -0
  138. ksadk/events/identity.py +86 -0
  139. ksadk/events/pipeline.py +455 -0
  140. ksadk/events/projections.py +66 -0
  141. ksadk/events/reducer.py +661 -0
  142. ksadk/events/replay.py +3 -36
  143. ksadk/events/runtime_event.py +20 -256
  144. ksadk/events/session_event.py +324 -0
  145. ksadk/events/store.py +3 -316
  146. ksadk/events/v1_compat.py +41 -0
  147. ksadk/harness/__init__.py +3 -2
  148. ksadk/harness/app.py +114 -123
  149. ksadk/harness/config.py +1 -1
  150. ksadk/harness/runtime.py +467 -0
  151. ksadk/hermes_terminal.py +5 -0
  152. ksadk/identity/resolver.py +4 -3
  153. ksadk/interaction/__init__.py +28 -0
  154. ksadk/interaction/contracts.py +136 -0
  155. ksadk/interaction/ledger.py +189 -0
  156. ksadk/interaction/provider.py +122 -0
  157. ksadk/interaction/providers/__init__.py +52 -0
  158. ksadk/interaction/providers/adk.py +40 -0
  159. ksadk/interaction/providers/codex.py +94 -0
  160. ksadk/interaction/providers/langgraph.py +58 -0
  161. ksadk/kernel/__init__.py +117 -0
  162. ksadk/kernel/authorization.py +258 -0
  163. ksadk/kernel/bootstrap.py +1074 -0
  164. ksadk/kernel/contract_fingerprints.py +61 -0
  165. ksadk/kernel/contracts.py +362 -0
  166. ksadk/kernel/control.py +219 -0
  167. ksadk/kernel/errors.py +79 -0
  168. ksadk/kernel/ingress.py +1102 -0
  169. ksadk/kernel/mapping.py +111 -0
  170. ksadk/kernel/memory_store.py +1133 -0
  171. ksadk/kernel/postgres_store.py +1756 -0
  172. ksadk/kernel/recovery.py +452 -0
  173. ksadk/kernel/runtime_identity.py +103 -0
  174. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  175. ksadk/kernel/sqlite_store.py +1410 -0
  176. ksadk/kernel/state.py +145 -0
  177. ksadk/kernel/store.py +232 -0
  178. ksadk/kernel/worker.py +953 -0
  179. ksadk/knowledge_base/client.py +22 -4
  180. ksadk/knowledge_base/service.py +32 -5
  181. ksadk/managed_a2a_card.py +160 -0
  182. ksadk/managed_runtime.py +16 -9
  183. ksadk/memory/__init__.py +61 -0
  184. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  185. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  186. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  187. ksadk/memory/adk/backends/sdk_ltm_backend.py +394 -5
  188. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  189. ksadk/memory/adk/long_term_memory.py +3 -2
  190. ksadk/memory/coordinator.py +461 -0
  191. ksadk/memory/events.py +202 -0
  192. ksadk/memory/extraction.py +228 -0
  193. ksadk/memory/ltm_backend_factory.py +16 -3
  194. ksadk/memory/models.py +316 -0
  195. ksadk/memory/policy.py +215 -0
  196. ksadk/memory/provider.py +47 -0
  197. ksadk/memory/provider_adapter.py +159 -0
  198. ksadk/memory/provider_resolver.py +71 -0
  199. ksadk/memory/providers/__init__.py +5 -0
  200. ksadk/memory/providers/local_sqlite.py +490 -0
  201. ksadk/memory/resolved_policy.py +145 -0
  202. ksadk/memory/service.py +198 -8
  203. ksadk/memory/tool.py +4 -0
  204. ksadk/model_proxy/bootstrap.py +16 -9
  205. ksadk/model_proxy/config.py +22 -1
  206. ksadk/model_proxy/detect.py +202 -9
  207. ksadk/model_proxy/namespace.py +67 -15
  208. ksadk/model_proxy/server.py +168 -6
  209. ksadk/model_proxy/transform.py +105 -3
  210. ksadk/observability/__init__.py +25 -0
  211. ksadk/observability/session_log.py +420 -0
  212. ksadk/observability/trajectory.py +105 -0
  213. ksadk/prompts/__init__.py +71 -0
  214. ksadk/prompts/compiler.py +215 -0
  215. ksadk/prompts/models.py +82 -0
  216. ksadk/prompts/projection.py +89 -0
  217. ksadk/prompts/resolved.py +137 -0
  218. ksadk/prompts/sources.py +233 -0
  219. ksadk/runners/_langgraph_runner_streams.py +822 -0
  220. ksadk/runners/adk_runner.py +14 -31
  221. ksadk/runners/base_runner.py +44 -3
  222. ksadk/runners/factory.py +3 -3
  223. ksadk/runners/langgraph_runner.py +252 -433
  224. ksadk/runners/utils/__init__.py +0 -10
  225. ksadk/runners/utils/loader.py +16 -0
  226. ksadk/runtime/__init__.py +67 -41
  227. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  228. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  229. ksadk/runtime/adapter.py +199 -16
  230. ksadk/runtime/conversation_execution.py +687 -0
  231. ksadk/runtime/executor.py +392 -0
  232. ksadk/runtime/factory.py +342 -0
  233. ksadk/runtime/framework_adapters.py +6 -12
  234. ksadk/runtime/hosted_finalizer.py +268 -0
  235. ksadk/runtime/launch.py +61 -0
  236. ksadk/runtime/preprocessing.py +49 -14
  237. ksadk/runtime/runner_adapter.py +330 -391
  238. ksadk/runtime/runner_loading.py +36 -0
  239. ksadk/runtime/usage.py +33 -0
  240. ksadk/sandbox/backends/e2b.py +36 -3
  241. ksadk/server/__init__.py +39 -4
  242. ksadk/server/app.py +18 -492
  243. ksadk/server/composition.py +36 -2
  244. ksadk/server/factory.py +210 -149
  245. ksadk/server/routes/common.py +15 -46
  246. ksadk/server/routes/control.py +13 -9
  247. ksadk/server/routes/kernel_ingress.py +258 -0
  248. ksadk/server/routes/misc.py +10 -33
  249. ksadk/server/routes/models.py +14 -6
  250. ksadk/server/routes/openai_compat.py +129 -27
  251. ksadk/server/routes/projection.py +84 -16
  252. ksadk/server/routes/run.py +347 -460
  253. ksadk/server/routes/sessions.py +37 -40
  254. ksadk/server/routes/streaming.py +52 -7
  255. ksadk/server/routes/workspace.py +54 -21
  256. ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  257. ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
  258. ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  259. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  260. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  261. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  262. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  263. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  264. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  265. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  266. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  267. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  268. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  269. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  270. ksadk/server/static/assets/{chunk-FMBD7UC4-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  271. ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  272. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  273. ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  274. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  275. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  276. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  277. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  278. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  279. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  280. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  281. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-CX3yotHq.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  282. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  283. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  284. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  285. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  286. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  287. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  288. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  289. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  290. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  291. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  292. ksadk/server/static/assets/{dist-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
  293. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  294. ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
  295. ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
  296. ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
  297. ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
  298. ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
  299. ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
  300. ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
  301. ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
  302. ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
  303. ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
  304. ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
  305. ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
  306. ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
  307. ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
  308. ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
  309. ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
  310. ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
  311. ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
  312. ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
  313. ksadk/server/static/assets/{dist-C99THtIA.js → dist-ngtN0DJB.js} +1 -1
  314. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  315. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  316. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  317. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  318. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  319. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  320. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  321. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  322. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  323. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  324. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  325. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  326. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  327. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  328. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  329. ksadk/server/static/assets/{linear-CvMBw9cA.js → linear-BHjG8b-J.js} +1 -1
  330. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  331. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-CSAQxEAe.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  332. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  333. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  334. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  335. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  336. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-CxIR4JXI.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  337. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  338. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  339. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  340. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  341. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  342. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  343. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  344. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  345. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  346. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  347. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  348. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  349. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  350. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  351. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-jqoYs3jQ.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  352. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  353. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  354. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  355. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  356. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  357. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  358. ksadk/server/static/index.html +2 -2
  359. ksadk/sessions/__init__.py +26 -9
  360. ksadk/sessions/_local_service_sync.py +688 -0
  361. ksadk/sessions/_local_tables.py +21 -0
  362. ksadk/sessions/_postgres_schema.py +305 -0
  363. ksadk/sessions/_postgres_tables.py +15 -0
  364. ksadk/sessions/base.py +80 -1
  365. ksadk/sessions/in_memory.py +53 -2
  366. ksadk/sessions/local_service.py +63 -604
  367. ksadk/sessions/postgres_service.py +58 -148
  368. ksadk/sessions/resilient.py +35 -1
  369. ksadk/skills/runtime/backends/e2b.py +1 -1
  370. ksadk/skills/service_client.py +13 -3
  371. ksadk/studio/__init__.py +5 -0
  372. ksadk/studio/agent_avatar_assets.py +120 -0
  373. ksadk/studio/agent_lifecycle.py +51 -0
  374. ksadk/studio/api.py +1598 -0
  375. ksadk/studio/api_catalog_routes.py +324 -0
  376. ksadk/studio/api_contracts.py +286 -0
  377. ksadk/studio/api_helpers.py +132 -0
  378. ksadk/studio/api_memory_routes.py +82 -0
  379. ksadk/studio/authoring.py +749 -0
  380. ksadk/studio/authoring_coordinator.py +1017 -0
  381. ksadk/studio/builder.py +397 -0
  382. ksadk/studio/capabilities.py +368 -0
  383. ksadk/studio/cloud.py +2099 -0
  384. ksadk/studio/codex_agent_service.py +694 -0
  385. ksadk/studio/codex_authoring.py +469 -0
  386. ksadk/studio/codex_builder.py +437 -0
  387. ksadk/studio/codex_manifest.py +307 -0
  388. ksadk/studio/codex_run.py +395 -0
  389. ksadk/studio/compiler.py +190 -0
  390. ksadk/studio/contracts.py +755 -0
  391. ksadk/studio/errors.py +47 -0
  392. ksadk/studio/event_store.py +214 -0
  393. ksadk/studio/framework_run.py +342 -0
  394. ksadk/studio/hosted_kernel.py +317 -0
  395. ksadk/studio/identifiers.py +33 -0
  396. ksadk/studio/manifest_resolver.py +131 -0
  397. ksadk/studio/mcp_runtime.py +229 -0
  398. ksadk/studio/model_client.py +629 -0
  399. ksadk/studio/model_profile_service.py +214 -0
  400. ksadk/studio/operations.py +275 -0
  401. ksadk/studio/otel_trace.py +1060 -0
  402. ksadk/studio/pagination.py +182 -0
  403. ksadk/studio/pcm_memory.py +85 -0
  404. ksadk/studio/python_tool_inspection.py +183 -0
  405. ksadk/studio/repository.py +327 -0
  406. ksadk/studio/resource_catalog.py +1260 -0
  407. ksadk/studio/run_service.py +1133 -0
  408. ksadk/studio/runtime_catalog.py +74 -0
  409. ksadk/studio/runtime_source.py +365 -0
  410. ksadk/studio/service.py +2249 -0
  411. ksadk/studio/shared_web.py +1004 -0
  412. ksadk/studio/skill_discovery.py +628 -0
  413. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  414. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  415. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  416. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  417. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  418. ksadk/studio/static/index.html +15 -0
  419. ksadk/studio/templates.py +722 -0
  420. ksadk/studio/validator.py +265 -0
  421. ksadk/studio/workspace.py +135 -0
  422. ksadk/tools/gateway.py +9 -0
  423. ksadk/toolsets/__init__.py +27 -1
  424. ksadk/toolsets/a2a.py +426 -0
  425. ksadk/tracing/__init__.py +19 -21
  426. ksadk/tracing/setup.py +317 -403
  427. ksadk/tracing/span_utils.py +0 -44
  428. ksadk/version.py +1 -1
  429. ksadk_runtime_common/memory_backend/registry.py +56 -56
  430. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  431. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  432. ksadk_runtime_common/workspace_files/router.py +8 -2
  433. agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
  434. ksadk/a2a/card_builder.py +0 -64
  435. ksadk/a2a/client.py +0 -309
  436. ksadk/events/parser.py +0 -191
  437. ksadk/harness/runner.py +0 -211
  438. ksadk/runners/codex_runner.py +0 -132
  439. ksadk/runners/utils/langfuse.py +0 -230
  440. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  441. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
  442. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
  443. ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
  444. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
  445. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
  446. ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
  447. ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
  448. ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
  449. ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
  450. ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
  451. ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
  452. ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
  453. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
  454. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
  455. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
  456. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  457. ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
  458. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  459. ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
  460. ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
  461. ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
  462. ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
  463. ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
  464. ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
  465. ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
  466. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
  467. ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
  468. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
  469. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
  470. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
  471. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  472. ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
  473. ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
  474. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
  475. ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
  476. ksadk/server/static/assets/katex-DATssjp1.js +0 -265
  477. ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
  478. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
  479. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
  480. ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
  481. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
  482. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
  483. ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
  484. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
  485. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
  486. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
  487. ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
  488. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
  489. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
  490. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
  491. ksadk/tracing/exporters/langfuse_exporter.py +0 -460
  492. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  493. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  494. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,455 @@
1
+ """Validated canonical event ingestion and deterministic conformance recovery."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import copy
7
+ import hashlib
8
+ import json
9
+ from collections import Counter
10
+ from collections.abc import Awaitable, Callable
11
+ from typing import Any, cast
12
+
13
+ from ksadk.events.canonical import (
14
+ ErrorInfo,
15
+ ItemCompleted,
16
+ ItemFailed,
17
+ ItemKind,
18
+ ItemSnapshotReplaced,
19
+ RunFailed,
20
+ RuntimeEvent,
21
+ SourceRef,
22
+ dump_runtime_event,
23
+ )
24
+ from ksadk.events.canonical_store import RuntimeEventStore
25
+ from ksadk.events.identity import stable_event_id
26
+ from ksadk.events.reducer import StreamConformanceError, StreamReducer
27
+ from ksadk.kernel.contracts import ActivationWriteGuard, WriteContext
28
+
29
+ Publisher = Callable[[str, RuntimeEvent], Awaitable[None]]
30
+
31
+
32
+ def _reconciliation_reason(event: RuntimeEvent) -> str:
33
+ if isinstance(event, ItemCompleted):
34
+ return "completed_snapshot_mismatch"
35
+ if isinstance(event, ItemSnapshotReplaced):
36
+ return "authoritative_snapshot_replace"
37
+ raise RuntimeError(f"reconciled patch has no declared metric semantics: {event.event_type!r}")
38
+
39
+
40
+ class PipelineMetrics:
41
+ """Small metrics seam; production collectors can mirror ``increment``."""
42
+
43
+ def __init__(self) -> None:
44
+ self._counts: Counter[tuple[str, tuple[tuple[str, str], ...]]] = Counter()
45
+
46
+ def increment(self, name: str, **labels: str) -> None:
47
+ self._counts[(name, tuple(sorted(labels.items())))] += 1
48
+
49
+ def value(self, name: str, **labels: str) -> int:
50
+ return self._counts[(name, tuple(sorted(labels.items())))]
51
+
52
+
53
+ class CanonicalEventPipeline:
54
+ """Prevalidate, persist, reduce and publish one canonical source mutation."""
55
+
56
+ def __init__(
57
+ self,
58
+ store: RuntimeEventStore,
59
+ *,
60
+ session_id: str,
61
+ reducer: StreamReducer | None = None,
62
+ publisher: Publisher | None = None,
63
+ metrics: PipelineMetrics | None = None,
64
+ ) -> None:
65
+ if not session_id.strip():
66
+ raise ValueError("session_id must be nonempty")
67
+ self.store = store
68
+ self.session_id = session_id
69
+ self.reducer = reducer or StreamReducer()
70
+ self.publisher = publisher
71
+ self.metrics = metrics or PipelineMetrics()
72
+ self._ingest_lock = asyncio.Lock()
73
+ self._hydrated_run_id = self.reducer.snapshot().run_id
74
+
75
+ async def ingest(self, event: RuntimeEvent) -> tuple[RuntimeEvent, ...]:
76
+ """Ingest one fact; invalid source facts become durable failure facts."""
77
+
78
+ async with self._ingest_lock:
79
+ return await self._ingest_locked(event)
80
+
81
+ async def emit(
82
+ self, event: RuntimeEvent, *, write_context: WriteContext
83
+ ) -> RuntimeEvent:
84
+ """Fenced typed append: persist (guard CAS) before publish.
85
+
86
+ 与 :meth:`ingest` 的差异:``emit`` 是 owner 内部写入路径,要求
87
+ ``WriteContext(activation_id, fencing_token)``,通过 typed
88
+ ``RuntimeEventStore``(SessionEventStore envelope 视图)走
89
+ ``append(event, guard=write_context)``;Store 在事务内比较 fence 后
90
+ 才分配 seq,旧 owner 在 takeover 后写入会得到
91
+ :class:`~ksadk.kernel.errors.StaleFenceError`。WriteContext 只作为
92
+ 写权限 guard,不进入 RuntimeEvent payload,也不进入公网 projection。
93
+ """
94
+
95
+ if not isinstance(write_context, ActivationWriteGuard):
96
+ raise TypeError(
97
+ "emit requires a typed WriteContext(activation_id, fencing_token)"
98
+ )
99
+ if self.store.event_store is None:
100
+ raise RuntimeError(
101
+ "emit requires a SessionEventStore-backed typed RuntimeEventStore"
102
+ )
103
+ if getattr(self.store, "session_id", None) != self.session_id:
104
+ raise ValueError("typed RuntimeEventStore session does not match pipeline")
105
+ # 先在影子 reducer 上预检 conformance,非法事实绝不落库。
106
+ shadow = copy.deepcopy(self.reducer)
107
+ shadow.apply(event.model_copy(update={"seq": self._validation_seq(event)}))
108
+ persisted = await self.store.append(event, guard=write_context)
109
+ last_seq = self.reducer.snapshot().last_seq
110
+ if last_seq is None or persisted.seq > last_seq:
111
+ self.reducer.apply(persisted)
112
+ await self._publish(persisted)
113
+ return persisted
114
+
115
+ async def _ingest_locked(self, event: RuntimeEvent) -> tuple[RuntimeEvent, ...]:
116
+ await self._hydrate_run_if_needed(event.run_id)
117
+ existing = await self.store.resolve_existing(self.session_id, event)
118
+ if existing is not None:
119
+ last_seq = self.reducer.snapshot().last_seq
120
+ if last_seq is None or existing.seq > last_seq:
121
+ self.reducer.apply(existing)
122
+ await self._publish(existing)
123
+ return (existing,)
124
+
125
+ candidate = event.model_copy(update={"seq": self._validation_seq(event)})
126
+ shadow = copy.deepcopy(self.reducer)
127
+ try:
128
+ preview = shadow.apply(candidate)
129
+ except StreamConformanceError as error:
130
+ return await self._recover(event, error)
131
+ reconciliation_reason = _reconciliation_reason(candidate) if preview.reconciled else None
132
+
133
+ persisted, created = await self.store.persist_one(self.session_id, event)
134
+ self.reducer.apply(persisted)
135
+ if created and reconciliation_reason is not None:
136
+ self.metrics.increment(
137
+ "stream_projection_reconciled_total",
138
+ source=event.source.framework,
139
+ reason=reconciliation_reason,
140
+ )
141
+ await self._publish(persisted)
142
+ return (persisted,)
143
+
144
+ async def _hydrate_run_if_needed(self, run_id: str) -> None:
145
+ if self._hydrated_run_id == run_id:
146
+ return
147
+ snapshot = self.reducer.snapshot()
148
+ if snapshot.run_id is not None and snapshot.run_id != run_id:
149
+ # Let the reducer produce its normal structured run-id error.
150
+ return
151
+ for persisted in await self.store.list(self.session_id, run_id=run_id):
152
+ self.reducer.apply(persisted)
153
+ self._hydrated_run_id = run_id
154
+
155
+ def _validation_seq(self, event: RuntimeEvent) -> int:
156
+ last_seq = self.reducer.snapshot().last_seq
157
+ return max((last_seq or 0) + 1, event.seq)
158
+
159
+ async def _recover(
160
+ self, offending: RuntimeEvent, error: StreamConformanceError
161
+ ) -> tuple[RuntimeEvent, ...]:
162
+ fingerprint = _canonical_fingerprint(offending)
163
+ terminal = await self.store.event_by_id(
164
+ self.session_id,
165
+ self._recovery_terminal_event_id(offending),
166
+ )
167
+ owner_locator = await self.store.event_by_id(
168
+ self.session_id,
169
+ self._recovery_owner_event_id(offending),
170
+ )
171
+ if terminal is not None or owner_locator is not None:
172
+ plan = self._load_recovery_plan(
173
+ offending,
174
+ fingerprint,
175
+ terminal=terminal,
176
+ owner_locator=owner_locator,
177
+ )
178
+ else:
179
+ plan = self._new_recovery_plan(offending, error, fingerprint)
180
+ self.metrics.increment(
181
+ "stream_conformance_error_total",
182
+ source=error.source,
183
+ reason=error.code,
184
+ )
185
+
186
+ planned = self._recovery_facts(offending, plan, fingerprint)
187
+ persisted_group: list[RuntimeEvent] = []
188
+ # Persist the complete plan before changing live projection or emitting.
189
+ for fact in planned:
190
+ persisted, _created = await self.store.persist_one(self.session_id, fact)
191
+ persisted_group.append(persisted)
192
+ # Apply the complete durable group before the first publish attempt.
193
+ for persisted in persisted_group:
194
+ last_seq = self.reducer.snapshot().last_seq
195
+ if last_seq is None or persisted.seq > last_seq:
196
+ self.reducer.apply(persisted)
197
+ # A retry republishes the whole group from its first member. Duplicate
198
+ # event ids are allowed at this live boundary; missing facts are not.
199
+ for persisted in persisted_group:
200
+ await self._publish(persisted)
201
+ return tuple(persisted_group)
202
+
203
+ def _load_recovery_plan(
204
+ self,
205
+ offending: RuntimeEvent,
206
+ fingerprint: str,
207
+ *,
208
+ terminal: RuntimeEvent | None,
209
+ owner_locator: RuntimeEvent | None,
210
+ ) -> dict[str, Any]:
211
+ terminal_id = self._recovery_terminal_event_id(offending)
212
+ owner_locator_id = self._recovery_owner_event_id(offending)
213
+ existing = tuple(event for event in (terminal, owner_locator) if event is not None)
214
+ owner_ids: set[str] = set()
215
+ for persisted in existing:
216
+ metadata = persisted.source.metadata
217
+ if (
218
+ metadata.get("recovery_for_event_id") != offending.event_id
219
+ or metadata.get("offending_fingerprint") != fingerprint
220
+ ):
221
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
222
+ owner_id = metadata.get("recovery_plan_owner_event_id")
223
+ if not isinstance(owner_id, str) or not owner_id:
224
+ raise ValueError("persisted recovery is missing its plan owner ref")
225
+ owner_ids.add(owner_id)
226
+ if len(owner_ids) != 1:
227
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
228
+
229
+ owner_id = owner_ids.pop()
230
+ if owner_id == terminal_id:
231
+ owner = terminal
232
+ elif owner_id == owner_locator_id:
233
+ owner = owner_locator
234
+ else:
235
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
236
+ if owner is None:
237
+ raise ValueError("persisted recovery plan owner is missing")
238
+ if terminal is not None and (
239
+ terminal.event_id != terminal_id or terminal.event_type != "run.failed"
240
+ ):
241
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
242
+ if owner_locator is not None and (
243
+ owner_locator.event_id != owner_locator_id or owner_locator.event_type != "item.failed"
244
+ ):
245
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
246
+ owner_metadata = owner.source.metadata
247
+ if (
248
+ owner.event_id != owner_id
249
+ or owner_metadata.get("recovery_for_event_id") != offending.event_id
250
+ or owner_metadata.get("offending_fingerprint") != fingerprint
251
+ or owner_metadata.get("recovery_plan_owner_event_id") != owner_id
252
+ ):
253
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
254
+ plan_value = owner_metadata.get("recovery_plan")
255
+ if not isinstance(plan_value, dict):
256
+ raise ValueError("persisted recovery plan owner is missing its complete plan")
257
+ if (
258
+ plan_value.get("offending_fingerprint") != fingerprint
259
+ or plan_value.get("owner_event_id") != owner_id
260
+ ):
261
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
262
+ entries = plan_value.get("events")
263
+ if (
264
+ not isinstance(entries, list)
265
+ or not entries
266
+ or not isinstance(entries[0], dict)
267
+ or entries[0].get("event_id") != owner_id
268
+ or entries[0].get("event_type")
269
+ != ("run.failed" if owner_id == terminal_id else "item.failed")
270
+ or not isinstance(entries[-1], dict)
271
+ or entries[-1].get("event_id") != terminal_id
272
+ or entries[-1].get("event_type") != "run.failed"
273
+ ):
274
+ raise ValueError(f"RuntimeEvent recovery collision for {offending.event_id!r}")
275
+ return plan_value
276
+
277
+ def _new_recovery_plan(
278
+ self,
279
+ offending: RuntimeEvent,
280
+ error: StreamConformanceError,
281
+ fingerprint: str,
282
+ ) -> dict[str, Any]:
283
+ entries: list[dict[str, Any]] = []
284
+ open_items = sorted(
285
+ (item for item in self.reducer.snapshot().items if item.status == "open"),
286
+ key=lambda item: (item.scope_id, item.item_id),
287
+ )
288
+ for index, item in enumerate(open_items):
289
+ entries.append(
290
+ {
291
+ "event_id": (
292
+ self._recovery_owner_event_id(offending)
293
+ if index == 0
294
+ else stable_event_id(
295
+ "ksadk",
296
+ item.scope_id,
297
+ item.item_id,
298
+ "item.failed",
299
+ "recovery",
300
+ offending.event_id,
301
+ 0,
302
+ )
303
+ ),
304
+ "event_type": "item.failed",
305
+ "scope_id": item.scope_id,
306
+ "item_id": item.item_id,
307
+ "item_kind": item.item_kind,
308
+ }
309
+ )
310
+ entries.append(
311
+ {
312
+ "event_id": self._recovery_terminal_event_id(offending),
313
+ "event_type": "run.failed",
314
+ "scope_id": offending.scope_id,
315
+ }
316
+ )
317
+ owner_event_id = str(entries[0]["event_id"])
318
+ return {
319
+ "version": 1,
320
+ "owner_event_id": owner_event_id,
321
+ "offending_fingerprint": fingerprint,
322
+ "error": {
323
+ "code": error.code,
324
+ "source": error.source,
325
+ "scope_id": error.scope_id,
326
+ "item_id": error.item_id,
327
+ },
328
+ "events": entries,
329
+ }
330
+
331
+ @staticmethod
332
+ def _recovery_owner_event_id(offending: RuntimeEvent) -> str:
333
+ return stable_event_id(
334
+ "ksadk",
335
+ "recovery",
336
+ offending.event_id,
337
+ "item.failed",
338
+ "plan-owner",
339
+ offending.event_id,
340
+ 0,
341
+ )
342
+
343
+ @staticmethod
344
+ def _recovery_terminal_event_id(offending: RuntimeEvent) -> str:
345
+ # The session-scoped offending event id is the collision domain. Do
346
+ # not include mutable candidate facts such as run/scope here: a retry
347
+ # that reuses event_id with different facts must hit this tombstone and
348
+ # fail fingerprint validation before writing a second recovery group.
349
+ return stable_event_id(
350
+ "ksadk",
351
+ "recovery",
352
+ offending.event_id,
353
+ "run.failed",
354
+ "tombstone",
355
+ offending.event_id,
356
+ 0,
357
+ )
358
+
359
+ @staticmethod
360
+ def _recovery_facts(
361
+ offending: RuntimeEvent,
362
+ plan: dict[str, Any],
363
+ fingerprint: str,
364
+ ) -> tuple[RuntimeEvent, ...]:
365
+ error_payload = plan.get("error")
366
+ entries = plan.get("events")
367
+ owner_event_id = plan.get("owner_event_id")
368
+ if (
369
+ not isinstance(error_payload, dict)
370
+ or not isinstance(entries, list)
371
+ or not isinstance(owner_event_id, str)
372
+ or not owner_event_id
373
+ ):
374
+ raise ValueError("persisted recovery plan is malformed")
375
+ error_info = ErrorInfo(
376
+ code=str(error_payload.get("code") or "stream_conformance_error"),
377
+ message="Canonical stream conformance failure",
378
+ source=str(error_payload.get("source") or offending.source.framework),
379
+ scope_id=str(error_payload.get("scope_id") or offending.scope_id),
380
+ item_id=(str(error_payload["item_id"]) if error_payload.get("item_id") else None),
381
+ source_ref=offending.source,
382
+ )
383
+ facts: list[RuntimeEvent] = []
384
+ for entry in entries:
385
+ if not isinstance(entry, dict):
386
+ raise ValueError("persisted recovery plan event is malformed")
387
+ event_id = str(entry.get("event_id") or "")
388
+ metadata: dict[str, Any] = {
389
+ "recovery_for_event_id": offending.event_id,
390
+ "offending_fingerprint": fingerprint,
391
+ "recovery_plan_owner_event_id": owner_event_id,
392
+ }
393
+ if event_id == owner_event_id:
394
+ metadata["recovery_plan"] = plan
395
+ recovery_source = SourceRef(
396
+ framework="ksadk",
397
+ native_event_id=offending.event_id,
398
+ native_run_id=offending.run_id,
399
+ metadata=metadata,
400
+ )
401
+ if entry.get("event_type") == "item.failed":
402
+ scope_id = str(entry.get("scope_id") or "")
403
+ item_id = str(entry.get("item_id") or "")
404
+ facts.append(
405
+ ItemFailed(
406
+ schema_version=2,
407
+ event_id=event_id,
408
+ seq=0,
409
+ timestamp=offending.timestamp,
410
+ run_id=offending.run_id,
411
+ run_seq=offending.run_seq,
412
+ scope_id=scope_id,
413
+ source=recovery_source,
414
+ item_id=item_id,
415
+ item_kind=cast(ItemKind, entry.get("item_kind") or "message"),
416
+ error=error_info.model_copy(
417
+ update={"scope_id": scope_id, "item_id": item_id}
418
+ ),
419
+ )
420
+ )
421
+ elif entry.get("event_type") == "run.failed":
422
+ facts.append(
423
+ RunFailed(
424
+ schema_version=2,
425
+ event_id=event_id,
426
+ seq=0,
427
+ timestamp=offending.timestamp,
428
+ run_id=offending.run_id,
429
+ run_seq=offending.run_seq,
430
+ scope_id=str(entry.get("scope_id") or offending.scope_id),
431
+ parent_scope_id=offending.parent_scope_id,
432
+ source=recovery_source,
433
+ status="failed",
434
+ error=error_info,
435
+ )
436
+ )
437
+ else:
438
+ raise ValueError("persisted recovery plan has unsupported event type")
439
+ return tuple(facts)
440
+
441
+ async def _publish(self, event: RuntimeEvent) -> None:
442
+ if self.publisher is not None:
443
+ await self.publisher(self.session_id, event)
444
+
445
+
446
+ __all__ = ["CanonicalEventPipeline", "PipelineMetrics"]
447
+
448
+
449
+ def _canonical_fingerprint(event: RuntimeEvent) -> str:
450
+ payload = dump_runtime_event(event)
451
+ payload.pop("seq", None)
452
+ encoded = json.dumps(payload, ensure_ascii=False, separators=(",", ":"), sort_keys=True).encode(
453
+ "utf-8"
454
+ )
455
+ return hashlib.sha256(encoded).hexdigest()
@@ -0,0 +1,66 @@
1
+ """Canonical 内部事实与公开投影的边界(重设计要素 3/3)。
2
+
3
+ canonical store(``ksadk/events/canonical_store.py`` 及 ``canonical.py`` 的事件
4
+ 模型)是唯一的存储事实(append-only、schema_version=2、含内部字段如
5
+ ``seq``/``run_seq``/``native_*``/``source.metadata``)。所有对外 wire 形态都是
6
+ 从 canonical 事实派生的**投影**:投影只承诺下表列出的最小公开字段集,除此之外
7
+ 的字段(含内部序号、native 游标、source 原始 metadata)均属内部不保证字段,
8
+ 消费方不得依赖。
9
+
10
+ 本模块是边界的**声明处**;契约的**执行形态**是 golden 测试
11
+ ``tests/protocol/test_cross_projection_golden.py`` 与 fixture
12
+ ``tests/events/fixtures/runtime_projection_golden.json``。修改任何投影的公开字段
13
+ 承诺必须同时更新本表与 golden 测试。
14
+
15
+ 投影矩阵(投影 | 实现位置 | 消费方 | 最小公开字段承诺):
16
+
17
+ | 投影 | 实现位置 | 消费方 | 公开承诺字段 |
18
+ | --- | --- | --- | --- |
19
+ | v1 legacy wire | ``events/v1_compat.py::project_to_v1`` | canonical_replay、cli cmd_replay、旧 SDK 客户端 | RuntimeEventV1 事件类型 + 各类型 payload(approval_id/call_id/kind/detail、surface_id/block_id/data、output_refs、status/error/reason)+ 身份字段 run_id/scope_id/item_id |
20
+ | Studio 事件流 | ``studio/run_service.py::project_runtime_event`` | 本地/托管 Studio UI(SSE) | ``runId``/``scopeId`` 全事件;message.*/thinking.* 含 ``itemId``/``partId``;tool.*/command.*/approval.*/a2ui.* 含 ``itemId``;a2ui.surface.* 含 ``surfaceId``/``a2uiOperations`` |
21
+ | AG-UI/A2UI operations | ``agui/a2ui_projection.py::project_a2ui_operations`` | AG-UI 兼容客户端与 message_projection | 操作列表 ``[{version: "v0.9", createSurface|updateComponents|updateDataModel|deleteSurface: ...}]``,每条含 ``surfaceId`` |
22
+ | 会话消息历史 | ``conversations/message_projection.py::project_session_messages`` | server GetSession/ListMessages、hosted UI 历史接口 | 消息 dict:``Role``/``Content.text``/``SeqId``/``StartSeqId``,可选 ``Reasoning``/``ToolEvents``(approval 含 ``ApprovalRequestId``)/``Activities``(含 ``surfaceId``) |
23
+ | Responses 历史 | ``conversations/context.py::project_responses_history`` | Responses API 请求回放 input | OpenAI Responses input items(``type``/``call_id``/``output``/role 消息),仅可靠 call_id 的 tool 项 |
24
+ | 模型 history | ``conversations/context.py::project_model_messages`` | 运行时模型上下文(内部投喂) | ``role``/``content`` 消息列表;control 事件不进入上下文 |
25
+ | server checkpoint payload | ``server/routes/projection.py::_checkpoint_event_to_action_payload`` | REST 断点续跑/预览接口 | ``EventId``/``SessionId``/``RunId``/``CheckpointId``/``Framework``/``FrameworkRef``/``IsResumable``/``ResumeStatus``/``IsTerminal``/``NextNode``(经 ``run_checkpoint`` 元数据或 ``continuation.created`` 投影) |
26
+ | server 动作事件 payload | ``server/routes/projection.py::_event_to_action_payload`` | REST 会话动作接口(事件原始形态透传) | ``EventId``/``SessionId``/``Author``/``EventType``/``Content``/``Timestamp``/``SeqId``(可选 ``InvocationId``)——序列化存储形态本身,非 canonical 派生 |
27
+
28
+ 内部不保证(任何投影都不承诺、消费方不得依赖):
29
+ - ``seq``/``run_seq`` 的具体数值与连续性(仅保序语义);
30
+ - ``source.native_event_id``/``native_cursor``/``native_run_id``/``native_item_id``;
31
+ - ``source.metadata`` 原始键值(capability 等仅经投影显式提炼后可见);
32
+ - 未列入上表的 payload 附加键。
33
+
34
+ 内部投影(非 wire,不构成公开承诺):
35
+ - ``events/reducer.py::StreamReducer.snapshot`` — 进程内 UI 聚合状态;
36
+ - ``events/canonical_replay.py::replay_projection`` — 内部重建 RunProjection 的路径,
37
+ 其 v1 输出复用 ``project_to_v1`` 的承诺。
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ PROJECTION_CONTRACT_VERSION = 1
43
+
44
+ #: 各投影实现位置的机器可读索引(供文档/校验工具引用;承诺文本见模块 docstring)。
45
+ PROJECTIONS: dict[str, str] = {
46
+ "v1": "ksadk.events.v1_compat:project_to_v1",
47
+ "studio": "ksadk.studio.run_service:project_runtime_event",
48
+ "a2ui": "ksadk.agui.a2ui_projection:project_a2ui_operations",
49
+ "session_messages": "ksadk.conversations.message_projection:project_session_messages",
50
+ "responses_history": "ksadk.conversations.context:project_responses_history",
51
+ "model_messages": "ksadk.conversations.context:project_model_messages",
52
+ "server_checkpoint": "ksadk.server.routes.projection:_checkpoint_event_to_action_payload",
53
+ "server_action_event": "ksadk.server.routes.projection:_event_to_action_payload",
54
+ }
55
+
56
+ #: 仅内部使用的投影(对外无 wire 契约)。
57
+ INTERNAL_PROJECTIONS: dict[str, str] = {
58
+ "stream_reducer": "ksadk.events.reducer:StreamReducer",
59
+ "replay_projection": "ksadk.events.canonical_replay:replay_projection",
60
+ }
61
+
62
+ __all__ = [
63
+ "INTERNAL_PROJECTIONS",
64
+ "PROJECTION_CONTRACT_VERSION",
65
+ "PROJECTIONS",
66
+ ]