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
@@ -23,6 +23,7 @@ chat completions 只认顶层 ``function`` 工具(chat 嵌套)和 ``function.nam
23
23
  from __future__ import annotations
24
24
 
25
25
  import hashlib
26
+ import json
26
27
  from typing import Any
27
28
 
28
29
  CHAT_TOOL_NAME_MAX_LEN = 64
@@ -64,19 +65,37 @@ def build_restore_map(tools: list[Any] | None) -> dict[str, dict[str, str]]:
64
65
  if not tools:
65
66
  return restore
66
67
  for tool in tools:
67
- if not isinstance(tool, dict) or tool.get("type") != "namespace":
68
+ if not isinstance(tool, dict):
69
+ continue
70
+ if tool.get("type") == "custom":
71
+ # custom 工具(如 apply_patch freeform)拍平为普通 function 转发,
72
+ # 响应侧据此把 function_call 还原成 custom_tool_call
73
+ custom_name = (tool.get("name") or "").strip()
74
+ if custom_name:
75
+ restore.setdefault(
76
+ custom_name,
77
+ {"custom": "true", "namespace": "", "name": custom_name},
78
+ )
79
+ continue
80
+ if tool.get("type") != "namespace":
68
81
  continue
69
82
  namespace = (tool.get("name") or "").strip()
70
83
  if not namespace:
71
84
  continue
72
85
  for child in _namespace_children(tool):
73
- if not isinstance(child, dict) or child.get("type") != "function":
86
+ if not isinstance(child, dict) or child.get("type") not in {
87
+ "function",
88
+ "custom",
89
+ }:
74
90
  continue
75
91
  name = (child.get("name") or "").strip()
76
92
  if not name:
77
93
  continue
78
94
  flat = flatten_namespace_tool_name(namespace, name)
79
- restore.setdefault(flat, {"namespace": namespace, "name": name})
95
+ entry = {"namespace": namespace, "name": name}
96
+ if child.get("type") == "custom":
97
+ entry["custom"] = "true"
98
+ restore.setdefault(flat, entry)
80
99
  return restore
81
100
 
82
101
 
@@ -91,7 +110,7 @@ def _rewrite_qualified_calls(value: Any, owners: dict[str, dict[str, str]]) -> b
91
110
  for item in value:
92
111
  changed |= _rewrite_qualified_calls(item, owners)
93
112
  elif isinstance(value, dict):
94
- if value.get("type") == "function_call":
113
+ if value.get("type") in {"function_call", "custom_tool_call"}:
95
114
  namespace = (value.get("namespace") or "").strip()
96
115
  name = (value.get("name") or "").strip()
97
116
  if namespace and name:
@@ -129,24 +148,39 @@ def flatten_request_namespaces(body: dict) -> dict[str, dict[str, str]]:
129
148
  if tool.get("type") == "namespace":
130
149
  namespace = (tool.get("name") or "").strip()
131
150
  for child in _namespace_children(tool):
132
- if not isinstance(child, dict) or child.get("type") != "function":
151
+ if not isinstance(child, dict) or child.get("type") not in {
152
+ "function",
153
+ "custom",
154
+ }:
133
155
  continue
134
156
  name = (child.get("name") or "").strip()
135
157
  if not name or not namespace:
136
158
  continue
137
159
  flat = flatten_namespace_tool_name(namespace, name)
138
160
  if flat in seen_flat:
139
- raise ValueError(
140
- f"namespace 拍平撞名:{flat} 来自不同 child,上游无法消歧"
141
- )
161
+ raise ValueError(f"namespace 拍平撞名:{flat} 来自不同 child,上游无法消歧")
142
162
  seen_flat.add(flat)
