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,469 @@
1
+ """Codex-authored conversation proposals.
2
+
3
+ veadk ``intelligent_development`` 模式的移植:每轮对话创建请求背后是一个真实的
4
+ Codex 会话——Codex 在沙箱工作区把 Agent Draft Patch 写成
5
+ ``.agentkit/authoring/<request_id>/agentkit.yaml`` 文件,产物经过与 chat 链路完全
6
+ 相同的 ``parse_conversation_proposal`` 验证器校验;校验失败把错误作为下一轮消息
7
+ 喂回同一个 Codex thread 让它改写文件(最多 ``max_retries`` 轮)。相对 chat 模型
8
+ 直接输出 JSON,文件产物 + 错误回喂显著降低非法 JSON 残缺 patch 的比例。
9
+
10
+ Codex 不可用(SDK 缺失、二进制缺失、turn 超时)时抛
11
+ ``CodexAuthoringUnavailableError``,由 coordinator 降级回 chat 链路。
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import asyncio
17
+ import json
18
+ import logging
19
+ import re
20
+ import shutil
21
+ import time
22
+ from dataclasses import dataclass, field
23
+ from pathlib import Path
24
+ from typing import Any, Callable
25
+ from uuid import uuid4
26
+
27
+ import yaml # type: ignore[import-untyped]
28
+
29
+ from ksadk.studio.authoring import AgentAuthoringService, ConversationProposal
30
+ from ksadk.studio.contracts import ResolvedModel, Usage
31
+ from ksadk.studio.errors import StudioError
32
+ from ksadk.studio.workspace import Workspace
33
+
34
+ LOGGER = logging.getLogger(__name__)
35
+
36
+ #: 单个 Codex turn 的执行超时;超时视为 codex 不可用并降级 chat 链。
37
+ DEFAULT_TURN_TIMEOUT_SECONDS = 240.0
38
+ #: 校验失败后的最大改写轮数(首轮之外)。
39
+ DEFAULT_MAX_RETRIES = 3
40
+ #: 失败产物目录保留数量,供诊断;成功目录立即清理。
41
+ _MAX_FAILED_DIRECTORIES = 5
42
+ _REQUEST_DIR_PREFIX = "codex-req-"
43
+
44
+ _MANIFEST_FILENAME = "agentkit.yaml"
45
+
46
+ _BUILDER_SCHEMA = """\
47
+ 你是 AgentKit Studio 的 Agent 配置编写器。你的唯一任务是把一份 Agent Draft Patch
48
+ 写成 YAML 文件(不是输出到对话里)。文件必须写到指定路径,使用合法 YAML,根节点
49
+ 是一个 JSON/YAML 对象,字段如下:
50
+
51
+ - name: 字符串,Agent 展示名(1-128 字符)
52
+ - slug: 字符串,小写字母数字与连字符(1-63 字符)
53
+ - runtimeType: 只能是 codex、adk、langgraph
54
+ - description: 字符串,可为空(最长 1024)
55
+ - spec: 完整 AgentSpec 对象,可包含:
56
+ - instructions(必须):包含 system(系统提示词)与 task(任务提示词)两个字符串
57
+ - runtime:对象,必须包含 type 字段(与 runtimeType 相同的值:codex/adk/langgraph),
58
+ 不要写 provider;adk/langgraph 可加 projectPath/entryPoint/agentVariable
59
+ - execution、context、memory、security、evaluation:按需
60
+
61
+ 完整示例(输出必须严格遵循此结构,字段名一字不差):
62
+
63
+ name: 每日科技新闻摘要
64
+ slug: daily-tech-news-summary
65
+ runtimeType: codex
66
+ description: 每天早晨抓取科技新闻源并生成中文简报
67
+ spec:
68
+ instructions:
69
+ system: 你是一名资深科技编辑,擅长从多条新闻中提炼要点。
70
+ task: 汇总当日科技新闻,按重要性排序输出中文简报,每条含标题与一句话摘要。
71
+ runtime:
72
+ type: codex
73
+
74
+ 注意:
75
+ - 示例中的 name/slug/description/instructions 值必须替换为符合用户
76
+ 对话的内容,不要照抄示例文字。
77
+ - 模型 Profile、模型参数、Tool、MCP、Skill、凭证、端点和资源 ID 是 Studio 的
78
+ 受控输入,严禁写入 model、bindings 或 capabilities。需要它们时只在
79
+ instructions/task 中描述语义用途,Studio 会在确认前注入已选资源。
80
+
81
+ 规则:
82
+ 0. 硬性要求:你必须在本轮实际调用 apply_patch 工具把完整 patch 写入目标文件,
83
+ 然后才能结束回复。只在回复文本里描述计划、或只在回复中给出 YAML/JSON 内容
84
+ (包括 Markdown 代码块)而没有实际写文件,都视为本轮失败。
85
+ 1. 必须用写文件工具把完整 patch 写入指定路径;不要只在回复中输出内容。
86
+ 2. 不要输出 Markdown 代码块包裹的 YAML 作为最终答案,文件本身就是产物。
87
+ 3. 首轮必须包含全部顶层字段;后续轮次(已有草稿时)输出完整合并后的新版本。
88
+ 4. 不得编造 Tool、MCP、Skill、模型、模型参数、资源 ID、凭证或端点;这些由
89
+ Studio 的资源选择器和策略层注入。
90
+ 5. 只做配置编写,不要创建其他文件、不要执行无关命令。
91
+ """
92
+
93
+
94
+ class CodexAuthoringUnavailableError(RuntimeError):
95
+ """Codex authoring 后端不可用(缺依赖/二进制、超时),调用方应降级。"""
96
+
97
+
98
+ @dataclass
99
+ class CodexAuthoringResult:
100
+ proposal: ConversationProposal
101
+ usage: Usage
102
+ attempts: int
103
+ final_message: str
104
+ request_id: str
105
+
106
+
107
+ @dataclass
108
+ class _TurnOutcome:
109
+ final_message: str
110
+ usage: Usage = field(default_factory=Usage)
111
+
112
+
113
+ def _sanitize_request_id(request_id: str | None) -> str:
114
+ candidate = str(request_id or "").strip()
115
+ if re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}", candidate):
116
+ return candidate
117
+ return uuid4().hex
118
+
119
+
120
+ def _extract_usage(params: dict[str, Any]) -> dict[str, int] | None:
121
+ usage = params.get("tokenUsage") or params.get("token_usage")
122
+ if not isinstance(usage, dict):
123
+ return None
124
+ last = usage.get("last")
125
+ if not isinstance(last, dict):
126
+ return None
127
+
128
+ def metric(camel: str, snake: str) -> int:
129
+ value = last.get(camel, last.get(snake, 0))
130
+ try:
131
+ return max(0, int(value)) # type: ignore[arg-type]
132
+ except (TypeError, ValueError):
133
+ return 0
134
+
135
+ return {
136
+ "input_tokens": metric("inputTokens", "input_tokens"),
137
+ "output_tokens": metric("outputTokens", "output_tokens"),
138
+ "total_tokens": metric("totalTokens", "total_tokens"),
139
+ "cached_input_tokens": metric("cachedInputTokens", "cached_input_tokens"),
140
+ "reasoning_output_tokens": metric("reasoningOutputTokens", "reasoning_output_tokens"),
141
+ }
142
+
143
+
144
+ class CodexAuthoringExecutor:
145
+ """让真实 Codex 会话在工作区文件里编写 Agent Draft Patch。"""
146
+
147
+ def __init__(
148
+ self,
149
+ workspace: Workspace,
150
+ credential_resolver: Any,
151
+ *,
152
+ client_factory: Callable[[dict[str, str]], Any] | None = None,
153
+ turn_timeout_seconds: float = DEFAULT_TURN_TIMEOUT_SECONDS,
154
+ max_retries: int = DEFAULT_MAX_RETRIES,
155
+ ) -> None:
156
+ self.workspace = workspace
157
+ self.root = workspace.resolve(".agentkit/authoring")
158
+ self.credentials = credential_resolver
159
+ self._client_factory = client_factory
160
+ self._turn_timeout_seconds = turn_timeout_seconds
161
+ self._max_retries = max(0, int(max_retries))
162
+
163
+ # ------------------------------------------------------------------
164
+ # Availability probe
165
+ # ------------------------------------------------------------------
166
+
167
+ def probe(self) -> None:
168
+ """Fail fast when the Codex backend cannot run on this host.
169
+
170
+ Raises ``CodexAuthoringUnavailableError`` so the coordinator can
171
+ silently fall back to the chat chain.
172
+ """
173
+
174
+ try:
175
+ import openai_codex # type: ignore[import-not-found] # noqa: F401
176
+ except ImportError as exc:
177
+ raise CodexAuthoringUnavailableError(
178
+ "openai-codex SDK 未安装 (pip install 'ksadk[codex]')"
179
+ ) from exc
180
+ try:
181
+ from codex_cli_bin import (
182
+ bundled_codex_path, # type: ignore[import-not-found, import-untyped]
183
+ )
184
+
185
+ binary = Path(str(bundled_codex_path()))
186
+ except (ImportError, OSError) as exc:
187
+ raise CodexAuthoringUnavailableError("本地 Codex 平台二进制不可用") from exc
188
+ if not binary.exists():
189
+ raise CodexAuthoringUnavailableError(f"Codex 二进制不存在: {binary}")
190
+
191
+ # ------------------------------------------------------------------
192
+ # Authoring flow
193
+ # ------------------------------------------------------------------
194
+
195
+ async def compose(
196
+ self,
197
+ *,
198
+ messages: list[dict[str, str]],
199
+ model: ResolvedModel,
200
+ base: ConversationProposal | None = None,
201
+ request_id: str | None = None,
202
+ ) -> CodexAuthoringResult:
203
+ normalized_request_id = _sanitize_request_id(request_id)
204
+ request_dir = self.workspace.resolve(
205
+ Path(".agentkit/authoring")
206
+ / f"{_REQUEST_DIR_PREFIX}{normalized_request_id}"
207
+ )
208
+ shutil.rmtree(request_dir, ignore_errors=True)
209
+ request_dir.mkdir(parents=True, exist_ok=True)
210
+ manifest_path = request_dir / _MANIFEST_FILENAME
211
+
212
+ env = self._codex_env(model)
213
+ client = self._create_client(env)
214
+ usage_total: dict[str, int] = {}
215
+ attempts = 0
216
+ validation_error = ""
217
+ last_message = ""
218
+ try:
219
+ thread_id = await client.start_thread(
220
+ {
221
+ "cwd": str(request_dir),
222
+ "sandbox": "workspace-write",
223
+ "approval_mode": "deny_all",
224
+ "model": model.model,
225
+ }
226
+ )
227
+ prompt = self._builder_prompt(messages, base=base, manifest_path=manifest_path)
228
+ for attempt in range(self._max_retries + 1):
229
+ attempts = attempt + 1
230
+ if validation_error:
231
+ prompt = self._correction_prompt(manifest_path, validation_error)
232
+ outcome = await self._run_turn(client, thread_id, prompt)
233
+ last_message = outcome.final_message
234
+ for key, value in outcome.usage.model_dump().items():
235
+ if key in {"reported", "source"}:
236
+ continue
237
+ usage_total[key] = usage_total.get(key, 0) + int(value or 0)
238
+ content = self._read_manifest(manifest_path)
239
+ if content is None:
240
+ # 兜底:部分模型不调用写文件工具,把 YAML/JSON 直接输出在
241
+ # agentMessage 里;从 ```yaml/```json 代码块恢复并落盘,
242
+ # 再走正常校验链,避免整轮作废。
243
+ recovered = self._recover_manifest_from_message(last_message)
244
+ if recovered is not None:
245
+ LOGGER.warning(
246
+ "codex authoring attempt %d wrote no manifest; recovered "
247
+ "fenced block from agent message: requestId=%s",
248
+ attempts,
249
+ normalized_request_id,
250
+ )
251
+ try:
252
+ manifest_path.write_text(recovered, encoding="utf-8")
253
+ content = recovered
254
+ except OSError:
255
+ LOGGER.warning(
256
+ "codex authoring fallback write failed: requestId=%s",
257
+ normalized_request_id,
258
+ )
259
+ if content is not None:
260
+ # Codex 习惯写 YAML;parse_conversation_proposal 的 JSON 提取器
261
+ # 遇到 YAML 里游离的 `{}` 会误解析成空 patch,这里先归一成 JSON。
262
+ try:
263
+ yaml_payload = yaml.safe_load(content)
264
+ except yaml.YAMLError:
265
+ yaml_payload = None
266
+ if isinstance(yaml_payload, dict):
267
+ content = json.dumps(yaml_payload, ensure_ascii=False)
268
+ if content is None:
269
+ validation_error = (
270
+ f"{_MANIFEST_FILENAME} 文件不存在或为空;你上一轮没有写文件,"
271
+ f"必须调用 apply_patch 工具(*** Begin Patch … Add File … "
272
+ f"*** End Patch)把完整 patch 写入 {manifest_path},"
273
+ "禁止只在回复文本中输出内容或 Markdown 代码块"
274
+ )
275
+ LOGGER.warning(
276
+ "codex authoring attempt %d produced no manifest: requestId=%s",
277
+ attempts,
278
+ normalized_request_id,
279
+ )
280
+ continue
281
+ try:
282
+ proposal = AgentAuthoringService.parse_conversation_proposal(content, base=base)
283
+ except StudioError as exc:
284
+ validation_error = str(exc.details.get("reason") or exc.message)
285
+ LOGGER.warning(
286
+ "codex authoring attempt %d invalid: requestId=%s reason=%s",
287
+ attempts,
288
+ normalized_request_id,
289
+ validation_error,
290
+ )
291
+ continue
292
+ self._cleanup_request_dir(request_dir, success=True)
293
+ return CodexAuthoringResult(
294
+ proposal=proposal,
295
+ usage=Usage(**usage_total, reported=True, source="codex-authoring"),
296
+ attempts=attempts,
297
+ final_message=last_message,
298
+ request_id=normalized_request_id,
299
+ )
300
+ raise StudioError(
301
+ "AUTHORING_MODEL_OUTPUT_INVALID",
302
+ "Codex 会话没有产出合法的 Agent Draft Patch",
303
+ status_code=502,
304
+ details={
305
+ "validationError": validation_error,
306
+ "attemptedCorrections": attempts - 1,
307
+ "requestId": normalized_request_id,
308
+ },
309
+ )
310
+ finally:
311
+ try:
312
+ await client.close()
313
+ except Exception: # pragma: no cover - defensive close
314
+ LOGGER.debug("codex authoring client close failed", exc_info=True)
315
+ self._cleanup_request_dir(request_dir, success=False)
316
+
317
+ # ------------------------------------------------------------------
318
+ # Internals
319
+ # ------------------------------------------------------------------
320
+
321
+ def _create_client(self, env: dict[str, str]) -> Any:
322
+ if self._client_factory is not None:
323
+ return self._client_factory(env)
324
+ try:
325
+ from openai_codex import CodexConfig # type: ignore[import-not-found]
326
+
327
+ from ksadk.codex.client import AsyncCodexClient
328
+ except ImportError as exc:
329
+ raise CodexAuthoringUnavailableError(
330
+ "openai-codex SDK 未安装 (pip install 'ksadk[codex]')"
331
+ ) from exc
332
+ return AsyncCodexClient(CodexConfig(env=env))
333
+
334
+ def _codex_env(self, model: ResolvedModel) -> dict[str, str]:
335
+ env: dict[str, str] = {}
336
+ try:
337
+ credential = self.credentials.resolve(model.credential_ref)
338
+ env["OPENAI_API_KEY"] = credential
339
+ except StudioError:
340
+ raise CodexAuthoringUnavailableError(f"无法解析模型凭证引用: {model.credential_ref}")
341
+ base_url = str(model.endpoint_url or "").rstrip("/")
342
+ for suffix in ("/chat/completions", "/responses"):
343
+ if base_url.endswith(suffix):
344
+ base_url = base_url[: -len(suffix)]
345
+ if base_url:
346
+ env["OPENAI_BASE_URL"] = base_url
347
+ env["OPENAI_API_BASE"] = base_url
348
+ env["OPENAI_MODEL_NAME"] = model.model
349
+ return env
350
+
351
+ def _builder_prompt(
352
+ self,
353
+ messages: list[dict[str, str]],
354
+ *,
355
+ base: ConversationProposal | None,
356
+ manifest_path: Path,
357
+ ) -> str:
358
+ parts = [_BUILDER_SCHEMA, f"\n目标文件路径(绝对路径):{manifest_path}\n"]
359
+ if base is not None:
360
+ current = base.model_dump(by_alias=True, mode="json", exclude_none=True)
361
+ parts.append(
362
+ "当前已有草稿(作为起点,必须合并用户最新要求后输出完整新版本):\n"
363
+ + yaml.safe_dump(current, allow_unicode=True, sort_keys=False)
364
+ )
365
+ transcript = "\n".join(
366
+ f"{str(item.get('role') or 'user')}: {str(item.get('content') or '').strip()}"
367
+ for item in messages
368
+ )
369
+ parts.append(f"用户对话(最后一条 user 消息是最新要求,必须优先满足):\n{transcript}\n")
370
+ parts.append("现在把完整的 Agent Draft Patch 写入目标文件。")
371
+ parts.append(
372
+ "写入方式要求:沙箱外命令已被审批策略拒绝,不要尝试 shell 重定向"
373
+ "(如 cat > file 或 echo > file)——它们会被静默拒绝导致文件不存在。"
374
+ "必须使用 apply_patch 工具(*** Begin Patch … Add File: <绝对路径> … "
375
+ "*** End Patch)把完整 YAML 内容写为目标文件。"
376
+ )
377
+ return "\n".join(parts)
378
+
379
+ @staticmethod
380
+ def _correction_prompt(manifest_path: Path, validation_error: str) -> str:
381
+ return (
382
+ f"你写入的 {_MANIFEST_FILENAME} 未通过 Agent Draft Patch 校验。\n"
383
+ f"校验错误细节如下,请逐条修正后重写文件 {manifest_path}(完整内容,"
384
+ "不是增量补丁):\n"
385
+ f"{validation_error}"
386
+ )
387
+
388
+ async def _run_turn(self, client: Any, thread_id: str, prompt: str) -> _TurnOutcome:
389
+ message_parts: list[str] = []
390
+ usage = Usage()
391
+ event_counts: dict[str, int] = {}
392
+ started = time.monotonic()
393
+ try:
394
+ # asyncio.timeout 是 3.11+;项目基线 3.10,用 wait_for 包装整轮消费。
395
+ async def _consume() -> None:
396
+ nonlocal usage
397
+ async for event in client.run_turn(thread_id, prompt):
398
+ if not isinstance(event, dict):
399
+ continue
400
+ method = str(event.get("method") or "")
401
+ event_counts[method] = event_counts.get(method, 0) + 1
402
+ params = event.get("params") or {}
403
+ if not isinstance(params, dict):
404
+ continue
405
+ if method == "item/agentMessage/delta":
406
+ message_parts.append(str(params.get("delta") or ""))
407
+ elif method == "thread/tokenUsage/updated":
408
+ metrics = _extract_usage(params)
409
+ if metrics:
410
+ usage = Usage(
411
+ **metrics, # type: ignore[arg-type]
412
+ reported=True,
413
+ )
414
+
415
+ await asyncio.wait_for(_consume(), timeout=self._turn_timeout_seconds)
416
+ except asyncio.TimeoutError as exc:
417
+ raise CodexAuthoringUnavailableError(
418
+ f"Codex authoring turn 超时({self._turn_timeout_seconds:.0f}s)"
419
+ ) from exc
420
+ LOGGER.info("codex authoring turn finished in %.2fs", time.monotonic() - started)
421
+ # 事件 method 分布:诊断"模型只回话不调工具"(无 item/*command* 事件)等
422
+ # 失败模式的关键证据,debug 级别避免常态噪音。
423
+ LOGGER.debug("codex authoring turn events: %s", dict(sorted(event_counts.items())))
424
+ return _TurnOutcome(final_message="".join(message_parts), usage=usage)
425
+
426
+ _FENCED_BLOCK_RE = re.compile(r"```[A-Za-z0-9_-]*[ \t]*\r?\n(.*?)```", re.DOTALL)
427
+
428
+ @classmethod
429
+ def _recover_manifest_from_message(cls, message: str) -> str | None:
430
+ """从 agentMessage 文本里恢复 patch:优先围栏代码块,其次裸 JSON 对象。"""
431
+
432
+ text = str(message or "").strip()
433
+ if not text:
434
+ return None
435
+ for match in cls._FENCED_BLOCK_RE.finditer(text):
436
+ block = match.group(1).strip()
437
+ if block:
438
+ return block
439
+ if text.startswith("{") and text.endswith("}"):
440
+ return text
441
+ return None
442
+
443
+ @staticmethod
444
+ def _read_manifest(manifest_path: Path) -> str | None:
445
+ try:
446
+ content = manifest_path.read_text(encoding="utf-8")
447
+ except OSError:
448
+ return None
449
+ return content or None
450
+
451
+ def _cleanup_request_dir(self, request_dir: Path, *, success: bool) -> None:
452
+ if success:
453
+ shutil.rmtree(request_dir, ignore_errors=True)
454
+ return
455
+ if not request_dir.exists():
456
+ return
457
+ failed = sorted(
458
+ (path for path in self.root.glob(f"{_REQUEST_DIR_PREFIX}*") if path.is_dir()),
459
+ key=lambda path: path.stat().st_mtime,
460
+ )
461
+ while len(failed) > _MAX_FAILED_DIRECTORIES:
462
+ shutil.rmtree(failed.pop(0), ignore_errors=True)
463
+
464
+
465
+ __all__ = [
466
+ "CodexAuthoringExecutor",
467
+ "CodexAuthoringResult",
468
+ "CodexAuthoringUnavailableError",
469
+ ]