agentengine-sdk-python 0.8.1__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 (411) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
  3. ksadk/a2a/_space_client_events.py +381 -0
  4. ksadk/a2a/event_adapter.py +156 -64
  5. ksadk/a2a/executor.py +179 -63
  6. ksadk/a2a/space_client.py +6 -333
  7. ksadk/a2ui/core.py +222 -53
  8. ksadk/agui/_agent_helpers.py +243 -0
  9. ksadk/agui/a2ui_projection.py +12 -5
  10. ksadk/agui/agent.py +443 -259
  11. ksadk/api/client.py +525 -27
  12. ksadk/builders/code_builder.py +284 -8
  13. ksadk/builders/container_builder.py +8 -1
  14. ksadk/builders/managed_runtime_builder.py +39 -35
  15. ksadk/cli/__init__.py +17 -0
  16. ksadk/cli/cmd_dashboard.py +15 -1
  17. ksadk/cli/cmd_deploy.py +10 -2
  18. ksadk/cli/cmd_eval.py +66 -9
  19. ksadk/cli/cmd_evalset.py +284 -0
  20. ksadk/cli/cmd_files.py +5 -1
  21. ksadk/cli/cmd_hermes.py +1 -126
  22. ksadk/cli/cmd_invoke.py +28 -38
  23. ksadk/cli/cmd_managed_runtime.py +95 -0
  24. ksadk/cli/cmd_observe.py +85 -0
  25. ksadk/cli/cmd_openclaw.py +1 -435
  26. ksadk/cli/cmd_replay.py +28 -4
  27. ksadk/cli/cmd_studio.py +99 -8
  28. ksadk/cli/cmd_web.py +10 -2
  29. ksadk/cli/hermes_env.py +151 -0
  30. ksadk/cli/invoke_payload.py +49 -0
  31. ksadk/cli/openclaw_env.py +458 -0
  32. ksadk/codex/client.py +180 -30
  33. ksadk/codex/runtime.py +428 -326
  34. ksadk/configs/env_registry.py +66 -12
  35. ksadk/configs/env_registry_pcm.py +181 -0
  36. ksadk/configs/env_var_spec.py +18 -0
  37. ksadk/configs/global_config.py +5 -0
  38. ksadk/context_engine/__init__.py +98 -0
  39. ksadk/context_engine/assembler.py +176 -0
  40. ksadk/context_engine/baseline.py +419 -0
  41. ksadk/context_engine/cache_observability.py +228 -0
  42. ksadk/context_engine/capabilities.py +443 -0
  43. ksadk/context_engine/contributors.py +344 -0
  44. ksadk/context_engine/hosted_pipeline.py +417 -0
  45. ksadk/context_engine/models.py +117 -0
  46. ksadk/context_engine/planner.py +698 -0
  47. ksadk/context_engine/policies.py +319 -0
  48. ksadk/context_engine/projection.py +31 -0
  49. ksadk/context_engine/shadow_plan.py +266 -0
  50. ksadk/context_engine/tokenizer.py +164 -0
  51. ksadk/conversations/context.py +126 -6
  52. ksadk/conversations/message_projection.py +292 -28
  53. ksadk/conversations/model_context.py +49 -3
  54. ksadk/conversations/runtime_compaction.py +207 -5
  55. ksadk/conversations/runtime_input.py +184 -2
  56. ksadk/conversations/runtime_invocation.py +81 -3
  57. ksadk/conversations/runtime_observability.py +141 -0
  58. ksadk/conversations/runtime_payloads.py +42 -0
  59. ksadk/conversations/runtime_preparation.py +272 -2
  60. ksadk/conversations/runtime_resume.py +20 -1
  61. ksadk/conversations/runtime_stream_events.py +94 -9
  62. ksadk/conversations/semantic_summary.py +311 -1
  63. ksadk/conversations/session_lock.py +51 -0
  64. ksadk/deployment/env_forward.py +72 -0
  65. ksadk/deployment/managed_runtime.py +5 -0
  66. ksadk/deployment/providers/serverless.py +143 -69
  67. ksadk/evaluation/__init__.py +32 -0
  68. ksadk/evaluation/a2a_adapter.py +9 -1
  69. ksadk/evaluation/adapters.py +18 -5
  70. ksadk/evaluation/agent_eval_client.py +395 -0
  71. ksadk/evaluation/cloud_binding.py +80 -0
  72. ksadk/evaluation/cloud_converter.py +194 -0
  73. ksadk/evaluation/cloud_service.py +199 -0
  74. ksadk/evaluation/contracts.py +73 -4
  75. ksadk/evaluation/evaluators.py +183 -17
  76. ksadk/evaluation/evidence.py +258 -0
  77. ksadk/evaluation/executor.py +31 -6
  78. ksadk/evaluation/local_adapter.py +550 -0
  79. ksadk/evaluation/service_env.py +27 -0
  80. ksadk/evaluation/studio_build_adapter.py +253 -0
  81. ksadk/evaluation/target.py +15 -6
  82. ksadk/events/__init__.py +13 -13
  83. ksadk/events/_v1_compat/__init__.py +1 -0
  84. ksadk/events/_v1_compat/models.py +299 -0
  85. ksadk/events/_v1_compat/parser.py +247 -0
  86. ksadk/events/_v1_compat/projection.py +753 -0
  87. ksadk/events/adapters/__init__.py +34 -0
  88. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  89. ksadk/events/adapters/_a2a_support.py +275 -0
  90. ksadk/events/adapters/_codex_interactions.py +375 -0
  91. ksadk/events/adapters/_codex_items.py +801 -0
  92. ksadk/events/adapters/_codex_validators.py +311 -0
  93. ksadk/events/adapters/_langgraph_support.py +785 -0
  94. ksadk/events/adapters/a2a.py +841 -0
  95. ksadk/events/adapters/adk.py +503 -0
  96. ksadk/events/adapters/codex.py +717 -0
  97. ksadk/events/adapters/langgraph.py +745 -0
  98. ksadk/events/canonical.py +440 -0
  99. ksadk/events/canonical_replay.py +497 -0
  100. ksadk/events/canonical_store.py +468 -0
  101. ksadk/events/cold_recovery.py +257 -0
  102. ksadk/events/content.py +89 -0
  103. ksadk/events/identity.py +86 -0
  104. ksadk/events/pipeline.py +455 -0
  105. ksadk/events/projections.py +66 -0
  106. ksadk/events/reducer.py +661 -0
  107. ksadk/events/replay.py +3 -36
  108. ksadk/events/runtime_event.py +20 -265
  109. ksadk/events/session_event.py +324 -0
  110. ksadk/events/store.py +3 -316
  111. ksadk/events/v1_compat.py +41 -0
  112. ksadk/harness/runtime.py +160 -57
  113. ksadk/identity/resolver.py +4 -3
  114. ksadk/interaction/__init__.py +28 -0
  115. ksadk/interaction/contracts.py +136 -0
  116. ksadk/interaction/ledger.py +189 -0
  117. ksadk/interaction/provider.py +122 -0
  118. ksadk/interaction/providers/__init__.py +52 -0
  119. ksadk/interaction/providers/adk.py +40 -0
  120. ksadk/interaction/providers/codex.py +94 -0
  121. ksadk/interaction/providers/langgraph.py +58 -0
  122. ksadk/kernel/__init__.py +117 -0
  123. ksadk/kernel/authorization.py +258 -0
  124. ksadk/kernel/bootstrap.py +1074 -0
  125. ksadk/kernel/contract_fingerprints.py +61 -0
  126. ksadk/kernel/contracts.py +362 -0
  127. ksadk/kernel/control.py +219 -0
  128. ksadk/kernel/errors.py +79 -0
  129. ksadk/kernel/ingress.py +1102 -0
  130. ksadk/kernel/mapping.py +111 -0
  131. ksadk/kernel/memory_store.py +1133 -0
  132. ksadk/kernel/postgres_store.py +1756 -0
  133. ksadk/kernel/recovery.py +452 -0
  134. ksadk/kernel/runtime_identity.py +103 -0
  135. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  136. ksadk/kernel/sqlite_store.py +1410 -0
  137. ksadk/kernel/state.py +145 -0
  138. ksadk/kernel/store.py +232 -0
  139. ksadk/kernel/worker.py +953 -0
  140. ksadk/knowledge_base/client.py +7 -0
  141. ksadk/knowledge_base/service.py +32 -5
  142. ksadk/memory/__init__.py +61 -0
  143. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  144. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  145. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  146. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  147. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  148. ksadk/memory/coordinator.py +461 -0
  149. ksadk/memory/events.py +202 -0
  150. ksadk/memory/extraction.py +228 -0
  151. ksadk/memory/ltm_backend_factory.py +16 -3
  152. ksadk/memory/models.py +316 -0
  153. ksadk/memory/policy.py +215 -0
  154. ksadk/memory/provider.py +47 -0
  155. ksadk/memory/provider_adapter.py +159 -0
  156. ksadk/memory/provider_resolver.py +71 -0
  157. ksadk/memory/providers/__init__.py +5 -0
  158. ksadk/memory/providers/local_sqlite.py +490 -0
  159. ksadk/memory/resolved_policy.py +145 -0
  160. ksadk/memory/service.py +188 -6
  161. ksadk/model_proxy/bootstrap.py +16 -9
  162. ksadk/model_proxy/detect.py +202 -9
  163. ksadk/model_proxy/namespace.py +39 -15
  164. ksadk/model_proxy/server.py +24 -5
  165. ksadk/model_proxy/transform.py +60 -2
  166. ksadk/observability/__init__.py +25 -0
  167. ksadk/observability/session_log.py +420 -0
  168. ksadk/observability/trajectory.py +105 -0
  169. ksadk/prompts/__init__.py +71 -0
  170. ksadk/prompts/compiler.py +215 -0
  171. ksadk/prompts/models.py +82 -0
  172. ksadk/prompts/projection.py +89 -0
  173. ksadk/prompts/resolved.py +137 -0
  174. ksadk/prompts/sources.py +233 -0
  175. ksadk/runners/_langgraph_runner_streams.py +822 -0
  176. ksadk/runners/adk_runner.py +5 -5
  177. ksadk/runners/base_runner.py +16 -0
  178. ksadk/runners/factory.py +1 -2
  179. ksadk/runners/langgraph_runner.py +198 -437
  180. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  181. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  182. ksadk/runtime/adapter.py +118 -2
  183. ksadk/runtime/conversation_execution.py +316 -182
  184. ksadk/runtime/executor.py +144 -3
  185. ksadk/runtime/factory.py +193 -7
  186. ksadk/runtime/hosted_finalizer.py +268 -0
  187. ksadk/runtime/launch.py +14 -1
  188. ksadk/runtime/preprocessing.py +25 -3
  189. ksadk/runtime/runner_adapter.py +288 -508
  190. ksadk/runtime/usage.py +33 -0
  191. ksadk/sandbox/backends/e2b.py +35 -2
  192. ksadk/server/composition.py +8 -0
  193. ksadk/server/factory.py +69 -6
  194. ksadk/server/routes/kernel_ingress.py +258 -0
  195. ksadk/server/routes/openai_compat.py +88 -8
  196. ksadk/server/routes/projection.py +35 -20
  197. ksadk/server/routes/run.py +94 -0
  198. ksadk/server/routes/sessions.py +2 -0
  199. ksadk/server/routes/streaming.py +5 -2
  200. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  201. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
  202. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  203. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  204. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  205. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  206. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  207. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  208. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  209. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  210. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  211. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  212. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  213. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  214. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  215. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  216. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  217. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  218. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  219. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  220. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  221. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  222. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  223. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  224. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  225. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  226. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  227. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  228. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  229. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  230. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  231. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  232. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  233. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  234. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  235. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  236. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
  237. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  238. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
  239. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
  240. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
  241. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
  242. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
  243. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
  244. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
  245. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
  246. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
  247. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
  248. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
  249. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
  250. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
  251. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
  252. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
  253. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
  254. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
  255. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
  256. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
  257. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-ngtN0DJB.js} +1 -1
  258. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  259. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  260. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  261. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  262. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  263. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  264. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  265. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  266. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  267. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  268. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  269. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  270. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  271. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  272. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  273. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-BHjG8b-J.js} +1 -1
  274. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  275. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  276. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  277. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  278. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  279. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  280. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  281. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  282. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  283. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  284. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  285. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  286. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  287. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  288. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  289. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  290. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  291. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  292. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  293. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  294. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  295. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  296. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  297. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  298. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  299. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  300. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  301. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  302. ksadk/server/static/index.html +2 -2
  303. ksadk/sessions/__init__.py +26 -9
  304. ksadk/sessions/_local_service_sync.py +688 -0
  305. ksadk/sessions/_local_tables.py +21 -0
  306. ksadk/sessions/_postgres_schema.py +305 -0
  307. ksadk/sessions/_postgres_tables.py +15 -0
  308. ksadk/sessions/base.py +80 -1
  309. ksadk/sessions/in_memory.py +53 -2
  310. ksadk/sessions/local_service.py +63 -604
  311. ksadk/sessions/postgres_service.py +58 -148
  312. ksadk/sessions/resilient.py +35 -1
  313. ksadk/studio/api.py +577 -25
  314. ksadk/studio/api_contracts.py +114 -5
  315. ksadk/studio/api_memory_routes.py +82 -0
  316. ksadk/studio/authoring.py +252 -27
  317. ksadk/studio/authoring_coordinator.py +799 -67
  318. ksadk/studio/builder.py +88 -11
  319. ksadk/studio/capabilities.py +17 -0
  320. ksadk/studio/cloud.py +1916 -95
  321. ksadk/studio/codex_agent_service.py +125 -14
  322. ksadk/studio/codex_authoring.py +469 -0
  323. ksadk/studio/codex_builder.py +138 -25
  324. ksadk/studio/codex_manifest.py +51 -22
  325. ksadk/studio/codex_run.py +46 -3
  326. ksadk/studio/compiler.py +1 -0
  327. ksadk/studio/contracts.py +114 -3
  328. ksadk/studio/event_store.py +25 -95
  329. ksadk/studio/framework_run.py +231 -3
  330. ksadk/studio/hosted_kernel.py +317 -0
  331. ksadk/studio/manifest_resolver.py +131 -0
  332. ksadk/studio/model_client.py +95 -9
  333. ksadk/studio/model_profile_service.py +1 -1
  334. ksadk/studio/operations.py +37 -5
  335. ksadk/studio/otel_trace.py +348 -42
  336. ksadk/studio/pcm_memory.py +85 -0
  337. ksadk/studio/repository.py +23 -2
  338. ksadk/studio/resource_catalog.py +43 -0
  339. ksadk/studio/run_service.py +563 -137
  340. ksadk/studio/runtime_source.py +42 -16
  341. ksadk/studio/service.py +1180 -72
  342. ksadk/studio/shared_web.py +32 -22
  343. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  344. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  345. ksadk/studio/static/index.html +2 -2
  346. ksadk/studio/templates.py +100 -8
  347. ksadk/studio/validator.py +19 -0
  348. ksadk/studio/workspace.py +30 -32
  349. ksadk/tracing/setup.py +304 -3
  350. ksadk/version.py +1 -1
  351. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  352. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  353. ksadk/events/parser.py +0 -191
  354. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  355. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  356. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  357. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  358. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  359. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  360. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  361. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  362. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  363. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  364. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  365. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  366. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  367. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  368. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  369. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  370. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  371. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  372. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  373. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  374. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  375. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  376. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  377. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  378. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  379. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  380. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  381. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  382. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  383. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  384. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  385. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  386. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  387. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  388. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  389. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  390. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  391. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  392. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  393. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  394. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  395. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  396. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  397. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  398. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  399. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  400. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  401. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  402. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  404. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  405. ksadk/studio/evaluation.py +0 -192
  406. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  407. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  408. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
  409. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  410. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  411. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