143
- flat_tools.append({
144
- "type": "function",
145
- "name": flat,
146
- "description": child.get("description", ""),
147
- "parameters": child.get("parameters", {"type": "object", "properties": {}}),
148
- **({"strict": child["strict"]} if "strict" in child else {}),
149
- })
163
+ if child.get("type") == "custom":
164
+ flat_tools.append(
165
+ {
166
+ "type": "custom",
167
+ "name": flat,
168
+ "description": child.get("description", ""),
169
+ **({"format": child["format"]} if "format" in child else {}),
170
+ }
171
+ )
172
+ else:
173
+ flat_tools.append(
174
+ {
175
+ "type": "function",
176
+ "name": flat,
177
+ "description": child.get("description", ""),
178
+ "parameters": child.get(
179
+ "parameters", {"type": "object", "properties": {}}
180
+ ),
181
+ **({"strict": child["strict"]} if "strict" in child else {}),
182
+ }
183
+ )
150
184
  else:
151
185
  flat_tools.append(tool)
152
186
  body["tools"] = flat_tools
@@ -168,6 +202,24 @@ def restore_function_call(item: dict, restore_map: dict[str, dict[str, str]]) ->
168
202
  flat = item.get("name")
169
203
  entry = restore_map.get(flat) if isinstance(flat, str) else None
170
204
  if entry:
205
+ if entry.get("custom") == "true":
206
+ # function_call(JSON arguments) -> custom_tool_call(原始文本 input)
207
+ raw_args = item.pop("arguments", "") or ""
208
+ try:
209
+ payload = json.loads(raw_args)
210
+ text_input = (
211
+ payload.get("input", raw_args) if isinstance(payload, dict) else raw_args
212
+ )
213
+ except Exception:
214
+ text_input = raw_args
215
+ item["type"] = "custom_tool_call"
216
+ item["name"] = entry["name"]
217
+ item["input"] = text_input
218
+ if entry.get("namespace"):
219
+ item["namespace"] = entry["namespace"]
220
+ else:
221
+ item.pop("namespace", None)
222
+ return item
171
223
  item["name"] = entry["name"]
172
224
  item["namespace"] = entry["namespace"]
173
225
  return item
@@ -18,11 +18,65 @@ from fastapi import FastAPI, Request
18
18
  from fastapi.responses import JSONResponse, StreamingResponse
19
19
 
20
20
  from .config import _LOOPBACK_HOSTS, ProxyConfig
21
- from .transform import Streamer, UnsupportedToolsError, chat_to_response, responses_to_chat
21
+ from .transform import (
22
+ Streamer,
23
+ UnsupportedToolsError,
24
+ chat_to_response,
25
+ clamp_reasoning_effort,
26
+ responses_to_chat,
27
+ )
22
28
 
23
29
  logger = logging.getLogger(__name__)
24
30
 
25
31
 
32
+ def _request_id(response: httpx.Response) -> str:
33
+ for name in (
34
+ "x-request-id",
35
+ "request-id",
36
+ "x-ks-request-id",
37
+ "x-amzn-requestid",
38
+ ):
39
+ value = response.headers.get(name)
40
+ if value:
41
+ return str(value)
42
+ return ""
43
+
44
+
45
+ def _reported_usage(raw: object) -> dict[str, int] | None:
46
+ if not isinstance(raw, dict):
47
+ return None
48
+ prompt_details = raw.get("prompt_tokens_details") or {}
49
+ completion_details = raw.get("completion_tokens_details") or {}
50
+ return {
51
+ "inputTokens": int(raw.get("prompt_tokens") or 0),
52
+ "outputTokens": int(raw.get("completion_tokens") or 0),
53
+ "totalTokens": int(raw.get("total_tokens") or 0),
54
+ "cachedInputTokens": int(prompt_details.get("cached_tokens") or 0),
55
+ "reasoningOutputTokens": int(completion_details.get("reasoning_tokens") or 0),
56
+ }
57
+
58
+
59
+ def _emit_completed(
60
+ config: ProxyConfig,
61
+ *,
62
+ response_id: str,
63
+ model: object,
64
+ status_code: int,
65
+ started: float,
66
+ usage: object = None,
67
+ ) -> None:
68
+ payload: dict[str, object] = {
69
+ "responseId": response_id,
70
+ "model": str(model or ""),
71
+ "statusCode": status_code,
72
+ "durationMs": max(0, int((time.monotonic() - started) * 1000)),
73
+ }
74
+ reported = _reported_usage(usage)
75
+ if reported is not None:
76
+ payload["usage"] = reported
77
+ config.emit("proxy.completed", payload)
78
+
79
+
26
80
  def _upstream_error(status_code: int) -> JSONResponse:
