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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
  3. ksadk/a2a/_space_client_events.py +381 -0
  4. ksadk/a2a/event_adapter.py +156 -64
  5. ksadk/a2a/executor.py +179 -63
  6. ksadk/a2a/space_client.py +6 -333
  7. ksadk/a2ui/core.py +222 -53
  8. ksadk/agui/_agent_helpers.py +243 -0
  9. ksadk/agui/a2ui_projection.py +12 -5
  10. ksadk/agui/agent.py +443 -259
  11. ksadk/api/client.py +525 -27
  12. ksadk/builders/code_builder.py +284 -8
  13. ksadk/builders/container_builder.py +8 -1
  14. ksadk/builders/managed_runtime_builder.py +39 -35
  15. ksadk/cli/__init__.py +17 -0
  16. ksadk/cli/cmd_dashboard.py +15 -1
  17. ksadk/cli/cmd_deploy.py +10 -2
  18. ksadk/cli/cmd_eval.py +66 -9
  19. ksadk/cli/cmd_evalset.py +284 -0
  20. ksadk/cli/cmd_files.py +5 -1
  21. ksadk/cli/cmd_hermes.py +1 -126
  22. ksadk/cli/cmd_invoke.py +28 -38
  23. ksadk/cli/cmd_managed_runtime.py +95 -0
  24. ksadk/cli/cmd_observe.py +85 -0
  25. ksadk/cli/cmd_openclaw.py +1 -435
  26. ksadk/cli/cmd_replay.py +28 -4
  27. ksadk/cli/cmd_studio.py +99 -8
  28. ksadk/cli/cmd_web.py +10 -2
  29. ksadk/cli/hermes_env.py +151 -0
  30. ksadk/cli/invoke_payload.py +49 -0
  31. ksadk/cli/openclaw_env.py +458 -0
  32. ksadk/codex/client.py +180 -30
  33. ksadk/codex/runtime.py +428 -326
  34. ksadk/configs/env_registry.py +66 -12
  35. ksadk/configs/env_registry_pcm.py +181 -0
  36. ksadk/configs/env_var_spec.py +18 -0
  37. ksadk/configs/global_config.py +5 -0
  38. ksadk/context_engine/__init__.py +98 -0
  39. ksadk/context_engine/assembler.py +176 -0
  40. ksadk/context_engine/baseline.py +419 -0
  41. ksadk/context_engine/cache_observability.py +228 -0
  42. ksadk/context_engine/capabilities.py +443 -0
  43. ksadk/context_engine/contributors.py +344 -0
  44. ksadk/context_engine/hosted_pipeline.py +417 -0
  45. ksadk/context_engine/models.py +117 -0
  46. ksadk/context_engine/planner.py +698 -0
  47. ksadk/context_engine/policies.py +319 -0
  48. ksadk/context_engine/projection.py +31 -0
  49. ksadk/context_engine/shadow_plan.py +266 -0
  50. ksadk/context_engine/tokenizer.py +164 -0
  51. ksadk/conversations/context.py +126 -6
  52. ksadk/conversations/message_projection.py +292 -28
  53. ksadk/conversations/model_context.py +49 -3
  54. ksadk/conversations/runtime_compaction.py +207 -5
  55. ksadk/conversations/runtime_input.py +184 -2
  56. ksadk/conversations/runtime_invocation.py +81 -3
  57. ksadk/conversations/runtime_observability.py +141 -0
  58. ksadk/conversations/runtime_payloads.py +42 -0
  59. ksadk/conversations/runtime_preparation.py +272 -2
  60. ksadk/conversations/runtime_resume.py +20 -1
  61. ksadk/conversations/runtime_stream_events.py +94 -9
  62. ksadk/conversations/semantic_summary.py +311 -1
  63. ksadk/conversations/session_lock.py +51 -0
  64. ksadk/deployment/env_forward.py +72 -0
  65. ksadk/deployment/managed_runtime.py +5 -0
  66. ksadk/deployment/providers/serverless.py +143 -69
  67. ksadk/evaluation/__init__.py +32 -0
  68. ksadk/evaluation/a2a_adapter.py +9 -1
  69. ksadk/evaluation/adapters.py +18 -5
  70. ksadk/evaluation/agent_eval_client.py +395 -0
  71. ksadk/evaluation/cloud_binding.py +80 -0
  72. ksadk/evaluation/cloud_converter.py +194 -0
  73. ksadk/evaluation/cloud_service.py +199 -0
  74. ksadk/evaluation/contracts.py +73 -4
  75. ksadk/evaluation/evaluators.py +183 -17
  76. ksadk/evaluation/evidence.py +258 -0
  77. ksadk/evaluation/executor.py +31 -6
  78. ksadk/evaluation/local_adapter.py +550 -0
  79. ksadk/evaluation/service_env.py +27 -0
  80. ksadk/evaluation/studio_build_adapter.py +253 -0
  81. ksadk/evaluation/target.py +15 -6
  82. ksadk/events/__init__.py +13 -13
  83. ksadk/events/_v1_compat/__init__.py +1 -0
  84. ksadk/events/_v1_compat/models.py +299 -0
  85. ksadk/events/_v1_compat/parser.py +247 -0
  86. ksadk/events/_v1_compat/projection.py +753 -0
  87. ksadk/events/adapters/__init__.py +34 -0
  88. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  89. ksadk/events/adapters/_a2a_support.py +275 -0
  90. ksadk/events/adapters/_codex_interactions.py +375 -0
  91. ksadk/events/adapters/_codex_items.py +801 -0
  92. ksadk/events/adapters/_codex_validators.py +311 -0
  93. ksadk/events/adapters/_langgraph_support.py +785 -0
  94. ksadk/events/adapters/a2a.py +841 -0
  95. ksadk/events/adapters/adk.py +503 -0
  96. ksadk/events/adapters/codex.py +717 -0
  97. ksadk/events/adapters/langgraph.py +745 -0
  98. ksadk/events/canonical.py +440 -0
  99. ksadk/events/canonical_replay.py +497 -0
  100. ksadk/events/canonical_store.py +468 -0
  101. ksadk/events/cold_recovery.py +257 -0
  102. ksadk/events/content.py +89 -0
  103. ksadk/events/identity.py +86 -0
  104. ksadk/events/pipeline.py +455 -0
  105. ksadk/events/projections.py +66 -0
  106. ksadk/events/reducer.py +661 -0
  107. ksadk/events/replay.py +3 -36
  108. ksadk/events/runtime_event.py +20 -265
  109. ksadk/events/session_event.py +324 -0
  110. ksadk/events/store.py +3 -316
  111. ksadk/events/v1_compat.py +41 -0
  112. ksadk/harness/runtime.py +160 -57
  113. ksadk/identity/resolver.py +4 -3
  114. ksadk/interaction/__init__.py +28 -0
  115. ksadk/interaction/contracts.py +136 -0
  116. ksadk/interaction/ledger.py +189 -0
  117. ksadk/interaction/provider.py +122 -0
  118. ksadk/interaction/providers/__init__.py +52 -0
  119. ksadk/interaction/providers/adk.py +40 -0
  120. ksadk/interaction/providers/codex.py +94 -0
  121. ksadk/interaction/providers/langgraph.py +58 -0
  122. ksadk/kernel/__init__.py +117 -0
  123. ksadk/kernel/authorization.py +258 -0
  124. ksadk/kernel/bootstrap.py +1074 -0
  125. ksadk/kernel/contract_fingerprints.py +61 -0
  126. ksadk/kernel/contracts.py +362 -0
  127. ksadk/kernel/control.py +219 -0
  128. ksadk/kernel/errors.py +79 -0
  129. ksadk/kernel/ingress.py +1102 -0
  130. ksadk/kernel/mapping.py +111 -0
  131. ksadk/kernel/memory_store.py +1133 -0
  132. ksadk/kernel/postgres_store.py +1756 -0
  133. ksadk/kernel/recovery.py +452 -0
  134. ksadk/kernel/runtime_identity.py +103 -0
  135. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  136. ksadk/kernel/sqlite_store.py +1410 -0
  137. ksadk/kernel/state.py +145 -0
  138. ksadk/kernel/store.py +232 -0
  139. ksadk/kernel/worker.py +953 -0
  140. ksadk/knowledge_base/client.py +7 -0
  141. ksadk/knowledge_base/service.py +32 -5
  142. ksadk/memory/__init__.py +61 -0
  143. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  144. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  145. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  146. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  147. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  148. ksadk/memory/coordinator.py +461 -0
  149. ksadk/memory/events.py +202 -0
  150. ksadk/memory/extraction.py +228 -0
  151. ksadk/memory/ltm_backend_factory.py +16 -3
  152. ksadk/memory/models.py +316 -0
  153. ksadk/memory/policy.py +215 -0
  154. ksadk/memory/provider.py +47 -0
  155. ksadk/memory/provider_adapter.py +159 -0
  156. ksadk/memory/provider_resolver.py +71 -0
  157. ksadk/memory/providers/__init__.py +5 -0
  158. ksadk/memory/providers/local_sqlite.py +490 -0
  159. ksadk/memory/resolved_policy.py +145 -0
  160. ksadk/memory/service.py +188 -6
  161. ksadk/model_proxy/bootstrap.py +16 -9
  162. ksadk/model_proxy/detect.py +202 -9
  163. ksadk/model_proxy/namespace.py +39 -15
  164. ksadk/model_proxy/server.py +24 -5
  165. ksadk/model_proxy/transform.py +60 -2
  166. ksadk/observability/__init__.py +25 -0
  167. ksadk/observability/session_log.py +420 -0
  168. ksadk/observability/trajectory.py +105 -0
  169. ksadk/prompts/__init__.py +71 -0
  170. ksadk/prompts/compiler.py +215 -0
  171. ksadk/prompts/models.py +82 -0
  172. ksadk/prompts/projection.py +89 -0
  173. ksadk/prompts/resolved.py +137 -0
  174. ksadk/prompts/sources.py +233 -0
  175. ksadk/runners/_langgraph_runner_streams.py +822 -0
  176. ksadk/runners/adk_runner.py +5 -5
  177. ksadk/runners/base_runner.py +16 -0
  178. ksadk/runners/factory.py +1 -2
  179. ksadk/runners/langgraph_runner.py +198 -437
  180. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  181. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  182. ksadk/runtime/adapter.py +118 -2
  183. ksadk/runtime/conversation_execution.py +316 -182
  184. ksadk/runtime/executor.py +144 -3
  185. ksadk/runtime/factory.py +193 -7
  186. ksadk/runtime/hosted_finalizer.py +268 -0
  187. ksadk/runtime/launch.py +14 -1
  188. ksadk/runtime/preprocessing.py +25 -3
  189. ksadk/runtime/runner_adapter.py +288 -508
  190. ksadk/runtime/usage.py +33 -0
  191. ksadk/sandbox/backends/e2b.py +35 -2
  192. ksadk/server/composition.py +8 -0
  193. ksadk/server/factory.py +69 -6
  194. ksadk/server/routes/kernel_ingress.py +258 -0
  195. ksadk/server/routes/openai_compat.py +88 -8
  196. ksadk/server/routes/projection.py +35 -20
  197. ksadk/server/routes/run.py +94 -0
  198. ksadk/server/routes/sessions.py +2 -0
  199. ksadk/server/routes/streaming.py +5 -2
  200. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  201. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
  202. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  203. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  204. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  205. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  206. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  207. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  208. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  209. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  210. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  211. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  212. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  213. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  214. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  215. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  216. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  217. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  218. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  219. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  220. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  221. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  222. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  223. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  224. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  225. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  226. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  227. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  228. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  229. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  230. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  231. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  232. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  233. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  234. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  235. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  236. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
  237. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  238. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
  239. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
  240. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
  241. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
  242. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
  243. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
  244. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
  245. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
  246. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
  247. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
  248. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
  249. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
  250. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
  251. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
  252. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
  253. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
  254. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
  255. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
  256. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
  257. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-ngtN0DJB.js} +1 -1
  258. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  259. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  260. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  261. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  262. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  263. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  264. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  265. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  266. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  267. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  268. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  269. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  270. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  271. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  272. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  273. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-BHjG8b-J.js} +1 -1
  274. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  275. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  276. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  277. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  278. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  279. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  280. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  281. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  282. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  283. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  284. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  285. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  286. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  287. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  288. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  289. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  290. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  291. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  292. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  293. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  294. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  295. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  296. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  297. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  298. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  299. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  300. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  301. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  302. ksadk/server/static/index.html +2 -2
  303. ksadk/sessions/__init__.py +26 -9
  304. ksadk/sessions/_local_service_sync.py +688 -0
  305. ksadk/sessions/_local_tables.py +21 -0
  306. ksadk/sessions/_postgres_schema.py +305 -0
  307. ksadk/sessions/_postgres_tables.py +15 -0
  308. ksadk/sessions/base.py +80 -1
  309. ksadk/sessions/in_memory.py +53 -2
  310. ksadk/sessions/local_service.py +63 -604
  311. ksadk/sessions/postgres_service.py +58 -148
  312. ksadk/sessions/resilient.py +35 -1
  313. ksadk/studio/api.py +577 -25
  314. ksadk/studio/api_contracts.py +114 -5
  315. ksadk/studio/api_memory_routes.py +82 -0
  316. ksadk/studio/authoring.py +252 -27
  317. ksadk/studio/authoring_coordinator.py +799 -67
  318. ksadk/studio/builder.py +88 -11
  319. ksadk/studio/capabilities.py +17 -0
  320. ksadk/studio/cloud.py +1916 -95
  321. ksadk/studio/codex_agent_service.py +125 -14
  322. ksadk/studio/codex_authoring.py +469 -0
  323. ksadk/studio/codex_builder.py +138 -25
  324. ksadk/studio/codex_manifest.py +51 -22
  325. ksadk/studio/codex_run.py +46 -3
  326. ksadk/studio/compiler.py +1 -0
  327. ksadk/studio/contracts.py +114 -3
  328. ksadk/studio/event_store.py +25 -95
  329. ksadk/studio/framework_run.py +231 -3
  330. ksadk/studio/hosted_kernel.py +317 -0
  331. ksadk/studio/manifest_resolver.py +131 -0
  332. ksadk/studio/model_client.py +95 -9
  333. ksadk/studio/model_profile_service.py +1 -1
  334. ksadk/studio/operations.py +37 -5
  335. ksadk/studio/otel_trace.py +348 -42
  336. ksadk/studio/pcm_memory.py +85 -0
  337. ksadk/studio/repository.py +23 -2
  338. ksadk/studio/resource_catalog.py +43 -0
  339. ksadk/studio/run_service.py +563 -137
  340. ksadk/studio/runtime_source.py +42 -16
  341. ksadk/studio/service.py +1180 -72
  342. ksadk/studio/shared_web.py +32 -22
  343. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  344. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  345. ksadk/studio/static/index.html +2 -2
  346. ksadk/studio/templates.py +100 -8
  347. ksadk/studio/validator.py +19 -0
  348. ksadk/studio/workspace.py +30 -32
  349. ksadk/tracing/setup.py +304 -3
  350. ksadk/version.py +1 -1
  351. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  352. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  353. ksadk/events/parser.py +0 -191
  354. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  355. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  356. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  357. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  358. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  359. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  360. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  361. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  362. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  363. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  364. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  365. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  366. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  367. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  368. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  369. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  370. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  371. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  372. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  373. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  374. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  375. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  376. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  377. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  378. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  379. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  380. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  381. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  382. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  383. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  384. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  385. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  386. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  387. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  388. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  389. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  390. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  391. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  392. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  393. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  394. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  395. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  396. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  397. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  398. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  399. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  400. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  401. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  402. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  404. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  405. ksadk/studio/evaluation.py +0 -192
  406. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  407. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  408. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
  409. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  410. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  411. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
ksadk/events/store.py CHANGED
@@ -1,317 +1,4 @@
1
- """RuntimeEventStore — 统一事件 store + 两类订阅 + projection (goal-10,H2 §4.3)。
1
+ """Public canonical RuntimeEvent storage implementation."""
2
2
 
3
- 复用现有 ``SessionEvent(seq_id cursor)`` 持久化骨架(session service),**不另造存储、
4
- 不改表**:RuntimeEvent 的 ``phase``/``payload``/``schema_version``/``user_id`` 打包进
5
- ``SessionEvent.content``/``metadata``(均为自由 dict),并以 ``_RUNTIME_MARKER`` 标记区分
6
- legacy session 事件(assistant_message/run_status 等),读取时只还原 runtime 事件。
7
-
8
- - ``append`` / ``list``:RuntimeEvent ↔ SessionEvent 双向映射。
9
- - ``subscribe_run``:单 invocation,终态(completed/failed/canceled)后关闭(对齐现有
10
- run 级 SSE 语义,新 schema)。
11
- - ``subscribe_session``:session 级 cursor stream,跨 invocation,支持 run 后 action 与
12
- replay(A2UI 依赖)。
13
- - ``project``:replay / 增量 projection(fold)。
14
- - cursor 断线续传:订阅方持 ``last_seq_id``,断线后按 ``after_seq_id`` 重连,不丢不重。
15
- """
16
-
17
- from __future__ import annotations
18
-
19
- import asyncio
20
- import logging
21
- from typing import Any, AsyncIterator, Callable, Iterable, Optional
22
-
23
- from ksadk.events.runtime_event import EventType, RuntimeEvent
24
- from ksadk.sessions.base import SessionEvent
25
-
26
- logger = logging.getLogger(__name__)
27
-
28
- #: SessionEvent.metadata 中的标记:该条是由 RuntimeEvent 持久化来的(区分 legacy 事件)。
29
- _RUNTIME_MARKER = "ksadk_runtime_event"
30
- _A2A_TASK_AGENT_STATE_KEY = "__ksadk_a2a_task_agents"
31
-
32
- #: run 终态(subscribe_run 遇到即关闭;interrupted 是 input-required 暂停,非终态)。
33
- _RUN_TERMINAL_EVENT_TYPES = frozenset(
34
- {
35
- EventType.RUN_COMPLETED,
36
- EventType.RUN_FAILED,
37
- EventType.RUN_CANCELED,
38
- }
39
- )
40
-
41
- #: 默认订阅轮询间隔(秒)与单条流上限(秒,防泄漏)。
42
- _DEFAULT_POLL_INTERVAL = 0.25
43
- _DEFAULT_STREAM_TIMEOUT = 5 * 60
44
-
45
-
46
- # ---------------------------------------------------------------------------
47
- # RuntimeEvent ↔ SessionEvent 映射
48
- # ---------------------------------------------------------------------------
49
-
50
-
51
- def runtime_event_to_session_event(event: RuntimeEvent) -> SessionEvent:
52
- """把 RuntimeEvent 打包为 SessionEvent(content/metadata 承载新 schema 字段,不改表)。"""
53
- event.validate_conformance()
54
- return SessionEvent(
55
- id=event.event_id,
56
- session_id=event.session_id,
57
- author=event.agent_id,
58
- event_type=event.event_type,
59
- content={"phase": event.phase, "payload": dict(event.payload)},
60
- timestamp=event.timestamp,
61
- seq_id=event.seq_id,
62
- invocation_id=event.invocation_id,
63
- metadata={
64
- _RUNTIME_MARKER: True,
65
- "user_id": event.user_id,
66
- "schema_version": event.schema_version,
67
- },
68
- )
69
-
70
-
71
- def session_event_to_runtime_event(event: SessionEvent) -> Optional[RuntimeEvent]:
72
- """把 SessionEvent 还原为 RuntimeEvent;非 runtime 事件(无标记)返回 None。"""
73
- if not (event.metadata or {}).get(_RUNTIME_MARKER):
74
- return None
75
- content = event.content or {}
76
- return RuntimeEvent.create(
77
- event.event_type,
78
- agent_id=event.author,
79
- user_id=str(event.metadata.get("user_id") or ""),
80
- session_id=event.session_id,
81
- invocation_id=event.invocation_id or "",
82
- seq_id=event.seq_id,
83
- payload=dict(content.get("payload") or {}),
84
- phase=content.get("phase"),
85
- event_id=event.id,
86
- timestamp=event.timestamp,
87
- )
88
-
89
-
90
- # ---------------------------------------------------------------------------
91
- # RuntimeEventStore
92
- # ---------------------------------------------------------------------------
93
-
94
-
95
- class RuntimeEventStore:
96
- """统一事件 store(复用 session service 的 seq_id cursor 持久化骨架)。"""
97
-
98
- def __init__(self, session_service: Any) -> None:
99
- self._service = session_service
100
-
101
- # ---- append ----
102
-
103
- async def append(self, events: Iterable[RuntimeEvent]) -> list[RuntimeEvent]:
104
- """持久化一组 RuntimeEvent,返回存储层分配 cursor 后的事件。"""
105
- appended: list[RuntimeEvent] = []
106
- for event in events:
107
- appended.append(await self.append_one(event))
108
- return appended
109
-
110
- async def append_one(self, event: RuntimeEvent) -> RuntimeEvent:
111
- """Idempotently persist one event using its durable ``event_id``.
112
-
113
- Replayed wire events return their original store-assigned cursor. Reuse
114
- of an ID for different content is rejected rather than silently losing a
115
- legal event.
116
- """
117
- persisted, _created = await self.reserve_once(event)
118
- return persisted
119
-
120
- async def reserve_once(self, event: RuntimeEvent) -> tuple[RuntimeEvent, bool]:
121
- """Durably claim ``event.event_id`` and report whether this caller won.
122
-
123
- SQL backends enforce a unique event id, so this is also the command
124
- reservation seam for side effects such as checkpoint resume. A loser
125
- receives the existing identical fact with ``created=False`` and must
126
- not repeat the side effect.
127
- """
128
- existing = await self._event_by_id(event.session_id, event.event_id)
129
- if existing is not None:
130
- self._assert_same_event(existing, event)
131
- return existing, False
132
- try:
133
- stored = await self._service.append_event(
134
- event.session_id, runtime_event_to_session_event(event)
135
- )
136
- except Exception:
137
- # Durable backends enforce a unique event id. A concurrent writer
138
- # may win between the read and append; resolve that race by reading
139
- # the persisted fact and validating its content.
140
- existing = await self._event_by_id(event.session_id, event.event_id)
141
- if existing is None:
142
- raise
143
- self._assert_same_event(existing, event)
144
- return existing, False
145
- persisted = session_event_to_runtime_event(stored)
146
- if persisted is None: # pragma: no cover - marker is set above by construction
147
- raise RuntimeError("RuntimeEvent 持久化后缺少 runtime marker")
148
- return persisted, True
149
-
150
- async def _event_by_id(self, session_id: str, event_id: str) -> RuntimeEvent | None:
151
- raw = await self._service.get_events(session_id)
152
- for stored in raw:
153
- if stored.id != event_id:
154
- continue
155
- return session_event_to_runtime_event(stored)
156
- return None
157
-
158
- @staticmethod
159
- def _assert_same_event(existing: RuntimeEvent, candidate: RuntimeEvent) -> None:
160
- comparable = (
161
- "event_type",
162
- "agent_id",
163
- "user_id",
164
- "session_id",
165
- "invocation_id",
166
- "phase",
167
- "payload",
168
- )
169
- if any(getattr(existing, field) != getattr(candidate, field) for field in comparable):
170
- raise ValueError(f"RuntimeEvent id collision for {candidate.event_id!r}")
171
-
172
- async def set_task_agent(self, session_id: str, task_id: str, agent_id: str) -> None:
173
- """Persist the outbound A2A task locator in session state."""
174
- session = await self._service.get_session_metadata(session_id)
175
- if session is None:
176
- raise ValueError(f"A2A space session {session_id!r} not found")
177
- current = await self._service.get_state(
178
- session.agent_id,
179
- session.user_id,
180
- session.id,
181
- scope="session",
182
- )
183
- mapping = dict((current.state if current else {}).get(_A2A_TASK_AGENT_STATE_KEY) or {})
184
- existing = mapping.get(task_id)
185
- if existing and existing != agent_id:
186
- raise ValueError(f"A2A task {task_id!r} is already bound to another agent")
187
- mapping[task_id] = agent_id
188
- await self._service.update_state(
189
- agent_id=session.agent_id,
190
- user_id=session.user_id,
191
- session_id=session.id,
192
- scope="session",
193
- state_delta={_A2A_TASK_AGENT_STATE_KEY: mapping},
194
- )
195
-
196
- async def get_task_agent(self, session_id: str, task_id: str) -> str | None:
197
- """Resolve a persisted outbound A2A task locator."""
198
- session = await self._service.get_session_metadata(session_id)
199
- if session is None:
200
- return None
201
- current = await self._service.get_state(
202
- session.agent_id,
203
- session.user_id,
204
- session.id,
205
- scope="session",
206
- )
207
- mapping = dict((current.state if current else {}).get(_A2A_TASK_AGENT_STATE_KEY) or {})
208
- value = mapping.get(task_id)
209
- return str(value) if value else None
210
-
211
- # ---- list ----
212
-
213
- async def list(
214
- self,
215
- session_id: str,
216
- *,
217
- after_seq_id: int = 0,
218
- before_seq_id: Optional[int] = None,
219
- invocation_id: Optional[str] = None,
220
- limit: Optional[int] = None,
221
- ) -> list[RuntimeEvent]:
222
- """按 seq cursor 读 RuntimeEvent(升序;可按 invocation 过滤 / before 上界回放)。"""
223
- raw = await self._service.get_events(
224
- session_id,
225
- after_seq_id=after_seq_id,
226
- before_seq_id=before_seq_id,
227
- limit=limit,
228
- )
229
- events = [e for e in (session_event_to_runtime_event(se) for se in raw) if e is not None]
230
- if invocation_id is not None:
231
- events = [e for e in events if e.invocation_id == invocation_id]
232
- events.sort(key=lambda e: e.seq_id)
233
- return events
234
-
235
- # ---- 两类订阅 ----
236
-
237
- async def subscribe_run(
238
- self,
239
- session_id: str,
240
- invocation_id: str,
241
- *,
242
- after_seq_id: int = 0,
243
- poll_interval: float = _DEFAULT_POLL_INTERVAL,
244
- timeout: float = _DEFAULT_STREAM_TIMEOUT,
245
- ) -> AsyncIterator[RuntimeEvent]:
246
- """单 invocation 订阅:只产该 invocation 的 RuntimeEvent,终态后关闭。
247
-
248
- 断线续传:调用方持返回事件的 ``seq_id``,断线后以 ``after_seq_id`` 重连即可续传,
249
- 不丢(>after 的全部重发)、不重(<=after 的不重发)。
250
- """
251
- last = int(after_seq_id or 0)
252
- deadline = asyncio.get_event_loop().time() + timeout
253
- while True:
254
- events = await self.list(session_id, after_seq_id=last, invocation_id=invocation_id)
255
- for event in events:
256
- last = max(last, event.seq_id)
257
- yield event
258
- if event.event_type in _RUN_TERMINAL_EVENT_TYPES:
259
- return
260
- if asyncio.get_event_loop().time() > deadline:
261
- return
262
- await asyncio.sleep(poll_interval)
263
-
264
- async def subscribe_session(
265
- self,
266
- session_id: str,
267
- *,
268
- after_seq_id: int = 0,
269
- poll_interval: float = _DEFAULT_POLL_INTERVAL,
270
- timeout: float = _DEFAULT_STREAM_TIMEOUT,
271
- ) -> AsyncIterator[RuntimeEvent]:
272
- """session 级 cursor stream:跨 invocation 产全部 RuntimeEvent(replay + live)。
273
-
274
- 支持 run 后 action 与跨 invocation replay(A2UI 依赖);断线续传同 subscribe_run。
275
- """
276
- last = int(after_seq_id or 0)
277
- deadline = asyncio.get_event_loop().time() + timeout
278
- while True:
279
- events = await self.list(session_id, after_seq_id=last)
280
- for event in events:
281
- last = max(last, event.seq_id)
282
- yield event
283
- if asyncio.get_event_loop().time() > deadline:
284
- return
285
- await asyncio.sleep(poll_interval)
286
-
287
- # ---- projection / replay ----
288
-
289
- async def project(
290
- self,
291
- session_id: str,
292
- projection: Optional[Callable[[Any, RuntimeEvent], Any]] = None,
293
- *,
294
- initial: Any = None,
295
- after_seq_id: int = 0,
296
- before_seq_id: Optional[int] = None,
297
- ) -> Any:
298
- """replay / projection。
299
-
300
- 默认(``projection=None``):返回按 seq 升序的 RuntimeEvent 序列(replay)。
301
- 给定 ``projection(acc, event) -> acc``:自 ``initial`` 起 fold 全部事件,支持
302
- 增量 projection(以 ``after_seq_id`` 从某个 checkpoint 续投影)。
303
- """
304
- events = await self.list(session_id, after_seq_id=after_seq_id, before_seq_id=before_seq_id)
305
- if projection is None:
306
- return events
307
- acc = initial
308
- for event in events:
309
- acc = projection(acc, event)
310
- return acc
311
-
312
-
313
- __all__ = [
314
- "RuntimeEventStore",
315
- "runtime_event_to_session_event",
316
- "session_event_to_runtime_event",
317
- ]
3
+ from ksadk.events.canonical_store import * # noqa: F403
4
+ from ksadk.events.canonical_store import __all__
@@ -0,0 +1,41 @@
1
+ """Read-only RuntimeEvent v1 wire compatibility.
2
+
3
+ This module is the only owner of the legacy v1 envelope, parser, and the
4
+ canonical-v2-to-v1 projection. It is deliberately not a persistence or
5
+ source-adapter boundary.
6
+
7
+ Implementation lives in the :mod:`ksadk.events._v1_compat` subpackage
8
+ (models / parser / projection); this module remains the stable import path.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from ksadk.events._v1_compat.models import (
14
+ ALL_V1_EVENT_TYPES,
15
+ V1_EVENT_PAYLOAD_REQUIRED_KEYS,
16
+ A2ATaskProjectionRef,
17
+ A2UIInteractionProjectionRef,
18
+ A2UISurfaceProjectionRef,
19
+ EventTypeV1,
20
+ RuntimeEventV1,
21
+ RuntimeEventV1ProjectionContext,
22
+ RuntimeEventV1ProjectionMode,
23
+ V1ProjectionContextRequiredError,
24
+ )
25
+ from ksadk.events._v1_compat.parser import RuntimeEventV1Parser
26
+ from ksadk.events._v1_compat.projection import project_to_v1
27
+
28
+ __all__ = [
29
+ "ALL_V1_EVENT_TYPES",
30
+ "A2ATaskProjectionRef",
31
+ "A2UIInteractionProjectionRef",
32
+ "A2UISurfaceProjectionRef",
33
+ "EventTypeV1",
34
+ "RuntimeEventV1",
35
+ "RuntimeEventV1Parser",
36
+ "RuntimeEventV1ProjectionContext",
37
+ "RuntimeEventV1ProjectionMode",
38
+ "V1ProjectionContextRequiredError",
39
+ "V1_EVENT_PAYLOAD_REQUIRED_KEYS",
40
+ "project_to_v1",
41
+ ]
ksadk/harness/runtime.py CHANGED
@@ -4,12 +4,35 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import json
7
+ import time
7
8
  import uuid
8
9
  from dataclasses import dataclass
9
10
  from pathlib import Path
10
11
  from typing import Any
11
12
 
12
- from ksadk.events import EventPhase, EventType, RuntimeEvent
13
+ from ksadk.events.canonical import (
14
+ ErrorInfo,
15
+ ItemCompleted,
16
+ ItemStarted,
17
+ ItemUpdated,
18
+ OutputRef,
19
+ RunCanceled,
20
+ RunCompleted,
21
+ RunFailed,
22
+ RunStarted,
23
+ SourceRef,
24
+ )
25
+ from ksadk.events.content import (
26
+ ContentSnapshot,
27
+ TextContent,
28
+ ToolCallContent,
29
+ ToolResultContent,
30
+ )
31
+ from ksadk.events.identity import (
32
+ stable_event_id,
33
+ stable_item_id,
34
+ stable_scope_id,
35
+ )
13
36
  from ksadk.harness.config import HarnessConfig
14
37
  from ksadk.harness.reasoner import HarnessReasoner, LiteLLMHarnessReasoner
15
38
  from ksadk.harness.sandbox import HarnessSandboxExecutor
@@ -237,86 +260,166 @@ class HarnessRuntimeAdapter(RuntimeAdapter):
237
260
 
238
261
  async def _stream(self, handle: RunHandle):
239
262
  run = self._require_run(handle)
263
+ framework = "ksadk"
264
+ run_id = handle.run_id
265
+ scope_id = stable_scope_id(framework, run_id)
266
+ message_item_id = stable_item_id(framework, run_id, "message", "final_answer")
267
+ run_item_id = stable_item_id(framework, run_id, "$run")
240
268
  seq = 0
269
+ started_items: set[tuple[str, str]] = set()
241
270
 
242
- def event(
243
- event_type: str,
244
- payload: dict[str, Any],
245
- *,
246
- phase: str | None = None,
247
- ) -> RuntimeEvent:
271
+ def next_seq() -> int:
248
272
  nonlocal seq
249
273
  seq += 1
250
- request = run.request
251
- return RuntimeEvent.create(
252
- event_type,
253
- agent_id=str(request.agent_id or self._agent_name),
254
- user_id=request.user_id,
255
- session_id=request.session_id,
256
- invocation_id=handle.run_id,
257
- seq_id=seq,
258
- payload=payload,
259
- phase=phase,
274
+ return seq
275
+
276
+ def make_source() -> SourceRef:
277
+ return SourceRef(
278
+ framework=framework,
279
+ native_run_id=run_id,
280
+ metadata={
281
+ "agent_id": str(run.request.agent_id or self._agent_name),
282
+ "user_id": run.request.user_id,
283
+ "session_id": run.request.session_id,
284
+ "invocation_id": run_id,
285
+ },
260
286
  )
261
287
 
288
+ def env_kwargs(
289
+ item_id: str, event_type: str, part_id: str
290
+ ) -> dict[str, Any]:
291
+ n = next_seq()
292
+ return {
293
+ "schema_version": 2,
294
+ "event_id": stable_event_id(
295
+ framework, scope_id, item_id, event_type, part_id, run_id, n
296
+ ),
297
+ "seq": n,
298
+ "timestamp": time.time(),
299
+ "run_id": run_id,
300
+ "scope_id": scope_id,
301
+ "source": make_source(),
302
+ }
303
+
304
+ def ensure_started(
305
+ item_id: str,
306
+ item_kind: str,
307
+ phase: str | None = None,
308
+ initial: ContentSnapshot | None = None,
309
+ ) -> list[ItemStarted]:
310
+ key = (scope_id, item_id)
311
+ if key in started_items:
312
+ return []
313
+ started_items.add(key)
314
+ return [
315
+ ItemStarted(
316
+ **env_kwargs(item_id, "item.started", "item"),
317
+ item_id=item_id,
318
+ item_kind=item_kind,
319
+ phase=phase,
320
+ initial=initial,
321
+ )
322
+ ]
323
+
262
324
  if run.pending_cancel:
263
325
  run.done = True
264
- yield event(
265
- EventType.RUN_CANCELED,
266
- {
267
- "status": "cancelled",
268
- "cancel_result": CancelResult.PENDING_CANCEL_RECORDED.value,
269
- },
326
+ yield RunCanceled(
327
+ **env_kwargs(run_item_id, "run.canceled", "run"),
328
+ status="canceled",
329
+ reason=CancelResult.PENDING_CANCEL_RECORDED.value,
270
330
  )
271
331
  return
272
- yield event(EventType.RUN_STARTED, {"status": "in_progress"})
332
+ yield RunStarted(
333
+ **env_kwargs(run_item_id, "run.started", "run"),
334
+ status="running",
335
+ )
273
336
  run.task = asyncio.create_task(self.execute_request(run.request))
274
337
  try:
275
338
  result = await run.task
276
339
  for call in result["tool_calls"]:
277
- yield event(
278
- EventType.TOOL_CALL_BEGIN,
279
- {
280
- "call_id": call["call_id"],
281
- "name": call["name"],
282
- "args": call["arguments"],
283
- },
284
- )
285
- yield event(
286
- EventType.TOOL_CALL_END,
287
- {
288
- "call_id": call["call_id"],
289
- "name": call["name"],
290
- "result": call["result"],
291
- },
340
+ call_id = call["call_id"]
341
+ tool_item_id = stable_item_id(framework, run_id, "tool_call", call_id)
342
+ for ev in ensure_started(
343
+ item_id=tool_item_id,
344
+ item_kind="tool_call",
345
+ initial=ContentSnapshot(
346
+ parts=(
347
+ ToolCallContent(
348
+ part_id="tool-0",
349
+ call_id=call_id,
350
+ name=call["name"],
351
+ arguments=call["arguments"],
352
+ ),
353
+ )
354
+ ),
355
+ ):
356
+ yield ev
357
+ yield ItemCompleted(
358
+ **env_kwargs(tool_item_id, "item.completed", "tool-0"),
359
+ item_id=tool_item_id,
360
+ item_kind="tool_call",
361
+ snapshot=ContentSnapshot(
362
+ parts=(
363
+ ToolResultContent(
364
+ part_id="tool-0",
365
+ call_id=call_id,
366
+ result=call["result"],
367
+ ),
368
+ )
369
+ ),
292
370
  )
293
371
  text = str(result["output"])
294
- yield event(
295
- EventType.TEXT_DELTA,
296
- {"text": text},
297
- phase=EventPhase.FINAL_ANSWER.value,
372
+ for ev in ensure_started(
373
+ item_id=message_item_id,
374
+ item_kind="message",
375
+ phase="final_answer",
376
+ ):
377
+ yield ev
378
+ yield ItemUpdated(
379
+ **env_kwargs(message_item_id, "item.updated", "text-0"),
380
+ item_id=message_item_id,
381
+ item_kind="message",
382
+ op="append",
383
+ update=TextContent(part_id="text-0", text=text),
298
384
  )
299
- yield event(
300
- EventType.TEXT_COMPLETED,
301
- {"text": text},
302
- phase=EventPhase.FINAL_ANSWER.value,
385
+ yield ItemCompleted(
386
+ **env_kwargs(message_item_id, "item.completed", "text-0"),
387
+ item_id=message_item_id,
388
+ item_kind="message",
389
+ snapshot=ContentSnapshot(
390
+ parts=(TextContent(part_id="text-0", text=text),)
391
+ ),
303
392
  )
304
393
  run.done = True
305
- yield event(EventType.RUN_COMPLETED, {"status": "completed"})
394
+ yield RunCompleted(
395
+ **env_kwargs(run_item_id, "run.completed", "run"),
396
+ status="completed",
397
+ output_refs=(
398
+ OutputRef(
399
+ scope_id=scope_id,
400
+ item_id=message_item_id,
401
+ part_id="text-0",
402
+ ),
403
+ ),
404
+ )
306
405
  except asyncio.CancelledError:
307
406
  run.done = True
308
- yield event(
309
- EventType.RUN_CANCELED,
310
- {
311
- "status": "cancelled",
312
- "cancel_result": CancelResult.INTERRUPTED_ACTIVE_TURN.value,
313
- },
407
+ yield RunCanceled(
408
+ **env_kwargs(run_item_id, "run.canceled", "run"),
409
+ status="canceled",
410
+ reason=CancelResult.INTERRUPTED_ACTIVE_TURN.value,
314
411
  )
315
412
  except Exception as exc: # noqa: BLE001
316
413
  run.done = True
317
- yield event(
318
- EventType.RUN_FAILED,
319
- {"status": "failed", "error": str(exc)},
414
+ yield RunFailed(
415
+ **env_kwargs(run_item_id, "run.failed", "run"),
416
+ status="failed",
417
+ error=ErrorInfo(
418
+ code="harness_failed",
419
+ message=str(exc),
420
+ source=framework,
421
+ scope_id=scope_id,
422
+ ),
320
423
  )
321
424
 
322
425
  def _require_run(self, handle: RunHandle) -> _HarnessRun:
@@ -305,9 +305,10 @@ def resolve_identity(
305
305
  access_keys = _call_list_all_user_access_keys(client, sdk_parts)
306
306
  user_name = _find_username_by_ak(access_keys, access_key)
307
307
  if not user_name:
308
- # AK 不在子用户列表(可能是主账号 AK),无法反查 user uuid
309
- logger.warning(
310
- "AK 指纹 %s 未在 ListAllUserAccessKeys 找到匹配(可能是主账号 AK)",
308
+ # 主账号 AK 不会出现在子用户列表,属预期路径:无子账号 uuid 可反查,
309
+ # 调用方将只注入主账号维度 header(account_id)。
310
+ logger.info(
311
+ "AK 为主账号密钥(指纹 %s),按主账号身份使用,不注入子账号 uuid",
311
312
  fingerprint,
312
313
  )
313
314
  return None
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Durable Interaction ledger(Phase 1 Task 5,Interaction/v1)。"""
3
+
4
+ from ksadk.interaction.contracts import (
5
+ InteractionRecord,
6
+ InteractionReceipt,
7
+ InteractionSubmission,
8
+ )
9
+ from ksadk.interaction.ledger import InteractionLedger
10
+ from ksadk.interaction.provider import (
11
+ RUNTIME_INTERACTION_UNAVAILABLE,
12
+ InteractionProvider,
13
+ InteractionProviderMode,
14
+ InteractionResolveContext,
15
+ UnavailableInteractionProvider,
16
+ )
17
+
18
+ __all__ = [
19
+ "RUNTIME_INTERACTION_UNAVAILABLE",
20
+ "InteractionLedger",
21
+ "InteractionProvider",
22
+ "InteractionProviderMode",
23
+ "InteractionRecord",
24
+ "InteractionReceipt",
25
+ "InteractionResolveContext",
26
+ "InteractionSubmission",
27
+ "UnavailableInteractionProvider",
28
+ ]