agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.3__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 (476) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/METADATA +25 -12
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/RECORD +421 -232
  3. ksadk/_build_provenance.json +1 -0
  4. ksadk/a2a/_space_client_events.py +381 -0
  5. ksadk/a2a/event_adapter.py +156 -64
  6. ksadk/a2a/executor.py +179 -63
  7. ksadk/a2a/space_client.py +6 -333
  8. ksadk/a2ui/core.py +222 -53
  9. ksadk/agui/_agent_helpers.py +247 -0
  10. ksadk/agui/a2ui_projection.py +12 -5
  11. ksadk/agui/agent.py +443 -259
  12. ksadk/api/client.py +528 -27
  13. ksadk/builders/code_builder.py +284 -8
  14. ksadk/builders/container_builder.py +8 -1
  15. ksadk/builders/managed_runtime_builder.py +42 -35
  16. ksadk/cli/__init__.py +23 -0
  17. ksadk/cli/cmd_dashboard.py +15 -1
  18. ksadk/cli/cmd_deploy.py +10 -2
  19. ksadk/cli/cmd_eval.py +66 -9
  20. ksadk/cli/cmd_evalset.py +284 -0
  21. ksadk/cli/cmd_files.py +5 -1
  22. ksadk/cli/cmd_hermes.py +1 -126
  23. ksadk/cli/cmd_invoke.py +28 -38
  24. ksadk/cli/cmd_managed_runtime.py +95 -0
  25. ksadk/cli/cmd_observe.py +85 -0
  26. ksadk/cli/cmd_openclaw.py +1 -435
  27. ksadk/cli/cmd_plugin.py +657 -0
  28. ksadk/cli/cmd_replay.py +28 -4
  29. ksadk/cli/cmd_studio.py +99 -8
  30. ksadk/cli/cmd_web.py +10 -2
  31. ksadk/cli/hermes_env.py +151 -0
  32. ksadk/cli/invoke_payload.py +49 -0
  33. ksadk/cli/openclaw_env.py +458 -0
  34. ksadk/codex/client.py +180 -30
  35. ksadk/codex/runtime.py +475 -331
  36. ksadk/configs/env_registry.py +94 -12
  37. ksadk/configs/env_registry_pcm.py +181 -0
  38. ksadk/configs/env_var_spec.py +18 -0
  39. ksadk/configs/global_config.py +5 -0
  40. ksadk/configs/settings.py +9 -0
  41. ksadk/context_engine/__init__.py +98 -0
  42. ksadk/context_engine/assembler.py +176 -0
  43. ksadk/context_engine/baseline.py +419 -0
  44. ksadk/context_engine/cache_observability.py +228 -0
  45. ksadk/context_engine/capabilities.py +443 -0
  46. ksadk/context_engine/contributors.py +409 -0
  47. ksadk/context_engine/hosted_pipeline.py +417 -0
  48. ksadk/context_engine/models.py +117 -0
  49. ksadk/context_engine/planner.py +698 -0
  50. ksadk/context_engine/policies.py +319 -0
  51. ksadk/context_engine/projection.py +31 -0
  52. ksadk/context_engine/shadow_plan.py +266 -0
  53. ksadk/context_engine/tokenizer.py +164 -0
  54. ksadk/conversations/__init__.py +19 -0
  55. ksadk/conversations/context.py +230 -30
  56. ksadk/conversations/contracts.py +266 -0
  57. ksadk/conversations/message_projection.py +308 -26
  58. ksadk/conversations/model_context.py +49 -3
  59. ksadk/conversations/projector.py +616 -0
  60. ksadk/conversations/reducer.py +98 -0
  61. ksadk/conversations/runtime_compaction.py +207 -5
  62. ksadk/conversations/runtime_input.py +184 -2
  63. ksadk/conversations/runtime_invocation.py +81 -3
  64. ksadk/conversations/runtime_observability.py +141 -0
  65. ksadk/conversations/runtime_payloads.py +42 -0
  66. ksadk/conversations/runtime_preparation.py +272 -2
  67. ksadk/conversations/runtime_resume.py +20 -1
  68. ksadk/conversations/runtime_stream_events.py +94 -9
  69. ksadk/conversations/semantic_summary.py +311 -1
  70. ksadk/conversations/session_lock.py +51 -0
  71. ksadk/deployment/env_forward.py +72 -0
  72. ksadk/deployment/managed_runtime.py +5 -0
  73. ksadk/deployment/providers/serverless.py +143 -69
  74. ksadk/evaluation/__init__.py +32 -0
  75. ksadk/evaluation/a2a_adapter.py +9 -1
  76. ksadk/evaluation/adapters.py +18 -5
  77. ksadk/evaluation/agent_eval_client.py +395 -0
  78. ksadk/evaluation/cloud_binding.py +80 -0
  79. ksadk/evaluation/cloud_converter.py +194 -0
  80. ksadk/evaluation/cloud_service.py +199 -0
  81. ksadk/evaluation/contracts.py +73 -4
  82. ksadk/evaluation/evaluators.py +183 -17
  83. ksadk/evaluation/evidence.py +258 -0
  84. ksadk/evaluation/executor.py +31 -6
  85. ksadk/evaluation/local_adapter.py +550 -0
  86. ksadk/evaluation/service_env.py +27 -0
  87. ksadk/evaluation/studio_build_adapter.py +253 -0
  88. ksadk/evaluation/target.py +15 -6
  89. ksadk/events/__init__.py +13 -13
  90. ksadk/events/_v1_compat/__init__.py +1 -0
  91. ksadk/events/_v1_compat/models.py +299 -0
  92. ksadk/events/_v1_compat/parser.py +247 -0
  93. ksadk/events/_v1_compat/projection.py +755 -0
  94. ksadk/events/adapters/__init__.py +34 -0
  95. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  96. ksadk/events/adapters/_a2a_support.py +275 -0
  97. ksadk/events/adapters/_codex_interactions.py +375 -0
  98. ksadk/events/adapters/_codex_items.py +801 -0
  99. ksadk/events/adapters/_codex_validators.py +311 -0
  100. ksadk/events/adapters/_langgraph_support.py +785 -0
  101. ksadk/events/adapters/a2a.py +841 -0
  102. ksadk/events/adapters/adk.py +503 -0
  103. ksadk/events/adapters/codex.py +907 -0
  104. ksadk/events/adapters/langgraph.py +745 -0
  105. ksadk/events/canonical.py +440 -0
  106. ksadk/events/canonical_replay.py +497 -0
  107. ksadk/events/canonical_store.py +468 -0
  108. ksadk/events/cold_recovery.py +257 -0
  109. ksadk/events/content.py +89 -0
  110. ksadk/events/identity.py +86 -0
  111. ksadk/events/pipeline.py +455 -0
  112. ksadk/events/projections.py +66 -0
  113. ksadk/events/reducer.py +661 -0
  114. ksadk/events/replay.py +3 -36
  115. ksadk/events/runtime_event.py +20 -265
  116. ksadk/events/session_event.py +324 -0
  117. ksadk/events/store.py +3 -316
  118. ksadk/events/v1_compat.py +41 -0
  119. ksadk/harness/__init__.py +45 -35
  120. ksadk/harness/runtime.py +220 -58
  121. ksadk/identity/resolver.py +4 -3
  122. ksadk/interaction/__init__.py +28 -0
  123. ksadk/interaction/contracts.py +136 -0
  124. ksadk/interaction/ledger.py +189 -0
  125. ksadk/interaction/provider.py +122 -0
  126. ksadk/interaction/providers/__init__.py +52 -0
  127. ksadk/interaction/providers/adk.py +40 -0
  128. ksadk/interaction/providers/codex.py +94 -0
  129. ksadk/interaction/providers/langgraph.py +58 -0
  130. ksadk/kernel/__init__.py +117 -0
  131. ksadk/kernel/authorization.py +258 -0
  132. ksadk/kernel/bootstrap.py +1074 -0
  133. ksadk/kernel/contract_fingerprints.py +62 -0
  134. ksadk/kernel/contracts.py +370 -0
  135. ksadk/kernel/control.py +220 -0
  136. ksadk/kernel/errors.py +79 -0
  137. ksadk/kernel/ingress.py +1123 -0
  138. ksadk/kernel/mapping.py +111 -0
  139. ksadk/kernel/memory_store.py +1134 -0
  140. ksadk/kernel/postgres_store.py +1757 -0
  141. ksadk/kernel/recovery.py +452 -0
  142. ksadk/kernel/runtime_identity.py +103 -0
  143. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  144. ksadk/kernel/sqlite_store.py +1411 -0
  145. ksadk/kernel/state.py +145 -0
  146. ksadk/kernel/store.py +232 -0
  147. ksadk/kernel/worker.py +964 -0
  148. ksadk/knowledge_base/client.py +7 -0
  149. ksadk/knowledge_base/service.py +32 -5
  150. ksadk/memory/__init__.py +61 -0
  151. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  152. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  153. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  154. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  155. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  156. ksadk/memory/coordinator.py +461 -0
  157. ksadk/memory/events.py +202 -0
  158. ksadk/memory/extraction.py +228 -0
  159. ksadk/memory/ltm_backend_factory.py +16 -3
  160. ksadk/memory/models.py +316 -0
  161. ksadk/memory/policy.py +215 -0
  162. ksadk/memory/provider.py +47 -0
  163. ksadk/memory/provider_adapter.py +159 -0
  164. ksadk/memory/provider_resolver.py +71 -0
  165. ksadk/memory/providers/__init__.py +5 -0
  166. ksadk/memory/providers/local_sqlite.py +497 -0
  167. ksadk/memory/resolved_policy.py +145 -0
  168. ksadk/memory/service.py +188 -6
  169. ksadk/model_proxy/bootstrap.py +16 -9
  170. ksadk/model_proxy/detect.py +202 -9
  171. ksadk/model_proxy/namespace.py +39 -15
  172. ksadk/model_proxy/server.py +24 -5
  173. ksadk/model_proxy/transform.py +60 -2
  174. ksadk/observability/__init__.py +25 -0
  175. ksadk/observability/session_log.py +420 -0
  176. ksadk/observability/trajectory.py +105 -0
  177. ksadk/plugins/__init__.py +167 -0
  178. ksadk/plugins/bridges/__init__.py +45 -0
  179. ksadk/plugins/bridges/codex.py +552 -0
  180. ksadk/plugins/bridges/dsh.py +1116 -0
  181. ksadk/plugins/builtins.py +747 -0
  182. ksadk/plugins/bundle.py +246 -0
  183. ksadk/plugins/bundle_security.py +167 -0
  184. ksadk/plugins/composition.py +529 -0
  185. ksadk/plugins/context_contributor.py +437 -0
  186. ksadk/plugins/contracts.py +451 -0
  187. ksadk/plugins/dsh_toolchain.py +935 -0
  188. ksadk/plugins/ecosystem_bridge.py +1105 -0
  189. ksadk/plugins/ecosystem_probe.py +191 -0
  190. ksadk/plugins/host.py +724 -0
  191. ksadk/plugins/providers/__init__.py +85 -0
  192. ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
  193. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
  194. ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
  195. ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
  196. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
  197. ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
  198. ksadk/plugins/providers/codex.py +722 -0
  199. ksadk/plugins/providers/codex_dsh.py +83 -0
  200. ksadk/plugins/providers/dsh.py +951 -0
  201. ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
  202. ksadk/plugins/providers/harness.py +627 -0
  203. ksadk/plugins/providers/harness_dsh.py +91 -0
  204. ksadk/plugins/providers/legacy.py +215 -0
  205. ksadk/plugins/providers/legacy_catalog.py +100 -0
  206. ksadk/plugins/providers/shipped_dsh.py +370 -0
  207. ksadk/plugins/resolver.py +331 -0
  208. ksadk/plugins/subagent_providers/__init__.py +12 -0
  209. ksadk/plugins/subagent_providers/codex.py +443 -0
  210. ksadk/plugins/subagents.py +333 -0
  211. ksadk/prompts/__init__.py +71 -0
  212. ksadk/prompts/compiler.py +215 -0
  213. ksadk/prompts/models.py +82 -0
  214. ksadk/prompts/projection.py +89 -0
  215. ksadk/prompts/resolved.py +137 -0
  216. ksadk/prompts/sources.py +233 -0
  217. ksadk/runners/_langgraph_runner_streams.py +822 -0
  218. ksadk/runners/adk_runner.py +5 -5
  219. ksadk/runners/base_runner.py +16 -0
  220. ksadk/runners/factory.py +1 -2
  221. ksadk/runners/langgraph_runner.py +198 -437
  222. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  223. ksadk/runtime/_runner_adapter/stream_mapping.py +797 -0
  224. ksadk/runtime/adapter.py +119 -2
  225. ksadk/runtime/conversation_execution.py +316 -182
  226. ksadk/runtime/executor.py +144 -3
  227. ksadk/runtime/factory.py +268 -8
  228. ksadk/runtime/framework_adapters.py +18 -0
  229. ksadk/runtime/hosted_finalizer.py +268 -0
  230. ksadk/runtime/launch.py +14 -1
  231. ksadk/runtime/preprocessing.py +25 -3
  232. ksadk/runtime/runner_adapter.py +293 -508
  233. ksadk/runtime/usage.py +33 -0
  234. ksadk/sandbox/__init__.py +2 -1
  235. ksadk/sandbox/backends/e2b.py +35 -2
  236. ksadk/sandbox/factory.py +72 -0
  237. ksadk/scheduler/__init__.py +18 -0
  238. ksadk/scheduler/calendar.py +102 -0
  239. ksadk/scheduler/contracts.py +254 -0
  240. ksadk/scheduler/dispatcher.py +129 -0
  241. ksadk/scheduler/engine.py +416 -0
  242. ksadk/scheduler/sqlite_store.py +563 -0
  243. ksadk/server/composition.py +8 -0
  244. ksadk/server/factory.py +69 -6
  245. ksadk/server/routes/kernel_ingress.py +258 -0
  246. ksadk/server/routes/openai_compat.py +88 -8
  247. ksadk/server/routes/projection.py +35 -20
  248. ksadk/server/routes/run.py +94 -0
  249. ksadk/server/routes/sessions.py +2 -0
  250. ksadk/server/routes/streaming.py +5 -2
  251. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-10GPXIJ6.js} +1 -1
  252. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-BXk1l-G1.js} +4 -4
  253. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  254. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-D9uB55Oh.js} +4 -4
  255. ksadk/server/static/assets/MermaidBlock--OEYoXIJ.js +312 -0
  256. ksadk/server/static/assets/NativeTerminalPanel-DrEe1syq.js +1 -0
  257. ksadk/server/static/assets/abnfDiagram-VCTEODGH-eeTFJLvo.js +1 -0
  258. ksadk/server/static/assets/arc-S3ZNbIAd.js +1 -0
  259. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +1 -0
  260. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-CRjgEJDX.js +36 -0
  261. ksadk/server/static/assets/blockDiagram-NRAW4CY4-C7bsBoNH.js +129 -0
  262. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-BX3c33Ob.js +38 -0
  263. ksadk/server/static/assets/channel-s354Yo6o.js +1 -0
  264. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +1 -0
  265. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-bZ7ws-8m.js} +1 -1
  266. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-D2r0pvhY.js} +1 -1
  267. ksadk/server/static/assets/chunk-G27WJ6UU-CZwF3oUP.js +231 -0
  268. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-DigFYCML.js} +1 -1
  269. ksadk/server/static/assets/chunk-LCL6LL3I-CnorGV5q.js +206 -0
  270. ksadk/server/static/assets/chunk-POPQ4Y6H-CexntQA-.js +1 -0
  271. ksadk/server/static/assets/chunk-RHFEMEQ7-CHTC7UxA.js +168 -0
  272. ksadk/server/static/assets/chunk-SVP7TREG-BC1EWt_-.js +88 -0
  273. ksadk/server/static/assets/chunk-XXDRQBXY-BTG24xN0.js +1 -0
  274. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +1 -0
  275. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +1 -0
  276. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-CkonRdAS.js} +1 -1
  277. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +1 -0
  278. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-DEOCBe15.js +62 -0
  279. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  280. ksadk/server/static/assets/dagre-3AP2YEHR-DBThPuLa.js +4 -0
  281. ksadk/server/static/assets/dagre-ClTPrTht.js +1 -0
  282. ksadk/server/static/assets/diagram-S7CK7UJ4-DsZHrnpJ.js +30 -0
  283. ksadk/server/static/assets/diagram-UQ7AKVKN-BJR4nhVr.js +41 -0
  284. ksadk/server/static/assets/diagram-VSXAHHWV-xzcERX0a.js +3 -0
  285. ksadk/server/static/assets/diagram-VX7I27RA-tn2xM1xu.js +24 -0
  286. ksadk/server/static/assets/diagram-Z3DM3KII-BZPGBkw5.js +24 -0
  287. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-4zN1_tq5.js} +1 -1
  288. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-8VWI-2bZ.js} +1 -1
  289. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-B-46q3Hk.js} +1 -1
  290. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-B0gdk4rl.js} +1 -1
  291. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-B1oWRmrH.js} +1 -1
  292. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-BI1qQH4n.js} +1 -1
  293. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-BJLUwH6W.js} +1 -1
  294. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Bbwqa8TG.js} +1 -1
  295. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-Btyo4vX4.js} +1 -1
  296. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-C71CsujO.js} +1 -1
  297. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-CXpH_Rdd.js} +1 -1
  298. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-Cq4OL6nO.js} +1 -1
  299. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-D1V3f1B4.js} +1 -1
  300. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-DJmCPRVB.js} +1 -1
  301. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DQAB0qn_.js} +2 -2
  302. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DUwKa_l6.js} +1 -1
  303. ksadk/server/static/assets/dist-DdRBIceA.js +1 -0
  304. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-DfGFrb0v.js} +1 -1
  305. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-DjhwGUgZ.js} +1 -1
  306. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-DyqV4fL4.js} +1 -1
  307. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-M67Hwu0n.js} +1 -1
  308. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-u8tVH5Ak.js} +1 -1
  309. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-DVfMsLge.js +1 -0
  310. ksadk/server/static/assets/erDiagram-SSCWMZ5O-CWEZSYaw.js +99 -0
  311. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +1 -0
  312. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +1 -0
  313. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-TWIxoyYL.js +292 -0
  314. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +1 -0
  315. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-DDh2hd2S.js +106 -0
  316. ksadk/server/static/assets/index-B2k_urY8.js +241 -0
  317. ksadk/server/static/assets/index-ILPt6IWF.css +2 -0
  318. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +1 -0
  319. ksadk/server/static/assets/infoDiagram-RXCK75RN-CgoyWiDR.js +2 -0
  320. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-CyRIu_om.js} +6 -6
  321. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DN5JXHzN.js} +6 -6
  322. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-CNP3ui66.js} +10 -10
  323. ksadk/server/static/assets/katex-DWEzQy1d.js +257 -0
  324. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-C-qHp7d2.js} +1 -1
  325. ksadk/server/static/assets/mermaid-parser.core-Cl-K943T.js +166 -0
  326. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-D5DB5mYm.js} +29 -29
  327. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +1 -0
  328. ksadk/server/static/assets/pegDiagram-XKGWAZYB-BQVc9ia_.js +1 -0
  329. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +1 -0
  330. ksadk/server/static/assets/pieDiagram-E7YTZNPT-B6UCAvtY.js +39 -0
  331. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-mIr2d3eb.js} +6 -6
  332. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +1 -0
  333. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +1 -0
  334. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +1 -0
  335. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +1 -0
  336. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +1 -0
  337. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-Dt3FFDmK.js +1 -0
  338. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-Cz_vQtgF.js +84 -0
  339. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-wlO1TsH5.js} +7 -7
  340. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-CHRbElYq.js} +10 -10
  341. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-DXX54iyO.js +1 -0
  342. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-Dp_lw9II.js +1 -0
  343. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +1 -0
  344. ksadk/server/static/assets/swimlanes-XN3QIQJK-D8O5UlLG.js +1 -0
  345. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +8 -0
  346. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-8mfKcxvG.js} +7 -7
  347. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +1 -0
  348. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +1 -0
  349. ksadk/server/static/assets/vennDiagram-4TSXK5OY-EnNl0DE7.js +34 -0
  350. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +1 -0
  351. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DBu5fbYr.js +78 -0
  352. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-BSVXs4IY.js +7 -0
  353. ksadk/server/static/index.html +2 -2
  354. ksadk/sessions/__init__.py +26 -9
  355. ksadk/sessions/_local_service_sync.py +688 -0
  356. ksadk/sessions/_local_tables.py +21 -0
  357. ksadk/sessions/_postgres_schema.py +305 -0
  358. ksadk/sessions/_postgres_tables.py +15 -0
  359. ksadk/sessions/base.py +80 -1
  360. ksadk/sessions/in_memory.py +53 -2
  361. ksadk/sessions/local_service.py +63 -604
  362. ksadk/sessions/postgres_service.py +58 -148
  363. ksadk/sessions/resilient.py +35 -1
  364. ksadk/skills/service_client.py +48 -0
  365. ksadk/studio/agent_lifecycle.py +26 -20
  366. ksadk/studio/api.py +1063 -69
  367. ksadk/studio/api_catalog_routes.py +5 -0
  368. ksadk/studio/api_contracts.py +148 -6
  369. ksadk/studio/api_memory_routes.py +82 -0
  370. ksadk/studio/api_plugin_routes.py +480 -0
  371. ksadk/studio/attachment_store.py +187 -0
  372. ksadk/studio/authoring.py +259 -28
  373. ksadk/studio/authoring_coordinator.py +809 -67
  374. ksadk/studio/builder.py +197 -40
  375. ksadk/studio/capabilities.py +17 -0
  376. ksadk/studio/cloud.py +1920 -95
  377. ksadk/studio/codex_agent_service.py +137 -15
  378. ksadk/studio/codex_authoring.py +469 -0
  379. ksadk/studio/codex_builder.py +177 -25
  380. ksadk/studio/codex_manifest.py +71 -22
  381. ksadk/studio/codex_run.py +59 -4
  382. ksadk/studio/compatibility_report.py +445 -0
  383. ksadk/studio/compiler.py +7 -1
  384. ksadk/studio/contracts.py +234 -4
  385. ksadk/studio/dsh_provider_registration.py +768 -0
  386. ksadk/studio/event_store.py +79 -101
  387. ksadk/studio/framework_run.py +264 -3
  388. ksadk/studio/hosted_kernel.py +317 -0
  389. ksadk/studio/manifest_resolver.py +131 -0
  390. ksadk/studio/model_client.py +95 -9
  391. ksadk/studio/model_profile_service.py +1 -1
  392. ksadk/studio/operations.py +47 -5
  393. ksadk/studio/otel_trace.py +348 -42
  394. ksadk/studio/pcm_memory.py +85 -0
  395. ksadk/studio/plugin_composition.py +301 -0
  396. ksadk/studio/plugin_kernel_adapter.py +128 -0
  397. ksadk/studio/plugin_runtime.py +652 -0
  398. ksadk/studio/repository.py +23 -2
  399. ksadk/studio/resource_catalog.py +49 -1
  400. ksadk/studio/run_service.py +1266 -202
  401. ksadk/studio/runtime_source.py +51 -17
  402. ksadk/studio/scheduler_runtime.py +374 -0
  403. ksadk/studio/scheduler_service.py +211 -0
  404. ksadk/studio/service.py +1815 -117
  405. ksadk/studio/shared_web.py +199 -50
  406. ksadk/studio/soul.py +52 -0
  407. ksadk/studio/static/assets/index-DXs1Eq4M.css +1 -0
  408. ksadk/studio/static/assets/index-DeDqwTsD.js +283 -0
  409. ksadk/studio/static/index.html +2 -2
  410. ksadk/studio/templates.py +100 -8
  411. ksadk/studio/validator.py +20 -1
  412. ksadk/studio/workspace.py +31 -32
  413. ksadk/tracing/setup.py +304 -3
  414. ksadk/version.py +1 -1
  415. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  416. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  417. ksadk_runtime_common/workspace_files/path_utils.py +41 -0
  418. ksadk/events/parser.py +0 -191
  419. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  420. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  421. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  422. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  423. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  424. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  425. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  426. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  427. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  428. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  429. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  430. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  431. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  432. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  433. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  434. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  435. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  436. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  437. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  438. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  439. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  440. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  441. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  442. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  443. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  444. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  445. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  446. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  447. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  448. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  449. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  450. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  451. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  452. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  453. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  454. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  455. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  456. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  457. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  458. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  459. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  460. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  461. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  462. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  463. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  464. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  465. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  466. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  467. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  468. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  469. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  470. ksadk/studio/evaluation.py +0 -192
  471. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  472. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  473. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/WHEEL +0 -0
  474. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/entry_points.txt +0 -0
  475. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/licenses/LICENSE +0 -0
  476. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/top_level.txt +0 -0