ksadk/cli/cmd_openclaw.py CHANGED
@@ -81,7 +81,7 @@ from ksadk.cli.ui import (
81
81
  from ksadk.configs.env_registry import is_sensitive_env_var
82
82
  from ksadk.conversations.model_context import normalize_model_metadata
83
83
  from ksadk.deployment.agent_access import get_latest_agent_access
84
- from ksadk.model_policy import build_runtime_model_policy_env
84
+ from ksadk.cli.openclaw_env import _build_openclaw_env_vars, _normalize_openclaw_gateway_auth_env
85
85
  from ksadk.openclaw_gateway import (
86
86
  OpenClawGatewayClient,
87
87
  OpenClawGatewayError,
@@ -97,15 +97,6 @@ DEFAULT_OPENCLAW_REPO = "openclaw"
97
97
  DEFAULT_OPENCLAW_VERSION = "2026.6.1"
98
98
  DEFAULT_OPENCLAW_REGISTRY = "ghcr.io/kingsoftcloud"
99
99
  DEFAULT_OPENCLAW_NAME = "openclaw-gateway"
100
- DEFAULT_TRUSTED_PROXY_USER_HEADER = "x-forwarded-user"
101
- DEFAULT_TRUSTED_PROXY_CIDRS = [
102
- "127.0.0.1",
103
- "::1",
104
- "10.0.0.0/8",
105
- "172.16.0.0/12",
106
- "192.168.0.0/16",
107
- "35.0.0.0/8",
108
- ]
109
100
  _GLOBAL_ENV_CACHE: Optional[Dict[str, str]] = None
110
101
  OPENCLAW_SECURITY_PROFILES = ("relaxed", "strict", "strictest")
111
102
  OPENCLAW_CHANNELS = ("weixin", "feishu", "wps-xiezuo")
@@ -386,33 +377,6 @@ def _openclaw_registry_env() -> dict[str, str]:
386
377
  return env
387
378
 
388
379
 
389
- def _resolve_model_base_url(cli_value: Optional[str]) -> Optional[str]:
390
- """解析模型 Base URL,缺失时回退到 settings.model.api_base(KSPMAS 自动探测)。"""
391
- if cli_value and str(cli_value).strip():
392
- return str(cli_value).strip()
393
-
394
- from_env = _resolve_env(
395
- "OPENCLAW_MODEL_BASE_URL",
396
- "OPENAI_BASE_URL",
397
- "OPENAI_API_BASE",
398
- "LLM_API_BASE",
399
- "MODEL_API_BASE",
400
- )
401
- if from_env:
402
- return from_env
403
-
404
- try:
405
- from ksadk.configs.settings import settings
406
-
407
- api_base = settings.model.api_base
408
- if api_base and str(api_base).strip():
409
- return str(api_base).strip()
410
- except Exception:
411
- pass
412
-
413
- return None
414
-
415
-
416
380
  def _summarize_openclaw_account(agents: list[Dict[str, Any]]) -> str:
417
381
  """汇总列表所属账号,优先使用响应字段,缺失时回退当前 CLI 上下文。"""
418
382
  accounts = sorted(
@@ -455,88 +419,6 @@ def _print_openclaw_list_summary(table: RichTable, summary_text: str) -> None:
455
419
  console.print(f"[muted]{summary_text}[/]")
456
420
 
457
421
 
458
- def _normalize_ui_locale(raw: Optional[str]) -> str:
459
- """标准化 UI 语言代码,默认 zh-CN。"""
460
- text = str(raw or "").strip()
461
- if not text:
462
- return "zh-CN"
463
-
464
- base = text.split(".", 1)[0].replace("_", "-").strip()
465
- low = base.lower()
466
-
467
- if low in {"c", "c-utf-8", "c.utf-8", "posix"}:
468
- return "zh-CN"
469
- if (
470
- low.startswith("zh-tw")
471
- or low.startswith("zh-hk")
472
- or low.startswith("zh-mo")
473
- or low.startswith("zh-hant")
474
- ):
475
- return "zh-TW"
476
- if low.startswith("zh"):
477
- return "zh-CN"
478
- if low.startswith("pt"):
479
- return "pt-BR"
480
- if low.startswith("de"):
481
- return "de"
482
- if low.startswith("en"):
483
- return "en"
484
-
485
- return "zh-CN"
486
-
487
-
488
- def _is_truthy(raw: Optional[str]) -> bool:
489
- text = str(raw or "").strip().lower()
490
- return text in {"1", "true", "yes", "on"}
491
-
492
-
493
- def _resolve_exec_profile_overrides(security_profile: Optional[str]) -> Dict[str, str]:
494
- """根据 CLI 安全预设返回 OpenClaw 运行时环境变量覆盖项。"""
495
- profile = str(security_profile or "").strip().lower()
496
- if not profile:
497
- return {}
498
-
499
- common = {
500
- "OPENCLAW_EXEC_HOST": "gateway",
501
- "OPENCLAW_EXEC_AUTO_ALLOW_SKILLS": "false",
502
- "OPENCLAW_ELEVATED_ENABLED": "false",
503
- }
504
- if profile == "relaxed":
505
- return {
506
- **common,
507
- "OPENCLAW_EXEC_STRICT_MODE": "false",
508
- "OPENCLAW_EXEC_UNSAFE_MODE": "true",
509
- "OPENCLAW_EXEC_SECURITY": "full",
510
- "OPENCLAW_EXEC_ASK": "off",
511
- "OPENCLAW_EXEC_ASK_FALLBACK": "full",
512
- "OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED": "false",
513
- "OPENCLAW_FS_WORKSPACE_ONLY": "false",
514
- }
515
- if profile == "strict":
516
- return {
517
- **common,
518
- "OPENCLAW_EXEC_STRICT_MODE": "true",
519
- "OPENCLAW_EXEC_UNSAFE_MODE": "false",
520
- "OPENCLAW_EXEC_SECURITY": "allowlist",
521
- "OPENCLAW_EXEC_ASK": "off",
522
- "OPENCLAW_EXEC_ASK_FALLBACK": "allowlist",
523
- "OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED": "true",
524
- "OPENCLAW_FS_WORKSPACE_ONLY": "false",
525
- }
526
- if profile == "strictest":
527
- return {
528
- **common,
529
- "OPENCLAW_EXEC_STRICT_MODE": "true",
530
- "OPENCLAW_EXEC_UNSAFE_MODE": "false",
531
- "OPENCLAW_EXEC_SECURITY": "deny",
532
- "OPENCLAW_EXEC_ASK": "off",
533
- "OPENCLAW_EXEC_ASK_FALLBACK": "deny",
534
- "OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED": "false",
535
- "OPENCLAW_FS_WORKSPACE_ONLY": "true",
536
- }
537
- raise ValueError(f"unsupported OpenClaw security profile: {security_profile}")
538
-
539
-
540
422
  def _strip_provider_prefix(provider_id: str, model_id: str) -> str:
541
423
  provider = str(provider_id or "").strip()
542
424
  model = str(model_id or "").strip()
@@ -739,322 +621,6 @@ def _filter_openclaw_provider_catalog(
739
621
  return selected
740
622
 
741
623
 
742
- def _build_openclaw_env_vars(
743
- *,
744
- model_base_url: Optional[str] = None,
745
- model_api_key: Optional[str] = None,
746
- default_model: Optional[str] = None,
747
- model_provider_id: Optional[str] = None,
748
- gateway_port: Optional[str] = None,
749
- public_port: Optional[str] = None,
750
- security_profile: Optional[str] = None,
751
- ) -> dict:
752
- """构建 OpenClaw 所需的环境变量,自动复用 OPENAI_* 环境变量"""
753
- env = {}
754
- default_provider_id = "ksyun"
755
- default_model_api = "openai-completions"
756
- default_model_base_url = "https://kspmas.ksyun.com/v1"
757
- exec_profile_overrides = _resolve_exec_profile_overrides(security_profile)
758
-
759
- # 模型配置:客户端只透传用户显式配置和可选的 API Key;
760
- # 其余默认值交给镜像 bootstrap 兜底,避免创建请求把服务端默认行为短路掉。
761
- openclaw_explicit_model = default_model or _resolve_env("OPENCLAW_DEFAULT_MODEL")
762
- generic_model_preference = _resolve_env("OPENAI_MODEL_NAME", "MODEL_NAME", "LLM_MODEL")
763
- model_preference = openclaw_explicit_model or generic_model_preference
764
- explicit_base_url = model_base_url or _resolve_env(
765
- "OPENCLAW_MODEL_BASE_URL", "OPENAI_BASE_URL", "OPENAI_API_BASE"
766
- )
767
- base_url = _resolve_model_base_url(explicit_base_url)
768
- api_key = model_api_key or _resolve_env(
769
- "OPENCLAW_MODEL_API_KEY", "OPENAI_API_KEY", "LLM_API_KEY", "MODEL_API_KEY"
770
- )
771
- model = model_preference or "glm-5.2"
772
- explicit_provider_id = model_provider_id or _resolve_env("OPENCLAW_MODEL_PROVIDER_ID")
773
- inferred_provider_id = explicit_provider_id
774
- if not inferred_provider_id and model and "/" in model:
775
- inferred_provider_id = model.split("/", 1)[0].strip()
776
- provider_id = inferred_provider_id or default_provider_id
777
- resolved_gateway_port = gateway_port or _resolve_env("OPENCLAW_GATEWAY_PORT", "PORT") or "8080"
778
- resolved_public_port = public_port or _resolve_env("OPENCLAW_PUBLIC_PORT") or "80"
779
- explicit_model_api = _resolve_env("OPENCLAW_MODEL_API")
780
- model_api = explicit_model_api or default_model_api
781
- trusted_proxy_user_header = (
782
- (
783
- _resolve_env(
784
- "OPENCLAW_TRUSTED_PROXY_USER_HEADER",
785
- "OPENCLAW_GATEWAY_TRUSTED_PROXY_USER_HEADER",
786
- )
787
- or DEFAULT_TRUSTED_PROXY_USER_HEADER
788
- )
789
- .strip()
790
- .lower()
791
- )
792
- internal_trusted_proxy_user = (
793
- _resolve_env("OPENCLAW_INTERNAL_TRUSTED_PROXY_USER") or "openclaw-backend"
794
- )
795
- internal_trusted_proxy_user_header = (
796
- (
797
- _resolve_env("OPENCLAW_INTERNAL_TRUSTED_PROXY_USER_HEADER")
798
- or trusted_proxy_user_header
799
- or DEFAULT_TRUSTED_PROXY_USER_HEADER
800
- )
801
- .strip()
802
- .lower()
803
- )
804
- trusted_proxies = _normalize_csv_list(
805
- _resolve_env("OPENCLAW_TRUSTED_PROXIES") or "",
806
- default_items=DEFAULT_TRUSTED_PROXY_CIDRS,
807
- )
808
- browser_enabled = _resolve_env("OPENCLAW_BROWSER_ENABLED")
809
- browser_no_sandbox = _resolve_env("OPENCLAW_BROWSER_NO_SANDBOX") or "true"
810
- browser_headless = _resolve_env("OPENCLAW_BROWSER_HEADLESS") or "true"
811
- browser_executable = _resolve_env(
812
- "OPENCLAW_BROWSER_EXECUTABLE_PATH", "OPENCLAW_BROWSER_EXECUTABLE"
813
- )
814
- ui_locale = _normalize_ui_locale(_resolve_env("OPENCLAW_UI_LOCALE", "LANG", "LC_ALL"))
815
- exec_strict_mode_raw = (
816
- exec_profile_overrides.get("OPENCLAW_EXEC_STRICT_MODE")
817
- or _resolve_env("OPENCLAW_EXEC_STRICT_MODE", "OPENCLAW_EXEC_SAFE_MODE")
818
- or "false"
819
- )
820
- exec_strict_mode = _is_truthy(exec_strict_mode_raw)
821
-
822
- exec_host = (
823
- exec_profile_overrides.get("OPENCLAW_EXEC_HOST")
824
- or _resolve_env("OPENCLAW_EXEC_HOST")
825
- or "gateway"
826
- )
827
- exec_security = (
828
- exec_profile_overrides.get("OPENCLAW_EXEC_SECURITY")
829
- or _resolve_env("OPENCLAW_EXEC_SECURITY")
830
- or ("allowlist" if exec_strict_mode else "full")
831
- )
832
- exec_ask = (
833
- exec_profile_overrides.get("OPENCLAW_EXEC_ASK")
834
- or _resolve_env("OPENCLAW_EXEC_ASK")
835
- or "off"
836
- )
837
- exec_ask_fallback = (
838
- exec_profile_overrides.get("OPENCLAW_EXEC_ASK_FALLBACK")
839
- or _resolve_env("OPENCLAW_EXEC_ASK_FALLBACK")
840
- or ("allowlist" if exec_strict_mode else "full")
841
- )
842
- exec_auto_allow_skills = (
843
- exec_profile_overrides.get("OPENCLAW_EXEC_AUTO_ALLOW_SKILLS")
844
- or _resolve_env("OPENCLAW_EXEC_AUTO_ALLOW_SKILLS")
845
- or "false"
846
- )
847
- elevated_enabled = (
848
- exec_profile_overrides.get("OPENCLAW_ELEVATED_ENABLED")
849
- or _resolve_env("OPENCLAW_ELEVATED_ENABLED")
850
- or "false"
851
- )
852
- exec_default_allowlist_enabled = (
853
- exec_profile_overrides.get("OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED")
854
- or _resolve_env("OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED")
855
- or ("true" if exec_strict_mode else "false")
856
- )
857
- exec_allowlist = _resolve_env("OPENCLAW_EXEC_ALLOWLIST")
858
- fs_workspace_only = (
859
- exec_profile_overrides.get("OPENCLAW_FS_WORKSPACE_ONLY")
860
- or _resolve_env("OPENCLAW_FS_WORKSPACE_ONLY")
861
- or "false"
862
- )
863
- model_api_key_secret_source = _resolve_env("OPENCLAW_MODEL_API_KEY_SECRET_SOURCE") or "file"
864
- model_api_key_secret_file_path = _resolve_env("OPENCLAW_MODEL_API_KEY_SECRET_FILE_PATH")
865
- gateway_auth_mode = _resolve_env("OPENCLAW_GATEWAY_AUTH_MODE")
866
- gateway_token = _resolve_env("OPENCLAW_GATEWAY_TOKEN")
867
- gateway_password = _resolve_env("OPENCLAW_GATEWAY_PASSWORD")
868
-
869
- env["OPENCLAW_GATEWAY_BIND"] = "lan"
870
- if gateway_auth_mode:
871
- env["OPENCLAW_GATEWAY_AUTH_MODE"] = gateway_auth_mode
872
- env["OPENCLAW_TRUSTED_PROXY_USER_HEADER"] = (
873
- trusted_proxy_user_header or DEFAULT_TRUSTED_PROXY_USER_HEADER
874
- )
875
- env["OPENCLAW_INTERNAL_TRUSTED_PROXY_USER"] = internal_trusted_proxy_user
876
- env["OPENCLAW_INTERNAL_TRUSTED_PROXY_USER_HEADER"] = (
877
- internal_trusted_proxy_user_header
878
- or trusted_proxy_user_header
879
- or DEFAULT_TRUSTED_PROXY_USER_HEADER
880
- )
881
- env["OPENCLAW_TRUSTED_PROXIES"] = trusted_proxies
882
- env["OPENCLAW_GATEWAY_PORT"] = str(resolved_gateway_port)
883
- env["OPENCLAW_PUBLIC_PORT"] = str(resolved_public_port)
884
- if browser_enabled:
885
- env["OPENCLAW_BROWSER_ENABLED"] = browser_enabled
886
- env["OPENCLAW_BROWSER_NO_SANDBOX"] = browser_no_sandbox
887
- env["OPENCLAW_BROWSER_HEADLESS"] = browser_headless
888
- if browser_executable:
889
- env["OPENCLAW_BROWSER_EXECUTABLE_PATH"] = browser_executable
890
- env["OPENCLAW_UI_LOCALE"] = ui_locale
891
- env["OPENCLAW_EXEC_HOST"] = exec_host
892
- env["OPENCLAW_EXEC_STRICT_MODE"] = "true" if exec_strict_mode else "false"
893
- env["OPENCLAW_EXEC_UNSAFE_MODE"] = "false" if exec_strict_mode else "true"
894
- env["OPENCLAW_EXEC_SECURITY"] = exec_security
895
- env["OPENCLAW_EXEC_ASK"] = exec_ask
896
- env["OPENCLAW_EXEC_ASK_FALLBACK"] = exec_ask_fallback
897
- env["OPENCLAW_EXEC_AUTO_ALLOW_SKILLS"] = exec_auto_allow_skills
898
- env["OPENCLAW_ELEVATED_ENABLED"] = elevated_enabled
899
- env["OPENCLAW_EXEC_DEFAULT_ALLOWLIST_ENABLED"] = exec_default_allowlist_enabled
900
- env["OPENCLAW_FS_WORKSPACE_ONLY"] = fs_workspace_only
901
- env["OPENCLAW_MODEL_API_KEY_SECRET_SOURCE"] = model_api_key_secret_source
902
- if exec_allowlist:
903
- env["OPENCLAW_EXEC_ALLOWLIST"] = exec_allowlist
904
- if model_api_key_secret_file_path:
905
- env["OPENCLAW_MODEL_API_KEY_SECRET_FILE_PATH"] = model_api_key_secret_file_path
906
-
907
- if explicit_provider_id and provider_id != default_provider_id:
908
- env["OPENCLAW_MODEL_PROVIDER_ID"] = provider_id
909
- elif not explicit_provider_id and provider_id and provider_id != default_provider_id:
910
- env["OPENCLAW_MODEL_PROVIDER_ID"] = provider_id
911
- if explicit_model_api and model_api != default_model_api:
912
- env["OPENCLAW_MODEL_API"] = model_api
913
- if explicit_base_url and base_url and base_url != default_model_base_url:
914
- env["OPENCLAW_MODEL_BASE_URL"] = base_url
915
- if api_key:
916
- env["OPENCLAW_MODEL_API_KEY"] = api_key
917
- normalized_model = model.strip() if model else None
918
- catalog_model_id = None
919
- resolved_model = None
920
- if normalized_model:
921
- if "/" in normalized_model:
922
- _, catalog_model_id = normalized_model.split("/", 1)
923
- resolved_model = normalized_model
924
- else:
925
- resolved_model = (
926
- f"{provider_id}/{normalized_model}" if provider_id else normalized_model
927
- )
928
- if openclaw_explicit_model:
929
- env["OPENCLAW_DEFAULT_MODEL"] = resolved_model
930
- elif generic_model_preference:
931
- env["OPENAI_MODEL_NAME"] = resolved_model
932
-
933
- # 额外的可选配置
934
- catalog = _resolve_env("OPENCLAW_MODEL_CATALOG_JSON")
935
- if catalog:
936
- env["OPENCLAW_MODEL_CATALOG_JSON"] = catalog
937
- openclaw_model_allowlist = _resolve_env("OPENCLAW_MODEL_ALLOWLIST")
938
- agentengine_model_allowlist = _resolve_env("AGENTENGINE_MODEL_ALLOWLIST")
939
- if openclaw_model_allowlist:
940
- env["OPENCLAW_MODEL_ALLOWLIST"] = openclaw_model_allowlist
941
- elif agentengine_model_allowlist:
942
- env["AGENTENGINE_MODEL_ALLOWLIST"] = agentengine_model_allowlist
943
- origins = _resolve_env("OPENCLAW_ALLOWED_ORIGINS")
944
- if origins:
945
- env["OPENCLAW_ALLOWED_ORIGINS"] = _normalize_allowed_origins(origins)
946
- else:
947
- # 统一输出 JSON 数组字符串,兼容旧版 bootstrap(仅支持 JSON.parse)。
948
- env["OPENCLAW_ALLOWED_ORIGINS"] = json.dumps(["*"])
949
- allow_insecure_auth = _resolve_env("OPENCLAW_ALLOW_INSECURE_AUTH")
950
- env["OPENCLAW_ALLOW_INSECURE_AUTH"] = allow_insecure_auth if allow_insecure_auth else "true"
951
- disable_device_auth = _resolve_env("OPENCLAW_DISABLE_DEVICE_AUTH")
952
- env["OPENCLAW_DISABLE_DEVICE_AUTH"] = disable_device_auth if disable_device_auth else "true"
953
- if gateway_token:
954
- env["OPENCLAW_GATEWAY_TOKEN"] = gateway_token
955
- if gateway_password:
956
- env["OPENCLAW_GATEWAY_PASSWORD"] = gateway_password
957
- for passthrough_key in [
958
- "OPENCLAW_CHANNEL_BOOTSTRAP_JSON",
959
- "OPENCLAW_BROWSER_SSRF_POLICY_JSON",
960
- "OPENCLAW_WEB_FETCH_ENABLED",
961
- "OPENCLAW_WEB_SEARCH_PROVIDER",
962
- "OPENCLAW_WEB_SEARCH_BASE_URL",
963
- "OPENCLAW_WEB_SEARCH_MODEL",
964
- "OPENCLAW_WEB_SEARCH_API_KEY",
965
- "OPENCLAW_WEB_SEARCH_API_KEY_SECRET_SOURCE",
966
- "OPENCLAW_WEB_SEARCH_API_KEY_SECRET_PROVIDER",
967
- "OPENCLAW_WEB_SEARCH_API_KEY_SECRET_ID",
968
- ]:
969
- passthrough_value = _resolve_env(passthrough_key)
970
- if passthrough_value:
971
- env[passthrough_key] = passthrough_value
972
-
973
- env = _normalize_openclaw_gateway_auth_env(env)
974
- return build_runtime_model_policy_env(env, runtime="openclaw")
975
-
976
-
977
- def _normalize_allowed_origins(raw: str) -> str:
978
- """标准化 OPENCLAW_ALLOWED_ORIGINS,统一输出 JSON 数组字符串。"""
979
- text = (raw or "").strip()
980
- if not text:
981
- return ""
982
-
983
- origins = []
984
- try:
985
- parsed = json.loads(text)
986
- if isinstance(parsed, list):
987
- origins = [str(x).strip() for x in parsed if str(x).strip()]
988
- except Exception:
989
- # Backward compatible: 支持逗号/分号/空白分隔字符串。
990
- parts = [p.strip() for p in text.replace(";", ",").replace(" ", ",").split(",")]
991
- origins = [p.strip() for p in parts if p.strip()]
992
-
993
- if not origins:
994
- origins = [text]
995
-
996
- deduped = list(dict.fromkeys(origins))
997
- return json.dumps(deduped, ensure_ascii=False)
998
-
999
-
1000
- def _normalize_csv_list(raw: str, *, default_items: Optional[list[str]] = None) -> str:
1001
- """标准化字符串列表为逗号分隔格式。"""
1002
- text = (raw or "").strip()
1003
- items: list[str] = []
1004
- if text:
1005
- try:
1006
- parsed = json.loads(text)
1007
- if isinstance(parsed, list):
1008
- items = [str(x).strip() for x in parsed if str(x).strip()]
1009
- except Exception:
1010
- parts = [p.strip() for p in text.replace(";", ",").replace(" ", ",").split(",")]
1011
- items = [p for p in parts if p]
1012
-
1013
- if not items:
1014
- items = [str(x).strip() for x in (default_items or []) if str(x).strip()]
1015
-
1016
- return ",".join(list(dict.fromkeys(items)))
1017
-
1018
-
1019
- def _normalize_openclaw_gateway_auth_env(env: dict[str, str]) -> dict[str, str]:
1020
- """标准化 OpenClaw gateway 鉴权模式与共享密钥配置。"""
1021
- normalized_env = dict(env or {})
1022
- raw_mode = str(normalized_env.get("OPENCLAW_GATEWAY_AUTH_MODE") or "").strip().lower()
1023
- raw_token = str(normalized_env.get("OPENCLAW_GATEWAY_TOKEN") or "").strip()
1024
- raw_password = str(normalized_env.get("OPENCLAW_GATEWAY_PASSWORD") or "").strip()
1025
-
1026
- if raw_mode and raw_mode not in {"trusted-proxy", "token", "none"}:
1027
- raise ValueError("OPENCLAW_GATEWAY_AUTH_MODE 仅支持 trusted-proxy、token 或 none")
1028
-
1029
- auth_mode = raw_mode or ("token" if raw_token or raw_password else "trusted-proxy")
1030
- if auth_mode == "token":
1031
- if raw_token and raw_password and raw_token != raw_password:
1032
- raise ValueError(
1033
- "OPENCLAW_GATEWAY_TOKEN 与 OPENCLAW_GATEWAY_PASSWORD 同时提供时必须一致"
1034
- )
1035
- shared_secret = raw_token or raw_password
1036
- if not shared_secret:
1037
- raise ValueError(
1038
- "OPENCLAW_GATEWAY_AUTH_MODE=token 时必须提供 "
1039
- "OPENCLAW_GATEWAY_TOKEN 或 OPENCLAW_GATEWAY_PASSWORD"
1040
- )
1041
- normalized_env["OPENCLAW_GATEWAY_AUTH_MODE"] = "token"
1042
- normalized_env["OPENCLAW_GATEWAY_TOKEN"] = shared_secret
1043
- normalized_env["OPENCLAW_GATEWAY_PASSWORD"] = shared_secret
1044
- return normalized_env
1045
-
1046
- if raw_token or raw_password:
1047
- raise ValueError(
1048
- "仅在 OPENCLAW_GATEWAY_AUTH_MODE=token 时支持 "
1049
- "OPENCLAW_GATEWAY_TOKEN 或 OPENCLAW_GATEWAY_PASSWORD"
1050
- )
1051
-
1052
- normalized_env["OPENCLAW_GATEWAY_AUTH_MODE"] = auth_mode
1053
- normalized_env.pop("OPENCLAW_GATEWAY_TOKEN", None)
1054
- normalized_env.pop("OPENCLAW_GATEWAY_PASSWORD", None)
1055
- return normalized_env
1056
-
1057
-
1058
624
  def _parse_extra_openclaw_env_pairs(items: tuple[str, ...] | list[str] | None) -> dict[str, str]:
1059
625
  """解析 deploy --env 传入的自定义环境变量,并对 gateway 鉴权模式做早期归一化。"""
1060
626
  parsed = parse_env_pairs(items)
ksadk/cli/cmd_replay.py CHANGED
@@ -17,8 +17,13 @@ import json
17
17
  import click
18
18
 
19
19
  from ksadk.cli.resource_common import CONTEXT_SETTINGS
20
- from ksadk.events.replay import replay_transcript
20
+ from ksadk.events.reducer import StreamReducer
21
21
  from ksadk.events.store import RuntimeEventStore
22
+ from ksadk.events.v1_compat import (
23
+ RuntimeEventV1Parser,
24
+ RuntimeEventV1ProjectionContext,
25
+ project_to_v1,
26
+ )
22
27
 
23
28
  _HELP = dict(help_option_names=["-h", "--help"])
24
29
 
@@ -43,9 +48,28 @@ async def _run(session_id: str, *, after_seq_id: int, before_seq_id: int | None,
43
48
  from ksadk.sessions import resolve_session_service
44
49
 
45
50
  store = RuntimeEventStore(resolve_session_service())
46
- parser = await replay_transcript(
47
- store, session_id, after_seq_id=after_seq_id, before_seq_id=before_seq_id
48
- )
51
+ service = resolve_session_service()
52
+ session = await service.get_session(session_id)
53
+ events = await store.list(session_id)
54
+ parser = RuntimeEventV1Parser()
55
+ reducers: dict[str, StreamReducer] = {}
56
+ for event in events:
57
+ reducer = reducers.get(event.run_id)
58
+ if reducer is not None and reducer.snapshot().status in {"completed", "failed", "canceled"}:
59
+ reducer = None
60
+ if reducer is None:
61
+ reducer = StreamReducer()
62
+ reducers[event.run_id] = reducer
63
+ reducer.apply(event)
64
+ projection = reducer.snapshot()
65
+ context = RuntimeEventV1ProjectionContext(
66
+ agent_id=session.agent_id if session else "",
67
+ user_id=session.user_id if session else "",
68
+ session_id=session_id,
69
+ projection=projection,
70
+ )
71
+ for v1_event in project_to_v1(event, mode="identity_replace", context=context):
72
+ parser.feed(v1_event)
49
73
  transcript = parser.transcript()
50
74
  if fmt == "json":
51
75
  click.echo(json.dumps(transcript, ensure_ascii=False, sort_keys=True))
ksadk/cli/cmd_studio.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import logging
5
6
  import os
6
7
  import secrets
7
8
  import webbrowser
@@ -12,14 +13,67 @@ import uvicorn
12
13
 
13
14
  from ksadk.cli.env_options import load_env_file
14
15
  from ksadk.cli.ui import print_info, print_kv, print_success, print_title
16
+
17
+ # veadk 风格:日志行带模块名与行号(filename:lineno),本地排障时能直接定位代码。
18
+ _LOG_FORMAT = "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)d %(message)s"
19
+
20
+ _STUDIO_LOG_CONFIG = {
21
+ "version": 1,
22
+ "disable_existing_loggers": False,
23
+ "formatters": {
24
+ "default": {"format": _LOG_FORMAT},
25
+ "access": {"format": _LOG_FORMAT},
26
+ },
27
+ "handlers": {
28
+ "default": {
29
+ "class": "logging.StreamHandler",
30
+ "formatter": "default",
31
+ "stream": "ext://sys.stderr",
32
+ },
33
+ "access": {
34
+ "class": "logging.StreamHandler",
35
+ "formatter": "access",
36
+ "stream": "ext://sys.stdout",
37
+ },
38
+ },
39
+ "loggers": {
40
+ "uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
41
+ "uvicorn.error": {"level": "INFO"},
42
+ "uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
43
+ },
44
+ "root": {"handlers": ["default"], "level": "INFO"},
45
+ }
46
+
15
47
  from ksadk.studio.api import create_studio_app
16
48
  from ksadk.studio.service import StudioService
17
49
 
50
+ # 模型环境变量白名单。OPENAI_BASE_URL 与 OPENAI_API_BASE 互为别名,两者都接受;
51
+ # 加载时做别名归一(见 studio()),运行时统一 OPENAI_BASE_URL 优先(与 cmd_config/cmd_model
52
+ # /api.py 一致,方案 §2.4 第 5 点)。
18
53
  _MODEL_ENV_KEYS = (
54
+ "OPENAI_BASE_URL",
19
55
  "OPENAI_API_BASE",
20
56
  "OPENAI_API_KEY",
21
57
  "OPENAI_MODEL_NAME",
22
58
  )
59
+ # Cloud-control credentials are intentionally process-only as well. Studio
60
+ # needs them to use the Server Action API for a deployed Agent, but they must
61
+ # never become browser settings, workspace files, or runtime environment.
62
+ _CLOUD_CONTROL_ENV_KEYS = (
63
+ "KSYUN_ACCESS_KEY",
64
+ "KSYUN_SECRET_KEY",
65
+ "KSYUN_REGION",
66
+ "AGENTENGINE_REGION",
67
+ "AGENTENGINE_SERVER_URL",
68
+ "AGENTENGINE_STREAM_SERVER_URL",
69
+ "AGENTENGINE_SIGN_SERVICE",
70
+ "KS3_BUCKET",
71
+ "KS3_ACCESS_KEY",
72
+ "KS3_SECRET_KEY",
73
+ )
74
+ _STUDIO_ENV_FILE_KEYS = (*_MODEL_ENV_KEYS, *_CLOUD_CONTROL_ENV_KEYS)
75
+ # 别名归一:两者任一有值时,把另一个也设上,保证下游无论读哪个都命中。
76
+ _MODEL_BASE_URL_ALIASES = ("OPENAI_BASE_URL", "OPENAI_API_BASE")
23
77
 
24
78
 
25
79
  @click.command(context_settings=dict(help_option_names=["-h", "--help"]))
@@ -29,7 +83,10 @@ _MODEL_ENV_KEYS = (
29
83
  @click.option(
30
84
  "--env-file",
31
85
  type=click.Path(exists=True, dir_okay=False),
32
- help="模型环境文件;只读取 OPENAI_API_BASE/API_KEY/MODEL_NAME",
86
+ help=(
87
+ "本地模型与云端控制环境文件;只读取允许的 OPENAI/KSYUN/KS3 "
88
+ "字段,且仅保留在 Studio 进程"
89
+ ),
33
90
  )
34
91
  @click.option(
35
92
  "--codex-proxy",
@@ -52,7 +109,7 @@ def studio(
52
109
  """
53
110
 
54
111
  root = Path(workspace).expanduser().resolve()
55
- managed_keys = (*_MODEL_ENV_KEYS, "KSADK_CODEX_USE_PROXY")
112
+ managed_keys = (*_STUDIO_ENV_FILE_KEYS, "KSADK_CODEX_USE_PROXY")
56
113
  previous = {key: os.environ.get(key) for key in managed_keys}
57
114
  previously_present = {key for key in managed_keys if key in os.environ}
58
115
  try:
@@ -61,14 +118,42 @@ def studio(
61
118
  values = load_env_file(env_file)
62
119
  except ValueError as exc:
63
120
  raise click.ClickException(str(exc)) from exc
64
- loaded = 0
121
+ loaded_models = 0
122
+ loaded_cloud_control = 0
65
123
  for key, value in values.items():
66
- if key not in _MODEL_ENV_KEYS or not value:
124
+ if key not in _STUDIO_ENV_FILE_KEYS or not value:
67
125
  continue
68
- loaded += 1
69
- if key not in os.environ:
126
+ if key in _MODEL_ENV_KEYS:
127
+ loaded_models += 1
128
+ else:
129
+ loaded_cloud_control += 1
130
+ # An explicit --env-file is the operator's selected cloud
131
+ # identity. Do not silently reuse inherited AK/SK from the
132
+ # shell, which can point Studio at another tenant. Model
133
+ # values keep their historical shell-first precedence.
134
+ if key in _CLOUD_CONTROL_ENV_KEYS or key not in os.environ:
70
135
  os.environ[key] = value
71
- print_kv("模型环境", f"已安全加载 {loaded}/{len(_MODEL_ENV_KEYS)} 个字段")
136
+ # 别名归一(方案 §2.4 第 5 点):OPENAI_BASE_URL 与 OPENAI_API_BASE 互为别名。
137
+ # 加载后任一有值则把另一个也设上,保证下游无论读哪个都命中;OPENAI_BASE_URL 优先。
138
+ resolved_base_url = os.environ.get("OPENAI_BASE_URL") or os.environ.get(
139
+ "OPENAI_API_BASE"
140
+ )
141
+ if resolved_base_url:
142
+ os.environ["OPENAI_BASE_URL"] = resolved_base_url
143
+ os.environ["OPENAI_API_BASE"] = resolved_base_url
144
+ # base_url 至少算一次,避免显示 0/4 误导。
145
+ loaded_models = max(loaded_models, 2)
146
+ print_kv(
147
+ "模型环境",
148
+ f"已安全加载 {loaded_models}/{len(_MODEL_ENV_KEYS)} 个字段",
149
+ )
150
+ if loaded_cloud_control:
151
+ print_kv(
152
+ "云端控制",
153
+ "已安全加载 "
154
+ f"{loaded_cloud_control}/{len(_CLOUD_CONTROL_ENV_KEYS)} 个字段"
155
+ "(仅本地进程)",
156
+ )
72
157
  if codex_proxy == "forced":
73
158
  os.environ["KSADK_CODEX_USE_PROXY"] = "1"
74
159
  elif codex_proxy == "direct":
@@ -95,12 +180,18 @@ def studio(
95
180
  print_info("按 Ctrl+C 停止")
96
181
  if not no_open:
97
182
  webbrowser.open(launch_url)
183
+ # 业务日志(ksadk.*)走 root handler,同样带 filename:lineno。
184
+ logging.basicConfig(level=logging.INFO, format=_LOG_FORMAT)
98
185
  uvicorn.run(
99
186
  app,
100
187
  host="127.0.0.1",
101
188
  port=port,
102
189
  log_level="info",
103
- access_log=False,
190
+ # Access logging stays enabled through the Studio log config while
191
+ # retaining filename/line-number context for both API and business
192
+ # logs. This preserves master's observability intent and the
193
+ # branch's richer diagnostic format.
194
+ log_config=_STUDIO_LOG_CONFIG,
104
195
  )
105
196
  finally:
106
197
  for key in managed_keys: