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,395 @@
1
+ """HTTP adapter for the EvalSmith-backed agent-eval dataset API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import json
7
+ import os
8
+ from typing import Any, Protocol
9
+
10
+ import httpx
11
+
12
+ from ksadk.common.kop_client import KOPClient, KOPError
13
+
14
+ from .cloud_converter import CloudDatasetColumn, CloudDatasetRow, CloudDatasetSnapshot
15
+ from .cloud_service import CloudEvalSetCatalogItem, CloudEvalSetPublishResult
16
+ from .service_env import resolve_agent_eval_direct_url, resolve_agent_eval_kop_connection
17
+
18
+
19
+ class AgentEvalCloudClientError(RuntimeError):
20
+ """The agent-eval cloud dataset API rejected or could not process a request."""
21
+
22
+
23
+ class _KOPActionClient(Protocol):
24
+ def post_action(self, action: str, payload: dict[str, Any] | None = None) -> dict[str, Any]: ...
25
+
26
+
27
+ class AgentEvalCloudDatasetClient:
28
+ """Publish immutable KsADK EvalSet snapshots through agent-eval and EvalSmith."""
29
+
30
+ _PUBLISH_PATH = "/agentengine/eval/api/v1/PublishEvaluationSetSnapshot"
31
+ _READ_PATH = "/agentengine/eval/api/v1/DescribeEvaluationSet"
32
+ _LIST_PATH = "/agentengine/eval/api/v1/ListEvaluationSet"
33
+ _READ_PAGE_SIZE = 200
34
+ _LIST_PAGE_SIZE = 100
35
+
36
+ def __init__(
37
+ self,
38
+ base_url: str | None = None,
39
+ *,
40
+ api_token: str | None = None,
41
+ account_id: str | None = None,
42
+ timeout_seconds: float = 30.0,
43
+ http_client: httpx.AsyncClient | None = None,
44
+ kop_client: _KOPActionClient | None = None,
45
+ ) -> None:
46
+ explicit_base_url = str(base_url).strip().rstrip("/") if base_url is not None else None
47
+ if explicit_base_url is None:
48
+ explicit_base_url = resolve_agent_eval_direct_url()
49
+ self._base_url = explicit_base_url or ""
50
+ self._api_token = str(
51
+ api_token if api_token is not None else os.environ.get("AGENT_EVAL_API_TOKEN", "")
52
+ ).strip()
53
+ self._account_id = str(
54
+ account_id
55
+ or os.environ.get("AGENT_EVAL_ACCOUNT_ID")
56
+ or os.environ.get("KSYUN_ACCOUNT_ID")
57
+ or ""
58
+ ).strip()
59
+ self._timeout_seconds = timeout_seconds
60
+ self._http_client = http_client
61
+ self._kop_client: _KOPActionClient | None = None
62
+ if not self._base_url:
63
+ if http_client is not None:
64
+ raise ValueError("http_client requires AGENT_EVAL_BASE_URL direct mode")
65
+ connection = resolve_agent_eval_kop_connection()
66
+ self._kop_client = kop_client or KOPClient(
67
+ base_url=connection["base_url"],
68
+ access_key=os.environ.get("KSYUN_ACCESS_KEY"),
69
+ secret_key=os.environ.get("KSYUN_SECRET_KEY"),
70
+ account_id=os.environ.get("KSYUN_ACCOUNT_ID"),
71
+ region=connection["region"],
72
+ timeout=timeout_seconds,
73
+ )
74
+ elif kop_client is not None:
75
+ raise ValueError("kop_client cannot be used with AGENT_EVAL_BASE_URL direct mode")
76
+
77
+ @property
78
+ def uses_kop(self) -> bool:
79
+ return self._kop_client is not None
80
+
81
+ async def publish_snapshot(
82
+ self,
83
+ snapshot: CloudDatasetSnapshot,
84
+ *,
85
+ dataset_id: str | None,
86
+ base_version: int | None,
87
+ idempotency_key: str,
88
+ ) -> CloudEvalSetPublishResult:
89
+ columns: list[dict[str, Any]] = []
90
+ for column in snapshot.columns:
91
+ item: dict[str, Any] = {
92
+ "Key": column.name,
93
+ "Name": column.name,
94
+ "ValueType": column.value_type,
95
+ "Required": column.required,
96
+ "Description": column.description,
97
+ }
98
+ if column.text_schema is not None:
99
+ item["TextSchema"] = column.text_schema
100
+ columns.append(item)
101
+
102
+ payload: dict[str, Any] = {
103
+ "Name": snapshot.name,
104
+ "Description": snapshot.description,
105
+ "Columns": columns,
106
+ "Rows": [
107
+ {"values": row.values, "split": "default", "source": "ksadk"}
108
+ for row in snapshot.rows
109
+ ],
110
+ "ContentDigest": snapshot.content_digest,
111
+ "SchemaHash": snapshot.schema_hash,
112
+ "IdempotencyKey": idempotency_key,
113
+ }
114
+ if dataset_id:
115
+ payload["DatasetId"] = dataset_id
116
+ if base_version is not None:
117
+ payload["BaseVersion"] = base_version
118
+ data = await self._request(
119
+ "PublishEvaluationSetSnapshot",
120
+ self._PUBLISH_PATH,
121
+ payload,
122
+ )
123
+ try:
124
+ return CloudEvalSetPublishResult(
125
+ dataset_id=data["DatasetId"],
126
+ dataset_version=data["DatasetVersion"],
127
+ project_id=data.get("ProjectId"),
128
+ schema_hash=data["SchemaHash"],
129
+ content_digest=data["ContentDigest"],
130
+ row_count=data["RowCount"],
131
+ )
132
+ except (KeyError, TypeError, ValueError) as exc:
133
+ raise AgentEvalCloudClientError(
134
+ "agent-eval snapshot publish returned an invalid result"
135
+ ) from exc
136
+
137
+ async def read_snapshot(
138
+ self,
139
+ dataset_id: str,
140
+ version: int,
141
+ *,
142
+ project_id: str | None = None,
143
+ ) -> CloudDatasetSnapshot:
144
+ if not dataset_id.strip() or version < 1:
145
+ raise ValueError("datasetId and version must be valid")
146
+ del project_id # DescribeEvaluationSet resolves the project from the account context.
147
+ page = 1
148
+ first_page: dict[str, Any] | None = None
149
+ raw_items: list[dict[str, Any]] = []
150
+ while True:
151
+ data = await self._request(
152
+ "DescribeEvaluationSet",
153
+ self._READ_PATH,
154
+ {
155
+ "DatasetId": dataset_id,
156
+ "DatasetVersion": version,
157
+ "Page": page,
158
+ "PageSize": self._READ_PAGE_SIZE,
159
+ },
160
+ )
161
+ if first_page is None:
162
+ first_page = data
163
+ page_items = data.get("Items")
164
+ if not isinstance(page_items, list) or not all(
165
+ isinstance(item, dict) for item in page_items
166
+ ):
167
+ raise AgentEvalCloudClientError("agent-eval snapshot read returned invalid items")
168
+ raw_items.extend(page_items)
169
+ if not data.get("HasMore"):
170
+ break
171
+ page += 1
172
+
173
+ assert first_page is not None
174
+ try:
175
+ current_version = int(first_page["CurrentVersion"])
176
+ if current_version != version:
177
+ raise ValueError("version mismatch")
178
+ raw_rows = [item["Row"] for item in raw_items]
179
+ rows = [CloudDatasetRow(values=dict(row)) for row in raw_rows if isinstance(row, dict)]
180
+ if len(rows) != len(raw_rows):
181
+ raise ValueError("invalid row")
182
+ expected_row_count = first_page.get("RowCount")
183
+ if expected_row_count is not None and int(expected_row_count) != len(rows):
184
+ raise ValueError("row count mismatch")
185
+ columns = [self._column_from_remote(column) for column in first_page["Columns"]]
186
+ content_digests = {
187
+ str(row.values.get("ksadk_content_digest") or "").strip() for row in rows
188
+ }
189
+ content_digests.discard("")
190
+ if len(content_digests) != 1:
191
+ raise ValueError("content digest mismatch")
192
+ source_formats = {str(row.values.get("source_format") or "").strip() for row in rows}
193
+ source_formats.discard("")
194
+ if len(source_formats) != 1:
195
+ raise ValueError("source format mismatch")
196
+ return CloudDatasetSnapshot(
197
+ name=first_page["Name"],
198
+ description=first_page.get("Description"),
199
+ content_digest=content_digests.pop(),
200
+ source_format=source_formats.pop(),
201
+ evalset_metadata={},
202
+ columns=columns,
203
+ rows=rows,
204
+ )
205
+ except (KeyError, TypeError, ValueError) as exc:
206
+ raise AgentEvalCloudClientError(
207
+ "agent-eval snapshot read returned an invalid result"
208
+ ) from exc
209
+
210
+ async def list_datasets(
211
+ self,
212
+ *,
213
+ project_id: str | None = None,
214
+ ) -> list[CloudEvalSetCatalogItem]:
215
+ payload: dict[str, Any] = {
216
+ "DatasetType": "Manual",
217
+ "Page": 1,
218
+ "PageSize": self._LIST_PAGE_SIZE,
219
+ }
220
+ if project_id:
221
+ payload["ProjectId"] = project_id
222
+ raw_items: list[dict[str, Any]] = []
223
+ while True:
224
+ data = await self._request("ListEvaluationSet", self._LIST_PATH, payload)
225
+ page_items = data.get("Items", data.get("items", data.get("EvaluationSets", [])))
226
+ if not isinstance(page_items, list):
227
+ raise AgentEvalCloudClientError("agent-eval dataset list returned invalid items")
228
+ raw_items.extend(item for item in page_items if isinstance(item, dict))
229
+
230
+ page = data.get("Page", payload["Page"])
231
+ page_size = data.get("PageSize", payload["PageSize"])
232
+ total = data.get("Total")
233
+ try:
234
+ has_next_page = bool(data.get("HasMore")) or (
235
+ total is not None and int(page) * int(page_size) < int(total)
236
+ )
237
+ except (TypeError, ValueError):
238
+ has_next_page = False
239
+ if not has_next_page:
240
+ break
241
+ payload["Page"] = int(payload["Page"]) + 1
242
+ items: list[CloudEvalSetCatalogItem] = []
243
+ for item in raw_items:
244
+ dataset_id = str(item.get("DatasetId", item.get("datasetId", ""))).strip()
245
+ version = item.get(
246
+ "Version",
247
+ item.get("version", item.get("CurrentVersion", item.get("currentVersion"))),
248
+ )
249
+ try:
250
+ version = int(version)
251
+ except (TypeError, ValueError):
252
+ continue
253
+ if not dataset_id or version < 1:
254
+ continue
255
+
256
+ schema_hash = item.get("SchemaHash", item.get("schemaHash"))
257
+ content_digest = item.get("ContentDigest", item.get("contentDigest"))
258
+ row_count = item.get("RowCount", item.get("rowCount"))
259
+ name = item.get("Name", item.get("name"))
260
+ item_project_id = item.get("ProjectId", item.get("projectId", project_id))
261
+ # Standard ListEvaluationSet omits KsADK's digest fields. Recover them
262
+ # from the immutable version and omit unrelated product datasets.
263
+ if not (
264
+ isinstance(schema_hash, str)
265
+ and len(schema_hash) == 64
266
+ and isinstance(content_digest, str)
267
+ and len(content_digest) == 64
268
+ ):
269
+ try:
270
+ snapshot = await self.read_snapshot(
271
+ dataset_id,
272
+ version,
273
+ project_id=item_project_id,
274
+ )
275
+ except AgentEvalCloudClientError:
276
+ continue
277
+ schema_hash = snapshot.schema_hash
278
+ content_digest = snapshot.content_digest
279
+ row_count = len(snapshot.rows)
280
+ name = name or snapshot.name
281
+ try:
282
+ items.append(
283
+ CloudEvalSetCatalogItem(
284
+ dataset_id=dataset_id,
285
+ name=name,
286
+ project_id=item_project_id,
287
+ version=version,
288
+ schema_hash=schema_hash,
289
+ content_digest=content_digest,
290
+ row_count=row_count,
291
+ )
292
+ )
293
+ except (TypeError, ValueError):
294
+ continue
295
+ return items
296
+
297
+ async def _request(
298
+ self,
299
+ action: str,
300
+ path: str,
301
+ payload: dict[str, Any],
302
+ ) -> dict[str, Any]:
303
+ if self._kop_client is not None:
304
+ try:
305
+ data = await asyncio.to_thread(self._kop_client.post_action, action, payload)
306
+ except KOPError as exc:
307
+ raise AgentEvalCloudClientError(
308
+ f"agent-eval KOP action {action} failed: {exc.message}"
309
+ ) from exc
310
+ except Exception as exc:
311
+ raise AgentEvalCloudClientError(
312
+ f"agent-eval KOP action {action} failed"
313
+ ) from exc
314
+ if not isinstance(data, dict):
315
+ raise AgentEvalCloudClientError(
316
+ f"agent-eval KOP action {action} returned invalid data"
317
+ )
318
+ return data
319
+
320
+ headers = {"Content-Type": "application/json"}
321
+ if self._api_token:
322
+ headers["Authorization"] = f"Bearer {self._api_token}"
323
+ if self._account_id:
324
+ headers["X-Ksc-Account-Id"] = self._account_id
325
+ try:
326
+ if self._http_client is not None:
327
+ response = await self._http_client.post(
328
+ f"{self._base_url}{path}", headers=headers, json=payload
329
+ )
330
+ else:
331
+ async with httpx.AsyncClient(
332
+ timeout=httpx.Timeout(self._timeout_seconds),
333
+ follow_redirects=False,
334
+ trust_env=False,
335
+ ) as client:
336
+ response = await client.post(
337
+ f"{self._base_url}{path}", headers=headers, json=payload
338
+ )
339
+ except httpx.HTTPError as exc:
340
+ raise AgentEvalCloudClientError("agent-eval snapshot request failed") from exc
341
+ if response.status_code >= 400:
342
+ raise AgentEvalCloudClientError(
343
+ f"agent-eval snapshot request failed with HTTP {response.status_code}"
344
+ )
345
+ try:
346
+ envelope = response.json()
347
+ except ValueError as exc:
348
+ raise AgentEvalCloudClientError(
349
+ "agent-eval snapshot request returned invalid JSON"
350
+ ) from exc
351
+ if not isinstance(envelope, dict) or envelope.get("Code") != 0:
352
+ raise AgentEvalCloudClientError("agent-eval snapshot request was rejected")
353
+ data = envelope.get("Data")
354
+ if not isinstance(data, dict):
355
+ raise AgentEvalCloudClientError("agent-eval request returned no result")
356
+ return data
357
+
358
+ @staticmethod
359
+ def _parse_text_schema(value: Any) -> dict[str, Any] | None:
360
+ if value is None:
361
+ return None
362
+ if isinstance(value, dict):
363
+ return value
364
+ if isinstance(value, str):
365
+ parsed = json.loads(value)
366
+ if isinstance(parsed, dict):
367
+ return parsed
368
+ raise ValueError("invalid text schema")
369
+
370
+ @staticmethod
371
+ def _normalize_value_type(value: Any) -> str:
372
+ normalized = str(value or "").strip()
373
+ if normalized.lower().startswith("array<"):
374
+ return "Array"
375
+ return normalized
376
+
377
+ @classmethod
378
+ def _column_from_remote(cls, column: dict[str, Any]) -> CloudDatasetColumn:
379
+ name = column.get("name") or column.get("Key") or column.get("Name")
380
+ text_schema = cls._parse_text_schema(
381
+ column.get("textSchema")
382
+ or column.get("TextSchema")
383
+ or column.get("textSchemaRaw")
384
+ or column.get("TextSchemaRaw")
385
+ )
386
+ value_type = cls._normalize_value_type(column.get("valueType") or column.get("ValueType"))
387
+ if text_schema == {"type": "string", "title": name}:
388
+ text_schema = None
389
+ return CloudDatasetColumn(
390
+ name=name,
391
+ value_type=value_type,
392
+ required=column.get("required", column.get("Required", False)),
393
+ description=column.get("description") or column.get("Description"),
394
+ text_schema=text_schema,
395
+ )
@@ -0,0 +1,80 @@
1
+ """Local, atomic bindings between workspace EvalSets and cloud Dataset versions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ from pathlib import Path
7
+
8
+ import yaml
9
+ from pydantic import Field, field_validator
10
+
11
+ from .contracts import EvaluationModel
12
+
13
+
14
+ class CloudBindingError(RuntimeError):
15
+ """Raised when a cloud binding cannot be read or safely persisted."""
16
+
17
+
18
+ class CloudBinding(EvaluationModel):
19
+ """Non-sensitive reference to one immutable cloud Dataset version."""
20
+
21
+ schema_version: str = "ksadk.eval.cloud/v1"
22
+ evalset_path: str = Field(min_length=1)
23
+ content_digest: str = Field(min_length=64, max_length=64)
24
+ provider: str = Field(min_length=1)
25
+ project_id: str | None = None
26
+ dataset_id: str = Field(min_length=1)
27
+ dataset_version: int = Field(ge=1)
28
+ schema_hash: str = Field(min_length=64, max_length=64)
29
+
30
+ @field_validator("evalset_path")
31
+ @classmethod
32
+ def validate_evalset_path(cls, value: str) -> str:
33
+ return _workspace_relative_path(value)
34
+
35
+
36
+ class CloudBindingStore:
37
+ """Persist bindings under the workspace without accepting arbitrary output paths."""
38
+
39
+ def __init__(self, workspace_root: str | Path):
40
+ self.workspace_root = Path(workspace_root).expanduser().resolve()
41
+ self.root = self.workspace_root / ".agentkit" / "evaluation-bindings"
42
+
43
+ def binding_path(self, evalset_path: str) -> Path:
44
+ normalized = _workspace_relative_path(evalset_path)
45
+ file_name = hashlib.sha256(normalized.encode("utf-8")).hexdigest() + ".yaml"
46
+ return self.root / file_name
47
+
48
+ def write(self, binding: CloudBinding) -> Path:
49
+ path = self.binding_path(binding.evalset_path)
50
+ path.parent.mkdir(parents=True, exist_ok=True)
51
+ temporary = path.with_name(f".{path.name}.tmp")
52
+ payload = yaml.safe_dump(
53
+ binding.model_dump(mode="json", by_alias=True, exclude_none=True),
54
+ allow_unicode=True,
55
+ sort_keys=True,
56
+ )
57
+ try:
58
+ temporary.write_text(payload, encoding="utf-8")
59
+ temporary.replace(path)
60
+ except OSError as exc:
61
+ temporary.unlink(missing_ok=True)
62
+ raise CloudBindingError("云端评测集绑定写入失败") from exc
63
+ return path
64
+
65
+ def read(self, evalset_path: str) -> CloudBinding | None:
66
+ path = self.binding_path(evalset_path)
67
+ if not path.is_file():
68
+ return None
69
+ try:
70
+ loaded = yaml.safe_load(path.read_text(encoding="utf-8"))
71
+ return CloudBinding.model_validate(loaded)
72
+ except (OSError, ValueError, yaml.YAMLError) as exc:
73
+ raise CloudBindingError("云端评测集绑定损坏或不可读") from exc
74
+
75
+
76
+ def _workspace_relative_path(value: str) -> str:
77
+ candidate = Path(value)
78
+ if candidate.is_absolute() or ".." in candidate.parts or not candidate.parts:
79
+ raise CloudBindingError("EvalSet 路径必须位于工作区内")
80
+ return candidate.as_posix()
@@ -0,0 +1,194 @@
1
+ """Lossless conversion between local EvalSets and cloud Dataset snapshots."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from typing import Any
8
+
9
+ from pydantic import Field, model_validator
10
+
11
+ from .contracts import EvalCase, EvalSetVersion, EvaluationModel
12
+
13
+
14
+ class EvalSetCloudConversionError(ValueError):
15
+ """Raised when a cloud Dataset cannot be represented as an EvalSet."""
16
+
17
+
18
+ class CloudDatasetColumn(EvaluationModel):
19
+ """A fixed cloud Dataset field used by the EvalSet converter."""
20
+
21
+ name: str = Field(min_length=1)
22
+ value_type: str = Field(min_length=1)
23
+ required: bool = False
24
+ description: str | None = None
25
+ text_schema: dict[str, Any] | None = None
26
+
27
+
28
+ class CloudDatasetRow(EvaluationModel):
29
+ """One cloud Dataset row with its server-independent field values."""
30
+
31
+ values: dict[str, Any]
32
+
33
+
34
+ class CloudDatasetSnapshot(EvaluationModel):
35
+ """A portable fixed Dataset version before it is sent to a cloud provider."""
36
+
37
+ name: str = Field(min_length=1, max_length=256)
38
+ description: str | None = None
39
+ content_digest: str = Field(min_length=64, max_length=64)
40
+ source_format: str = Field(min_length=1)
41
+ evalset_metadata: dict[str, Any] = Field(default_factory=dict)
42
+ columns: list[CloudDatasetColumn] = Field(min_length=1)
43
+ rows: list[CloudDatasetRow] = Field(min_length=1)
44
+ schema_hash: str = ""
45
+
46
+ @model_validator(mode="after")
47
+ def validate_schema_hash(self) -> "CloudDatasetSnapshot":
48
+ expected = _schema_hash(self.columns)
49
+ if self.schema_hash and self.schema_hash != expected:
50
+ raise ValueError("schemaHash 与列定义不一致")
51
+ self.schema_hash = expected
52
+ return self
53
+
54
+
55
+ _COLUMNS = (
56
+ CloudDatasetColumn(
57
+ name="case_id", value_type="String", required=True, description="KsADK Case ID"
58
+ ),
59
+ CloudDatasetColumn(
60
+ name="turns",
61
+ value_type="Array",
62
+ required=True,
63
+ description="Ordered Eval turns",
64
+ text_schema={
65
+ "type": "array",
66
+ "items": {"type": "object", "additionalProperties": True},
67
+ },
68
+ ),
69
+ CloudDatasetColumn(
70
+ name="assertions",
71
+ value_type="Array",
72
+ required=True,
73
+ description="Eval assertions",
74
+ text_schema={
75
+ "type": "array",
76
+ "items": {"type": "object", "additionalProperties": True},
77
+ },
78
+ ),
79
+ CloudDatasetColumn(
80
+ name="case_metadata",
81
+ value_type="Object",
82
+ description="Case metadata",
83
+ text_schema={"type": "object", "additionalProperties": True},
84
+ ),
85
+ CloudDatasetColumn(
86
+ name="source_format", value_type="String", required=True, description="Source format"
87
+ ),
88
+ CloudDatasetColumn(
89
+ name="ksadk_content_digest",
90
+ value_type="String",
91
+ required=True,
92
+ description="Normalized EvalSet content digest",
93
+ ),
94
+ )
95
+ _COLUMN_NAMES = tuple(column.name for column in _COLUMNS)
96
+
97
+
98
+ def evalset_to_dataset_snapshot(evalset: EvalSetVersion) -> CloudDatasetSnapshot:
99
+ """Convert a normalized EvalSet into the single supported cloud Dataset schema."""
100
+
101
+ return CloudDatasetSnapshot(
102
+ name=evalset.name,
103
+ content_digest=evalset.content_digest,
104
+ source_format=evalset.source_format,
105
+ evalset_metadata=evalset.metadata,
106
+ columns=list(_COLUMNS),
107
+ rows=[
108
+ CloudDatasetRow(
109
+ values={
110
+ "case_id": case.id,
111
+ "turns": [turn.model_dump(mode="json", by_alias=True) for turn in case.turns],
112
+ "assertions": [
113
+ assertion.model_dump(mode="json", by_alias=True)
114
+ for assertion in case.assertions
115
+ ],
116
+ "case_metadata": case.metadata,
117
+ "source_format": evalset.source_format,
118
+ "ksadk_content_digest": evalset.content_digest,
119
+ }
120
+ )
121
+ for case in evalset.cases
122
+ ],
123
+ )
124
+
125
+
126
+ def evalset_from_dataset_snapshot(snapshot: CloudDatasetSnapshot) -> EvalSetVersion:
127
+ """Restore an EvalSet from one fixed Dataset snapshot without losing supported data."""
128
+
129
+ _validate_columns(snapshot.columns)
130
+ cases: list[EvalCase] = []
131
+ source_formats: set[str] = set()
132
+ row_digests: set[str] = set()
133
+ for index, row in enumerate(snapshot.rows, start=1):
134
+ values = row.values
135
+ _validate_row(values, index)
136
+ source_formats.add(str(values["source_format"]))
137
+ row_digests.add(str(values["ksadk_content_digest"]))
138
+ try:
139
+ cases.append(
140
+ EvalCase.model_validate(
141
+ {
142
+ "id": values["case_id"],
143
+ "turns": values["turns"],
144
+ "assertions": values["assertions"],
145
+ "metadata": values["case_metadata"],
146
+ }
147
+ )
148
+ )
149
+ except ValueError as exc:
150
+ raise EvalSetCloudConversionError(f"第 {index} 行不能转换为 EvalCase") from exc
151
+
152
+ if len(source_formats) != 1 or snapshot.source_format not in source_formats:
153
+ raise EvalSetCloudConversionError("Rows 中的 source_format 必须与 Dataset snapshot 一致")
154
+ if row_digests != {snapshot.content_digest}:
155
+ raise EvalSetCloudConversionError(
156
+ "Rows 中的 ksadk_content_digest 必须与 Dataset snapshot 一致"
157
+ )
158
+ try:
159
+ return EvalSetVersion(
160
+ name=snapshot.name,
161
+ cases=cases,
162
+ metadata=snapshot.evalset_metadata,
163
+ source_format=snapshot.source_format,
164
+ content_digest=snapshot.content_digest,
165
+ )
166
+ except ValueError as exc:
167
+ raise EvalSetCloudConversionError("Dataset snapshot 内容无效") from exc
168
+
169
+
170
+ def _validate_columns(columns: list[CloudDatasetColumn]) -> None:
171
+ if [column.name for column in columns] != list(_COLUMN_NAMES):
172
+ raise EvalSetCloudConversionError("Dataset 列定义必须匹配 KsADK EvalSet 固定 schema")
173
+ for actual, expected in zip(columns, _COLUMNS):
174
+ if actual.value_type != expected.value_type or actual.required != expected.required:
175
+ raise EvalSetCloudConversionError(f"Dataset 列 {actual.name} 的类型或必填属性不匹配")
176
+
177
+
178
+ def _validate_row(values: dict[str, Any], index: int) -> None:
179
+ missing = [name for name in _COLUMN_NAMES if name not in values]
180
+ if missing:
181
+ raise EvalSetCloudConversionError(f"第 {index} 行缺少字段: {', '.join(missing)}")
182
+ unknown = sorted(set(values) - set(_COLUMN_NAMES))
183
+ if unknown:
184
+ raise EvalSetCloudConversionError(f"第 {index} 行包含未知字段: {', '.join(unknown)}")
185
+
186
+
187
+ def _schema_hash(columns: list[CloudDatasetColumn]) -> str:
188
+ payload = [
189
+ column.model_dump(mode="json", by_alias=True, exclude_none=True) for column in columns
190
+ ]
191
+ encoded = json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode(
192
+ "utf-8"
193
+ )
194
+ return hashlib.sha256(encoded).hexdigest()