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
ksadk/server/factory.py CHANGED
@@ -194,6 +194,7 @@ class RuntimeAppConfig:
194
194
  agui: Optional[Any] = None,
195
195
  runtime_executor: RuntimeExecutor | None = None,
196
196
  launch_context: RuntimeLaunchContext | None = None,
197
+ kernel_adapter_provider: Callable[[], RuntimeAdapter] | None = None,
197
198
  session_service_provider: Callable[[], Any] | None = None,
198
199
  session_backend_provider: Callable[[], dict[str, Any]] | None = None,
199
200
  ) -> None:
@@ -208,6 +209,9 @@ class RuntimeAppConfig:
208
209
  self.agui = agui
209
210
  self.runtime_executor = runtime_executor
210
211
  self.launch_context = launch_context
212
+ # 特殊 runtime 可显式提供 worker/recovery 的 adapter;常规部署从
213
+ # runtime_executor 的同一 registry 派生,见 _kernel_adapter_provider。
214
+ self.kernel_adapter_provider = kernel_adapter_provider
211
215
  self.session_service_provider = session_service_provider
212
216
  self.session_backend_provider = session_backend_provider
213
217
 
@@ -353,6 +357,40 @@ def create_runtime_app(
353
357
 
354
358
  @asynccontextmanager
355
359
  async def _lifespan(app: FastAPI) -> AsyncIterator[None]:
360
+ # 生产 kernel 的 composition root 必须启动 worker/lease/recovery,
361
+ # 不能只注册一个可接收命令、却永远不会消费的 ingress kernel。
362
+ from ksadk.kernel import ingress as _kernel_ingress
363
+ from ksadk.kernel.bootstrap import (
364
+ bootstrap_agent_kernel_runtime_from_env,
365
+ clear_agent_kernel_runtime,
366
+ )
367
+ from ksadk.runtime.factory import kernel_start_request_defaults
368
+
369
+ adapter_provider = _kernel_adapter_provider(config)
370
+ request_defaults = (
371
+ kernel_start_request_defaults(config.launch_context)
372
+ if config.launch_context is not None
373
+ else {}
374
+ )
375
+ kernel_runtime = await bootstrap_agent_kernel_runtime_from_env(
376
+ adapter_provider=adapter_provider,
377
+ runtime_executor=config.runtime_executor,
378
+ launch_context=config.launch_context,
379
+ start_request_defaults=request_defaults,
380
+ session_service=state.resolve_session_service(),
381
+ )
382
+ app.state.agent_kernel_runtime = kernel_runtime
383
+ if kernel_runtime is not None:
384
+ # Kernel canonical events are the replay authority for the normal
385
+ # Session APIs as well. In memory/ephemeral mode bootstrap reuses
386
+ # the app-owned service above; in PostgreSQL mode it owns the
387
+ # durable service and the HTTP routes must adopt that exact one.
388
+ # Keeping two services made foreground SSE look correct while a
389
+ # later ListSessionEvents call returned an empty history forever.
390
+ kernel_session_service = kernel_runtime.config.session_service
391
+ if kernel_session_service is None: # pragma: no cover - defensive
392
+ raise RuntimeError("agent kernel runtime has no Session service")
393
+ state.session_service = kernel_session_service
356
394
  try:
357
395
  if state.a2a_bootstrap is not None:
358
396
  await state.a2a_bootstrap.start()
@@ -360,6 +398,10 @@ def create_runtime_app(
360
398
  finally:
361
399
  if state.a2a_bootstrap is not None:
362
400
  await state.a2a_bootstrap.stop()
401
+ if kernel_runtime is not None:
402
+ await kernel_runtime.close()
403
+ clear_agent_kernel_runtime()
404
+ _kernel_ingress.clear_agent_kernel()
363
405
  await shutdown_runtime_resources(state)
364
406
 
365
407
  app = FastAPI(
@@ -488,6 +530,25 @@ def create_runtime_app(
488
530
  return app
489
531
 
490
532
 
533
+ def _kernel_adapter_provider(
534
+ config: RuntimeAppConfig,
535
+ ) -> Callable[[], RuntimeAdapter] | None:
536
+ """Return the adapter source used by the durable kernel runtime.
537
+
538
+ Hosted startup deliberately fails when neither a provider nor a Runtime
539
+ launch context is available. It must never construct an unrelated local
540
+ adapter merely to make the ingress look healthy.
541
+ """
542
+
543
+ if config.kernel_adapter_provider is not None:
544
+ return config.kernel_adapter_provider
545
+ if config.a2a_runtime_adapter is not None:
546
+ return lambda: config.a2a_runtime_adapter
547
+ if config.runtime_executor is not None and config.launch_context is not None:
548
+ return lambda: config.runtime_executor.create_adapter(config.launch_context)
549
+ return None
550
+
551
+
491
552
  def _wire_a2a_if_enabled(app: FastAPI, state: RuntimeAppState, config: RuntimeAppConfig) -> None:
492
553
  """Mount A2A with an explicitly injected RuntimeAdapter.
493
554
 
@@ -569,15 +630,17 @@ def _wire_agui_if_enabled(app: FastAPI, state: RuntimeAppState, config: RuntimeA
569
630
  self._service = service
570
631
  self._store = RuntimeEventStore(service)
571
632
 
572
- async def append_one(self, event: Any) -> Any:
573
- existing = await self._service.get_session(event.session_id)
633
+ async def append_one(self, session_id: str, event: Any) -> Any:
634
+ existing = await self._service.get_session(session_id)
574
635
  if existing is None:
636
+ metadata = getattr(event, "source", None)
637
+ meta = metadata.metadata if metadata is not None else {}
575
638
  await self._service.create_session(
576
- event.agent_id,
577
- event.user_id,
578
- event.session_id,
639
+ str(meta.get("agent_id") or "agent"),
640
+ str(meta.get("user_id") or "user"),
641
+ session_id,
579
642
  )
580
- return await self._store.append_one(event)
643
+ return await self._store.append_one(session_id, event)
581
644
 
582
645
  async def reserve_once(self, event: Any) -> Any:
583
646
  existing = await self._service.get_session(event.session_id)
@@ -0,0 +1,258 @@
1
+ # -*- coding: utf-8 -*-
2
+ """RunAgent / Responses 入口的 kernel 路径(Phase 1 Task 8 Step 3-5)。
3
+
4
+ 只在 ``kernel_route_active()`` 时启用(灰度 opt-in);旧 HTTP 行为保持兼容:
5
+ - accepted -> 202、duplicate -> 200、rejected -> 400、unsupported -> 409、
6
+ queue_full -> 429、persistence_uncertain -> 503(RECEIPT_HTTP_STATUS)。
7
+ - 旧响应 shape 不变;非流式在 receipt accepted 后才开始消费 stream。
8
+ - SSE 的 reconnect cursor 源自同一 Session seq(SessionEventSubscription)。
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import logging
15
+ from typing import Any
16
+
17
+ from fastapi.responses import JSONResponse, StreamingResponse
18
+
19
+ from ksadk.kernel import ingress
20
+ from ksadk.kernel.contracts import AgentControlReceipt
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ def _envelope_text(payload: dict[str, Any]) -> str:
26
+ return str(payload.get("delta") or payload.get("text") or "")
27
+
28
+
29
+ async def _kernel_submit(
30
+ *,
31
+ mapper: str,
32
+ session_id: str,
33
+ idempotency_key: str,
34
+ content: Any,
35
+ correlation_ref: str | None,
36
+ source_kind: str,
37
+ runtime_options: dict[str, Any] | None = None,
38
+ ) -> tuple[AgentControlReceipt, ingress.TrustedRuntimeContext]:
39
+ trusted = ingress.trusted_context(
40
+ source_kind=source_kind,
41
+ source_ref=idempotency_key,
42
+ session_id=session_id,
43
+ # A foreground compatibility request admits a mutation and then reads
44
+ # the same session's canonical stream. It remains session-bound, but
45
+ # needs explicit authority for both operations.
46
+ operations=("enqueue", "subscribe_events"),
47
+ )
48
+ correlation_kwarg = {
49
+ "map_run_request": "invocation_id",
50
+ "map_responses_request": "response_id",
51
+ "map_agui_request": "run_id",
52
+ "map_a2a_task": "task_id",
53
+ "map_studio_request": "run_id",
54
+ }[mapper]
55
+ command = getattr(ingress, mapper)(
56
+ trusted=trusted,
57
+ session_id=session_id,
58
+ idempotency_key=idempotency_key,
59
+ content=content,
60
+ **({correlation_kwarg: correlation_ref} if correlation_ref else {}),
61
+ **({"runtime_options": runtime_options} if runtime_options else {}),
62
+ )
63
+ receipt = await ingress.submit_command(command, permit=trusted.permit)
64
+ return receipt, trusted
65
+
66
+
67
+ def _kernel_error_response(receipt: AgentControlReceipt) -> JSONResponse:
68
+ return JSONResponse(
69
+ status_code=ingress.receipt_http_status(receipt),
70
+ content={
71
+ "error": ingress.receipt_error_payload(receipt),
72
+ },
73
+ headers=ingress.receipt_response_headers(receipt),
74
+ )
75
+
76
+
77
+ def _sse_chunk(payload: dict[str, Any], *, event: str | None, seq: int) -> str:
78
+ prefix = f"event: {event}\n" if event else ""
79
+ return f"id: {seq}\n{prefix}data: {json.dumps(payload, ensure_ascii=False)}\n\n"
80
+
81
+
82
+ def kernel_stream_response(
83
+ *,
84
+ receipt: AgentControlReceipt,
85
+ trusted: ingress.TrustedRuntimeContext,
86
+ session_id: str,
87
+ ) -> StreamingResponse:
88
+ """统一 cursor:从 receipt.accepted_seq 之后读 Session 事件。"""
89
+
90
+ after_seq = int(receipt.accepted_seq or 0)
91
+
92
+ async def generator():
93
+ async for seq, projected in ingress.subscribe_projected(
94
+ session_id,
95
+ trusted=trusted,
96
+ after_seq=after_seq,
97
+ projector=_new_responses_projector(),
98
+ ):
99
+ if projected is None:
100
+ continue
101
+ kind, payload = projected
102
+ yield _sse_chunk(payload, event=kind, seq=seq)
103
+ if kind == "response.output_item.done" and (
104
+ (payload.get("item") or {}).get("type") == "mcp_approval_request"
105
+ ):
106
+ yield _sse_chunk(
107
+ {"type": "response.incomplete"},
108
+ event="response.incomplete",
109
+ seq=seq,
110
+ )
111
+ return
112
+ # A foreground response stream is scoped to one admitted run.
113
+ # SessionEventStore subscriptions are deliberately long-lived for
114
+ # replay/SSE clients, so do not leave this HTTP response open after
115
+ # the terminal fact has been projected.
116
+ if kind in {"response.completed", "response.failed", "response.canceled"}:
117
+ return
118
+
119
+ return StreamingResponse(generator(), media_type="text/event-stream")
120
+
121
+
122
+ def _responses_projector(envelope: Any) -> tuple[str, dict[str, Any]] | None:
123
+ """Session envelope -> 旧 Responses SSE shape(cursor 仍用 envelope.seq)。"""
124
+
125
+ payload = envelope.payload or {}
126
+ event_type = envelope.event_type
127
+ if event_type == "interaction.requested":
128
+ request = payload.get("request") or {}
129
+ presentation = request.get("presentation") or {}
130
+ description = presentation.get("description") or ""
131
+ try:
132
+ visible = json.loads(description) if description else {}
133
+ except (TypeError, json.JSONDecodeError):
134
+ visible = {}
135
+ arguments = visible.get("arguments") if isinstance(visible, dict) else {}
136
+ return "response.output_item.done", {
137
+ "type": "response.output_item.done",
138
+ "item": {
139
+ "id": str(payload.get("interaction_id") or ""),
140
+ "type": "mcp_approval_request",
141
+ "name": str(presentation.get("title") or payload.get("kind") or "approval"),
142
+ "arguments": json.dumps(arguments or {}, ensure_ascii=False),
143
+ },
144
+ }
145
+ if event_type == "run.completed":
146
+ text = str(payload.get("output_text") or "")
147
+ return "response.completed", {
148
+ "type": "response.completed",
149
+ "output_text": text,
150
+ "delta": text,
151
+ }
152
+ if event_type == "run.failed":
153
+ return "response.failed", {
154
+ "type": "response.failed",
155
+ "error": payload.get("error") or {"code": "runtime_failed"},
156
+ }
157
+ if event_type in {"run.canceled", "run.interrupted"}:
158
+ return "response.canceled", {
159
+ "type": "response.canceled",
160
+ "reason": payload.get("reason") or event_type,
161
+ }
162
+ text = _envelope_text(payload)
163
+ if text:
164
+ return "response.output_text.delta", {
165
+ "type": "response.output_text.delta",
166
+ "delta": text,
167
+ }
168
+ return None
169
+
170
+
171
+ def _new_responses_projector():
172
+ """Create a session-scoped canonical RuntimeEvent -> Responses projector.
173
+
174
+ ``run.completed.output_refs`` deliberately point at canonical items instead
175
+ of duplicating answer text. A projector therefore keeps only the small
176
+ item snapshot needed for this one HTTP/SSE response and resolves those
177
+ refs when the terminal fact arrives.
178
+ """
179
+
180
+ item_text: dict[str, str] = {}
181
+
182
+ def project(envelope: Any) -> tuple[str, dict[str, Any]] | None:
183
+ payload = envelope.payload or {}
184
+ event_type = envelope.event_type
185
+ if event_type == "item.updated":
186
+ item_id = str(payload.get("item_id") or "")
187
+ update = payload.get("update") or {}
188
+ text = str(update.get("text") or "")
189
+ if item_id and text:
190
+ item_text[item_id] = (
191
+ text if payload.get("op") == "replace" else item_text.get(item_id, "") + text
192
+ )
193
+ return None
194
+ if event_type == "item.completed":
195
+ item_id = str(payload.get("item_id") or "")
196
+ parts = (payload.get("snapshot") or {}).get("parts") or []
197
+ if item_id and isinstance(parts, list):
198
+ item_text[item_id] = "".join(
199
+ str(part.get("text") or "") for part in parts if isinstance(part, dict)
200
+ )
201
+ return None
202
+ if event_type == "run.completed":
203
+ refs = payload.get("output_refs") or []
204
+ output = "".join(
205
+ item_text.get(str(ref.get("item_id") or ""), "")
206
+ for ref in refs
207
+ if isinstance(ref, dict)
208
+ )
209
+ projected_payload = dict(payload)
210
+ projected_payload["output_text"] = output or str(payload.get("output_text") or "")
211
+ return _responses_projector(
212
+ type("Envelope", (), {"event_type": event_type, "payload": projected_payload})()
213
+ )
214
+ return _responses_projector(envelope)
215
+
216
+ return project
217
+
218
+
219
+ async def kernel_conversation_turn(
220
+ *,
221
+ receipt: AgentControlReceipt,
222
+ trusted: ingress.TrustedRuntimeContext,
223
+ session_id: str,
224
+ build_payload,
225
+ ):
226
+ """非流式 kernel 路径:receipt accepted 后订阅聚合 output_text。"""
227
+
228
+ if receipt.status not in ("accepted", "duplicate"):
229
+ return _kernel_error_response(receipt)
230
+ output_text = ""
231
+ async for _seq, projected in ingress.subscribe_projected(
232
+ session_id,
233
+ trusted=trusted,
234
+ after_seq=int(receipt.accepted_seq or 0),
235
+ projector=_new_responses_projector(),
236
+ ):
237
+ if projected and projected[0] == "response.completed":
238
+ output_text = str(projected[1].get("output_text") or output_text)
239
+ break
240
+ if projected and projected[0] in {"response.failed", "response.canceled"}:
241
+ return JSONResponse(
242
+ status_code=502,
243
+ content={"error": projected[1]},
244
+ )
245
+ elif projected:
246
+ output_text += str(projected[1].get("delta") or "")
247
+ payload = build_payload(output_text)
248
+ return JSONResponse(
249
+ status_code=ingress.receipt_http_status(receipt),
250
+ content=payload,
251
+ headers=ingress.receipt_response_headers(receipt),
252
+ )
253
+
254
+
255
+ __all__ = [
256
+ "kernel_conversation_turn",
257
+ "kernel_stream_response",
258
+ ]
@@ -6,6 +6,7 @@ import uuid
6
6
  from collections.abc import Mapping
7
7
  from typing import Any, Dict, List, Optional
8
8
 
9
+ from fastapi import HTTPException
9
10
  from fastapi.responses import StreamingResponse
10
11
  from pydantic import BaseModel
11
12
 
@@ -20,11 +21,18 @@ from ksadk.conversations.runtime_streaming import (
20
21
  stream_runtime_conversation_turn,
21
22
  stream_runtime_responses_conversation_turn,
22
23
  )
24
+ from ksadk.kernel.ingress import kernel_route_active
23
25
  from ksadk.runtime.conversation_execution import invoke_runtime_conversation_once
24
26
  from ksadk.server.factory import get_runtime_execution
25
27
 
26
28
  from . import dependencies as deps
27
29
  from .checkpoint_resolution import _resolve_checkpoint_resume_input_from_session
30
+ from .kernel_ingress import (
31
+ _kernel_error_response,
32
+ _kernel_submit,
33
+ kernel_conversation_turn,
34
+ kernel_stream_response,
35
+ )
28
36
  from .models import (
29
37
  ResponsesRequest,
30
38
  _clean_optional_string,
@@ -60,6 +68,26 @@ async def list_openai_models():
60
68
  """Expose the current model catalog through the OpenAI-compatible path."""
61
69
 
62
70
  payload = await _build_models_payload()
71
+ try:
72
+ _executor, launch_context = get_runtime_execution()
73
+ except HTTPException:
74
+ launch_context = None
75
+ if launch_context is not None:
76
+ config = dict(launch_context.config)
77
+ raw_allowed = (
78
+ config.get("models") or config.get("allowed_models") or config.get("allowedModels")
79
+ )
80
+ if isinstance(raw_allowed, (list, tuple, set)):
81
+ allowed = {str(item).strip() for item in raw_allowed if str(item).strip()}
82
+ default_model = str(config.get("model") or "").strip()
83
+ if default_model:
84
+ allowed.add(default_model)
85
+ payload = dict(payload)
86
+ payload["data"] = [
87
+ item
88
+ for item in payload.get("data", [])
89
+ if str(item.get("id") or "").strip() in allowed
90
+ ]
63
91
  return {
64
92
  "object": "list",
65
93
  "data": payload.get("data", []),
@@ -72,6 +100,8 @@ async def list_openai_models():
72
100
  async def responses(request: ResponsesRequest):
73
101
  """OpenAI Responses 兼容接口。"""
74
102
  executor, launch_context = get_runtime_execution()
103
+ if kernel_route_active():
104
+ return await _kernel_responses(request, launch_context)
75
105
  resolved_session_id, resolved_user_id = _resolve_responses_session_and_user(request)
76
106
  agent_id = _runtime_agent_id(launch_context)
77
107
 
@@ -82,11 +112,7 @@ async def responses(request: ResponsesRequest):
82
112
  session_id=resolved_session_id,
83
113
  resume_input=resume_input,
84
114
  )
85
- messages = (
86
- []
87
- if resume_input is not None
88
- else normalize_responses_input(request.input)
89
- )
115
+ messages = [] if resume_input is not None else normalize_responses_input(request.input)
90
116
  custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
91
117
  if request.previous_response_id:
92
118
  request_metadata["previous_response_id"] = request.previous_response_id
@@ -105,9 +131,7 @@ async def responses(request: ResponsesRequest):
105
131
 
106
132
  if request.stream:
107
133
  runtime_preparation = (
108
- None
109
- if resume_input is not None
110
- else await executor.prepare_start(launch_context)
134
+ None if resume_input is not None else await executor.prepare_start(launch_context)
111
135
  )
112
136
  resume_key = _detached_resume_key_from_input(resolved_session_id, resume_input)
113
137
  _reject_if_detached_resume_active(resume_key)
@@ -169,6 +193,62 @@ async def responses(request: ResponsesRequest):
169
193
  )
170
194
 
171
195
 
196
+ async def _kernel_responses(request: ResponsesRequest, launch_context):
197
+ """kernel 路径(灰度 opt-in):Responses -> AgentControlCommand -> receipt。"""
198
+
199
+ from ksadk.conversations.runtime_persistence import ensure_conversation_session
200
+
201
+ resolved_session_id, resolved_user_id = _resolve_responses_session_and_user(request)
202
+ session = await ensure_conversation_session(
203
+ agent_id=_runtime_agent_id(launch_context),
204
+ user_id=resolved_user_id,
205
+ session_id=resolved_session_id,
206
+ session_service_provider=deps.resolve_session_service,
207
+ )
208
+ session_id = session.id
209
+ metadata = request.metadata if isinstance(request.metadata, dict) else {}
210
+ idempotency_key = (
211
+ _clean_optional_string(metadata.get("idempotency_key"))
212
+ or _metadata_invocation_id(metadata)
213
+ or f"resp_{uuid.uuid4().hex}"
214
+ )
215
+ messages = normalize_responses_input(request.input)
216
+ response_id = f"resp_{uuid.uuid4().hex}"
217
+ receipt, trusted = await _kernel_submit(
218
+ mapper="map_responses_request",
219
+ session_id=session_id,
220
+ idempotency_key=idempotency_key,
221
+ content=messages,
222
+ correlation_ref=response_id,
223
+ source_kind="responses",
224
+ )
225
+ if receipt.status not in ("accepted", "duplicate"):
226
+ return _kernel_error_response(receipt)
227
+
228
+ def build_payload(output_text: str):
229
+ return build_responses_payload(
230
+ output_text=output_text,
231
+ model=request.model,
232
+ session_id=session_id,
233
+ response_id=response_id,
234
+ metadata=None,
235
+ usage=None,
236
+ )
237
+
238
+ if request.stream:
239
+ return kernel_stream_response(
240
+ receipt=receipt,
241
+ trusted=trusted,
242
+ session_id=session_id,
243
+ )
244
+ return await kernel_conversation_turn(
245
+ receipt=receipt,
246
+ trusted=trusted,
247
+ session_id=session_id,
248
+ build_payload=build_payload,
249
+ )
250
+
251
+
172
252
  @openai_compat_router.post("/v1/chat/completions")
173
253
  async def chat_completions(request: ChatCompletionRequest):
174
254
  """OpenAI 兼容的聊天补全接口 (支持流式和非流式)"""
@@ -15,7 +15,8 @@ from ksadk.conversations.session_title import (
15
15
  build_fallback_title,
16
16
  build_heuristic_title,
17
17
  )
18
- from ksadk.events.runtime_event import EventType
18
+ from ksadk.events.canonical import ContinuationCreated
19
+ from ksadk.events.canonical_store import session_event_to_runtime_event
19
20
  from ksadk.server.factory import get_runtime_execution, get_state
20
21
  from ksadk.sessions import Session, SessionEvent
21
22
 
@@ -149,6 +150,13 @@ def _runtime_continuity_payload() -> dict[str, Any]:
149
150
 
150
151
 
151
152
  def _event_to_action_payload(event: SessionEvent) -> dict[str, Any]:
153
+ """Serialize a stored SessionEvent for the REST action wire.
154
+
155
+ 公开承诺字段(契约声明见 ``ksadk/events/projections.py``):
156
+ ``EventId``/``SessionId``/``Author``/``EventType``/``Content``/``Timestamp``/
157
+ ``SeqId``(有值时附 ``InvocationId``)。这是存储事件形态本身的透传,
158
+ ``Content``/``Metadata`` 的内部结构不在承诺范围。
159
+ """
152
160
  payload = {
153
161
  "EventId": event.id,
154
162
  "SessionId": event.session_id,
@@ -231,34 +239,41 @@ async def _iter_with_idle_heartbeat(source: AsyncIterator[Any]):
231
239
 
232
240
 
233
241
  def _checkpoint_event_to_action_payload(event: SessionEvent) -> dict[str, Any] | None:
242
+ """Project a checkpoint-bearing event into the REST checkpoint action payload.
243
+
244
+ 公开承诺字段(契约声明见 ``ksadk/events/projections.py``):``EventId``/
245
+ ``SessionId``/``InvocationId``/``SeqId``/``Timestamp``/``RunId``/
246
+ ``CheckpointId``/``Framework``/``FrameworkRef``/``IsResumable``/
247
+ ``ResumeStatus``/``IsTerminal``/``NextNode``。来源为显式 ``run_checkpoint``
248
+ 事件元数据,或 ``continuation.created`` canonical 事件的投影。
249
+ 非 checkpoint 事件(或不可识别的 continuation_kind)返回 ``None``。
250
+ 内部不保证字段:其余元数据透传键(``Metadata`` 内容随存储演进可变)。
251
+ """
234
252
  if event.event_type == "run_checkpoint":
235
253
  metadata = event.metadata or {}
236
- elif event.event_type == EventType.CHECKPOINT_CREATED:
237
- content = event.content or {}
238
- payload = content.get("payload") if isinstance(content, Mapping) else {}
239
- if not isinstance(payload, Mapping):
254
+ else:
255
+ canonical = session_event_to_runtime_event(event)
256
+ if not isinstance(canonical, ContinuationCreated):
240
257
  return None
241
- framework_ref = payload.get("framework_ref") or payload.get("resume_target") or {}
242
- if not isinstance(framework_ref, Mapping):
243
- framework_ref = {}
244
- framework = str(payload.get("framework") or "").strip()
245
- if not framework and len(framework_ref) == 1:
246
- framework = str(next(iter(framework_ref)))
247
- capability = payload.get("capability")
258
+ if canonical.continuation_kind != "graph_checkpoint":
259
+ return None
260
+ framework = canonical.source.framework
261
+ framework_ref = {framework: dict(canonical.ref)}
262
+ capability = canonical.source.metadata.get("capability")
248
263
  capability = capability if isinstance(capability, Mapping) else {}
249
264
  metadata = {
250
265
  **dict(event.metadata or {}),
251
- "run_id": str(payload.get("run_id") or event.invocation_id or ""),
252
- "checkpoint_id": str(payload.get("checkpoint_id") or ""),
266
+ **dict(canonical.source.metadata),
267
+ "continuation_kind": canonical.continuation_kind,
268
+ "run_id": canonical.run_id,
269
+ "checkpoint_id": canonical.continuation_id,
253
270
  "framework": framework,
254
271
  "framework_ref": dict(framework_ref),
255
- "backend": str(payload.get("backend") or capability.get("backend") or "unknown"),
256
- "scope": str(payload.get("scope") or capability.get("scope") or "unknown"),
257
- "durable": bool(payload.get("durable", capability.get("durable", False))),
258
- "is_resumable": bool(payload.get("is_resumable", True)),
272
+ "backend": str(capability.get("backend") or "unknown"),
273
+ "scope": str(capability.get("scope") or "unknown"),
274
+ "durable": bool(capability.get("durable", False)),
275
+ "is_resumable": canonical.resumable,
259
276
  }
260
- else:
261
- return None
262
277
  run_id = str(metadata.get("run_id") or "").strip()
263
278
  checkpoint_id = str(metadata.get("checkpoint_id") or "").strip()
264
279
  framework = str(metadata.get("framework") or "").strip()