@@ -20,6 +20,8 @@ _GENERATED_MARKER = ".agentkit-generated"
20
20
  def materialize_generated_runtime_source(
21
21
  workspace: Workspace,
22
22
  draft: AgentDraft,
23
+ *,
24
+ catalog: LocalResourceCatalog | None = None,
23
25
  ) -> None:
24
26
  """Create or refresh the source owned by a generated ADK/LangGraph draft.
25
27
 
@@ -28,7 +30,15 @@ def materialize_generated_runtime_source(
28
30
  """
29
31
 
30
32
  runtime = draft.spec.runtime
31
- if runtime is None or runtime.type == "codex" or not runtime.project_path:
33
+ # Only the two legacy Python-framework runtimes own generated source.
34
+ # Harness and externally installed AgentProviders are bundle compositions;
35
+ # treating either as the ``else`` branch here would silently generate a
36
+ # LangGraph project and change the selected provider's execution model.
37
+ if (
38
+ runtime is None
39
+ or runtime.type not in {"adk", "langgraph"}
40
+ or not runtime.project_path
41
+ ):
32
42
  return
33
43
  root = workspace.resolve(runtime.project_path)
34
44
  marker = root / _GENERATED_MARKER
@@ -37,9 +47,14 @@ def materialize_generated_runtime_source(
37
47
  root.mkdir(parents=True, exist_ok=True)
38
48
  entry = workspace.resolve(Path(runtime.project_path) / (runtime.entry_point or "agent.py"))
39
49
  entry.parent.mkdir(parents=True, exist_ok=True)
40
- prompt, tool_names, python_tools = _runtime_inputs(workspace, draft)
50
+ resolved_catalog = catalog or LocalResourceCatalog(workspace)
51
+ prompt, tool_names, python_tools = _runtime_inputs(
52
+ workspace,
53
+ draft,
54
+ catalog=resolved_catalog,
55
+ )
41
56
  _snapshot_python_tools(workspace, root, python_tools)
42
- model = _configured_model(draft)
57
+ model = _configured_model(resolved_catalog, draft)
43
58
  if runtime.type == "adk":
44
59
  source = _adk_source(
45
60
  draft.metadata.id,
@@ -73,7 +88,10 @@ def materialize_generated_runtime_source(
73
88
  )
74
89
 
75
90
 
76
- def _configured_model(draft: AgentDraft) -> str:
91
+ def _configured_model(catalog: LocalResourceCatalog, draft: AgentDraft) -> str:
92
+ resolved = catalog.resolve_model(draft.spec.bindings)
93
+ if resolved is not None:
94
+ return resolved.model
77
95
  if draft.spec.model is not None:
78
96
  return draft.spec.model.model
79
97
  return str(draft.metadata.labels.get("agentkit.ksyun.com/model") or "glm-5.1")
@@ -82,8 +100,9 @@ def _configured_model(draft: AgentDraft) -> str:
82
100
  def _runtime_inputs(
83
101
  workspace: Workspace,
84
102
  draft: AgentDraft,
103
+ *,
104
+ catalog: LocalResourceCatalog,
85
105
  ) -> tuple[str, list[str], list[dict[str, str]]]:
86
- catalog = LocalResourceCatalog(workspace)
87
106
  tools, _permissions = catalog.policy_preview(draft.spec.bindings)
88
107
  builtin_names = [tool.name for tool in tools if tool.enabled and tool.executor == "builtin"]
89
108
  python_tools = [
@@ -316,23 +335,38 @@ def _call_model(state: AgentState):
316
335
  client = ChatOpenAI(
317
336
  model=selected,
318
337
  api_key=os.environ["OPENAI_API_KEY"],
319
- base_url=os.getenv("OPENAI_API_BASE") or os.getenv("OPENAI_BASE_URL"),
338
+ base_url=os.getenv("OPENAI_BASE_URL") or os.getenv("OPENAI_API_BASE"),
339
+ stream_usage=True,
320
340
  )
321
341
  runnable = client.bind_tools(_tools) if _tools else client
322
- messages = [SystemMessage(content={json.dumps(prompt)}), *state["messages"]]
342
+ messages = list(state["messages"])
343
+ # KsADK Runtime 已投影 CompiledPrompt/ContextPlan 时,state 中存在 SystemMessage,
344
+ # 不再重复注入模板 Prompt;直接调用 graph 时仍保留独立运行能力。
345
+ if not any(isinstance(message, SystemMessage) for message in messages):
346
+ messages.insert(0, SystemMessage(content={json.dumps(prompt)}))
323
347
  return {{"messages": [runnable.invoke(messages)]}}
324
348
 
325
349
 
326
- _builder = StateGraph(AgentState)
327
- _builder.add_node("model", _call_model)
328
- _builder.add_edge(START, "model")
329
- if _tools:
330
- _builder.add_node("tools", ToolNode(_tools))
331
- _builder.add_conditional_edges("model", tools_condition)
332
- _builder.add_edge("tools", "model")
333
- else:
334
- _builder.add_edge("model", END)
335
- {variable} = _builder.compile(checkpointer=MemorySaver())
350
+ def ksadk_graph_factory(*, checkpointer):
351
+ """Compile the graph with a caller-owned checkpoint backend.
352
+
353
+ Studio uses ``MemorySaver`` for local authoring. The hosted KsADK runner
354
+ rebuilds this graph through the same factory with its admitted PostgreSQL
355
+ saver before the first turn, so an interrupt can resume after a Pod move.
356
+ """
357
+ builder = StateGraph(AgentState)
358
+ builder.add_node("model", _call_model)
359
+ builder.add_edge(START, "model")
360
+ if _tools:
361
+ builder.add_node("tools", ToolNode(_tools))
362
+ builder.add_conditional_edges("model", tools_condition)
363
+ builder.add_edge("tools", "model")
364
+ else:
365
+ builder.add_edge("model", END)
366
+ return builder.compile(checkpointer=checkpointer)
367
+
368
+
369
+ {variable} = ksadk_graph_factory(checkpointer=MemorySaver())
336
370
  '''
337
371
 
338
372
 
@@ -0,0 +1,374 @@
1
+ """Build-pinned AgentKernel runtimes owned by the local Studio scheduler.
2
+
3
+ The ordinary Studio conversation path may keep using its historical direct
4
+ RuntimeExecutor or an independently enabled HTTP Kernel. Scheduler Lite owns
5
+ neither of those lifecycles. Instead it lazily starts one in-process Kernel
6
+ runtime for each immutable Build referenced by a local scheduled task.
7
+
8
+ This is intentionally a registry rather than another process-global Kernel:
9
+ one AgentKernelWorker has one concrete RuntimeAdapter factory, so reusing a
10
+ single global worker for multiple Studio Builds can execute the wrong Agent.
11
+ The registry keeps ``Build -> instance -> Runtime`` exact and dispatches every
12
+ occurrence through that runtime's AgentControl Inbox and canonical
13
+ SessionEvent log.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import asyncio
19
+ import hashlib
20
+ from collections.abc import Callable
21
+ from dataclasses import dataclass
22
+ from uuid import uuid4
23
+
24
+ from ksadk.kernel.bootstrap import (
25
+ AgentKernelRuntime,
26
+ AgentKernelRuntimeConfig,
27
+ build_agent_kernel_runtime,
28
+ )
29
+ from ksadk.kernel.contracts import (
30
+ AgentControlCommand,
31
+ AgentControlPermit,
32
+ AgentControlReceipt,
33
+ SessionEventSubscription,
34
+ )
35
+ from ksadk.kernel.ingress import trusted_context
36
+ from ksadk.runtime import RuntimeAdapter
37
+ from ksadk.scheduler.contracts import ScheduledTaskTarget, ScheduleOccurrence
38
+ from ksadk.sessions.base import BaseSessionService
39
+ from ksadk.studio.run_service import StudioRunSpec
40
+
41
+ ResolveBuild = Callable[[str], StudioRunSpec]
42
+ ResolveAdapterProvider = Callable[
43
+ [StudioRunSpec], Callable[[], RuntimeAdapter]
44
+ ]
45
+
46
+
47
+ class StudioSchedulerRuntimeError(RuntimeError):
48
+ """Stable local scheduling failure safe to persist on an occurrence."""
49
+
50
+ def __init__(self, code: str, message: str) -> None:
51
+ super().__init__(message)
52
+ self.code = code
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class StudioScheduledRuntimeTarget:
57
+ """Server-owned immutable routing facts persisted on ScheduledTask/v1."""
58
+
59
+ build_id: str
60
+ agent_id: str
61
+ tenant_id: str
62
+ agent_instance_id: str
63
+
64
+
65
+ @dataclass
66
+ class _RuntimeEntry:
67
+ target: StudioScheduledRuntimeTarget
68
+ spec: StudioRunSpec
69
+ runtime: AgentKernelRuntime
70
+
71
+
72
+ class StudioScheduledKernelRegistry:
73
+ """Own exact per-Build Kernel runtimes for one Studio process.
74
+
75
+ The registry does not register anything in ``ksadk.kernel.ingress`` and
76
+ therefore cannot redirect normal conversations or hosted HTTP traffic.
77
+ Scheduler dispatch uses :meth:`submit` and :meth:`read_events` directly,
78
+ while still crossing the frozen AgentControl permit/admission boundary.
79
+ """
80
+
81
+ def __init__(
82
+ self,
83
+ *,
84
+ resolve_build: ResolveBuild,
85
+ resolve_adapter_provider: ResolveAdapterProvider,
86
+ session_service: BaseSessionService,
87
+ runtime_executor: object | None = None,
88
+ tenant_id: str = "local-studio",
89
+ workspace_id: str = "studio-scheduler",
90
+ poll_interval: float = 0.05,
91
+ lease_ttl_seconds: float = 30.0,
92
+ ) -> None:
93
+ self._resolve_build = resolve_build
94
+ self._resolve_adapter_provider = resolve_adapter_provider
95
+ self._session_service = session_service
96
+ self._runtime_executor = runtime_executor
97
+ self._tenant_id = tenant_id
98
+ self._workspace_id = workspace_id
99
+ self._poll_interval = poll_interval
100
+ self._lease_ttl_seconds = lease_ttl_seconds
101
+ self._owner_id = uuid4().hex
102
+ self._entries_by_build: dict[str, _RuntimeEntry] = {}
103
+ self._build_by_instance: dict[str, str] = {}
104
+ self._lock = asyncio.Lock()
105
+ self._started = False
106
+
107
+ @property
108
+ def started(self) -> bool:
109
+ return self._started
110
+
111
+ @property
112
+ def active_runtime_count(self) -> int:
113
+ return len(self._entries_by_build)
114
+
115
+ async def start(self) -> None:
116
+ self._started = True
117
+
118
+ async def ensure_build(
119
+ self,
120
+ build_id: str,
121
+ *,
122
+ expected_agent_id: str | None = None,
123
+ ) -> StudioScheduledRuntimeTarget:
124
+ """Start or return the exact Runtime owned by one immutable Build."""
125
+
126
+ normalized = str(build_id).strip()
127
+ if not normalized:
128
+ raise StudioSchedulerRuntimeError(
129
+ "SCHEDULER_BUILD_REQUIRED",
130
+ "定时任务缺少不可变 Build 标识",
131
+ )
132
+ if not self._started:
133
+ raise StudioSchedulerRuntimeError(
134
+ "SCHEDULER_RUNTIME_NOT_STARTED",
135
+ "Studio Scheduler Runtime 尚未启动",
136
+ )
137
+ existing = self._entries_by_build.get(normalized)
138
+ if existing is not None:
139
+ self._require_agent(existing.spec, expected_agent_id)
140
+ return existing.target
141
+
142
+ async with self._lock:
143
+ existing = self._entries_by_build.get(normalized)
144
+ if existing is not None:
145
+ self._require_agent(existing.spec, expected_agent_id)
146
+ return existing.target
147
+ try:
148
+ spec = self._resolve_build(normalized)
149
+ except Exception as error:
150
+ raise StudioSchedulerRuntimeError(
151
+ "SCHEDULER_BUILD_UNAVAILABLE",
152
+ f"定时任务绑定的 Build {normalized!r} 不可用",
153
+ ) from error
154
+ if spec.build_id != normalized:
155
+ raise StudioSchedulerRuntimeError(
156
+ "SCHEDULER_BUILD_MISMATCH",
157
+ "Build 解析结果与定时任务绑定不一致",
158
+ )
159
+ self._require_agent(spec, expected_agent_id)
160
+ try:
161
+ adapter_provider = self._resolve_adapter_provider(spec)
162
+ except Exception as error:
163
+ raise StudioSchedulerRuntimeError(
164
+ "SCHEDULER_PROVIDER_UNAVAILABLE",
165
+ f"Build {normalized!r} 的 AgentProvider 不可用",
166
+ ) from error
167
+
168
+ # ``build_agent_kernel_runtime`` asks the provider once to snapshot
169
+ # capabilities. Retain that exact adapter for the first worker or
170
+ # recovery acquisition instead of constructing and discarding a
171
+ # resource-owning Codex/Harness adapter during registration.
172
+ retained_first_adapter: RuntimeAdapter | None = None
173
+ first_adapter_borrowed = False
174
+
175
+ def checked_adapter_provider() -> RuntimeAdapter:
176
+ nonlocal retained_first_adapter, first_adapter_borrowed
177
+ if retained_first_adapter is not None and not first_adapter_borrowed:
178
+ first_adapter_borrowed = True
179
+ adapter = retained_first_adapter
180
+ retained_first_adapter = None
181
+ return adapter
182
+ adapter = adapter_provider()
183
+ if not isinstance(adapter, RuntimeAdapter):
184
+ raise StudioSchedulerRuntimeError(
185
+ "SCHEDULER_PROVIDER_INVALID",
186
+ "AgentProvider 没有返回 RuntimeAdapter",
187
+ )
188
+ if retained_first_adapter is None and not first_adapter_borrowed:
189
+ retained_first_adapter = adapter
190
+ return adapter
191
+
192
+ instance_id = self._instance_id(normalized)
193
+ config = AgentKernelRuntimeConfig(
194
+ agent_instance_id=instance_id,
195
+ authority_mode="local",
196
+ driver="memory",
197
+ durability_tier="ephemeral",
198
+ adapter_provider=checked_adapter_provider,
199
+ session_service=self._session_service,
200
+ runtime_executor=self._runtime_executor,
201
+ launch_context=spec.launch_context,
202
+ start_request_defaults=self._start_defaults(spec),
203
+ tenant_id=self._tenant_id,
204
+ workspace_id=self._workspace_id,
205
+ poll_interval=self._poll_interval,
206
+ lease_ttl_seconds=self._lease_ttl_seconds,
207
+ activation_id=f"studio-scheduler:{self._owner_id}:{instance_id}",
208
+ runtime_type=spec.launch_context.runtime_type,
209
+ bundle_digest=spec.manifest_sha256 or normalized,
210
+ )
211
+ runtime = build_agent_kernel_runtime(config)
212
+ try:
213
+ await runtime.start()
214
+ except Exception:
215
+ await runtime.close()
216
+ raise
217
+ target = StudioScheduledRuntimeTarget(
218
+ build_id=normalized,
219
+ agent_id=spec.agent_id,
220
+ tenant_id=self._tenant_id,
221
+ agent_instance_id=instance_id,
222
+ )
223
+ self._entries_by_build[normalized] = _RuntimeEntry(
224
+ target=target,
225
+ spec=spec,
226
+ runtime=runtime,
227
+ )
228
+ self._build_by_instance[instance_id] = normalized
229
+ return target
230
+
231
+ async def ensure_target(
232
+ self, target: ScheduledTaskTarget
233
+ ) -> StudioScheduledRuntimeTarget:
234
+ build_id = str(target.agent_version_ref or "").strip()
235
+ exact = await self.ensure_build(
236
+ build_id,
237
+ expected_agent_id=target.agent_id,
238
+ )
239
+ if (
240
+ target.tenant_id != exact.tenant_id
241
+ or target.agent_instance_id != exact.agent_instance_id
242
+ ):
243
+ raise StudioSchedulerRuntimeError(
244
+ "SCHEDULER_TARGET_MISMATCH",
245
+ "定时任务目标与不可变 Build 的 Kernel 身份不一致",
246
+ )
247
+ return exact
248
+
249
+ def runtime_for_build(self, build_id: str) -> AgentKernelRuntime:
250
+ entry = self._entries_by_build.get(str(build_id))
251
+ if entry is None:
252
+ raise StudioSchedulerRuntimeError(
253
+ "SCHEDULER_TARGET_UNAVAILABLE",
254
+ "定时任务目标 Kernel 未注册",
255
+ )
256
+ return entry.runtime
257
+
258
+ async def submit(
259
+ self,
260
+ command: AgentControlCommand,
261
+ permit: AgentControlPermit,
262
+ ) -> AgentControlReceipt:
263
+ entry = self._entry_for_instance(command.agent_instance_id)
264
+ if command.tenant_id != entry.target.tenant_id:
265
+ raise StudioSchedulerRuntimeError(
266
+ "SCHEDULER_TARGET_MISMATCH",
267
+ "AgentControl tenant 与 Build Kernel 不一致",
268
+ )
269
+ if await self._session_service.get_session(command.session_id) is None:
270
+ await self._session_service.create_session(
271
+ agent_id=entry.target.agent_id,
272
+ user_id=command.tenant_id,
273
+ session_id=command.session_id,
274
+ )
275
+ return await entry.runtime.kernel.submit(command, permit=permit)
276
+
277
+ async def read_events(
278
+ self, occurrence: ScheduleOccurrence
279
+ ) -> tuple[tuple[int, object], ...]:
280
+ target = occurrence.target
281
+ if target is None:
282
+ return ()
283
+ await self.ensure_target(target)
284
+ entry = self._entry_for_instance(target.agent_instance_id)
285
+ trusted = trusted_context(
286
+ source_kind="scheduler",
287
+ source_ref=occurrence.occurrence_id,
288
+ tenant_id=target.tenant_id,
289
+ agent_instance_id=target.agent_instance_id,
290
+ session_id=occurrence.session_id,
291
+ operations=("subscribe_events",),
292
+ )
293
+ cursor = occurrence.last_event_seq
294
+ if cursor is None:
295
+ cursor = occurrence.accepted_seq or 0
296
+ subscription = SessionEventSubscription(
297
+ tenant_id=trusted.tenant_id,
298
+ agent_instance_id=trusted.agent_instance_id,
299
+ session_id=occurrence.session_id,
300
+ authorization_ref=trusted.permit.permit_id,
301
+ after_seq=cursor,
302
+ )
303
+ result: list[tuple[int, object]] = []
304
+ stream = entry.runtime.kernel.subscribe(
305
+ subscription,
306
+ permit=trusted.permit,
307
+ timeout=0.05,
308
+ )
309
+ try:
310
+ async for envelope in stream:
311
+ result.append((int(envelope.seq), envelope))
312
+ if len(result) >= 100:
313
+ break
314
+ finally:
315
+ await stream.aclose()
316
+ return tuple(result)
317
+
318
+ async def close(self) -> None:
319
+ async with self._lock:
320
+ entries = list(self._entries_by_build.values())
321
+ self._entries_by_build.clear()
322
+ self._build_by_instance.clear()
323
+ self._started = False
324
+ first_error: BaseException | None = None
325
+ for entry in reversed(entries):
326
+ try:
327
+ await entry.runtime.close()
328
+ except BaseException as error: # cleanup must continue for other Builds
329
+ if first_error is None:
330
+ first_error = error
331
+ if first_error is not None:
332
+ raise first_error
333
+
334
+ def _entry_for_instance(self, instance_id: str) -> _RuntimeEntry:
335
+ build_id = self._build_by_instance.get(str(instance_id))
336
+ entry = self._entries_by_build.get(build_id or "")
337
+ if entry is None:
338
+ raise StudioSchedulerRuntimeError(
339
+ "SCHEDULER_TARGET_UNAVAILABLE",
340
+ "定时任务目标 Kernel 未注册",
341
+ )
342
+ return entry
343
+
344
+ def _instance_id(self, build_id: str) -> str:
345
+ digest = hashlib.sha256(build_id.encode("utf-8")).hexdigest()[:24]
346
+ return f"studio-schedule-{digest}"
347
+
348
+ @staticmethod
349
+ def _require_agent(spec: StudioRunSpec, expected_agent_id: str | None) -> None:
350
+ if expected_agent_id and spec.agent_id != expected_agent_id:
351
+ raise StudioSchedulerRuntimeError(
352
+ "SCHEDULER_AGENT_MISMATCH",
353
+ "定时任务 Agent 与不可变 Build 不一致",
354
+ )
355
+
356
+ @staticmethod
357
+ def _start_defaults(spec: StudioRunSpec) -> dict[str, object]:
358
+ defaults: dict[str, object] = {
359
+ "agent_id": spec.agent_id,
360
+ "config": dict(spec.request_config),
361
+ }
362
+ if spec.model:
363
+ defaults["model"] = spec.model
364
+ defaults["allowed_models"] = [spec.model]
365
+ return defaults
366
+
367
+
368
+ __all__ = [
369
+ "ResolveAdapterProvider",
370
+ "ResolveBuild",
371
+ "StudioScheduledKernelRegistry",
372
+ "StudioScheduledRuntimeTarget",
373
+ "StudioSchedulerRuntimeError",
374
+ ]