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
+ """Resolve an immutable Codex build into a canonical StudioRunSpec."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import zipfile
7
+ from typing import Any, cast
8
+
9
+ import yaml # type: ignore[import-untyped]
10
+
11
+ from ksadk.configs import ModelConfig
12
+ from ksadk.runtime import RuntimeLaunchContext
13
+ from ksadk.studio.codex_builder import CodexBuildRepository
14
+ from ksadk.studio.codex_manifest import CodexAgentManifest, CodexManifestRepository
15
+ from ksadk.studio.contracts import ModelSpec
16
+ from ksadk.studio.errors import StudioError
17
+ from ksadk.studio.run_service import StudioRunSpec
18
+ from ksadk.studio.workspace import Workspace
19
+ from ksadk.tools.gateway import normalize_tool_approval_mode
20
+
21
+
22
+ class CodexRunSpecResolver:
23
+ """Validate a build snapshot without creating another Runtime abstraction."""
24
+
25
+ def __init__(
26
+ self,
27
+ workspace: Workspace,
28
+ *,
29
+ build_repository: CodexBuildRepository | None = None,
30
+ manifest_repository: CodexManifestRepository | None = None,
31
+ credential_resolver: Any = None,
32
+ resource_catalog: Any = None,
33
+ draft_repository: Any = None,
34
+ ) -> None:
35
+ self.workspace = workspace
36
+ self.builds = build_repository or CodexBuildRepository(workspace)
37
+ self.manifests = manifest_repository or CodexManifestRepository(workspace)
38
+ self.credentials = credential_resolver
39
+ self.catalog = resource_catalog
40
+ self.drafts = draft_repository
41
+
42
+ def resolve(
43
+ self,
44
+ build_id: str,
45
+ *,
46
+ model: str | None = None,
47
+ sandbox: str | None = None,
48
+ approval_mode: str | None = None,
49
+ ) -> StudioRunSpec:
50
+ build = self.builds.get(build_id)
51
+ current = self.manifests.load(build.agent_name)
52
+ if build.manifest_sha256 != current.manifest_sha256:
53
+ raise StudioError(
54
+ "CODEX_BUILD_STALE",
55
+ "agentengine.yaml 已修改,请重新构建后再运行",
56
+ status_code=409,
57
+ details={
58
+ "buildManifestSha256": build.manifest_sha256,
59
+ "currentManifestSha256": current.manifest_sha256,
60
+ },
61
+ )
62
+ manifest = self._load_build_manifest(build.artifact_path)
63
+ selected_model = self._select_model(manifest, model)
64
+ project_dir = self.workspace.root.resolve()
65
+ skills = self._skill_inputs(manifest)
66
+ codex_overrides = self._mcp_overrides(manifest)
67
+ approval_profile = normalize_tool_approval_mode(approval_mode) if approval_mode else ""
68
+ sandbox, approval = self._resolve_sandbox(
69
+ manifest,
70
+ override=sandbox,
71
+ approval_mode=approval_profile or None,
72
+ )
73
+ if sandbox == "workspace-write":
74
+ # workspace-write 默认断网;MCP/搜索类工具需要显式放行网络
75
+ codex_overrides = [*codex_overrides, "sandbox_workspace_write.network_access=true"]
76
+ launch_config: dict[str, Any] = {
77
+ "sandbox_read_only": sandbox == "read-only",
78
+ "sandbox": sandbox,
79
+ "approval_mode": approval,
80
+ }
81
+ if codex_overrides:
82
+ launch_config["codex_overrides"] = codex_overrides
83
+ runtime_env = {
84
+ **self._resolve_model_env(build, manifest, selected_model),
85
+ **self._resolve_mcp_env(manifest),
86
+ }
87
+ if runtime_env:
88
+ launch_config["env"] = runtime_env
89
+ agent_task = str(manifest.task_prompt or "").strip()
90
+ # PCM 策略从不可变 Manifest 读取(方案 §5.1:Build 锁定后 sidecar 修改不影响旧 Build)
91
+ # manifest.context/memory 由 _manifest() 从 AgentSpec 写入,随 Build 进入 Artifact
92
+ resolved_context = manifest.context
93
+ resolved_memory = manifest.memory
94
+ base_instructions = manifest.prompt
95
+ if agent_task:
96
+ base_instructions = f"{manifest.prompt}\n\n{agent_task}"
97
+ request_config: dict[str, Any] = {
98
+ # Codex 原生只接收 base_instructions,因此运行前合并;PCM 证据仍使用下面
99
+ # 两个独立来源生成 agent_identity / agent_policy 的分段 hash。
100
+ "base_instructions": base_instructions,
101
+ "agent_system": manifest.prompt,
102
+ "agent_task": agent_task,
103
+ "cwd": str(project_dir),
104
+ "skills": skills,
105
+ "sandbox_read_only": sandbox == "read-only",
106
+ "sandbox": sandbox,
107
+ "approval_mode": approval,
108
+ "summary": "auto",
109
+ # Studio sessions resume the same native Codex thread across turns.
110
+ "ephemeral": False,
111
+ # PCM 配置(方案 §5.1):从 Manifest 读取预算和 rollout
112
+ "max_input_tokens": resolved_context.max_input_tokens if resolved_context else None,
113
+ "reserve_output_tokens": (
114
+ resolved_context.reserve_output_tokens if resolved_context else None
115
+ ),
116
+ "context_engine_rollout": (
117
+ resolved_context.rollout.context_engine if resolved_context else None
118
+ ),
119
+ "memory_recall_enabled": (resolved_memory.recall.enabled if resolved_memory else None),
120
+ "memory_recall_top_k": resolved_memory.recall.top_k if resolved_memory else None,
121
+ "memory_recall_max_tokens": (
122
+ resolved_memory.recall.max_tokens if resolved_memory else None
123
+ ),
124
+ "memory_recall_min_score": (
125
+ resolved_memory.recall.min_score if resolved_memory else None
126
+ ),
127
+ "memory_write_rollout": (
128
+ resolved_context.rollout.memory_write if resolved_context else None
129
+ ),
130
+ "memory_enabled": resolved_memory.enabled if resolved_memory else False,
131
+ "memory_write_mode": resolved_memory.write.mode if resolved_memory else "candidate",
132
+ "flush_before_compaction": (
133
+ resolved_memory.write.flush_before_compaction if resolved_memory else True
134
+ ),
135
+ "provider_ref": resolved_memory.provider_ref if resolved_memory else "local-default",
136
+ }
137
+ if approval_profile:
138
+ request_config["tool_approval_mode"] = approval_profile
139
+ return StudioRunSpec(
140
+ launch_context=RuntimeLaunchContext(
141
+ runtime_type="codex",
142
+ project_dir=project_dir,
143
+ config=launch_config,
144
+ ),
145
+ build_id=build.id,
146
+ agent_id=manifest.name,
147
+ model=selected_model,
148
+ request_config=request_config,
149
+ manifest_sha256=build.manifest_sha256,
150
+ )
151
+
152
+ def _resolve_model_env(
153
+ self,
154
+ build: Any,
155
+ manifest: CodexAgentManifest,
156
+ selected_model: str,
157
+ ) -> dict[str, str]:
158
+ resolver = self.credentials
159
+ if resolver is None:
160
+ from ksadk.studio.model_client import CredentialResolver
161
+
162
+ resolver = CredentialResolver(self.workspace)
163
+ self.credentials = resolver
164
+ profile = self._resolve_model_profile(build, manifest, selected_model)
165
+ credential_ref = profile.credential_ref if profile else "env://OPENAI_API_KEY"
166
+ try:
167
+ credential = resolver.resolve(credential_ref)
168
+ except StudioError:
169
+ return {}
170
+ base_url = (
171
+ self._model_base_url(profile)
172
+ if profile is not None
173
+ else ModelConfig().api_base.rstrip("/")
174
+ )
175
+ return {
176
+ "OPENAI_API_KEY": credential,
177
+ "OPENAI_BASE_URL": base_url,
178
+ "OPENAI_API_BASE": base_url,
179
+ "OPENAI_MODEL_NAME": selected_model,
180
+ }
181
+
182
+ def _resolve_model_profile(
183
+ self,
184
+ build: Any,
185
+ manifest: CodexAgentManifest,
186
+ selected_model: str,
187
+ ) -> ModelSpec | None:
188
+ # New build records own an immutable connection snapshot. An empty
189
+ # mapping explicitly means this build uses the process/workspace
190
+ # default connection; only legacy records may consult live Catalog
191
+ # state for backward compatibility.
192
+ snapshots = getattr(build, "model_profiles", None)
193
+ if snapshots is not None:
194
+ payload = snapshots.get(selected_model)
195
+ return ModelSpec.model_validate(payload) if payload is not None else None
196
+
197
+ if self.catalog is None:
198
+ from ksadk.studio.resource_catalog import LocalResourceCatalog
199
+
200
+ self.catalog = LocalResourceCatalog(self.workspace)
201
+ if self.drafts is None:
202
+ from ksadk.studio.codex_agent_service import CodexDraftRepository
203
+
204
+ self.drafts = CodexDraftRepository(self.workspace)
205
+
206
+ draft = self.drafts.get(manifest.name)
207
+ if draft is not None:
208
+ bindings = draft.spec.bindings
209
+ resource_ids = list(bindings.model_profile_ids)
210
+ if not resource_ids and bindings.model_profile_id:
211
+ resource_ids = [bindings.model_profile_id]
212
+ for resource_id in resource_ids:
213
+ try:
214
+ descriptor = self.catalog.get(resource_id)
215
+ profile = ModelSpec.model_validate(descriptor.contract)
216
+ except (StudioError, ValueError):
217
+ continue
218
+ if profile.model == selected_model:
219
+ return profile
220
+
221
+ matches: list[ModelSpec] = []
222
+ for descriptor in self.catalog.list(kind="model", limit=500):
223
+ try:
224
+ profile = ModelSpec.model_validate(descriptor.contract)
225
+ except ValueError:
226
+ continue
227
+ if profile.model == selected_model:
228
+ matches.append(profile)
229
+ return matches[0] if len(matches) == 1 else None
230
+
231
+ @staticmethod
232
+ def _model_base_url(profile: ModelSpec) -> str:
233
+ raw = str(profile.base_url or profile.endpoint_url or "").rstrip("/")
234
+ for suffix in ("/chat/completions", "/responses"):
235
+ if raw.endswith(suffix):
236
+ return raw[: -len(suffix)]
237
+ return raw
238
+
239
+ @staticmethod
240
+ def _mcp_overrides(manifest: CodexAgentManifest) -> list[str]:
241
+ """Translate bound MCP servers into codex --config overrides."""
242
+ overrides: list[str] = []
243
+ for server in manifest.mcp_servers or []:
244
+ name = str(server.get("name") or "").strip()
245
+ url = str(server.get("url") or "").strip()
246
+ if not name or not url:
247
+ continue
248
+ overrides.append(f"mcp_servers.{name}.url={url}")
249
+ env_key = str(server.get("env_key") or "").strip()
250
+ if env_key:
251
+ overrides.append(f"mcp_servers.{name}.bearer_token_env_var={env_key}")
252
+ return overrides
253
+
254
+ def _resolve_mcp_env(self, manifest: CodexAgentManifest) -> dict[str, str]:
255
+ """把 manifest 中 MCP 的 env_key 解析为真实值,注入 codex 子进程环境。
256
+
257
+ codex app-server 的 bearer_token_env_var 直接读子进程环境变量,不经过
258
+ Studio 的凭证解析链(session → 工作区 secrets.env → 环境变量),必须在
259
+ 启动前完成解析。缺凭证时快速失败并指出具体引用。
260
+ """
261
+ env: dict[str, str] = {}
262
+ for server in manifest.mcp_servers or []:
263
+ env_key = str(server.get("env_key") or "").strip()
264
+ if not env_key:
265
+ continue
266
+ if env_key in env:
267
+ continue
268
+ resolver = self.credentials
269
+ if resolver is None:
270
+ from ksadk.studio.model_client import CredentialResolver
271
+
272
+ resolver = CredentialResolver(self.workspace)
273
+ self.credentials = resolver
274
+ try:
275
+ env[env_key] = resolver.resolve(f"env://{env_key}")
276
+ except Exception as exc:
277
+ raise StudioError(
278
+ "MCP_CREDENTIAL_MISSING",
279
+ f"MCP Server「{server.get('name')}」需要凭证 {env_key},"
280
+ "请先在 MCP 页连接时保存该环境变量的值",
281
+ status_code=422,
282
+ details={
283
+ "server": str(server.get("name") or ""),
284
+ "reference": f"env://{env_key}",
285
+ },
286
+ ) from exc
287
+ return env
288
+
289
+ @staticmethod
290
+ def _resolve_sandbox(
291
+ manifest: CodexAgentManifest,
292
+ override: str | None = None,
293
+ approval_mode: str | None = None,
294
+ ) -> tuple[str, str]:
295
+ """Resolve (sandbox, approval_mode): per-run override > manifest > env > default.
296
+
297
+ UI 4 档: read_only / workspace_write / workspace_write_auto / full_access
298
+ """
299
+ presets = {
300
+ "read_only": ("read-only", "deny_all"),
301
+ "read-only": ("read-only", "deny_all"),
302
+ "workspace_write": ("workspace-write", "deny_all"),
303
+ "workspace-write": ("workspace-write", "deny_all"),
304
+ "workspace_write_auto": ("workspace-write", "auto_review"),
305
+ "workspace-write-auto": ("workspace-write", "auto_review"),
306
+ "full_access": ("full-access", "deny_all"),
307
+ "full-access": ("full-access", "deny_all"),
308
+ }
309
+ approval_presets = {
310
+ "ask": ("workspace-write", "manual"),
311
+ "risk": ("workspace-write", "auto_review"),
312
+ "full": ("full-access", "deny_all"),
313
+ }
314
+ if approval_mode:
315
+ return approval_presets[normalize_tool_approval_mode(approval_mode)]
316
+ raw = (
317
+ (override or os.environ.get("KSADK_CODEX_SANDBOX") or manifest.sandbox or "read_only")
318
+ .strip()
319
+ .lower()
320
+ )
321
+ return presets.get(raw, ("read-only", "deny_all"))
322
+
323
+ def _skill_inputs(self, manifest: CodexAgentManifest) -> list[dict[str, str]]:
324
+ """Resolve bound skill resource ids to codex SkillInput wire dicts."""
325
+ if not manifest.skills:
326
+ return []
327
+ skills_root = self.workspace.resolve("capabilities/skills")
328
+ inputs: list[dict[str, str]] = []
329
+ for sid in manifest.skills:
330
+ name = self._skill_name_from_id(sid)
331
+ if not name:
332
+ continue
333
+ skill_dir = skills_root / name
334
+ if not skill_dir.is_dir():
335
+ continue
336
+ inputs.append({"name": name, "path": str(skill_dir.resolve())})
337
+ return inputs
338
+
339
+ @staticmethod
340
+ def _skill_name_from_id(resource_id: str) -> str:
341
+ parts = str(resource_id).split(":")
342
+ if len(parts) >= 4 and parts[0] == "skill":
343
+ return parts[2]
344
+ if len(parts) == 2:
345
+ return parts[1]
346
+ return ""
347
+
348
+ @staticmethod
349
+ def _select_model(manifest: CodexAgentManifest, requested: str | None) -> str:
350
+ selected = str(requested or manifest.model).strip()
351
+ if selected not in manifest.allowed_models:
352
+ raise StudioError(
353
+ "MODEL_NOT_BOUND",
354
+ "请求模型未绑定到当前 Agent Build",
355
+ status_code=422,
356
+ details={
357
+ "model": selected,
358
+ "allowedModels": list(manifest.allowed_models),
359
+ },
360
+ )
361
+ environment_allowlist = {
362
+ item.strip()
363
+ for item in os.environ.get("AGENTENGINE_MODEL_ALLOWLIST", "").split(",")
364
+ if item.strip()
365
+ }
366
+ if environment_allowlist and selected not in environment_allowlist:
367
+ raise StudioError(
368
+ "MODEL_NOT_AVAILABLE",
369
+ "请求模型不在当前运行环境的模型白名单中",
370
+ status_code=422,
371
+ details={"model": selected},
372
+ )
373
+ return selected
374
+
375
+ def _load_build_manifest(self, artifact_path: str) -> CodexAgentManifest:
376
+ archive_path = self.workspace.resolve(artifact_path, must_exist=True)
377
+ try:
378
+ if archive_path.suffix == ".zip":
379
+ # Compatibility for historical local audit receipts. New
380
+ # YAML-only builds keep the declaration as a plain immutable
381
+ # file, so they cannot be mistaken for a user-code package.
382
+ with zipfile.ZipFile(archive_path) as archive:
383
+ payload = yaml.safe_load(archive.read("agentengine.yaml"))
384
+ else:
385
+ payload = yaml.safe_load(archive_path.read_bytes())
386
+ return cast(CodexAgentManifest, CodexAgentManifest.model_validate(payload))
387
+ except (OSError, KeyError, ValueError, zipfile.BadZipFile) as exc:
388
+ raise StudioError(
389
+ "CODEX_BUILD_INVALID",
390
+ "Codex Build 缺少有效的 agentengine.yaml",
391
+ status_code=500,
392
+ ) from exc
393
+
394
+
395
+ __all__ = ["CodexRunSpecResolver"]
@@ -0,0 +1,190 @@
1
+ """Deterministic compilation from AgentDraft to ResolvedAgentSpec."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any
7
+ from urllib.parse import urlparse
8
+
9
+ from ksadk.studio.capabilities import (
10
+ CapabilityResolver,
11
+ LocalCapabilityResolver,
12
+ canonical_json,
13
+ sha256_digest,
14
+ )
15
+ from ksadk.studio.contracts import (
16
+ AgentDraft,
17
+ CapabilitiesSpec,
18
+ ResolvedAgentSpec,
19
+ ResolvedCapabilities,
20
+ )
21
+ from ksadk.studio.errors import StudioError
22
+ from ksadk.studio.resource_catalog import LocalResourceCatalog
23
+ from ksadk.studio.validator import AgentValidator
24
+ from ksadk.studio.workspace import Workspace
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class CompileResult:
29
+ resolved: ResolvedAgentSpec
30
+ dependency_lock: dict[str, Any]
31
+
32
+
33
+ class AgentCompiler:
34
+ def __init__(
35
+ self,
36
+ workspace: Workspace,
37
+ *,
38
+ resolver: CapabilityResolver | None = None,
39
+ validator: AgentValidator | None = None,
40
+ catalog: LocalResourceCatalog | None = None,
41
+ ) -> None:
42
+ self.workspace = workspace
43
+ self.resolver = resolver or LocalCapabilityResolver(workspace)
44
+ self.validator = validator or AgentValidator()
45
+ self.catalog = catalog or LocalResourceCatalog(workspace)
46
+
47
+ def compile(self, draft: AgentDraft) -> CompileResult:
48
+ source_payload = draft.model_dump(by_alias=True, exclude_none=True, mode="json")
49
+ source_digest = sha256_digest(canonical_json(source_payload))
50
+ materialized = self._materialize_bindings(draft)
51
+ self.validator.validate(materialized, level="build", raise_on_error=True)
52
+ assert materialized.spec.model is not None
53
+
54
+ skills = [
55
+ self.resolver.resolve_skill(ref)
56
+ for ref in materialized.spec.capabilities.skills
57
+ if ref.enabled
58
+ ]
59
+ mcp_servers = [
60
+ self.resolver.resolve_mcp(ref)
61
+ for ref in materialized.spec.capabilities.mcp_servers
62
+ if ref.enabled
63
+ ]
64
+ tools = [
65
+ self.resolver.resolve_tool(tool)
66
+ for tool in materialized.spec.capabilities.tools
67
+ ]
68
+ skills.sort(key=lambda item: (item["name"], item["version"], item["digest"]))
69
+ mcp_servers.sort(key=lambda item: (item["name"], item["version"], item["digest"]))
70
+ tools.sort(key=lambda item: (item.name, item.version, item.digest or ""))
71
+
72
+ resolved = ResolvedAgentSpec(
73
+ agent_id=draft.metadata.id,
74
+ source_revision=draft.metadata.revision,
75
+ instructions=materialized.spec.instructions,
76
+ model=self.resolver.resolve_model(materialized.spec.model),
77
+ capabilities=ResolvedCapabilities(
78
+ skills=skills,
79
+ mcp_servers=mcp_servers,
80
+ tools=tools,
81
+ ),
82
+ execution=materialized.spec.execution,
83
+ context=materialized.spec.context,
84
+ memory=materialized.spec.memory,
85
+ security=materialized.spec.security,
86
+ evaluation=materialized.spec.evaluation,
87
+ source_digest=source_digest,
88
+ )
89
+ digest_payload = resolved.model_dump(
90
+ by_alias=True,
91
+ exclude={"resolved_digest"},
92
+ exclude_none=True,
93
+ mode="json",
94
+ )
95
+ resolved.resolved_digest = sha256_digest(canonical_json(digest_payload))
96
+ dependency_lock = {
97
+ "lockVersion": "agentkit.lock/v1",
98
+ "agentId": draft.metadata.id,
99
+ "sourceRevision": draft.metadata.revision,
100
+ "resolvedDigest": resolved.resolved_digest,
101
+ "model": resolved.model.model_dump(
102
+ by_alias=True,
103
+ exclude_none=True,
104
+ mode="json",
105
+ ),
106
+ "skills": skills,
107
+ "mcpServers": mcp_servers,
108
+ "tools": [
109
+ tool.model_dump(by_alias=True, exclude_none=True, mode="json")
110
+ for tool in tools
111
+ ],
112
+ }
113
+ return CompileResult(resolved=resolved, dependency_lock=dependency_lock)
114
+
115
+ def _materialize_bindings(self, draft: AgentDraft) -> AgentDraft:
116
+ bindings = draft.spec.bindings
117
+ if (
118
+ not bindings.model_profile_id
119
+ and not bindings.tools
120
+ and not bindings.mcp_servers
121
+ and not bindings.skills
122
+ ):
123
+ return draft
124
+ materialized = draft.model_copy(deep=True)
125
+ model = self.catalog.resolve_model(bindings) or materialized.spec.model
126
+ if model is None:
127
+ raise StudioError(
128
+ "AGENT_MODEL_REQUIRED",
129
+ "必须选择一个可用的 Model Profile",
130
+ status_code=422,
131
+ field="spec.bindings.modelProfileId",
132
+ )
133
+ bound_tools, permissions = self.catalog.policy_preview(bindings)
134
+ bound_mcp_tools = self.catalog.resolve_mcp_tools(bindings)
135
+ capabilities = CapabilitiesSpec(
136
+ skills=[
137
+ *materialized.spec.capabilities.skills,
138
+ *self.catalog.resolve_skills(bindings),
139
+ ],
140
+ mcp_servers=[
141
+ *materialized.spec.capabilities.mcp_servers,
142
+ *self.catalog.resolve_mcp_servers(bindings),
143
+ ],
144
+ tools=[
145
+ *materialized.spec.capabilities.tools,
146
+ *bound_tools,
147
+ *bound_mcp_tools,
148
+ ],
149
+ )
150
+ self._require_unique(
151
+ [item.name for item in capabilities.skills],
152
+ kind="Skill",
153
+ )
154
+ self._require_unique(
155
+ [item.name for item in capabilities.mcp_servers],
156
+ kind="MCP Server",
157
+ )
158
+ self._require_unique(
159
+ [item.name for item in capabilities.tools],
160
+ kind="Tool",
161
+ )
162
+ materialized.spec.model = model
163
+ materialized.spec.capabilities = capabilities
164
+ materialized.spec.security.allowed_permissions = sorted(
165
+ set(materialized.spec.security.allowed_permissions)
166
+ | set(permissions)
167
+ | {
168
+ permission
169
+ for tool in bound_mcp_tools
170
+ for permission in tool.permissions
171
+ }
172
+ )
173
+ endpoint = model.endpoint_url or model.base_url or ""
174
+ hostname = (urlparse(endpoint).hostname or "").lower().rstrip(".")
175
+ if hostname and materialized.spec.security.network.mode == "restricted":
176
+ materialized.spec.security.network.allowed_hosts = sorted(
177
+ set(materialized.spec.security.network.allowed_hosts) | {hostname}
178
+ )
179
+ return materialized
180
+
181
+ @staticmethod
182
+ def _require_unique(names: list[str], *, kind: str) -> None:
183
+ duplicates = sorted({name for name in names if names.count(name) > 1})
184
+ if duplicates:
185
+ raise StudioError(
186
+ "CAPABILITY_DUPLICATE",
187
+ f"{kind} binding 重复",
188
+ status_code=422,
189
+ details={"names": duplicates},
190
+ )