agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.1__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 (450) hide show
  1. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/METADATA +52 -20
  2. agentengine_sdk_python-0.8.1.dist-info/RECORD +644 -0
  3. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +180 -11
  5. ksadk/a2a/bootstrap.py +332 -0
  6. ksadk/a2a/card.py +15 -0
  7. ksadk/a2a/context_store.py +203 -0
  8. ksadk/a2a/control_plane.py +1056 -0
  9. ksadk/a2a/credential.py +99 -0
  10. ksadk/a2a/event_adapter.py +149 -0
  11. ksadk/a2a/executor.py +361 -137
  12. ksadk/a2a/external_transport.py +516 -0
  13. ksadk/a2a/identity.py +304 -0
  14. ksadk/a2a/ids.py +22 -0
  15. ksadk/a2a/langgraph.py +285 -0
  16. ksadk/a2a/resume_store.py +201 -0
  17. ksadk/a2a/routes.py +112 -0
  18. ksadk/a2a/server.py +102 -62
  19. ksadk/a2a/service_env.py +33 -0
  20. ksadk/a2a/space_client.py +1122 -0
  21. ksadk/a2a/task_adapter.py +423 -0
  22. ksadk/a2a/task_event_dispatcher.py +167 -0
  23. ksadk/a2a/task_event_outbox.py +326 -0
  24. ksadk/a2a/task_store.py +206 -0
  25. ksadk/a2a_card.py +101 -0
  26. ksadk/a2ui/__init__.py +27 -0
  27. ksadk/a2ui/core.py +186 -0
  28. ksadk/a2ui/models.py +166 -0
  29. ksadk/a2ui/renderer.py +198 -0
  30. ksadk/agui/__init__.py +9 -0
  31. ksadk/agui/a2ui_projection.py +92 -0
  32. ksadk/agui/agent.py +872 -0
  33. ksadk/agui/config.py +92 -0
  34. ksadk/agui/routes.py +47 -0
  35. ksadk/api/client.py +238 -204
  36. ksadk/api/environment.py +27 -0
  37. ksadk/builders/__init__.py +2 -0
  38. ksadk/builders/base.py +16 -14
  39. ksadk/builders/code_builder.py +375 -270
  40. ksadk/builders/container_builder.py +240 -200
  41. ksadk/builders/framework_requirements.py +31 -12
  42. ksadk/builders/ks3_uploader.py +60 -29
  43. ksadk/builders/managed_runtime_builder.py +173 -0
  44. ksadk/builders/mcp_builder.py +91 -92
  45. ksadk/builders/requirements_utils.py +1 -5
  46. ksadk/cli/__init__.py +97 -171
  47. ksadk/cli/cmd_a2a.py +255 -84
  48. ksadk/cli/cmd_agent.py +19 -5
  49. ksadk/cli/cmd_build.py +158 -29
  50. ksadk/cli/cmd_completion.py +47 -35
  51. ksadk/cli/cmd_config.py +267 -198
  52. ksadk/cli/cmd_create.py +507 -740
  53. ksadk/cli/cmd_dashboard.py +120 -45
  54. ksadk/cli/cmd_deploy.py +135 -59
  55. ksadk/cli/cmd_destroy.py +44 -14
  56. ksadk/cli/cmd_eval.py +386 -0
  57. ksadk/cli/cmd_files.py +63 -24
  58. ksadk/cli/cmd_hermes.py +313 -135
  59. ksadk/cli/cmd_invoke.py +184 -122
  60. ksadk/cli/cmd_launch.py +76 -28
  61. ksadk/cli/cmd_mcp.py +98 -64
  62. ksadk/cli/cmd_model.py +14 -5
  63. ksadk/cli/cmd_openclaw.py +564 -268
  64. ksadk/cli/cmd_replay.py +71 -0
  65. ksadk/cli/cmd_run.py +58 -73
  66. ksadk/cli/cmd_status.py +80 -31
  67. ksadk/cli/cmd_studio.py +110 -0
  68. ksadk/cli/cmd_version.py +20 -13
  69. ksadk/cli/cmd_web.py +95 -18
  70. ksadk/cli/deploy_utils.py +20 -20
  71. ksadk/cli/dry_run.py +7 -4
  72. ksadk/cli/env_options.py +83 -0
  73. ksadk/cli/error_utils.py +37 -12
  74. ksadk/cli/global_options.py +4 -3
  75. ksadk/cli/local_runtime.py +1 -2
  76. ksadk/cli/model_catalog.py +6 -2
  77. ksadk/cli/network_options.py +41 -19
  78. ksadk/cli/resource_common.py +6 -2
  79. ksadk/cli/runtime_bootstrap.py +51 -0
  80. ksadk/cli/storage.py +0 -1
  81. ksadk/cli/ui.py +11 -3
  82. ksadk/cli/workflow_common.py +52 -18
  83. ksadk/codex/__init__.py +12 -0
  84. ksadk/codex/client.py +1042 -0
  85. ksadk/codex/phase.py +143 -0
  86. ksadk/codex/runtime.py +940 -0
  87. ksadk/common/aicp_env.py +0 -1
  88. ksadk/common/auth.py +2 -2
  89. ksadk/common/constants.py +1 -3
  90. ksadk/common/kop_client.py +232 -0
  91. ksadk/common/llm_utils.py +17 -13
  92. ksadk/compat/__init__.py +5 -0
  93. ksadk/compat/adk_compat.py +200 -0
  94. ksadk/compat/copilotkit_a2ui.py +330 -0
  95. ksadk/configs/__init__.py +12 -14
  96. ksadk/configs/env_registry.py +661 -116
  97. ksadk/configs/global_config.py +3 -2
  98. ksadk/configs/settings.py +133 -209
  99. ksadk/conversations/__init__.py +85 -92
  100. ksadk/conversations/attachment_storage.py +16 -11
  101. ksadk/conversations/attachments.py +44 -36
  102. ksadk/conversations/compaction_pipeline.py +12 -12
  103. ksadk/conversations/compaction_prompt.py +9 -5
  104. ksadk/conversations/context.py +221 -6
  105. ksadk/conversations/message_projection.py +438 -51
  106. ksadk/conversations/model_context.py +12 -6
  107. ksadk/conversations/model_options.py +0 -1
  108. ksadk/conversations/normalize.py +20 -16
  109. ksadk/conversations/reasoning_markup.py +1 -1
  110. ksadk/conversations/runtime.py +339 -5255
  111. ksadk/conversations/runtime_compaction.py +333 -0
  112. ksadk/conversations/runtime_constants.py +27 -0
  113. ksadk/conversations/runtime_governance.py +185 -0
  114. ksadk/conversations/runtime_input.py +660 -0
  115. ksadk/conversations/runtime_invocation.py +395 -0
  116. ksadk/conversations/runtime_metadata.py +475 -0
  117. ksadk/conversations/runtime_observability.py +367 -0
  118. ksadk/conversations/runtime_payloads.py +272 -0
  119. ksadk/conversations/runtime_persistence.py +440 -0
  120. ksadk/conversations/runtime_preparation.py +426 -0
  121. ksadk/conversations/runtime_resume.py +836 -0
  122. ksadk/conversations/runtime_stream_events.py +902 -0
  123. ksadk/conversations/runtime_streaming.py +700 -0
  124. ksadk/conversations/semantic_summary.py +17 -5
  125. ksadk/conversations/session_title.py +6 -3
  126. ksadk/deployment/__init__.py +15 -16
  127. ksadk/deployment/agent_access.py +12 -23
  128. ksadk/deployment/base.py +51 -38
  129. ksadk/deployment/managed_runtime.py +33 -0
  130. ksadk/deployment/manager.py +85 -71
  131. ksadk/deployment/providers/serverless.py +379 -210
  132. ksadk/deployment/registry.py +38 -32
  133. ksadk/deployment/state.py +11 -11
  134. ksadk/deployment/ui_config.py +1 -1
  135. ksadk/detection/__init__.py +1 -1
  136. ksadk/detection/detector.py +146 -83
  137. ksadk/detection/mcp_detector.py +9 -6
  138. ksadk/evaluation/__init__.py +84 -0
  139. ksadk/evaluation/a2a_adapter.py +444 -0
  140. ksadk/evaluation/adapters.py +54 -0
  141. ksadk/evaluation/contracts.py +409 -0
  142. ksadk/evaluation/evalset.py +351 -0
  143. ksadk/evaluation/evaluators.py +461 -0
  144. ksadk/evaluation/executor.py +118 -0
  145. ksadk/evaluation/storage.py +68 -0
  146. ksadk/evaluation/target.py +73 -0
  147. ksadk/events/__init__.py +25 -0
  148. ksadk/events/parser.py +191 -0
  149. ksadk/events/replay.py +37 -0
  150. ksadk/events/runtime_event.py +273 -0
  151. ksadk/events/store.py +317 -0
  152. ksadk/harness/__init__.py +35 -0
  153. ksadk/harness/app.py +269 -0
  154. ksadk/harness/config.py +181 -0
  155. ksadk/harness/reasoner.py +105 -0
  156. ksadk/harness/runtime.py +364 -0
  157. ksadk/harness/sandbox.py +141 -0
  158. ksadk/harness/tools.py +222 -0
  159. ksadk/hermes_terminal.py +28 -12
  160. ksadk/identity/resolver.py +15 -9
  161. ksadk/ids.py +32 -0
  162. ksadk/knowledge_base/adk_tool.py +1 -1
  163. ksadk/knowledge_base/client.py +38 -33
  164. ksadk/managed_a2a_card.py +160 -0
  165. ksadk/managed_runtime.py +195 -0
  166. ksadk/markdown.py +5 -2
  167. ksadk/mcp_runtime/__init__.py +9 -6
  168. ksadk/memory/__init__.py +1 -1
  169. ksadk/memory/adk/__init__.py +2 -0
  170. ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
  171. ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
  172. ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
  173. ksadk/memory/adk/backends/sdk_ltm_backend.py +36 -36
  174. ksadk/memory/adk/long_term_memory.py +34 -37
  175. ksadk/memory/adk/resilient_session_service.py +4 -5
  176. ksadk/memory/adk/short_term_memory.py +12 -21
  177. ksadk/memory/adk_tool.py +3 -2
  178. ksadk/memory/backends/base.py +19 -19
  179. ksadk/memory/backends/memory.py +24 -25
  180. ksadk/memory/backends/redis.py +31 -30
  181. ksadk/memory/langchain_tool.py +2 -1
  182. ksadk/memory/manager.py +52 -47
  183. ksadk/memory/service.py +16 -6
  184. ksadk/memory/tool.py +4 -0
  185. ksadk/model_policy.py +15 -7
  186. ksadk/model_proxy/__init__.py +51 -0
  187. ksadk/model_proxy/bootstrap.py +80 -0
  188. ksadk/model_proxy/cache.py +165 -0
  189. ksadk/model_proxy/config.py +66 -0
  190. ksadk/model_proxy/demo_webui.py +115 -0
  191. ksadk/model_proxy/detect.py +145 -0
  192. ksadk/model_proxy/gate.py +68 -0
  193. ksadk/model_proxy/namespace.py +201 -0
  194. ksadk/model_proxy/protocol_proxy.py +22 -0
  195. ksadk/model_proxy/server.py +443 -0
  196. ksadk/model_proxy/transform.py +735 -0
  197. ksadk/openclaw_gateway.py +29 -14
  198. ksadk/runners/adk_runner.py +354 -146
  199. ksadk/runners/base_runner.py +71 -29
  200. ksadk/runners/deepagents_runner.py +0 -1
  201. ksadk/runners/factory.py +18 -5
  202. ksadk/runners/langchain_runner.py +29 -742
  203. ksadk/runners/langgraph_runner.py +417 -97
  204. ksadk/runners/patch_langchain.py +16 -16
  205. ksadk/runners/remote_runner.py +134 -33
  206. ksadk/runners/usage_accumulator.py +1 -0
  207. ksadk/runners/utils/__init__.py +0 -10
  208. ksadk/runners/utils/loader.py +23 -7
  209. ksadk/runtime/__init__.py +67 -0
  210. ksadk/runtime/adapter.py +412 -0
  211. ksadk/runtime/conversation_execution.py +553 -0
  212. ksadk/runtime/executor.py +251 -0
  213. ksadk/runtime/factory.py +156 -0
  214. ksadk/runtime/framework_adapters.py +118 -0
  215. ksadk/runtime/launch.py +48 -0
  216. ksadk/runtime/preprocessing.py +131 -0
  217. ksadk/runtime/runner_adapter.py +1032 -0
  218. ksadk/runtime/runner_loading.py +36 -0
  219. ksadk/runtime_context.py +18 -3
  220. ksadk/runtime_state.py +0 -1
  221. ksadk/sandbox/__init__.py +4 -1
  222. ksadk/sandbox/backends/__init__.py +4 -1
  223. ksadk/sandbox/backends/e2b.py +13 -5
  224. ksadk/sandbox/backends/local_process.py +11 -3
  225. ksadk/sandbox/base.py +10 -15
  226. ksadk/sandbox/factory.py +14 -4
  227. ksadk/sandbox/registry.py +57 -6
  228. ksadk/server/__init__.py +39 -4
  229. ksadk/server/api_models.py +15 -5
  230. ksadk/server/app.py +24 -3928
  231. ksadk/server/composition.py +47 -0
  232. ksadk/server/factory.py +622 -0
  233. ksadk/server/routes/__init__.py +1 -0
  234. ksadk/server/routes/checkpoint_resolution.py +116 -0
  235. ksadk/server/routes/common.py +682 -0
  236. ksadk/server/routes/control.py +331 -0
  237. ksadk/server/routes/dependencies.py +98 -0
  238. ksadk/server/routes/misc.py +425 -0
  239. ksadk/server/routes/models.py +451 -0
  240. ksadk/server/routes/openai_compat.py +229 -0
  241. ksadk/server/routes/projection.py +848 -0
  242. ksadk/server/routes/routers.py +52 -0
  243. ksadk/server/routes/run.py +519 -0
  244. ksadk/server/routes/sessions.py +644 -0
  245. ksadk/server/routes/streaming.py +265 -0
  246. ksadk/server/routes/workspace.py +414 -0
  247. ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-CakCqxEN.js} +1 -1
  248. ksadk/server/static/assets/CodeBlock-CynLknyO.js +9 -0
  249. ksadk/server/static/assets/MathMessageMarkdown-3sQdOysS.js +8 -0
  250. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +303 -0
  251. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +1 -0
  252. ksadk/server/static/assets/{arc-BA13sHc9.js → arc-DrgjcKhl.js} +1 -1
  253. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +1 -0
  254. ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-BXoVRbQ6.js} +1 -1
  255. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-BnaB3Ywv.js} +1 -1
  256. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-Dw4weZcp.js} +1 -1
  257. ksadk/server/static/assets/channel-Dt3rQTFI.js +1 -0
  258. ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-ChjpLK7j.js} +1 -1
  259. ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-B9drTgOW.js} +1 -1
  260. ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-CK4ROATy.js} +1 -1
  261. ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B9KtTTgw.js} +1 -1
  262. ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-1O1mki3m.js} +1 -1
  263. ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-B_fH2YuH.js} +1 -1
  264. ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D6rFLaVV.js} +1 -1
  265. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +1 -0
  266. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +1 -0
  267. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +1 -0
  268. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-ChNs_Mdk.js} +1 -1
  269. ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-D0QXg_MQ.js} +1 -1
  270. ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-DBDDKwBQ.js} +1 -1
  271. ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-BkwDOxmO.js} +1 -1
  272. ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Bv8waYvY.js} +1 -1
  273. ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-e1VECDdu.js} +1 -1
  274. ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-Ds9adfRl.js} +1 -1
  275. ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-4N2NMVYg.js} +1 -1
  276. ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-B-jNR6Vn.js} +1 -1
  277. ksadk/server/static/assets/{dist-D57wnGWd.js → dist-B5J2uhNk.js} +1 -1
  278. ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-B5oS1zcj.js} +1 -1
  279. ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BB3-OwTQ.js} +1 -1
  280. ksadk/server/static/assets/{dist-2hInLS_J.js → dist-BIlKoW0k.js} +1 -1
  281. ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-BjOdlDjj.js} +1 -1
  282. ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-C1sz5Eo3.js} +1 -1
  283. ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-CWV4lDr1.js} +1 -1
  284. ksadk/server/static/assets/{dist-D-xOD048.js → dist-CmZHzlwZ.js} +1 -1
  285. ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-D6MpCZtz.js} +1 -1
  286. ksadk/server/static/assets/{dist-DyOkZmze.js → dist-DJN_6Y39.js} +1 -1
  287. ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-DQU9EWw-.js} +1 -1
  288. ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-DWKByxWV.js} +1 -1
  289. ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-Dli7qW-B.js} +1 -1
  290. ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-DsHPdk3W.js} +1 -1
  291. ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-X4TnqwOK.js} +1 -1
  292. ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-_pHPTyZ-.js} +1 -1
  293. ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-fhOuWds5.js} +1 -1
  294. ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-gLnrGsoU.js} +1 -1
  295. ksadk/server/static/assets/{dist-BssVmjIo.js → dist-j6Dxmf_j.js} +1 -1
  296. ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-o2OVmKvt.js} +1 -1
  297. ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-BPItFKH6.js} +1 -1
  298. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +1 -0
  299. ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-BbYB9w5Y.js} +1 -1
  300. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-TQXa0KXv.js} +1 -1
  301. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +1 -0
  302. ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-bKblCnpa.js} +1 -1
  303. ksadk/server/static/assets/index-R52pJJvg.js +177 -0
  304. ksadk/server/static/assets/index-jJr3_955.css +2 -0
  305. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +1 -0
  306. ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-BGVT7J_i.js} +1 -1
  307. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-K0OOfVna.js} +1 -1
  308. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-8LeOJaZp.js} +1 -1
  309. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-C6uCgZrW.js} +1 -1
  310. ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-CYWseY5E.js} +1 -1
  311. ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-hdBcYzM8.js} +1 -1
  312. ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-BWrDjSZM.js} +2 -2
  313. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-Bjy_2v4_.js} +1 -1
  314. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +1 -0
  315. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +1 -0
  316. ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-GmmqNiVH.js} +1 -1
  317. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-BmkRbwCg.js} +1 -1
  318. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +1 -0
  319. ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DSWFqL7c.js} +1 -1
  320. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-l6iXmU65.js} +1 -1
  321. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-Cq6UBeQB.js} +1 -1
  322. ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-qzTQpg3Y.js} +1 -1
  323. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +1 -0
  324. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-DEz24vV0.js} +1 -1
  325. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +1 -0
  326. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +1 -0
  327. ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-CMCixki2.js} +1 -1
  328. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +1 -0
  329. ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-CVzB8F9K.js} +1 -1
  330. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-BFBqBLc1.js} +1 -1
  331. ksadk/server/static/index.html +2 -2
  332. ksadk/server/terminal_sessions.py +111 -58
  333. ksadk/sessions/__init__.py +69 -19
  334. ksadk/sessions/base.py +31 -11
  335. ksadk/sessions/continuity.py +2 -3
  336. ksadk/sessions/in_memory.py +46 -2
  337. ksadk/sessions/local_service.py +148 -17
  338. ksadk/sessions/postgres_service.py +143 -25
  339. ksadk/sessions/resilient.py +36 -8
  340. ksadk/skills/models.py +17 -5
  341. ksadk/skills/package_store.py +5 -2
  342. ksadk/skills/runtime/agent.py +20 -5
  343. ksadk/skills/runtime/artifacts.py +1 -5
  344. ksadk/skills/runtime/backends/e2b.py +10 -4
  345. ksadk/skills/runtime/backends/local.py +15 -3
  346. ksadk/skills/runtime/base.py +1 -2
  347. ksadk/skills/runtime/executor.py +10 -3
  348. ksadk/skills/runtime/factory.py +4 -2
  349. ksadk/skills/runtime/loader.py +1 -2
  350. ksadk/skills/runtime/registry.py +15 -10
  351. ksadk/skills/runtime/request.py +3 -1
  352. ksadk/skills/service_client.py +47 -16
  353. ksadk/skills/tool_defs.py +15 -10
  354. ksadk/studio/__init__.py +5 -0
  355. ksadk/studio/agent_avatar_assets.py +120 -0
  356. ksadk/studio/agent_lifecycle.py +51 -0
  357. ksadk/studio/api.py +1046 -0
  358. ksadk/studio/api_catalog_routes.py +324 -0
  359. ksadk/studio/api_contracts.py +177 -0
  360. ksadk/studio/api_helpers.py +132 -0
  361. ksadk/studio/authoring.py +524 -0
  362. ksadk/studio/authoring_coordinator.py +285 -0
  363. ksadk/studio/builder.py +320 -0
  364. ksadk/studio/capabilities.py +351 -0
  365. ksadk/studio/cloud.py +278 -0
  366. ksadk/studio/codex_agent_service.py +583 -0
  367. ksadk/studio/codex_builder.py +324 -0
  368. ksadk/studio/codex_manifest.py +278 -0
  369. ksadk/studio/codex_run.py +352 -0
  370. ksadk/studio/compiler.py +189 -0
  371. ksadk/studio/contracts.py +644 -0
  372. ksadk/studio/errors.py +47 -0
  373. ksadk/studio/evaluation.py +192 -0
  374. ksadk/studio/event_store.py +284 -0
  375. ksadk/studio/framework_run.py +114 -0
  376. ksadk/studio/identifiers.py +33 -0
  377. ksadk/studio/mcp_runtime.py +229 -0
  378. ksadk/studio/model_client.py +543 -0
  379. ksadk/studio/model_profile_service.py +214 -0
  380. ksadk/studio/operations.py +243 -0
  381. ksadk/studio/otel_trace.py +754 -0
  382. ksadk/studio/pagination.py +182 -0
  383. ksadk/studio/python_tool_inspection.py +183 -0
  384. ksadk/studio/repository.py +306 -0
  385. ksadk/studio/resource_catalog.py +1217 -0
  386. ksadk/studio/run_service.py +707 -0
  387. ksadk/studio/runtime_catalog.py +74 -0
  388. ksadk/studio/runtime_source.py +339 -0
  389. ksadk/studio/service.py +1141 -0
  390. ksadk/studio/shared_web.py +994 -0
  391. ksadk/studio/skill_discovery.py +628 -0
  392. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  393. ksadk/studio/static/assets/index-CaEN0eTR.css +1 -0
  394. ksadk/studio/static/assets/index-DI2eY_NH.js +252 -0
  395. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  396. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  397. ksadk/studio/static/index.html +15 -0
  398. ksadk/studio/templates.py +630 -0
  399. ksadk/studio/validator.py +246 -0
  400. ksadk/studio/workspace.py +137 -0
  401. ksadk/terminal_exec_policy.py +3 -4
  402. ksadk/tools/gateway.py +101 -15
  403. ksadk/tools/result_budget.py +12 -4
  404. ksadk/toolsets/__init__.py +161 -37
  405. ksadk/toolsets/a2a.py +426 -0
  406. ksadk/toolsets/platform.py +21 -5
  407. ksadk/toolsets/sandbox.py +82 -16
  408. ksadk/toolsets/skills.py +200 -39
  409. ksadk/toolsets/web.py +123 -26
  410. ksadk/toolsets/workspace.py +212 -101
  411. ksadk/tracing/__init__.py +19 -21
  412. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  413. ksadk/tracing/setup.py +135 -506
  414. ksadk/tracing/span_utils.py +0 -41
  415. ksadk/tui/loop.py +78 -30
  416. ksadk/tui/stream_render.py +1 -0
  417. ksadk/ui_config.py +5 -3
  418. ksadk/version.py +1 -1
  419. ksadk_runtime_common/memory_backend/registry.py +56 -56
  420. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  421. ksadk_runtime_common/workspace_files/router.py +8 -2
  422. agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
  423. ksadk/a2a/card_builder.py +0 -64
  424. ksadk/a2a/client.py +0 -309
  425. ksadk/runners/utils/langfuse.py +0 -230
  426. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
  427. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
  428. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
  429. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
  430. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
  431. ksadk/server/static/assets/channel-CTuydARX.js +0 -1
  432. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
  433. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
  434. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
  435. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
  436. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
  437. ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
  438. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  439. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
  440. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
  441. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
  442. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
  443. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
  444. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
  445. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
  446. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
  447. ksadk/tracing/exporters/langfuse_exporter.py +0 -445
  448. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/entry_points.txt +0 -0
  449. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/licenses/LICENSE +0 -0
  450. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,141 @@
