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,199 @@
1
+ """Cloud EvalSet publication orchestration shared by CLI and Studio."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ from pathlib import Path
7
+ from typing import Protocol
8
+
9
+ from pydantic import Field
10
+
11
+ from .cloud_binding import CloudBinding, CloudBindingStore
12
+ from .cloud_converter import (
13
+ CloudDatasetSnapshot,
14
+ evalset_from_dataset_snapshot,
15
+ evalset_to_dataset_snapshot,
16
+ )
17
+ from .contracts import CloudDatasetRef, DataPolicy, EvalSetVersion, EvaluationModel
18
+
19
+
20
+ class CloudEvalSetPreviewError(ValueError):
21
+ """Raised before an EvalSet body is allowed to leave the local process."""
22
+
23
+
24
+ class CloudEvalSetPublishResult(EvaluationModel):
25
+ """Provider acknowledgement for one immutable Dataset snapshot."""
26
+
27
+ dataset_id: str = Field(min_length=1)
28
+ dataset_version: int = Field(ge=1)
29
+ project_id: str | None = None
30
+ schema_hash: str = Field(min_length=64, max_length=64)
31
+ content_digest: str = Field(min_length=64, max_length=64)
32
+ row_count: int = Field(ge=0)
33
+
34
+
35
+ class CloudEvalSetPullResult(EvaluationModel):
36
+ """One validated immutable cloud snapshot and its normalized local form."""
37
+
38
+ snapshot: CloudDatasetSnapshot
39
+ evalset: EvalSetVersion
40
+ cloud_dataset: CloudDatasetRef
41
+
42
+
43
+ class CloudEvalSetCatalogItem(EvaluationModel):
44
+ """One immutable Dataset version exposed by the cloud catalog."""
45
+
46
+ dataset_id: str = Field(min_length=1)
47
+ name: str = Field(min_length=1)
48
+ project_id: str | None = None
49
+ version: int = Field(ge=1)
50
+ schema_hash: str = Field(min_length=64, max_length=64)
51
+ content_digest: str = Field(min_length=64, max_length=64)
52
+ row_count: int = Field(ge=0)
53
+
54
+
55
+ class CloudDatasetClient(Protocol):
56
+ """Minimal provider contract required before a snapshot can be published."""
57
+
58
+ async def publish_snapshot(
59
+ self,
60
+ snapshot: CloudDatasetSnapshot,
61
+ *,
62
+ dataset_id: str | None,
63
+ base_version: int | None,
64
+ idempotency_key: str,
65
+ ) -> CloudEvalSetPublishResult: ...
66
+
67
+ async def read_snapshot(
68
+ self,
69
+ dataset_id: str,
70
+ version: int,
71
+ *,
72
+ project_id: str | None = None,
73
+ ) -> CloudDatasetSnapshot: ...
74
+
75
+ async def list_datasets(
76
+ self,
77
+ *,
78
+ project_id: str | None = None,
79
+ ) -> list[CloudEvalSetCatalogItem]: ...
80
+
81
+
82
+ class CloudEvalSetService:
83
+ """Validate, publish, and bind EvalSets without changing runtime execution."""
84
+
85
+ def __init__(
86
+ self,
87
+ workspace_root: str | Path,
88
+ client: CloudDatasetClient,
89
+ *,
90
+ provider: str = "agent-eval/evalsmith",
91
+ ):
92
+ self.bindings = CloudBindingStore(workspace_root)
93
+ self.client = client
94
+ self.provider = provider
95
+
96
+ def preview(self, evalset: EvalSetVersion, *, data_policy: DataPolicy) -> CloudDatasetSnapshot:
97
+ """Return the exact outgoing snapshot or fail before any network request."""
98
+
99
+ if data_policy is DataPolicy.LOCAL_ONLY:
100
+ raise CloudEvalSetPreviewError("DataPolicy=local_only 禁止上传 EvalSet 正文")
101
+ if data_policy is DataPolicy.METADATA_ONLY:
102
+ raise CloudEvalSetPreviewError(
103
+ "DataPolicy=metadata_only 不能发布包含 Case 正文的 EvalSet"
104
+ )
105
+ if data_policy is not DataPolicy.FULL_TRACE:
106
+ raise CloudEvalSetPreviewError("当前端云评测集发布仅支持显式 DataPolicy=full_trace")
107
+ return evalset_to_dataset_snapshot(evalset)
108
+
109
+ async def publish(
110
+ self,
111
+ evalset: EvalSetVersion,
112
+ *,
113
+ evalset_path: str,
114
+ data_policy: DataPolicy,
115
+ dataset_id: str | None = None,
116
+ idempotency_key: str | None = None,
117
+ ) -> CloudEvalSetPublishResult:
118
+ """Publish a full snapshot to an existing Dataset and advance its binding."""
119
+
120
+ if idempotency_key is not None and not idempotency_key.strip():
121
+ raise ValueError("Idempotency-Key 不能为空")
122
+ snapshot = self.preview(evalset, data_policy=data_policy)
123
+ existing = self.bindings.read(evalset_path)
124
+ requested_dataset_id = str(dataset_id or "").strip() or None
125
+ target_dataset_id = requested_dataset_id or (existing.dataset_id if existing else None)
126
+ if target_dataset_id is None:
127
+ raise ValueError("datasetId is required for the first publish of an EvalSet")
128
+ resolved_idempotency_key = idempotency_key or self._idempotency_key(
129
+ target_dataset_id,
130
+ snapshot.content_digest,
131
+ )
132
+ result = await self.client.publish_snapshot(
133
+ snapshot,
134
+ dataset_id=target_dataset_id,
135
+ base_version=None,
136
+ idempotency_key=resolved_idempotency_key,
137
+ )
138
+ if result.dataset_id != target_dataset_id:
139
+ raise CloudEvalSetPreviewError("云端返回的 datasetId 与目标 Dataset 不一致")
140
+ if result.content_digest != snapshot.content_digest:
141
+ raise CloudEvalSetPreviewError("云端返回的 contentDigest 与本地预检结果不一致")
142
+ if result.schema_hash != snapshot.schema_hash:
143
+ raise CloudEvalSetPreviewError("云端返回的 schemaHash 与本地预检结果不一致")
144
+ if result.row_count != len(snapshot.rows):
145
+ raise CloudEvalSetPreviewError("云端返回的 RowCount 与本地预检结果不一致")
146
+ self.bindings.write(
147
+ CloudBinding(
148
+ evalset_path=evalset_path,
149
+ content_digest=snapshot.content_digest,
150
+ provider=self.provider,
151
+ project_id=result.project_id,
152
+ dataset_id=result.dataset_id,
153
+ dataset_version=result.dataset_version,
154
+ schema_hash=result.schema_hash,
155
+ )
156
+ )
157
+ return result
158
+
159
+ @staticmethod
160
+ def _idempotency_key(dataset_id: str, content_digest: str) -> str:
161
+ identity = f"{dataset_id}:{content_digest}".encode("utf-8")
162
+ return f"ksadk-evalset-{hashlib.sha256(identity).hexdigest()}"
163
+
164
+ async def pull(
165
+ self,
166
+ *,
167
+ dataset_id: str,
168
+ version: int,
169
+ project_id: str | None = None,
170
+ ) -> CloudEvalSetPullResult:
171
+ """Read and validate one immutable Dataset version before execution."""
172
+
173
+ if not dataset_id.strip() or version < 1:
174
+ raise ValueError("datasetId 和 version 必须有效")
175
+ snapshot = await self.client.read_snapshot(
176
+ dataset_id,
177
+ version,
178
+ project_id=project_id,
179
+ )
180
+ evalset = evalset_from_dataset_snapshot(snapshot)
181
+ if evalset.content_digest != snapshot.content_digest:
182
+ raise CloudEvalSetPreviewError("云端 snapshot 的 contentDigest 校验失败")
183
+ reference = CloudDatasetRef(
184
+ provider=self.provider,
185
+ project_id=project_id,
186
+ dataset_id=dataset_id,
187
+ version=version,
188
+ schema_hash=snapshot.schema_hash,
189
+ content_digest=snapshot.content_digest,
190
+ row_count=len(snapshot.rows),
191
+ )
192
+ return CloudEvalSetPullResult(
193
+ snapshot=snapshot,
194
+ evalset=evalset,
195
+ cloud_dataset=reference,
196
+ )
197
+
198
+ async def catalog(self, *, project_id: str | None = None) -> list[CloudEvalSetCatalogItem]:
199
+ return await self.client.list_datasets(project_id=project_id)
@@ -0,0 +1,478 @@
1
+ """Stable, serializable data objects shared by CLI and Studio evaluation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime, timezone
6
+ from enum import Enum
7
+ from typing import Any, Literal
8
+
9
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
10
+
11
+ # ---------------------------------------------------------------------------
12
+ # Base model & helpers
13
+ # ---------------------------------------------------------------------------
14
+
15
+
16
+ def _to_camel_case(value: str) -> str:
17
+ head, *tail = value.split("_")
18
+ return head + "".join(part.capitalize() for part in tail)
19
+
20
+
21
+ def _content_digest(payload: dict[str, Any]) -> str:
22
+ import hashlib
23
+ import json
24
+
25
+ encoded = json.dumps(
26
+ payload,
27
+ ensure_ascii=False,
28
+ sort_keys=True,
29
+ separators=(",", ":"),
30
+ ).encode("utf-8")
31
+ return hashlib.sha256(encoded).hexdigest()
32
+
33
+
34
+ class EvaluationModel(BaseModel):
35
+ """Use camelCase on the wire while keeping Python fields snake_case."""
36
+
37
+ model_config = ConfigDict(
38
+ alias_generator=_to_camel_case,
39
+ populate_by_name=True,
40
+ extra="forbid",
41
+ )
42
+
43
+
44
+ # ---------------------------------------------------------------------------
45
+ # Enums
46
+ # ---------------------------------------------------------------------------
47
+
48
+
49
+ # Assertion kinds & data egress policy (configure how cases are asserted and
50
+ # what data may leave the local process).
51
+ class AssertionType(str, Enum):
52
+ """Deterministic assertion kinds supported by the first evaluation phase."""
53
+
54
+ RESPONSE_EQUALS = "response.equals"
55
+ RESPONSE_CONTAINS = "response.contains"
56
+ RESPONSE_NOT_CONTAINS = "response.notContains"
57
+ RESPONSE_JSON_SCHEMA = "response.jsonSchema"
58
+ RUNTIME_MAX_LATENCY_MS = "runtime.maxLatencyMs"
59
+ RUNTIME_MAX_INPUT_TOKENS = "runtime.maxInputTokens"
60
+ RUNTIME_MAX_OUTPUT_TOKENS = "runtime.maxOutputTokens"
61
+ RUNTIME_MAX_TOTAL_TOKENS = "runtime.maxTotalTokens"
62
+ TOOL_CALLED = "tool.called"
63
+ TOOL_NOT_CALLED = "tool.notCalled"
64
+ TOOL_SUCCEEDED = "tool.succeeded"
65
+ TOOL_SEQUENCE = "tool.sequence"
66
+
67
+
68
+ class DataPolicy(str, Enum):
69
+ """Controls what evaluation data may leave the local process."""
70
+
71
+ LOCAL_ONLY = "local_only"
72
+ METADATA_ONLY = "metadata_only"
73
+ REDACTED_TRACE = "redacted_trace"
74
+ FULL_TRACE = "full_trace"
75
+
76
+
77
+ # Lifecycle & outcome statuses (run-level, per-case target invocation, and
78
+ # per-metric verdicts).
79
+ class EvalRunStatus(str, Enum):
80
+ """Lifecycle status for an entire evaluation run."""
81
+
82
+ PENDING = "PENDING"
83
+ RUNNING = "RUNNING"
84
+ PASSED = "PASSED"
85
+ FAILED = "FAILED"
86
+ ERROR = "ERROR"
87
+ CANCELLED = "CANCELLED"
88
+
89
+
90
+ class TargetRunStatus(str, Enum):
91
+ """Terminal status returned by one target invocation."""
92
+
93
+ PASSED = "PASSED"
94
+ FAILED = "FAILED"
95
+ ERROR = "ERROR"
96
+ CANCELLED = "CANCELLED"
97
+ UNAVAILABLE = "UNAVAILABLE"
98
+
99
+
100
+ class MetricStatus(str, Enum):
101
+ """Outcome of a single deterministic metric."""
102
+
103
+ PASS = "PASS"
104
+ FAIL = "FAIL"
105
+ UNAVAILABLE = "UNAVAILABLE"
106
+ ERROR = "ERROR"
107
+
108
+
109
+ # ---------------------------------------------------------------------------
110
+ # Evaluation set & input cases
111
+ # ---------------------------------------------------------------------------
112
+
113
+
114
+ class EvalTurn(EvaluationModel):
115
+ """A single conversational turn within a multi-turn case."""
116
+
117
+ input: str = Field(min_length=1, max_length=32768)
118
+ expected_output: str | None = Field(default=None, max_length=32768)
119
+ expected_tools: list[dict[str, Any]] = Field(default_factory=list)
120
+ metadata: dict[str, Any] = Field(default_factory=dict)
121
+
122
+
123
+ class AssertionSpec(EvaluationModel):
124
+ """A single deterministic assertion with type-dependent value validation."""
125
+
126
+ type: AssertionType
127
+ value: Any
128
+ required: bool = True
129
+
130
+ @model_validator(mode="after")
131
+ def validate_value(self) -> "AssertionSpec":
132
+ if self.type is AssertionType.RESPONSE_JSON_SCHEMA:
133
+ if not isinstance(self.value, dict):
134
+ raise ValueError("response.jsonSchema 的 value 必须是对象")
135
+ elif self.type.value.startswith("runtime."):
136
+ if isinstance(self.value, bool) or not isinstance(self.value, (int, float)):
137
+ raise ValueError(f"{self.type} 的 value 必须是非负数字")
138
+ if self.value < 0:
139
+ raise ValueError(f"{self.type} 的 value 必须是非负数字")
140
+ elif self.type is AssertionType.TOOL_SEQUENCE:
141
+ if (
142
+ not isinstance(self.value, list)
143
+ or not self.value
144
+ or any(not isinstance(item, str) or not item.strip() for item in self.value)
145
+ ):
146
+ raise ValueError("tool.sequence 的 value 必须是非空工具名称数组")
147
+ elif not isinstance(self.value, str):
148
+ raise ValueError(f"{self.type} 的 value 必须是字符串")
149
+ return self
150
+
151
+
152
+ class EvalCase(EvaluationModel):
153
+ """One evaluation case: ordered turns plus assertions to check."""
154
+
155
+ id: str = Field(min_length=1, max_length=128)
156
+ turns: list[EvalTurn] = Field(min_length=1)
157
+ assertions: list[AssertionSpec] = Field(default_factory=list)
158
+ metadata: dict[str, Any] = Field(default_factory=dict)
159
+
160
+ @model_validator(mode="before")
161
+ @classmethod
162
+ def normalize_single_input(cls, value: Any) -> Any:
163
+ if not isinstance(value, dict):
164
+ return value
165
+ data = dict(value)
166
+ if "input" in data and "turns" not in data:
167
+ turn = {"input": data.pop("input")}
168
+ for field in (
169
+ "expected_output",
170
+ "expectedOutput",
171
+ "reference_output",
172
+ "referenceOutput",
173
+ "expected_tools",
174
+ "expectedTools",
175
+ ):
176
+ if field in data:
177
+ normalized_field = (
178
+ "expected_output"
179
+ if field in {"reference_output", "referenceOutput"}
180
+ else field
181
+ )
182
+ turn[normalized_field] = data.pop(field)
183
+ data["turns"] = [turn]
184
+ return data
185
+
186
+ @property
187
+ def input(self) -> str:
188
+ """Return the final turn for legacy single-input consumers."""
189
+
190
+ return self.turns[-1].input
191
+
192
+
193
+ class EvalSetVersion(EvaluationModel):
194
+ """A versioned, content-digested evaluation set of one or more cases."""
195
+
196
+ schema_version: Literal["ksadk.eval/v1"] = "ksadk.eval/v1"
197
+ name: str = Field(min_length=1, max_length=256)
198
+ cases: list[EvalCase] = Field(min_length=1)
199
+ metadata: dict[str, Any] = Field(default_factory=dict)
200
+ source_format: str = "native"
201
+ content_digest: str = ""
202
+
203
+ @model_validator(mode="after")
204
+ def validate_and_digest(self) -> "EvalSetVersion":
205
+ ids = [case.id for case in self.cases]
206
+ if len(ids) != len(set(ids)):
207
+ raise ValueError("评测集中的 case id 必须唯一")
208
+ expected = self.compute_digest()
209
+ if self.content_digest and self.content_digest != expected:
210
+ raise ValueError("contentDigest 与规范化评测集内容不一致")
211
+ self.content_digest = expected
212
+ return self
213
+
214
+ def compute_digest(self) -> str:
215
+ """Hash normalized cases, excluding transport format and the digest itself."""
216
+
217
+ payload = self.model_dump(
218
+ mode="json",
219
+ by_alias=False,
220
+ exclude={"content_digest", "source_format"},
221
+ )
222
+ return _content_digest(payload)
223
+
224
+
225
+ class CloudDatasetRef(EvaluationModel):
226
+ """Immutable reference to the exact cloud Dataset snapshot used by a run."""
227
+
228
+ provider: str = Field(min_length=1, max_length=256)
229
+ project_id: str | None = Field(default=None, min_length=1, max_length=256)
230
+ dataset_id: str = Field(min_length=1, max_length=256)
231
+ version: int = Field(ge=1)
232
+ schema_hash: str = Field(min_length=64, max_length=64)
233
+ content_digest: str = Field(min_length=64, max_length=64)
234
+ row_count: int = Field(default=0, ge=0)
235
+
236
+
237
+ # ---------------------------------------------------------------------------
238
+ # Target identity & references
239
+ # ---------------------------------------------------------------------------
240
+
241
+
242
+ class TargetKind(str, Enum):
243
+ """Supported target categories; adapters own their implementation details."""
244
+
245
+ LOCAL_SOURCE = "local_source"
246
+ STUDIO_BUILD = "studio_build"
247
+ A2A = "a2a"
248
+ CODEX_WORKTREE = "codex_worktree"
249
+
250
+
251
+ class TargetSnapshot(EvaluationModel):
252
+ """Immutable target identity recorded with an evaluation run."""
253
+
254
+ kind: TargetKind
255
+ entrypoint: str = Field(min_length=1, max_length=1024)
256
+ revision_digest: str = Field(min_length=1, max_length=128)
257
+ runtime: str = Field(default="", max_length=128)
258
+ metadata: dict[str, Any] = Field(default_factory=dict)
259
+
260
+
261
+ class TargetRef(EvaluationModel):
262
+ """Unresolved target supplied by CLI/Studio before an adapter snapshots it."""
263
+
264
+ kind: TargetKind
265
+ locator: str = Field(min_length=1, max_length=2048)
266
+ entrypoint: str | None = Field(default=None, min_length=1, max_length=1024)
267
+ credential_ref: str | None = Field(default=None, min_length=1, max_length=512)
268
+ profile: str | None = Field(default=None, min_length=1, max_length=256)
269
+
270
+
271
+ # ---------------------------------------------------------------------------
272
+ # Execution config & request / spec
273
+ # ---------------------------------------------------------------------------
274
+
275
+
276
+ class EvaluationConfig(EvaluationModel):
277
+ """Execution limits and evaluator selection shared by CLI and Studio."""
278
+
279
+ timeout_seconds: int = Field(default=120, ge=1, le=3600)
280
+ fail_fast: bool = False
281
+ evaluators: list[str] = Field(default_factory=list)
282
+ data_policy: DataPolicy = DataPolicy.LOCAL_ONLY
283
+ judge_model: str | None = Field(default=None, min_length=1, max_length=256)
284
+ judge_api_base: str | None = Field(default=None, min_length=1, max_length=2048)
285
+ judge_api_key_env: str = Field(
286
+ default="KSADK_EVAL_JUDGE_API_KEY",
287
+ pattern=r"^[A-Za-z_][A-Za-z0-9_]*$",
288
+ max_length=128,
289
+ )
290
+
291
+
292
+ class EvaluationRequest(EvaluationModel):
293
+ """Validated input passed into the one public evaluation executor."""
294
+
295
+ evalset: EvalSetVersion
296
+ target: TargetRef
297
+ config: EvaluationConfig = Field(default_factory=EvaluationConfig)
298
+ report_dir: str | None = Field(default=None, min_length=1, max_length=2048)
299
+ cloud_dataset: CloudDatasetRef | None = None
300
+
301
+
302
+ class EvalRunSpec(EvaluationModel):
303
+ """Immutable execution plan after the target has been snapshotted."""
304
+
305
+ id: str = Field(min_length=1, max_length=128)
306
+ evalset: EvalSetVersion
307
+ target: TargetSnapshot
308
+ config: EvaluationConfig = Field(default_factory=EvaluationConfig)
309
+ environment_digest: str = Field(default="", max_length=128)
310
+ attempt: int = Field(default=1, ge=1)
311
+ cloud_dataset: CloudDatasetRef | None = None
312
+
313
+
314
+ # ---------------------------------------------------------------------------
315
+ # Run results: trace, usage, target run, metric results, case run, report
316
+ # ---------------------------------------------------------------------------
317
+
318
+
319
+ # Per-case adapter output: trace linkage, token usage, and the normalized
320
+ # invocation result returned by a target adapter.
321
+ class TraceRef(EvaluationModel):
322
+ """Queryable linkage to a recorded trace; at least one id required."""
323
+
324
+ run_id: str | None = None
325
+ trace_id: str | None = None
326
+ root_span_id: str | None = None
327
+ session_id: str | None = None
328
+ invocation_id: str | None = None
329
+ seq_start: int | None = Field(default=None, ge=1)
330
+ seq_end: int | None = Field(default=None, ge=1)
331
+ remote_task_id: str | None = None
332
+ seq_id: int | None = Field(default=None, ge=1)
333
+
334
+ @model_validator(mode="after")
335
+ def require_reference(self) -> "TraceRef":
336
+ if not any(
337
+ (
338
+ self.run_id,
339
+ self.trace_id,
340
+ self.session_id,
341
+ self.invocation_id,
342
+ self.remote_task_id,
343
+ self.seq_id,
344
+ )
345
+ ):
346
+ raise ValueError("TraceRef 至少需要一个可查询 ID")
347
+ return self
348
+
349
+
350
+ class UsageSnapshot(EvaluationModel):
351
+ """Token usage for one invocation; zero unless the adapter reported it."""
352
+
353
+ input_tokens: int = Field(default=0, ge=0)
354
+ output_tokens: int = Field(default=0, ge=0)
355
+ total_tokens: int = Field(default=0, ge=0)
356
+ reported: bool = False
357
+
358
+
359
+ class ToolCallEvidence(EvaluationModel):
360
+ """Non-sensitive projection of one runtime tool invocation."""
361
+
362
+ call_id: str = Field(min_length=1, max_length=256)
363
+ name: str = Field(min_length=1, max_length=256)
364
+ status: Literal["SUCCEEDED", "ERROR", "INCOMPLETE"]
365
+ seq_start: int | None = Field(default=None, ge=1)
366
+ seq_end: int | None = Field(default=None, ge=1)
367
+
368
+
369
+ class TargetRun(EvaluationModel):
370
+ """Normalized result returned by a target adapter for one case."""
371
+
372
+ status: TargetRunStatus
373
+ output: str = ""
374
+ duration_ms: int | None = Field(default=None, ge=0)
375
+ usage: UsageSnapshot = Field(default_factory=UsageSnapshot)
376
+ error_code: str | None = None
377
+ error_message: str | None = None
378
+ trace_ref: TraceRef | None = None
379
+ trace_refs: list[TraceRef] = Field(default_factory=list)
380
+ tool_calls: list[ToolCallEvidence] = Field(default_factory=list)
381
+ metadata: dict[str, Any] = Field(default_factory=dict)
382
+
383
+
384
+ # Evaluator output: per-metric verdicts, per-case aggregation, run-level
385
+ # summary counts, and the canonical persisted report.
386
+ class MetricResult(EvaluationModel):
387
+ """One deterministic evaluator result and its non-sensitive evidence."""
388
+
389
+ name: str = Field(min_length=1, max_length=128)
390
+ version: str = Field(default="v1", min_length=1, max_length=32)
391
+ status: MetricStatus
392
+ score: float | None = Field(default=None, ge=0, le=1)
393
+ required: bool = True
394
+ evidence: dict[str, Any] = Field(default_factory=dict)
395
+
396
+
397
+ class CaseRun(EvaluationModel):
398
+ """Target result and metric results for one case attempt."""
399
+
400
+ case_id: str = Field(min_length=1, max_length=128)
401
+ attempt: int = Field(default=1, ge=1)
402
+ target_run: TargetRun
403
+ metrics: list[MetricResult] = Field(default_factory=list)
404
+
405
+ @property
406
+ def passed(self) -> bool:
407
+ return self.target_run.status is TargetRunStatus.PASSED and all(
408
+ metric.status is MetricStatus.PASS for metric in self.metrics if metric.required
409
+ )
410
+
411
+
412
+ class EvalRunSummary(EvaluationModel):
413
+ """Derived terminal counts; callers must not construct their own summary."""
414
+
415
+ total_cases: int = Field(default=0, ge=0)
416
+ passed_cases: int = Field(default=0, ge=0)
417
+ failed_cases: int = Field(default=0, ge=0)
418
+ unavailable_cases: int = Field(default=0, ge=0)
419
+ error_cases: int = Field(default=0, ge=0)
420
+ cancelled_cases: int = Field(default=0, ge=0)
421
+
422
+
423
+ class EvalRunReport(EvaluationModel):
424
+ """Canonical persisted result consumed by CLI, Studio, and future sync."""
425
+
426
+ schema_version: Literal["ksadk.eval.report/v1"] = "ksadk.eval.report/v1"
427
+ spec: EvalRunSpec
428
+ status: EvalRunStatus
429
+ created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
430
+ case_runs: list[CaseRun] = Field(default_factory=list)
431
+ summary: EvalRunSummary = Field(default_factory=EvalRunSummary)
432
+ report_digest: str = ""
433
+
434
+ @model_validator(mode="after")
435
+ def validate_case_ids(self) -> "EvalRunReport":
436
+ case_ids = [case.case_id for case in self.case_runs]
437
+ if len(case_ids) != len(set(case_ids)):
438
+ raise ValueError("一次评测中 case_id 不能重复")
439
+ self.summary = self._summarize_cases()
440
+ expected = self.compute_digest()
441
+ if self.report_digest and self.report_digest != expected:
442
+ legacy_payload = self.model_dump(
443
+ mode="json", by_alias=False, exclude={"report_digest"}
444
+ )
445
+ legacy_payload["spec"].pop("cloud_dataset", None)
446
+ if self.spec.cloud_dataset is not None or self.report_digest != _content_digest(
447
+ legacy_payload
448
+ ):
449
+ raise ValueError("reportDigest 与规范化报告内容不一致")
450
+ self.report_digest = expected
451
+ return self
452
+
453
+ def _summarize_cases(self) -> EvalRunSummary:
454
+ counts = EvalRunSummary(total_cases=len(self.case_runs))
455
+ for case_run in self.case_runs:
456
+ if case_run.target_run.status is TargetRunStatus.ERROR or any(
457
+ metric.required and metric.status is MetricStatus.ERROR
458
+ for metric in case_run.metrics
459
+ ):
460
+ counts.error_cases += 1
461
+ elif case_run.target_run.status is TargetRunStatus.CANCELLED:
462
+ counts.cancelled_cases += 1
463
+ elif case_run.target_run.status is TargetRunStatus.UNAVAILABLE or any(
464
+ metric.required and metric.status is MetricStatus.UNAVAILABLE
465
+ for metric in case_run.metrics
466
+ ):
467
+ counts.unavailable_cases += 1
468
+ elif case_run.passed:
469
+ counts.passed_cases += 1
470
+ else:
471
+ counts.failed_cases += 1
472
+ return counts
473
+
474
+ def compute_digest(self) -> str:
475
+ """Return a stable digest excluding the digest field itself."""
476
+
477
+ payload = self.model_dump(mode="json", by_alias=False, exclude={"report_digest"})
478
+ return _content_digest(payload)