27
81
  """Return a stable public error without relaying an upstream traceback."""
28
82
  return JSONResponse(
@@ -98,8 +152,8 @@ def create_app(config: ProxyConfig) -> FastAPI:
98
152
  body = await req.json()
99
153
  try:
100
154
  chat_req, restore_map = responses_to_chat(body)
101
- except UnsupportedToolsError as e:
102
- logger.info("responses request uses unsupported tools: %s", e)
155
+ except UnsupportedToolsError:
156
+ logger.info("responses request uses unsupported tools", exc_info=True)
103
157
  return JSONResponse(
104
158
  status_code=400,
105
159
  content={
@@ -109,22 +163,84 @@ def create_app(config: ProxyConfig) -> FastAPI:
109
163
  }
110
164
  },
111
165
  )
166
+ # codex 会对内建能力发内部伪模型名(如 auto_review guardian 用 codex-auto-review),
167
+ # 单上游代理必须落回配置的真实模型,否则上游按未知模型 403。
168
+ # 真实模型名(codex 端已配置 model= 或 thread 级 model 覆盖)必须原样透传:
169
+ # RunAgent 的 Model 覆盖靠它生效,整体改写会把覆盖吞掉(终验 403 根因)。
170
+ requested_model = str(chat_req.get("model") or "")
171
+ if (
172
+ config.upstream_model
173
+ and requested_model.startswith("codex-")
174
+ and requested_model != config.upstream_model
175
+ ):
176
+ logger.debug(
177
+ "responses pseudo model rewrite: %s -> %s",
178
+ requested_model,
179
+ config.upstream_model,
180
+ )
181
+ chat_req["model"] = config.upstream_model
182
+ # 上游模型族的 reasoning_effort 上限不同(qwen3.7 对 xhigh 400),
183
+ # 按改写后的真实上游模型钳位(codex 对自家模型默认发 xhigh)。
184
+ if chat_req.get("reasoning_effort"):
185
+ chat_req["reasoning_effort"] = clamp_reasoning_effort(
186
+ chat_req["model"], chat_req["reasoning_effort"]
187
+ )
112
188
  rid = "resp_" + uuid.uuid4().hex[:24]
113
189
  model = body.get("model")
190
+ started = time.monotonic()
191
+ config.emit(
192
+ "proxy.requested",
193
+ {
194
+ "responseId": rid,
195
+ "model": str(model or ""),
196
+ "protocol": "responses-to-chat",
197
+ "stream": bool(body.get("stream")),
198
+ },
199
+ )
114
200
  if body.get("stream"):
115
201
  chat_req["stream"] = True
116
202
  chat_req["stream_options"] = {"include_usage": True}
117
203
  return StreamingResponse(
118
- _stream_gen(config, base, headers, chat_req, rid, model, cancel, restore_map),
204
+ _stream_gen(
205
+ config,
206
+ base,
207
+ headers,
208
+ chat_req,
209
+ rid,
210
+ model,
211
+ cancel,
212
+ restore_map,
213
+ started,
214
+ ),
119
215
  media_type="text/event-stream",
120
216
  headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
121
217
  )
122
218
  async with httpx.AsyncClient(timeout=config.timeout) as c:
123
219
  r = await c.post(f"{base}/chat/completions", json=chat_req, headers=headers)
220
+ config.emit(
221
+ "proxy.upstream",
222
+ {"requestId": _request_id(r), "statusCode": r.status_code},
223
+ )
124
224
  if r.status_code != 200:
225
+ _emit_completed(
226
+ config,
227
+ response_id=rid,
228
+ model=model,
229
+ status_code=r.status_code,
230
+ started=started,
231
+ )
125
232
  logger.warning("responses upstream rejected request: status=%s", r.status_code)
126
233
  return _upstream_error(r.status_code)
127
- return JSONResponse(chat_to_response(r.json(), rid, restore_map))
234
+ upstream_payload = r.json()
235
+ _emit_completed(
236
+ config,
237
+ response_id=rid,
238
+ model=model,
239
+ status_code=r.status_code,
240
+ started=started,
241
+ usage=upstream_payload.get("usage"),
242
+ )
243
+ return JSONResponse(chat_to_response(upstream_payload, rid, restore_map))
128
244
 
129
245
  return app
130
246
 
@@ -152,7 +268,9 @@ async def _stream_gen(
152
268
  model,
153
269
  cancel: threading.Event,
154
270
  restore_map: dict | None = None,
271
+ started: float | None = None,
155
272
  ):
273
+ started = time.monotonic() if started is None else started
156
274
  s = Streamer(rid, model, restore_map)
157
275
  for e in s.start():
158
276
  yield e
@@ -162,8 +280,28 @@ async def _stream_gen(
162
280
  async with c.stream(
163
281
  "POST", f"{base}/chat/completions", json=chat_req, headers=headers
164
282
  ) as r:
283
+ config.emit(
284
+ "proxy.upstream",
285
+ {"requestId": _request_id(r), "statusCode": r.status_code},
286
+ )
165
287
  if r.status_code != 200:
166
- logger.warning("responses upstream stream rejected: status=%s", r.status_code)
288
+ _emit_completed(
289
+ config,
290
+ response_id=rid,
291
+ model=model,
292
+ status_code=r.status_code,
293
+ started=started,
294
+ )
295
+ logger.warning(
296
+ "responses upstream stream rejected: status=%s model=%s tools=%s "
297
+ "msgs=%s bytes=%s has_text_format=%s",
298
+ r.status_code,
299
+ chat_req.get("model"),
300
+ len(chat_req.get("tools") or []),
301
+ len(chat_req.get("messages") or []),
302
+ len(json.dumps(chat_req)),
303
+ bool(chat_req.get("response_format")),
304
+ )
167
305
  yield Streamer.ev(
168
306
  "response.failed",
169
307
  {
@@ -177,6 +315,14 @@ async def _stream_gen(
177
315
  return
178
316
  async for line in r.aiter_lines():
179
317
  if cancel.is_set():
318
+ _emit_completed(
319
+ config,
320
+ response_id=rid,
321
+ model=model,
322
+ status_code=499,
323
+ started=started,
324
+ usage=s.usage,
325
+ )
180
326
  return # stop() 置位:主动中断活动 SSE,让线程能及时回收
181
327
  line = line.strip()
182
328
  if not line.startswith("data:"):
@@ -191,6 +337,14 @@ async def _stream_gen(
191
337
  for e in s.handle(chunk):
192
338
  yield e
193
339
  except Exception as exc: # noqa: BLE001
340
+ _emit_completed(
341
+ config,
342
+ response_id=rid,
343
+ model=model,
344
+ status_code=502,
345
+ started=started,
346
+ usage=s.usage,
347
+ )
194
348
  logger.warning("responses upstream stream failed", exc_info=exc)
195
349
  yield Streamer.ev(
196
350
  "response.failed",
@@ -205,6 +359,14 @@ async def _stream_gen(
205
359
  return
206
360
  for e in s.finalize():
207
361
  yield e
362
+ _emit_completed(
363
+ config,
364
+ response_id=rid,
365
+ model=model,
366
+ status_code=200,
367
+ started=started,
368
+ usage=s.usage,
369
+ )
208
370
 
209
371
 
210
372
  class ProxyServer:
@@ -122,6 +122,30 @@ def input_to_messages(inp):
122
122
  },
123
123
  }
124
124
  )
125
+ elif t == "custom_tool_call":
126
+ # 历史里的 custom_tool_call:还原为 function 调用(input 包进 JSON)
127
+ pending_tc.append(
128
+ {
129
+ "id": item.get("call_id") or f"call_{len(pending_tc)}",
130
+ "type": "function",
131
+ "function": {
132
+ "name": item.get("name"),
133
+ "arguments": json.dumps(
134
+ {"input": item.get("input") or ""}, ensure_ascii=False
135
+ ),
136
+ },
137
+ }
138
+ )
139
+ elif t == "custom_tool_call_output":
140
+ flush()
141
+ out = item.get("output")
142
+ messages.append(
143
+ {
144
+ "role": "tool",
145
+ "tool_call_id": item.get("call_id") or "",
146
+ "content": out if isinstance(out, str) else json.dumps(out, ensure_ascii=False),
147
+ }
148
+ )
125
149
  elif t == "function_call_output":
126
150
  flush()
127
151
  out = item.get("output")
@@ -155,9 +179,30 @@ def convert_tools(tools):
155
179
  if "strict" in t:
156
180
  fn["strict"] = t["strict"]
157
181
  out.append({"type": "function", "function": fn})
182
+ elif isinstance(t, dict) and t.get("type") == "custom" and t.get("name"):
183
+ # custom 工具(apply_patch 等 freeform 输入)转为单 input 字符串参数的 function
184
+ out.append(
185
+ {
186
+ "type": "function",
187
+ "function": {
188
+ "name": t.get("name"),
189
+ "description": t.get("description", ""),
190
+ "parameters": {
191
+ "type": "object",
192
+ "properties": {"input": {"type": "string"}},
193
+ "required": ["input"],
194
+ },
195
+ },
196
+ }
197
+ )
158
198
  else:
159
199
  t = t or {}
160
- unsupported.append(t.get("type") or t.get("name") or "unknown")
200
+ import json as _json
201
+
202
+ try:
203
+ unsupported.append(_json.dumps(t, ensure_ascii=False)[:300])
204
+ except Exception:
205
+ unsupported.append(str(t.get("type") or t.get("name") or "unknown"))
161
206
  if unsupported:
162
207
  raise UnsupportedToolsError(
163
208
  f"不支持转换的 codex 工具类型: {unsupported};"
@@ -180,6 +225,32 @@ def convert_tool_choice(tc):
180
225
  return tc
181
226
 
182
227
 
228
+ # 各上游模型族的 reasoning_effort 上限(qwen3.7 系实测 xhigh 400;报错文案会列出
229
+ # xhigh 但 DashScope 后端实际只认到 high,故不能用报错文案反推)。未列出的族原样透传。
230
+ _EFFORT_RANK = {"none": 0, "minimal": 1, "low": 2, "medium": 3, "high": 4, "xhigh": 5}
231
+ _EFFORT_CAP_PREFIXES = (
232
+ ("qwen3.7", "high"),
233
+ ("qwen3.6", "high"),
234
+ ("qwen3.5", "high"),
235
+ )
236
+
237
+
238
+ def clamp_reasoning_effort(model, effort):
239
+ """把超出上游模型族支持上限的 reasoning_effort 钳到最高合法档。
240
+
241
+ codex 对自家模型默认发 xhigh;qwen3.7 系上游 400,需钳到 high。
242
+ 未知档位/未知模型族原样返回(不做发明式映射)。
243
+ """
244
+ if not isinstance(effort, str) or effort not in _EFFORT_RANK:
245
+ return effort
246
+ for prefix, cap in _EFFORT_CAP_PREFIXES:
247
+ if isinstance(model, str) and model.startswith(prefix):
248
+ if _EFFORT_RANK[effort] > _EFFORT_RANK[cap]:
249
+ return cap
250
+ return effort
251
+ return effort
252
+
253
+
183
254
  def _convert_text_format(fmt):
184
255
  """responses text.format -> chat response_format(structured output 结构重组)。
185
256
 
@@ -199,6 +270,35 @@ def _convert_text_format(fmt):
199
270
  return None
200
271
 
201
272
 
273
+ def _promote_additional_tools(body):
274
+ """Promote Codex Harness dynamic tool input items to Responses tools.
275
+
276
+ Codex 0.147 no longer always sends tool declarations in the top-level
277
+ ``tools`` field. It can prepend one or more developer input items shaped
278
+ as ``{"type": "additional_tools", "tools": [...]}``. Chat Completions
279
+ has no equivalent input item, so the proxy must merge those declarations
280
+ into the canonical Responses tool list before namespace flattening.
281
+ """
282
+
283
+ inp = body.get("input")
284
+ if not isinstance(inp, list):
285
+ return
286
+ promoted = []
287
+ retained = []
288
+ for item in inp:
289
+ if isinstance(item, dict) and item.get("type") == "additional_tools":
290
+ tools = item.get("tools")
291
+ if isinstance(tools, list):
292
+ promoted.extend(tool for tool in tools if isinstance(tool, dict))
293
+ continue
294
+ retained.append(item)
295
+ if not promoted:
296
+ return
297
+ existing = body.get("tools")
298
+ body["tools"] = (list(existing) if isinstance(existing, list) else []) + promoted
299
+ body["input"] = retained
300
+
301
+
202
302
  def responses_to_chat(body):
203
303
  """responses 请求 -> chat 请求;返回 (chat_req, restore_map)。
204
304
 
@@ -207,6 +307,7 @@ def responses_to_chat(body):
207
307
  """
208
308
  from .namespace import flatten_request_namespaces
209
309
 
310
+ _promote_additional_tools(body)
210
311
  restore_map = flatten_request_namespaces(body)
211
312
  out = {"model": body.get("model")}
212
313
  msgs = []
@@ -229,8 +330,9 @@ def responses_to_chat(body):
229
330
  rf = _convert_text_format(text.get("format"))
230
331
  if rf is not None:
231
332
  out["response_format"] = rf
232
- if text.get("verbosity"):
233
- out["verbosity"] = text["verbosity"]
333
+ # text.verbosity("low"/"high")不转发:chat completions 无标准字段,
334
+ # kspmas 把顶层 verbosity 反序列化为 i32,字符串值直接 400(glm-5.2 实测;
335
+ # cc-switch 也不透传该字段)。
234
336
  if body.get("prompt_cache_key"):
235
337
  out["prompt_cache_key"] = body["prompt_cache_key"]
236
338
  tools = convert_tools(body.get("tools"))
@@ -0,0 +1,25 @@
1
+ """Local observability exports and trajectory projections."""
2
+
3
+ from ksadk.observability.session_log import (
4
+ SESSION_LOG_SCHEMA,
5
+ SessionLogError,
6
+ SessionLogResult,
7
+ export_session_log,
8
+ verify_session_log,
9
+ )
10
+ from ksadk.observability.trajectory import (
11
+ PROJECTION_VERSION,
12
+ encode_sse,
13
+ project_trajectory_event,
14
+ )
15
+
16
+ __all__ = [
17
+ "SESSION_LOG_SCHEMA",
18
+ "PROJECTION_VERSION",
19
+ "SessionLogError",
20
+ "SessionLogResult",
21
+ "export_session_log",
22
+ "encode_sse",
23
+ "project_trajectory_event",
24
+ "verify_session_log",
25
+ ]