1
+ """Invocation-owned execution policy for Harness sandbox tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import os
7
+ import shlex
8
+ import subprocess
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+
13
+ class SandboxPolicyDenied(PermissionError):
14
+ """Raised before execution when a Harness sandbox action violates policy."""
15
+
16
+
17
+ _READ_COMMANDS = frozenset({"cat", "head", "ls", "pwd", "stat", "tail", "wc"})
18
+ _NO_PATH_COMMANDS = frozenset({"pwd"})
19
+ _REQUIRE_PATH_COMMANDS = frozenset({"cat", "head", "stat", "tail", "wc"})
20
+ _VALUE_OPTIONS = frozenset({"-n", "--bytes", "--lines", "--max-unchanged-stats"})
21
+ _SHELL_OPERATORS = frozenset({"|", "||", "&", "&&", ";", ">", ">>", "<", "<<"})
22
+
23
+
24
+ class HarnessSandboxExecutor:
25
+ """Run a deliberately small read-only command surface inside one workspace.
26
+
27
+ Commands are executed without a shell. Path operands are resolved before the
28
+ child process starts, including symlinks, so reads cannot escape the configured
29
+ workspace. The narrow command surface also excludes network clients and process
30
+ launchers entirely.
31
+ """
32
+
33
+ def __init__(self, *, workspace_root: str | Path, read_only: bool = True) -> None:
34
+ self._workspace_root = Path(workspace_root).expanduser().resolve()
35
+ self._workspace_root.mkdir(parents=True, exist_ok=True)
36
+ self._read_only = read_only
37
+
38
+ @property
39
+ def workspace_root(self) -> Path:
40
+ return self._workspace_root
41
+
42
+ @property
43
+ def read_only(self) -> bool:
44
+ return self._read_only
45
+
46
+ async def read_file(self, path: str) -> dict[str, Any]:
47
+ target = self._resolve_path(path)
48
+ content = await asyncio.to_thread(target.read_text, encoding="utf-8")
49
+ return {
50
+ "ok": True,
51
+ "path": target.relative_to(self._workspace_root).as_posix(),
52
+ "content": content,
53
+ "policy": "read-only",
54
+ }
55
+
56
+ async def run_command(self, command: str) -> dict[str, Any]:
57
+ argv = self._validate_command(command)
58
+ completed = await asyncio.to_thread(
59
+ subprocess.run,
60
+ argv,
61
+ cwd=self._workspace_root,
62
+ env={"PATH": os.environ.get("PATH", "")},
63
+ capture_output=True,
64
+ text=True,
65
+ timeout=10,
66
+ check=False,
67
+ )
68
+ return {
69
+ "ok": completed.returncode == 0,
70
+ "command": " ".join(argv),
71
+ "stdout": completed.stdout,
72
+ "stderr": completed.stderr,
73
+ "exit_code": completed.returncode,
74
+ "policy": "read-only",
75
+ }
76
+
77
+ def _validate_command(self, command: str) -> list[str]:
78
+ try:
79
+ argv = shlex.split(str(command or ""), posix=True)
80
+ except ValueError as exc:
81
+ raise SandboxPolicyDenied(f"read-only sandbox denied malformed command: {exc}") from exc
82
+ if not argv:
83
+ raise SandboxPolicyDenied("read-only sandbox denied empty command")
84
+ if any(argument in _SHELL_OPERATORS for argument in argv):
85
+ raise SandboxPolicyDenied(
86
+ "read-only sandbox denied shell redirection, pipelines, or command chaining"
87
+ )
88
+ executable = argv[0]
89
+ if executable not in _READ_COMMANDS:
90
+ raise SandboxPolicyDenied(
91
+ f"read-only sandbox denied command {executable!r}; network, write, and "
92
+ "dangerous process actions are not allowed"
93
+ )
94
+ if executable in _NO_PATH_COMMANDS:
95
+ if len(argv) != 1:
96
+ raise SandboxPolicyDenied(
97
+ f"read-only sandbox denied arguments for command {executable!r}"
98
+ )
99
+ return argv
100
+
101
+ normalized = [executable]
102
+ skip_option_value = False
103
+ saw_path = False
104
+ for argument in argv[1:]:
105
+ if skip_option_value:
106
+ normalized.append(argument)
107
+ skip_option_value = False
108
+ continue
109
+ if argument == "--":
110
+ normalized.append(argument)
111
+ continue
112
+ if argument in _VALUE_OPTIONS:
113
+ normalized.append(argument)
114
+ skip_option_value = True
115
+ continue
116
+ if argument.startswith("-"):
117
+ normalized.append(argument)
118
+ continue
119
+ target = self._resolve_path(argument)
120
+ normalized.append(str(target))
121
+ saw_path = True
122
+ if executable in _REQUIRE_PATH_COMMANDS and not saw_path:
123
+ raise SandboxPolicyDenied(
124
+ f"read-only sandbox denied command {executable!r} without a workspace path"
125
+ )
126
+ return normalized
127
+
128
+ def _resolve_path(self, path: str) -> Path:
129
+ raw = str(path or "").strip()
130
+ if not raw:
131
+ raise SandboxPolicyDenied("read-only sandbox requires a workspace path")
132
+ candidate = Path(raw)
133
+ if not candidate.is_absolute():
134
+ candidate = self._workspace_root / candidate
135
+ resolved = candidate.expanduser().resolve()
136
+ if resolved != self._workspace_root and self._workspace_root not in resolved.parents:
137
+ raise SandboxPolicyDenied(f"read-only sandbox denied path outside workspace: {raw!r}")
138
+ return resolved
139
+
140
+
141
+ __all__ = ["HarnessSandboxExecutor", "SandboxPolicyDenied"]
ksadk/harness/tools.py ADDED
@@ -0,0 +1,222 @@
1
+ """Tool catalog for one Harness runner."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import uuid
7
+ from dataclasses import dataclass
8
+ from typing import Any, Awaitable, Callable
9
+
10
+ from ksadk.compat.adk_compat import Agent, InMemorySessionService, InvocationContext, ToolContext
11
+ from ksadk.harness.config import McpToolSpec
12
+ from ksadk.harness.sandbox import HarnessSandboxExecutor
13
+ from ksadk.mcp_runtime import MCPServerConfig, build_mcp_toolset
14
+
15
+ ToolHandler = Callable[[dict[str, Any], str | None], Awaitable[Any]]
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class HarnessTool:
20
+ name: str
21
+ description: str
22
+ parameters: dict[str, Any]
23
+ handler: ToolHandler
24
+ source: str
25
+
26
+ @property
27
+ def openai_schema(self) -> dict[str, Any]:
28
+ return {
29
+ "type": "function",
30
+ "function": {
31
+ "name": self.name,
32
+ "description": self.description,
33
+ "parameters": self.parameters,
34
+ },
35
+ }
36
+
37
+ async def call(self, arguments: dict[str, Any], *, call_id: str | None = None) -> Any:
38
+ return await self.handler(arguments, call_id)
39
+
40
+
41
+ def sandbox_tools(sandbox: HarnessSandboxExecutor) -> list[HarnessTool]:
42
+ async def _read_file(arguments: dict[str, Any], call_id: str | None) -> Any:
43
+ del call_id
44
+ return await sandbox.read_file(str(arguments.get("path") or ""))
45
+
46
+ async def _run_command(arguments: dict[str, Any], call_id: str | None) -> Any:
47
+ del call_id
48
+ return await sandbox.run_command(str(arguments.get("command") or ""))
49
+
50
+ return [
51
+ HarnessTool(
52
+ name="sandbox_read_file",
53
+ description="Read one UTF-8 file inside the Harness workspace.",
54
+ parameters={
55
+ "type": "object",
56
+ "properties": {"path": {"type": "string"}},
57
+ "required": ["path"],
58
+ "additionalProperties": False,
59
+ },
60
+ handler=_read_file,
61
+ source="sandbox",
62
+ ),
63
+ HarnessTool(
64
+ name="sandbox_run_command",
65
+ description=(
66
+ "Run an allowlisted read-only command inside the Harness workspace. "
67
+ "Writes, network access, and dangerous process actions are denied."
68
+ ),
69
+ parameters={
70
+ "type": "object",
71
+ "properties": {"command": {"type": "string"}},
72
+ "required": ["command"],
73
+ "additionalProperties": False,
74
+ },
75
+ handler=_run_command,
76
+ source="sandbox",
77
+ ),
78
+ ]
79
+
80
+
81
+ async def load_mcp_tools(spec: McpToolSpec) -> tuple[Any, list[HarnessTool]]:
82
+ config = MCPServerConfig(
83
+ name=spec.name,
84
+ url=spec.url,
85
+ api_key=spec.api_key,
86
+ tool_filter=spec.tool_filter,
87
+ tool_name_prefix=spec.tool_name_prefix,
88
+ )
89
+ toolset = build_mcp_toolset(config)
90
+ try:
91
+ native_tools = await toolset.get_tools_with_prefix()
92
+ except Exception as exc:
93
+ await toolset.close()
94
+ raise RuntimeError(
95
+ f"Harness MCP server {spec.name!r} at {spec.url!r} failed to start: {exc}"
96
+ ) from exc
97
+
98
+ available_names = {str(tool.name) for tool in native_tools}
99
+ expected_names = {
100
+ f"{spec.tool_name_prefix}_{name}" if spec.tool_name_prefix else name
101
+ for name in spec.tool_filter
102
+ }
103
+ missing_names = sorted(expected_names - available_names)
104
+ if missing_names:
105
+ await toolset.close()
106
+ raise RuntimeError(
107
+ f"Harness MCP server {spec.name!r} at {spec.url!r} did not expose configured "
108
+ f"tool(s): {missing_names}"
109
+ )
110
+ if not native_tools:
111
+ await toolset.close()
112
+ raise RuntimeError(
113
+ f"Harness MCP server {spec.name!r} at {spec.url!r} exposed no callable tools"
114
+ )
115
+
116
+ tools: list[HarnessTool] = []
117
+ for native_tool in native_tools:
118
+ # ADK's declaration builder is private and changed across 1.x/2.x.
119
+ # MCP exposes the original public tool schema, which is stable across
120
+ # the supported versions.
121
+ raw_tool = getattr(native_tool, "raw_mcp_tool", None)
122
+ parameters = getattr(raw_tool, "inputSchema", None)
123
+ if parameters is None:
124
+ parameters = getattr(raw_tool, "input_schema", None)
125
+ if parameters is None:
126
+ parameters = getattr(native_tool, "input_schema", None)
127
+ if not isinstance(parameters, dict):
128
+ parameters = {"type": "object", "properties": {}}
129
+ parameters = _normalize_json_schema(parameters)
130
+
131
+ async def _call(
132
+ arguments: dict[str, Any],
133
+ call_id: str | None,
134
+ *,
135
+ _native_tool=native_tool,
136
+ _tool_name=str(native_tool.name),
137
+ ) -> Any:
138
+ try:
139
+ context = await _new_tool_context(call_id or _tool_name)
140
+ result = await _native_tool.run_async(args=arguments, tool_context=context)
141
+ return _normalize_tool_result(result, context)
142
+ except Exception as exc:
143
+ raise RuntimeError(
144
+ f"Harness MCP tool {_tool_name!r} on server {spec.name!r} failed: {exc}"
145
+ ) from exc
146
+
147
+ tools.append(
148
+ HarnessTool(
149
+ name=str(native_tool.name),
150
+ description=str(getattr(native_tool, "description", None) or "MCP tool"),
151
+ parameters=parameters,
152
+ handler=_call,
153
+ source=f"mcp:{spec.name}",
154
+ )
155
+ )
156
+ return toolset, tools
157
+
158
+
159
+ async def _new_tool_context(tool_name: str) -> Any:
160
+ """Build a real ADK ToolContext for a standalone MCP invocation."""
161
+ service = InMemorySessionService()
162
+ session = await service.create_session(
163
+ app_name="ksadk-harness",
164
+ user_id="harness",
165
+ session_id=f"tool-{uuid.uuid4().hex}",
166
+ )
167
+ invocation = InvocationContext(
168
+ session_service=service,
169
+ invocation_id=f"harness-tool-{tool_name}",
170
+ # ADK 1.34 requires an agent while 2.x makes it optional. Supplying a
171
+ # minimal public Agent keeps the same ToolContext construction on both.
172
+ agent=Agent(name="harness_tool", model="gemini-2.0-flash"),
173
+ session=session,
174
+ )
175
+ return ToolContext(invocation_context=invocation, function_call_id=tool_name)
176
+
177
+
178
+ def _normalize_tool_result(result: Any, context: Any) -> Any:
179
+ """Keep MCP failures structured so the reasoner can produce a final answer."""
180
+ confirmations = getattr(context.actions, "requested_tool_confirmations", {})
181
+ if confirmations:
182
+ error = result.get("error") if isinstance(result, dict) else None
183
+ return {
184
+ "ok": False,
185
+ "confirmation_required": True,
186
+ "confirmation_ids": sorted(str(item) for item in confirmations),
187
+ "error": str(error or "tool confirmation is required"),
188
+ }
189
+ if isinstance(result, dict) and result.get("error") is not None:
190
+ return {"ok": False, "error": str(result["error"])}
191
+ return result
192
+
193
+
194
+ def tool_result_text(result: Any) -> str:
195
+ if isinstance(result, str):
196
+ return result
197
+ if isinstance(result, dict):
198
+ content = result.get("content")
199
+ if isinstance(content, list):
200
+ texts = [
201
+ str(item.get("text"))
202
+ for item in content
203
+ if isinstance(item, dict) and item.get("text") is not None
204
+ ]
205
+ if texts:
206
+ return "\n".join(texts)
207
+ return json.dumps(result, ensure_ascii=False, default=str)
208
+
209
+
210
+ def _normalize_json_schema(value: Any) -> Any:
211
+ if isinstance(value, dict):
212
+ normalized = {key: _normalize_json_schema(item) for key, item in value.items()}
213
+ schema_type = normalized.get("type")
214
+ if isinstance(schema_type, str):
215
+ normalized["type"] = schema_type.lower()
216
+ return normalized
217
+ if isinstance(value, list):
218
+ return [_normalize_json_schema(item) for item in value]
219
+ return value
220
+
221
+
222
+ __all__ = ["HarnessTool", "load_mcp_tools", "sandbox_tools", "tool_result_text"]
ksadk/hermes_terminal.py CHANGED
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import contextlib
7
7
  import ctypes
