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,151 @@
1
+ """Hermes deploy 的运行时环境变量构建。
2
+
3
+ 从 cmd_hermes.py 拆出(模块体积治理);``_env_value`` 与全局 env 缓存仍留在
4
+ cmd_hermes(测试 monkeypatch 点),此处通过延迟 import 访问。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os
10
+ from typing import Any, Optional
11
+
12
+ from ksadk.cli.env_options import apply_explicit_env_with_shell_priority
13
+ from ksadk.configs.env_registry import is_sensitive_env_var
14
+ from ksadk.deployment.env_forward import forward_shell_process_env
15
+ from ksadk.model_policy import build_runtime_model_policy_env
16
+
17
+
18
+ def _env_value(*names: str) -> str:
19
+ from ksadk.cli import cmd_hermes
20
+
21
+ return cmd_hermes._env_value(*names)
22
+
23
+
24
+ def _normalize_hermes_ui_locale(raw: Optional[str]) -> str:
25
+ """标准化 Hermes UI 语言代码,当前 upstream 只支持 en / zh。"""
26
+ text = str(raw or "").strip()
27
+ if not text:
28
+ return "zh"
29
+
30
+ base = text.split(".", 1)[0].replace("_", "-").strip().lower()
31
+ if base in {"c", "c-utf-8", "c.utf-8", "posix"}:
32
+ return "zh"
33
+ if base.startswith("en"):
34
+ return "en"
35
+ if base.startswith("zh"):
36
+ return "zh"
37
+ return "zh"
38
+
39
+
40
+ def _default_context_length_for_model(model: str | None) -> str:
41
+ from ksadk.cli import cmd_hermes
42
+
43
+ normalized = str(model or "").strip().lower()
44
+ if not normalized:
45
+ return ""
46
+ for model_fragment, context_length in cmd_hermes.DEFAULT_HERMES_CONTEXT_LENGTHS:
47
+ if model_fragment in normalized:
48
+ return context_length
49
+ return ""
50
+
51
+
52
+ def _normalize_hermes_runtime_base_url(base_url: str | None) -> str:
53
+ normalized = str(base_url or "").strip()
54
+ return normalized
55
+
56
+
57
+ def _build_hermes_env_vars(
58
+ *,
59
+ model_base_url: str | None = None,
60
+ model_api_key: str | None = None,
61
+ default_model: str | None = None,
62
+ model_metadata: dict[str, Any] | None = None,
63
+ cli_env: dict[str, str] | None = None,
64
+ auto_dotenv: dict[str, str] | None = None,
65
+ shell_keys: set[str] | None = None,
66
+ ) -> list[dict[str, Any]]:
67
+ from ksadk.cli import cmd_hermes
68
+
69
+ raw_model_base_url = model_base_url or _env_value("OPENAI_BASE_URL")
70
+ resolved_model_base_url = (
71
+ _normalize_hermes_runtime_base_url(raw_model_base_url)
72
+ if raw_model_base_url
73
+ else cmd_hermes.DEFAULT_HERMES_RUNTIME_BASE_URL
74
+ )
75
+ resolved_default_model = (
76
+ default_model or _env_value("OPENAI_MODEL_NAME") or cmd_hermes.DEFAULT_HERMES_MODEL_NAME
77
+ )
78
+ metadata_context_length = ""
79
+ if isinstance(model_metadata, dict):
80
+ metadata_context_length = str(model_metadata.get("context_window_tokens") or "").strip()
81
+ context_length = (
82
+ _env_value("HERMES_CONTEXT_LENGTH", "OPENAI_CONTEXT_LENGTH", "MODEL_CONTEXT_LENGTH")
83
+ or metadata_context_length
84
+ or _default_context_length_for_model(resolved_default_model)
85
+ )
86
+ ui_locale = _normalize_hermes_ui_locale(_env_value("HERMES_UI_LOCALE", "LANG", "LC_ALL"))
87
+ raw = {
88
+ "OPENAI_API_KEY": model_api_key or _env_value("OPENAI_API_KEY"),
89
+ "OPENAI_BASE_URL": resolved_model_base_url,
90
+ "OPENAI_MODEL_NAME": resolved_default_model,
91
+ "API_SERVER_ENABLED": "true",
92
+ "API_SERVER_HOST": "127.0.0.1",
93
+ "API_SERVER_PORT": "8642",
94
+ "HERMES_DASHBOARD_HOST": "127.0.0.1",
95
+ "HERMES_DASHBOARD_PORT": "9119",
96
+ "KSADK_RUNTIME_PORT": _env_value("PORT") or "8080",
97
+ "HERMES_UI_LOCALE": ui_locale,
98
+ }
99
+ if context_length:
100
+ raw["HERMES_CONTEXT_LENGTH"] = context_length
101
+ fallback_model = _env_value("HERMES_FALLBACK_MODEL", "OPENAI_FALLBACK_MODEL_NAME")
102
+ if fallback_model:
103
+ raw["HERMES_FALLBACK_PROVIDER"] = _env_value("HERMES_FALLBACK_PROVIDER") or "custom"
104
+ raw["HERMES_FALLBACK_MODEL"] = fallback_model
105
+ raw["HERMES_FALLBACK_BASE_URL"] = (
106
+ _env_value("HERMES_FALLBACK_BASE_URL") or resolved_model_base_url
107
+ )
108
+ api_server_key = _env_value("API_SERVER_KEY", "HERMES_API_SERVER_KEY")
109
+ if api_server_key:
110
+ raw["API_SERVER_KEY"] = api_server_key
111
+ # Observability routes and credentials are platform-managed. The Hermes
112
+ # deploy CLI must not translate or forward legacy Langfuse SDK variables;
113
+ # server/runtime inject the standard OTLP primary and CloudMonitor secondary.
114
+ for key in (
115
+ "WPSXIEZUO_APP_ID",
116
+ "WPSXIEZUO_APP_KEY",
117
+ "WPSXIEZUO_API_BASE",
118
+ "WPSXIEZUO_WS_ENDPOINT",
119
+ "WPSXIEZUO_GROUP_AT_ONLY",
120
+ "WPSXIEZUO_ALLOWED_USERS",
121
+ "WPSXIEZUO_ALLOW_ALL_USERS",
122
+ "WPSXIEZUO_HOME_CHANNEL",
123
+ ):
124
+ value = _env_value(key)
125
+ if value:
126
+ raw[key] = value
127
+ raw = build_runtime_model_policy_env(raw, runtime="hermes")
128
+ # shell 前缀转发 (KSADK_/OPENAI_/KSYUN_/E2B_ + allowlist),对齐通用 deploy;
129
+ # setdefault 语义不覆盖上面已 resolve 的固定键,--env/--env-file 仍可覆盖。
130
+ forward_shell_process_env(raw)
131
+ if raw.get("HERMES_FALLBACK_MODEL"):
132
+ raw.setdefault(
133
+ "HERMES_FALLBACK_PROVIDER", _env_value("HERMES_FALLBACK_PROVIDER") or "custom"
134
+ )
135
+ raw.setdefault(
136
+ "HERMES_FALLBACK_BASE_URL",
137
+ _env_value("HERMES_FALLBACK_BASE_URL") or resolved_model_base_url,
138
+ )
139
+ if cli_env or auto_dotenv:
140
+ apply_explicit_env_with_shell_priority(
141
+ raw, cli_env or {}, auto_dotenv or {}, shell_keys or set(os.environ)
142
+ )
143
+ return [
144
+ {
145
+ "Key": key,
146
+ "Value": str(value),
147
+ "IsSensitive": is_sensitive_env_var(key),
148
+ }
149
+ for key, value in raw.items()
150
+ if value is not None and str(value).strip() != ""
151
+ ]
@@ -0,0 +1,49 @@
1
+ """ksadk invoke 的 OpenAI 兼容请求载荷构造。
2
+
3
+ 从 cmd_invoke.py 抽出,避免 cli 模块继续膨胀(架构守护限制 1000 行,
4
+ cmd_invoke 已处于 legacy 白名单,只许缩不许涨)。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Optional
10
+
11
+
12
+ def build_chat_request(
13
+ endpoint: str,
14
+ message: str,
15
+ *,
16
+ session_id: Optional[str] = None,
17
+ model: Optional[str] = None,
18
+ api_format: str = "chat_completions",
19
+ default_model: Optional[str] = None,
20
+ stream: bool = False,
21
+ ) -> tuple[str, dict[str, Any]]:
22
+ """构造 (url, payload),按 api_format 区分 chat/completions 与 responses。
23
+
24
+ OpenClaw gateway 2026.7.1+ 的 /v1/responses 特殊处理:
25
+ - input 传纯字符串,不再接受 {role, content} 对象数组(服务端自行包装 user turn)
26
+ - 拒绝顶层 session_id,会话标识放 metadata 传递
27
+ - model 必填且只接受 "openclaw"/"openclaw/<agentId>"(业务模型由 gateway 配置决定),
28
+ 未显式传 --model 时用 default_model 补默认路由值,避免 400
29
+ """
30
+ normalized_api_format = str(api_format or "chat_completions").strip().lower()
31
+ if normalized_api_format == "responses":
32
+ url = f"{endpoint.rstrip('/')}/v1/responses"
33
+ payload: dict[str, Any] = {"input": message, "stream": stream}
34
+ else:
35
+ url = f"{endpoint.rstrip('/')}/v1/chat/completions"
36
+ payload = {"messages": [{"role": "user", "content": message}], "stream": stream}
37
+
38
+ if session_id:
39
+ if normalized_api_format == "responses":
40
+ payload.setdefault("metadata", {})["session_id"] = session_id
41
+ else:
42
+ payload["session_id"] = session_id
43
+
44
+ if model:
45
+ payload["model"] = model
46
+ elif default_model and normalized_api_format == "responses":
47
+ payload["model"] = default_model
48
+
49
+ return url, payload
@@ -316,11 +316,13 @@ def _resolve_subnet_availability_zone(*, subnet_id: str, region: str) -> str | N
316
316
 
317
317
 
318
318
  def _import_vpc_sdk():
319
- from ksyun.client.vpc.v20160304.client import VpcClient
320
- from ksyun.client.vpc.v20160304.models import DescribeSubnetsRequest
321
- from ksyun.common.credential import Credential
322
- from ksyun.common.profile.client_profile import ClientProfile
323
- from ksyun.common.profile.http_profile import HttpProfile
319
+ from ksyun.client.vpc.v20160304.client import VpcClient # type: ignore[import-untyped]
320
+ from ksyun.client.vpc.v20160304.models import ( # type: ignore[import-untyped]
321
+ DescribeSubnetsRequest,
322
+ )
323
+ from ksyun.common.credential import Credential # type: ignore[import-untyped]
324
+ from ksyun.common.profile.client_profile import ClientProfile # type: ignore[import-untyped]
325
+ from ksyun.common.profile.http_profile import HttpProfile # type: ignore[import-untyped]
324
326
 
325
327
  return VpcClient, DescribeSubnetsRequest, Credential, ClientProfile, HttpProfile
326
328
 
@@ -0,0 +1,458 @@
1
+ """OpenClaw deploy 的运行时环境变量构建。
2
+
3
+ 从 cmd_openclaw.py 拆出(模块体积治理);``_resolve_env`` 与全局 env 缓存仍留在
4
+ cmd_openclaw(测试 monkeypatch 点),此处通过延迟 import 访问。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from typing import Any, Dict, Optional
11
+
12
+ from ksadk.deployment.env_forward import forward_shell_process_env
13
+ from ksadk.model_policy import build_runtime_model_policy_env
14
+
15
+ DEFAULT_TRUSTED_PROXY_USER_HEADER = "x-forwarded-user"
16
+ DEFAULT_TRUSTED_PROXY_CIDRS = [
17
+ "127.0.0.1",
18
+ "::1",
19
+ "10.0.0.0/8",
20
+ "172.16.0.0/12",
21
+ "192.168.0.0/16",
22
+ "35.0.0.0/8",
23
+ ]
24
+
25
+
26
+ def _resolve_env(*keys: str, default: Optional[str] = None) -> Optional[str]:
27
+ from ksadk.cli import cmd_openclaw
28
+
29
+ return cmd_openclaw._resolve_env(*keys, default=default)
30
+
31
+
32
+ def _resolve_model_base_url(cli_value: Optional[str]) -> Optional[str]:
33
+ """解析模型 Base URL,缺失时回退到 settings.model.api_base(KSPMAS 自动探测)。"""
34
+ if cli_value and str(cli_value).strip():
35
+ return str(cli_value).strip()
36
+
37
+ from_env = _resolve_env(
38
+ "OPENCLAW_MODEL_BASE_URL",
39
+ "OPENAI_BASE_URL",
40
+ "OPENAI_API_BASE",
41
+ "LLM_API_BASE",
42
+ "MODEL_API_BASE",
43
+ )
44
+ if from_env:
45
+ return from_env
46
+
47
+ try:
48
+ from ksadk.configs.settings import settings
49
+
50
+ api_base = settings.model.api_base
51
+ if api_base and str(api_base).strip():
52
+ return str(api_base).strip()
53
+ except Exception:
54
+ pass
55
+
56
+ return None
57
+
58
+
59
+ def _normalize_ui_locale(raw: Optional[str]) -> str:
60
+ """标准化 UI 语言代码,默认 zh-CN。"""
61
+ text = str(raw or "").strip()
62
+ if not text:
63
+ return "zh-CN"
64
+
65
+ base = text.split(".", 1)[0].replace("_", "-").strip()
66
+ low = base.lower()
67
+
68
+ if low in {"c", "c-utf-8", "c.utf-8", "posix"}:
69
+ return "zh-CN"
70
+ if (
71
+ low.startswith("zh-tw")
72
+ or low.startswith("zh-hk")
73
+ or low.startswith("zh-mo")
74
+ or low.startswith("zh-hant")
75
+ ):
76
+ return "zh-TW"
77
+ if low.startswith("zh"):
78
+ return "zh-CN"
79
+ if low.startswith("pt"):
80
+ return "pt-BR"
81
+ if low.startswith("de"):
82
+ return "de"
83
+ if low.startswith("en"):
84
+ return "en"
85
+
86
+ return "zh-CN"
87
+
88
+
89
+ def _is_truthy(raw: Optional[str]) -> bool:
90
+ text = str(raw or "").strip().lower()
91
+ return text in {"1", "true", "yes", "on"}
92
+
93
+
94
+ def _resolve_exec_profile_overrides(security_profile: Optional[str]) -> Dict[str, str]:
95
+ """根据 CLI 安全预设返回 OpenClaw 运行时环境变量覆盖项。"""
96
+ profile = str(security_profile or "").strip().lower()
97
+ if not profile:
98
+ return {}
99
+
100
+ common = {
101
+ "OPENCLAW_EXEC_HOST": "gateway",
102
+ "OPENCLAW_EXEC_AUTO_ALLOW_SKILLS": "false",
103
+ "OPENCLAW_ELEVATED_ENABLED": "false",
104
+ }
105
+ if profile == "relaxed":
106
+ return {
107
+ **common,
108
+ "OPENCLAW_EXEC_STRICT_MODE": "false",
109
+ "OPENCLAW_EXEC_UNSAFE_MODE": "true",
110
+ "OPENCLAW_EXEC_SECURITY": "full",
111
+ "OPENCLAW_EXEC_ASK": "off",
112
+ "OPENCLAW_EXEC_ASK_FALLBACK": "full",
113
+ "OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED": "false",
114
+ "OPENCLAW_FS_WORKSPACE_ONLY": "false",
115
+ }
116
+ if profile == "strict":
117
+ return {
118
+ **common,
119
+ "OPENCLAW_EXEC_STRICT_MODE": "true",
120
+ "OPENCLAW_EXEC_UNSAFE_MODE": "false",
121
+ "OPENCLAW_EXEC_SECURITY": "allowlist",
122
+ "OPENCLAW_EXEC_ASK": "off",
123
+ "OPENCLAW_EXEC_ASK_FALLBACK": "allowlist",
124
+ "OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED": "true",
125
+ "OPENCLAW_FS_WORKSPACE_ONLY": "false",
126
+ }
127
+ if profile == "strictest":
128
+ return {
129
+ **common,
130
+ "OPENCLAW_EXEC_STRICT_MODE": "true",
131
+ "OPENCLAW_EXEC_UNSAFE_MODE": "false",
132
+ "OPENCLAW_EXEC_SECURITY": "deny",
133
+ "OPENCLAW_EXEC_ASK": "off",
134
+ "OPENCLAW_EXEC_ASK_FALLBACK": "deny",
135
+ "OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED": "false",
136
+ "OPENCLAW_FS_WORKSPACE_ONLY": "true",
137
+ }
138
+ raise ValueError(f"unsupported OpenClaw security profile: {security_profile}")
139
+
140
+
141
+ def _normalize_allowed_origins(raw: str) -> str:
142
+ """标准化 OPENCLAW_ALLOWED_ORIGINS,统一输出 JSON 数组字符串。"""
143
+ text = (raw or "").strip()
144
+ if not text:
145
+ return ""
146
+
147
+ origins = []
148
+ try:
149
+ parsed = json.loads(text)
150
+ if isinstance(parsed, list):
151
+ origins = [str(x).strip() for x in parsed if str(x).strip()]
152
+ except Exception:
153
+ # Backward compatible: 支持逗号/分号/空白分隔字符串。
154
+ parts = [p.strip() for p in text.replace(";", ",").replace(" ", ",").split(",")]
155
+ origins = [p.strip() for p in parts if p.strip()]
156
+
157
+ if not origins:
158
+ origins = [text]
159
+
160
+ deduped = list(dict.fromkeys(origins))
161
+ return json.dumps(deduped, ensure_ascii=False)
162
+
163
+
164
+ def _normalize_csv_list(raw: str, *, default_items: Optional[list[str]] = None) -> str:
165
+ """标准化字符串列表为逗号分隔格式。"""
166
+ text = (raw or "").strip()
167
+ items: list[str] = []
168
+ if text:
169
+ try:
170
+ parsed = json.loads(text)
171
+ if isinstance(parsed, list):
172
+ items = [str(x).strip() for x in parsed if str(x).strip()]
173
+ except Exception:
174
+ parts = [p.strip() for p in text.replace(";", ",").replace(" ", ",").split(",")]
175
+ items = [p for p in parts if p]
176
+
177
+ if not items:
178
+ items = [str(x).strip() for x in (default_items or []) if str(x).strip()]
179
+
180
+ return ",".join(list(dict.fromkeys(items)))
181
+
182
+
183
+ def _normalize_openclaw_gateway_auth_env(env: dict[str, str]) -> dict[str, str]:
184
+ """标准化 OpenClaw gateway 鉴权模式与共享密钥配置。"""
185
+ normalized_env = dict(env or {})
186
+ raw_mode = str(normalized_env.get("OPENCLAW_GATEWAY_AUTH_MODE") or "").strip().lower()
187
+ raw_token = str(normalized_env.get("OPENCLAW_GATEWAY_TOKEN") or "").strip()
188
+ raw_password = str(normalized_env.get("OPENCLAW_GATEWAY_PASSWORD") or "").strip()
189
+
190
+ if raw_mode and raw_mode not in {"trusted-proxy", "token", "none"}:
191
+ raise ValueError("OPENCLAW_GATEWAY_AUTH_MODE 仅支持 trusted-proxy、token 或 none")
192
+
193
+ auth_mode = raw_mode or ("token" if raw_token or raw_password else "trusted-proxy")
194
+ if auth_mode == "token":
195
+ if raw_token and raw_password and raw_token != raw_password:
196
+ raise ValueError(
197
+ "OPENCLAW_GATEWAY_TOKEN 与 OPENCLAW_GATEWAY_PASSWORD 同时提供时必须一致"
198
+ )
199
+ shared_secret = raw_token or raw_password
200
+ if not shared_secret:
201
+ raise ValueError(
202
+ "OPENCLAW_GATEWAY_AUTH_MODE=token 时必须提供 "
203
+ "OPENCLAW_GATEWAY_TOKEN 或 OPENCLAW_GATEWAY_PASSWORD"
204
+ )
205
+ normalized_env["OPENCLAW_GATEWAY_AUTH_MODE"] = "token"
206
+ normalized_env["OPENCLAW_GATEWAY_TOKEN"] = shared_secret
207
+ normalized_env["OPENCLAW_GATEWAY_PASSWORD"] = shared_secret
208
+ return normalized_env
209
+
210
+ if raw_token or raw_password:
211
+ raise ValueError(
212
+ "仅在 OPENCLAW_GATEWAY_AUTH_MODE=token 时支持 "
213
+ "OPENCLAW_GATEWAY_TOKEN 或 OPENCLAW_GATEWAY_PASSWORD"
214
+ )
215
+
216
+ normalized_env["OPENCLAW_GATEWAY_AUTH_MODE"] = auth_mode
217
+ normalized_env.pop("OPENCLAW_GATEWAY_TOKEN", None)
218
+ normalized_env.pop("OPENCLAW_GATEWAY_PASSWORD", None)
219
+ return normalized_env
220
+
221
+
222
+ def _build_openclaw_env_vars(
223
+ *,
224
+ model_base_url: Optional[str] = None,
225
+ model_api_key: Optional[str] = None,
226
+ default_model: Optional[str] = None,
227
+ model_provider_id: Optional[str] = None,
228
+ gateway_port: Optional[str] = None,
229
+ public_port: Optional[str] = None,
230
+ security_profile: Optional[str] = None,
231
+ ) -> dict:
232
+ """构建 OpenClaw 所需的环境变量,自动复用 OPENAI_* 环境变量"""
233
+ env = {}
234
+ default_provider_id = "ksyun"
235
+ default_model_api = "openai-completions"
236
+ default_model_base_url = "https://kspmas.ksyun.com/v1"
237
+ exec_profile_overrides = _resolve_exec_profile_overrides(security_profile)
238
+
239
+ # 模型配置:客户端只透传用户显式配置和可选的 API Key;
240
+ # 其余默认值交给镜像 bootstrap 兜底,避免创建请求把服务端默认行为短路掉。
241
+ openclaw_explicit_model = default_model or _resolve_env("OPENCLAW_DEFAULT_MODEL")
242
+ generic_model_preference = _resolve_env("OPENAI_MODEL_NAME", "MODEL_NAME", "LLM_MODEL")
243
+ model_preference = openclaw_explicit_model or generic_model_preference
244
+ explicit_base_url = model_base_url or _resolve_env(
245
+ "OPENCLAW_MODEL_BASE_URL", "OPENAI_BASE_URL", "OPENAI_API_BASE"
246
+ )
247
+ base_url = _resolve_model_base_url(explicit_base_url)
248
+ api_key = model_api_key or _resolve_env(
249
+ "OPENCLAW_MODEL_API_KEY", "OPENAI_API_KEY", "LLM_API_KEY", "MODEL_API_KEY"
250
+ )
251
+ model = model_preference or "glm-5.2"
252
+ explicit_provider_id = model_provider_id or _resolve_env("OPENCLAW_MODEL_PROVIDER_ID")
253
+ inferred_provider_id = explicit_provider_id
254
+ if not inferred_provider_id and model and "/" in model:
255
+ inferred_provider_id = model.split("/", 1)[0].strip()
256
+ provider_id = inferred_provider_id or default_provider_id
257
+ resolved_gateway_port = gateway_port or _resolve_env("OPENCLAW_GATEWAY_PORT", "PORT") or "8080"
258
+ resolved_public_port = public_port or _resolve_env("OPENCLAW_PUBLIC_PORT") or "80"
259
+ explicit_model_api = _resolve_env("OPENCLAW_MODEL_API")
260
+ model_api = explicit_model_api or default_model_api
261
+ trusted_proxy_user_header = (
262
+ (
263
+ _resolve_env(
264
+ "OPENCLAW_TRUSTED_PROXY_USER_HEADER",
265
+ "OPENCLAW_GATEWAY_TRUSTED_PROXY_USER_HEADER",
266
+ )
267
+ or DEFAULT_TRUSTED_PROXY_USER_HEADER
268
+ )
269
+ .strip()
270
+ .lower()
271
+ )
272
+ internal_trusted_proxy_user = (
273
+ _resolve_env("OPENCLAW_INTERNAL_TRUSTED_PROXY_USER") or "openclaw-backend"
274
+ )
275
+ internal_trusted_proxy_user_header = (
276
+ (
277
+ _resolve_env("OPENCLAW_INTERNAL_TRUSTED_PROXY_USER_HEADER")
278
+ or trusted_proxy_user_header
279
+ or DEFAULT_TRUSTED_PROXY_USER_HEADER
280
+ )
281
+ .strip()
282
+ .lower()
283
+ )
284
+ trusted_proxies = _normalize_csv_list(
285
+ _resolve_env("OPENCLAW_TRUSTED_PROXIES") or "",
286
+ default_items=DEFAULT_TRUSTED_PROXY_CIDRS,
287
+ )
288
+ browser_enabled = _resolve_env("OPENCLAW_BROWSER_ENABLED")
289
+ browser_no_sandbox = _resolve_env("OPENCLAW_BROWSER_NO_SANDBOX") or "true"
290
+ browser_headless = _resolve_env("OPENCLAW_BROWSER_HEADLESS") or "true"
291
+ browser_executable = _resolve_env(
292
+ "OPENCLAW_BROWSER_EXECUTABLE_PATH", "OPENCLAW_BROWSER_EXECUTABLE"
293
+ )
294
+ ui_locale = _normalize_ui_locale(_resolve_env("OPENCLAW_UI_LOCALE", "LANG", "LC_ALL"))
295
+ exec_strict_mode_raw = (
296
+ exec_profile_overrides.get("OPENCLAW_EXEC_STRICT_MODE")
297
+ or _resolve_env("OPENCLAW_EXEC_STRICT_MODE", "OPENCLAW_EXEC_SAFE_MODE")
298
+ or "false"
299
+ )
300
+ exec_strict_mode = _is_truthy(exec_strict_mode_raw)
301
+
302
+ exec_host = (
303
+ exec_profile_overrides.get("OPENCLAW_EXEC_HOST")
304
+ or _resolve_env("OPENCLAW_EXEC_HOST")
305
+ or "gateway"
306
+ )
307
+ exec_security = (
308
+ exec_profile_overrides.get("OPENCLAW_EXEC_SECURITY")
309
+ or _resolve_env("OPENCLAW_EXEC_SECURITY")
310
+ or ("allowlist" if exec_strict_mode else "full")
311
+ )
312
+ exec_ask = (
313
+ exec_profile_overrides.get("OPENCLAW_EXEC_ASK")
314
+ or _resolve_env("OPENCLAW_EXEC_ASK")
315
+ or "off"
316
+ )
317
+ exec_ask_fallback = (
318
+ exec_profile_overrides.get("OPENCLAW_EXEC_ASK_FALLBACK")
319
+ or _resolve_env("OPENCLAW_EXEC_ASK_FALLBACK")
320
+ or ("allowlist" if exec_strict_mode else "full")
321
+ )
322
+ exec_auto_allow_skills = (
323
+ exec_profile_overrides.get("OPENCLAW_EXEC_AUTO_ALLOW_SKILLS")
324
+ or _resolve_env("OPENCLAW_EXEC_AUTO_ALLOW_SKILLS")
325
+ or "false"
326
+ )
327
+ elevated_enabled = (
328
+ exec_profile_overrides.get("OPENCLAW_ELEVATED_ENABLED")
329
+ or _resolve_env("OPENCLAW_ELEVATED_ENABLED")
330
+ or "false"
331
+ )
332
+ exec_default_allowlist_enabled = (
333
+ exec_profile_overrides.get("OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED")
334
+ or _resolve_env("OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED")
335
+ or ("true" if exec_strict_mode else "false")
336
+ )
337
+ exec_allowlist = _resolve_env("OPENCLAW_EXEC_ALLOWLIST")
338
+ fs_workspace_only = (
339
+ exec_profile_overrides.get("OPENCLAW_FS_WORKSPACE_ONLY")
340
+ or _resolve_env("OPENCLAW_FS_WORKSPACE_ONLY")
341
+ or "false"
342
+ )
343
+ model_api_key_secret_source = _resolve_env("OPENCLAW_MODEL_API_KEY_SECRET_SOURCE") or "file"
344
+ model_api_key_secret_file_path = _resolve_env("OPENCLAW_MODEL_API_KEY_SECRET_FILE_PATH")
345
+ gateway_auth_mode = _resolve_env("OPENCLAW_GATEWAY_AUTH_MODE")
346
+ gateway_token = _resolve_env("OPENCLAW_GATEWAY_TOKEN")
347
+ gateway_password = _resolve_env("OPENCLAW_GATEWAY_PASSWORD")
348
+
349
+ env["OPENCLAW_GATEWAY_BIND"] = "lan"
350
+ if gateway_auth_mode:
351
+ env["OPENCLAW_GATEWAY_AUTH_MODE"] = gateway_auth_mode
352
+ env["OPENCLAW_TRUSTED_PROXY_USER_HEADER"] = (
353
+ trusted_proxy_user_header or DEFAULT_TRUSTED_PROXY_USER_HEADER
354
+ )
355
+ env["OPENCLAW_INTERNAL_TRUSTED_PROXY_USER"] = internal_trusted_proxy_user
356
+ env["OPENCLAW_INTERNAL_TRUSTED_PROXY_USER_HEADER"] = (
357
+ internal_trusted_proxy_user_header
358
+ or trusted_proxy_user_header
359
+ or DEFAULT_TRUSTED_PROXY_USER_HEADER
360
+ )
361
+ env["OPENCLAW_TRUSTED_PROXIES"] = trusted_proxies
362
+ env["OPENCLAW_GATEWAY_PORT"] = str(resolved_gateway_port)
363
+ env["OPENCLAW_PUBLIC_PORT"] = str(resolved_public_port)
364
+ if browser_enabled:
365
+ env["OPENCLAW_BROWSER_ENABLED"] = browser_enabled
366
+ env["OPENCLAW_BROWSER_NO_SANDBOX"] = browser_no_sandbox
367
+ env["OPENCLAW_BROWSER_HEADLESS"] = browser_headless
368
+ if browser_executable:
369
+ env["OPENCLAW_BROWSER_EXECUTABLE_PATH"] = browser_executable
370
+ env["OPENCLAW_UI_LOCALE"] = ui_locale
371
+ env["OPENCLAW_EXEC_HOST"] = exec_host
372
+ env["OPENCLAW_EXEC_STRICT_MODE"] = "true" if exec_strict_mode else "false"
373
+ env["OPENCLAW_EXEC_UNSAFE_MODE"] = "false" if exec_strict_mode else "true"
374
+ env["OPENCLAW_EXEC_SECURITY"] = exec_security
375
+ env["OPENCLAW_EXEC_ASK"] = exec_ask
376
+ env["OPENCLAW_EXEC_ASK_FALLBACK"] = exec_ask_fallback
377
+ env["OPENCLAW_EXEC_AUTO_ALLOW_SKILLS"] = exec_auto_allow_skills
378
+ env["OPENCLAW_ELEVATED_ENABLED"] = elevated_enabled
379
+ env["OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED"] = exec_default_allowlist_enabled
380
+ env["OPENCLAW_FS_WORKSPACE_ONLY"] = fs_workspace_only
381
+ env["OPENCLAW_MODEL_API_KEY_SECRET_SOURCE"] = model_api_key_secret_source
382
+ if exec_allowlist:
383
+ env["OPENCLAW_EXEC_ALLOWLIST"] = exec_allowlist
384
+ if model_api_key_secret_file_path:
385
+ env["OPENCLAW_MODEL_API_KEY_SECRET_FILE_PATH"] = model_api_key_secret_file_path
386
+
387
+ if explicit_provider_id and provider_id != default_provider_id:
388
+ env["OPENCLAW_MODEL_PROVIDER_ID"] = provider_id
389
+ elif not explicit_provider_id and provider_id and provider_id != default_provider_id:
390
+ env["OPENCLAW_MODEL_PROVIDER_ID"] = provider_id
391
+ if explicit_model_api and model_api != default_model_api:
392
+ env["OPENCLAW_MODEL_API"] = model_api
393
+ if explicit_base_url and base_url and base_url != default_model_base_url:
394
+ env["OPENCLAW_MODEL_BASE_URL"] = base_url
395
+ if api_key:
396
+ env["OPENCLAW_MODEL_API_KEY"] = api_key
397
+ normalized_model = model.strip() if model else None
398
+ catalog_model_id = None
399
+ resolved_model = None
400
+ if normalized_model:
401
+ if "/" in normalized_model:
402
+ _, catalog_model_id = normalized_model.split("/", 1)
403
+ resolved_model = normalized_model
404
+ else:
405
+ resolved_model = (
406
+ f"{provider_id}/{normalized_model}" if provider_id else normalized_model
407
+ )
408
+ if openclaw_explicit_model:
409
+ env["OPENCLAW_DEFAULT_MODEL"] = resolved_model
410
+ elif generic_model_preference:
411
+ env["OPENAI_MODEL_NAME"] = resolved_model
412
+
413
+ # 额外的可选配置
414
+ catalog = _resolve_env("OPENCLAW_MODEL_CATALOG_JSON")
415
+ if catalog:
416
+ env["OPENCLAW_MODEL_CATALOG_JSON"] = catalog
417
+ openclaw_model_allowlist = _resolve_env("OPENCLAW_MODEL_ALLOWLIST")
418
+ agentengine_model_allowlist = _resolve_env("AGENTENGINE_MODEL_ALLOWLIST")
419
+ if openclaw_model_allowlist:
420
+ env["OPENCLAW_MODEL_ALLOWLIST"] = openclaw_model_allowlist
421
+ elif agentengine_model_allowlist:
422
+ env["AGENTENGINE_MODEL_ALLOWLIST"] = agentengine_model_allowlist
423
+ origins = _resolve_env("OPENCLAW_ALLOWED_ORIGINS")
424
+ if origins:
425
+ env["OPENCLAW_ALLOWED_ORIGINS"] = _normalize_allowed_origins(origins)
426
+ else:
427
+ # 统一输出 JSON 数组字符串,兼容旧版 bootstrap(仅支持 JSON.parse)。
428
+ env["OPENCLAW_ALLOWED_ORIGINS"] = json.dumps(["*"])
429
+ allow_insecure_auth = _resolve_env("OPENCLAW_ALLOW_INSECURE_AUTH")
430
+ env["OPENCLAW_ALLOW_INSECURE_AUTH"] = allow_insecure_auth if allow_insecure_auth else "true"
431
+ disable_device_auth = _resolve_env("OPENCLAW_DISABLE_DEVICE_AUTH")
432
+ env["OPENCLAW_DISABLE_DEVICE_AUTH"] = disable_device_auth if disable_device_auth else "true"
433
+ if gateway_token:
434
+ env["OPENCLAW_GATEWAY_TOKEN"] = gateway_token
435
+ if gateway_password:
436
+ env["OPENCLAW_GATEWAY_PASSWORD"] = gateway_password
437
+ for passthrough_key in [
438
+ "OPENCLAW_CHANNEL_BOOTSTRAP_JSON",
439
+ "OPENCLAW_BROWSER_SSRF_POLICY_JSON",
440
+ "OPENCLAW_WEB_FETCH_ENABLED",
441
+ "OPENCLAW_WEB_SEARCH_PROVIDER",
442
+ "OPENCLAW_WEB_SEARCH_BASE_URL",
443
+ "OPENCLAW_WEB_SEARCH_MODEL",
444
+ "OPENCLAW_WEB_SEARCH_API_KEY",
445
+ "OPENCLAW_WEB_SEARCH_API_KEY_SECRET_SOURCE",
446
+ "OPENCLAW_WEB_SEARCH_API_KEY_SECRET_PROVIDER",
447
+ "OPENCLAW_WEB_SEARCH_API_KEY_SECRET_ID",
448
+ ]:
449
+ passthrough_value = _resolve_env(passthrough_key)
450
+ if passthrough_value:
451
+ env[passthrough_key] = passthrough_value
452
+
453
+ env = _normalize_openclaw_gateway_auth_env(env)
454
+ env = build_runtime_model_policy_env(env, runtime="openclaw")
455
+ # shell 前缀转发 (KSADK_/OPENAI_/KSYUN_/E2B_ + allowlist),对齐通用 deploy;
456
+ # setdefault 语义不覆盖上面已 resolve 的固定键,--env/--env-file 仍可覆盖。
457
+ forward_shell_process_env(env)
458
+ return env