8
+ import importlib
8
9
  import io
9
10
  import json
10
11
  import os
@@ -89,6 +90,7 @@ def build_start_frame(
89
90
  argv: Sequence[str],
90
91
  cols: int,
91
92
  rows: int,
93
+ session_id: str | None = None,
92
94
  cwd: str | None = None,
93
95
  options: Mapping[str, Any] | None = None,
94
96
  ) -> str:
@@ -105,6 +107,9 @@ def build_start_frame(
105
107
  normalized_cwd = str(cwd or "").strip()
106
108
  if normalized_cwd:
107
109
  payload["cwd"] = normalized_cwd
110
+ normalized_session_id = str(session_id or "").strip()
111
+ if normalized_session_id:
112
+ payload["session_id"] = normalized_session_id
108
113
  if options:
109
114
  payload["options"] = dict(options)
110
115
  return json.dumps(payload, ensure_ascii=False)
@@ -123,7 +128,9 @@ def validate_terminal_exec_argv(argv: Iterable[str]) -> list[str]:
123
128
  return validate_exec_argv_with_policy(argv, policy=GENERIC_TERMINAL_EXEC_POLICY)
124
129
 
125
130
 
126
- def build_terminal_exec_validator(policy: TerminalExecPolicy) -> Callable[[Iterable[str]], list[str]]:
131
+ def build_terminal_exec_validator(
132
+ policy: TerminalExecPolicy,
133
+ ) -> Callable[[Iterable[str]], list[str]]:
127
134
  def _validator(argv: Iterable[str]) -> list[str]:
128
135
  return validate_exec_argv_with_policy(argv, policy=policy)
129
136
 
@@ -190,30 +197,34 @@ def _raw_terminal(stdin: Any):
190
197
 
191
198
 
192
199
  @contextlib.contextmanager
193
- def _windows_raw_terminal(stdin: Any, *, kernel32: Any | None = None, msvcrt_module: Any | None = None):
200
+ def _windows_raw_terminal(
201
+ stdin: Any, *, kernel32: Any | None = None, msvcrt_module: Any | None = None
202
+ ):
194
203
  if not hasattr(stdin, "fileno") or not hasattr(stdin, "isatty") or not stdin.isatty():
195
204
  yield
196
205
  return
197
206
 
207
+ resolved_kernel32: Any = kernel32
208
+ resolved_msvcrt: Any = msvcrt_module
198
209
  try:
199
- if kernel32 is None:
200
- kernel32 = ctypes.windll.kernel32
201
- if msvcrt_module is None:
202
- import msvcrt as msvcrt_module # type: ignore[no-redef]
210
+ if resolved_kernel32 is None:
211
+ resolved_kernel32 = getattr(ctypes, "windll").kernel32
212
+ if resolved_msvcrt is None:
213
+ resolved_msvcrt = importlib.import_module("msvcrt")
203
214
  except Exception:
204
215
  yield
205
216
  return
206
217
 
207
218
  try:
208
219
  fd = stdin.fileno()
209
- handle = msvcrt_module.get_osfhandle(fd)
220
+ handle = resolved_msvcrt.get_osfhandle(fd)
210
221
  except Exception:
211
222
  yield
212
223
  return
213
224
 
214
225
  original_mode = wintypes.DWORD()
215
226
  try:
216
- if not kernel32.GetConsoleMode(handle, ctypes.byref(original_mode)):
227
+ if not resolved_kernel32.GetConsoleMode(handle, ctypes.byref(original_mode)):
217
228
  yield
218
229
  return
219
230
  except Exception:
@@ -233,7 +244,7 @@ def _windows_raw_terminal(stdin: Any, *, kernel32: Any | None = None, msvcrt_mod
233
244
  )
234
245
 
235
246
  try:
236
- if not kernel32.SetConsoleMode(handle, raw_mode):
247
+ if not resolved_kernel32.SetConsoleMode(handle, raw_mode):
237
248
  yield
238
249
  return
239
250
  except Exception:
@@ -244,14 +255,18 @@ def _windows_raw_terminal(stdin: Any, *, kernel32: Any | None = None, msvcrt_mod
244
255
  yield
245
256
  finally:
246
257
  with contextlib.suppress(Exception):
247
- kernel32.SetConsoleMode(handle, int(original_mode.value))
258
+ resolved_kernel32.SetConsoleMode(handle, int(original_mode.value))
248
259
 
249
260
 
250
- async def _connect_websocket(ws_url: str, headers: dict[str, str], ssl_context: ssl.SSLContext | None):
261
+ async def _connect_websocket(
262
+ ws_url: str, headers: dict[str, str], ssl_context: ssl.SSLContext | None
263
+ ):
251
264
  try:
252
265
  import websockets
253
266
  except ImportError as e:
254
- raise RuntimeError("missing dependency websockets, please install ksadk with websocket support") from e
267
+ raise RuntimeError(
268
+ "missing dependency websockets, please install ksadk with websocket support"
269
+ ) from e
255
270
 
256
271
  kwargs: dict[str, Any] = {"subprotocols": [TERMINAL_SUBPROTOCOL]}
257
272
  if ssl_context is not None:
@@ -404,6 +419,7 @@ async def run_hermes_terminal_session(
404
419
  argv=normalized_argv,
405
420
  cols=size.cols,
406
421
  rows=size.rows,
422
+ session_id=session_id,
407
423
  cwd=cwd,
408
424
  options=options,
409
425
  )
@@ -31,11 +31,11 @@ _KRN_ACCOUNT_RE = re.compile(r"krn:ksc:iam::([^:]+):user/")
31
31
  class ResolvedIdentity:
32
32
  """AK/SK 反查到的身份信息。"""
33
33
 
34
- user_uuid: Optional[str] # 子账号 UserId(X-Ksc-User-uuid 值);主账号 AK 时 None
34
+ user_uuid: Optional[str] # 子账号 UserId(X-Ksc-User-uuid 值);主账号 AK 时 None
35
35
  main_account_id: Optional[str] # 从 Krn 提取的主账号 ID
36
- user_name: Optional[str] # 子账号 UserName(调试用)
37
- krn: Optional[str] # 原始 Krn(调试用)
38
- ak_fingerprint: str # sha256(AK)[:16],缓存 key
36
+ user_name: Optional[str] # 子账号 UserName(调试用)
37
+ krn: Optional[str] # 原始 Krn(调试用)
38
+ ak_fingerprint: str # sha256(AK)[:16],缓存 key
39
39
 
40
40
 
41
41
  # ---------------------------------------------------------------------------
@@ -107,14 +107,20 @@ def _should_retry_intranet(error: Exception | None) -> bool:
107
107
  def _import_iam_sdk():
108
108
  """惰性导入 ksyun IAM SDK,失败返回 None。"""
109
109
  try:
110
- from ksyun.client.iam.v20151101.client import IamClient
111
- from ksyun.client.iam.v20151101.models import (
110
+ from ksyun.client.iam.v20151101.client import ( # type: ignore[import-untyped]
111
+ IamClient,
112
+ )
113
+ from ksyun.client.iam.v20151101.models import ( # type: ignore[import-untyped]
112
114
  GetUserRequest,
113
115
  ListAllUserAccessKeysRequest,
114
116
  )
115
- from ksyun.common.credential import Credential
116
- from ksyun.common.profile.client_profile import ClientProfile
117
- from ksyun.common.profile.http_profile import HttpProfile
117
+ from ksyun.common.credential import Credential # type: ignore[import-untyped]
118
+ from ksyun.common.profile.client_profile import ( # type: ignore[import-untyped]
119
+ ClientProfile,
120
+ )
121
+ from ksyun.common.profile.http_profile import ( # type: ignore[import-untyped]
122
+ HttpProfile,
123
+ )
118
124
  except Exception as exc:
119
125
  logger.warning("导入 ksyun IAM SDK 失败: %s", exc)
120
126
  return None
ksadk/ids.py ADDED
@@ -0,0 +1,32 @@
1
+ """统一 id 铸造规范。
2
+
3
+ 历史上 session / run(invocation) id 各层格式混杂:
4
+
5
+ - agentengine-server hosted 会话: ``sess-<16 hex>``(conversation_service)
6
+ - ksadk 本地 session: 裸 ``<16 hex>``(sessions/base.generate_id)
7
+ - ksadk 后台 run: ``inv_<32 hex>``(server/app RunAgent)
8
+ - ksadk conversation turn: 裸 ``uuid4``(conversations/runtime)
9
+ - research-ui run_agent 模式: ``run_<session段>``(由 session id 推导)
10
+
11
+ 新代码统一走这里:
12
+
13
+ - session id: ``sess-<16 hex>``,与 agentengine-server 对齐。
14
+ - run/invocation id: ``run_<32 hex>``,每次 run 唯一且固定长度。
15
+
16
+ id 均为不透明字符串,仅在铸造时保证格式,消费方不做结构解析。
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import uuid
22
+
23
+
24
+ def new_session_id() -> str:
25
+ """铸造 session id:``sess-<16 hex>``。"""
26
+ return f"sess-{uuid.uuid4().hex[:16]}"
27
+
28
+
29
+ def new_run_id(session_id: str | None = None) -> str:
30
+ """铸造固定长度 opaque run/invocation id:``run_<32 hex>``。"""
31
+ del session_id
32
+ return f"run_{uuid.uuid4().hex}"
@@ -36,7 +36,7 @@ def create_adk_tool():
36
36
  可直接注入到 ADK Agent 的工具对象
37
37
  """
38
38
  try:
39
- from google.adk.tools import FunctionTool
39
+ from ksadk.compat.adk_compat import FunctionTool
40
40
 
41
41
  return FunctionTool(func=search_knowledge_base)
42
42
  except ImportError: