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
@@ -0,0 +1,21 @@
1
+ """Local SQLite session 存储的表名常量(纯移动自 local_service,行为不变)。"""
2
+
3
+ KSADK_SESSIONS_TABLE = "ksadk_sessions"
4
+ KSADK_EVENTS_TABLE = "ksadk_events"
5
+ KSADK_STATES_TABLE = "ksadk_states"
6
+
7
+ LEGACY_SESSIONS_TABLE = "sessions"
8
+ LEGACY_EVENTS_TABLE = "events"
9
+ LEGACY_STATES_TABLE = "states"
10
+
11
+ DEFAULT_SESSION_DB_NAME = "sessions.sqlite"
12
+
13
+ __all__ = [
14
+ "DEFAULT_SESSION_DB_NAME",
15
+ "KSADK_EVENTS_TABLE",
16
+ "KSADK_SESSIONS_TABLE",
17
+ "KSADK_STATES_TABLE",
18
+ "LEGACY_EVENTS_TABLE",
19
+ "LEGACY_SESSIONS_TABLE",
20
+ "LEGACY_STATES_TABLE",
21
+ ]
@@ -0,0 +1,305 @@
1
+ """PostgresSessionService 的 schema 初始化/迁移 DDL(纯移动自 postgres_service,行为不变)。
2
+
3
+ 以 mixin 形式被 :class:`PostgresSessionService` 继承,依赖宿主提供
4
+ ``_schema_ready`` / ``_schema_lock`` / ``_ensure_pool`` / ``_pool``。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ from typing import Any
11
+
12
+ from ksadk.sessions._postgres_tables import (
13
+ _PG_SCHEMA_ADVISORY_LOCK_KEY,
14
+ KSADK_PG_EVENTS_TABLE,
15
+ KSADK_PG_SESSIONS_TABLE,
16
+ KSADK_PG_STATES_TABLE,
17
+ PG_READABLE_EVENTS_VIEW,
18
+ )
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class _PostgresSchemaMixin:
24
+ async def _ensure_schema(self) -> None:
25
+ if self._schema_ready:
26
+ return
27
+ async with self._schema_lock:
28
+ if self._schema_ready:
29
+ return
30
+ await self._ensure_pool()
31
+ async with self._pool.acquire() as connection:
32
+ # A new service instance normally points at an already-current
33
+ # shared schema. Avoid taking any DDL lock in that hot path;
34
+ # otherwise a cold initializer can deadlock with a ready pod's
35
+ # concurrent event INSERT.
36
+ if await self._core_schema_is_current(connection):
37
+ self._schema_ready = True
38
+ return
39
+
40
+ migrated = False
41
+ async with connection.transaction():
42
+ # Instance-local asyncio locks cannot coordinate pods. The
43
+ # transaction-scoped database lock serializes true schema
44
+ # creation/migration, then the second shape check lets a
45
+ # waiting initializer skip duplicate DDL.
46
+ await connection.execute(
47
+ "SELECT pg_advisory_xact_lock($1)",
48
+ _PG_SCHEMA_ADVISORY_LOCK_KEY,
49
+ )
50
+ if not await self._core_schema_is_current(connection):
51
+ await self._create_core_schema(connection)
52
+ if not await self._core_schema_is_current(connection):
53
+ raise RuntimeError(
54
+ "Postgres session schema migration did not produce "
55
+ "the required core shape"
56
+ )
57
+ migrated = True
58
+
59
+ # The readable view is optional. Create it only for the one
60
+ # initializer that changed core schema, after the core DDL has
61
+ # committed so a view permission error cannot roll it back.
62
+ if migrated:
63
+ try:
64
+ await connection.execute(f"""
65
+ CREATE OR REPLACE VIEW {PG_READABLE_EVENTS_VIEW} AS
66
+ SELECT
67
+ event_row.namespace,
68
+ event_row.tenant_id,
69
+ event_row.workspace_id,
70
+ session_row.agent_id,
71
+ session_row.user_id,
72
+ session_row.title AS session_title,
73
+ event_row.session_id,
74
+ event_row.seq_id,
75
+ event_row.id AS event_id,
76
+ event_row.invocation_id,
77
+ event_row.author,
78
+ event_row.event_type,
79
+ CASE
80
+ WHEN event_row.event_type = 'user_message' THEN 'user'
81
+ WHEN event_row.event_type IN (
82
+ 'assistant_message', 'reasoning', 'tool_call'
83
+ ) THEN 'assistant'
84
+ WHEN event_row.event_type = 'tool_result' THEN 'tool'
85
+ ELSE NULL
86
+ END AS message_role,
87
+ COALESCE(
88
+ NULLIF(event_row.content_json #>> '{{parts,0,text}}', ''),
89
+ NULLIF(event_row.content_json ->> 'text', ''),
90
+ NULLIF(event_row.metadata_json ->> 'reasoning', ''),
91
+ NULLIF(event_row.metadata_json ->> 'tool_output', '')
92
+ ) AS message_text,
93
+ event_row.metadata_json ->> 'tool_name' AS tool_name,
94
+ CASE
95
+ WHEN event_row.event_type = 'run_status' THEN COALESCE(
96
+ event_row.content_json ->> 'status',
97
+ event_row.metadata_json ->> 'status'
98
+ )
99
+ ELSE NULL
100
+ END AS lifecycle_status,
101
+ to_timestamp(event_row.timestamp) AS created_at,
102
+ event_row.content_json,
103
+ event_row.state_delta_json,
104
+ event_row.metadata_json
105
+ FROM {KSADK_PG_EVENTS_TABLE} AS event_row
106
+ JOIN {KSADK_PG_SESSIONS_TABLE} AS session_row
107
+ ON session_row.namespace = event_row.namespace
108
+ AND session_row.id = event_row.session_id;
109
+ """)
110
+ except Exception as exc:
111
+ logger.warning("Postgres readable session view unavailable: %s", exc)
112
+ self._schema_ready = True
113
+
114
+ @staticmethod
115
+ async def _core_schema_is_current(connection: Any) -> bool:
116
+ return bool(await connection.fetchval(f"""
117
+ SELECT
118
+ to_regclass('{KSADK_PG_SESSIONS_TABLE}') IS NOT NULL
119
+ AND to_regclass('{KSADK_PG_EVENTS_TABLE}') IS NOT NULL
120
+ AND to_regclass('{KSADK_PG_STATES_TABLE}') IS NOT NULL
121
+ AND to_regclass('idx_ksadk_pg_events_session_seq') IS NOT NULL
122
+ AND to_regclass('idx_ksadk_pg_events_session_invocation_seq') IS NOT NULL
123
+ AND to_regclass('idx_ksadk_pg_events_session_ts') IS NOT NULL
124
+ AND to_regclass('idx_ksadk_pg_sessions_agent_updated') IS NOT NULL
125
+ AND NOT EXISTS (
126
+ SELECT 1
127
+ FROM (
128
+ VALUES
129
+ ('{KSADK_PG_SESSIONS_TABLE}', 'namespace'),
130
+ ('{KSADK_PG_SESSIONS_TABLE}', 'tenant_id'),
131
+ ('{KSADK_PG_SESSIONS_TABLE}', 'workspace_id'),
132
+ ('{KSADK_PG_SESSIONS_TABLE}', 'id'),
133
+ ('{KSADK_PG_SESSIONS_TABLE}', 'agent_id'),
134
+ ('{KSADK_PG_SESSIONS_TABLE}', 'user_id'),
135
+ ('{KSADK_PG_SESSIONS_TABLE}', 'title'),
136
+ ('{KSADK_PG_SESSIONS_TABLE}', 'title_source'),
137
+ ('{KSADK_PG_SESSIONS_TABLE}', 'summary'),
138
+ ('{KSADK_PG_SESSIONS_TABLE}', 'first_prompt'),
139
+ ('{KSADK_PG_SESSIONS_TABLE}', 'last_prompt'),
140
+ ('{KSADK_PG_SESSIONS_TABLE}', 'state_json'),
141
+ ('{KSADK_PG_SESSIONS_TABLE}', 'created_at'),
142
+ ('{KSADK_PG_SESSIONS_TABLE}', 'updated_at'),
143
+ ('{KSADK_PG_SESSIONS_TABLE}', 'version'),
144
+ ('{KSADK_PG_EVENTS_TABLE}', 'namespace'),
145
+ ('{KSADK_PG_EVENTS_TABLE}', 'tenant_id'),
146
+ ('{KSADK_PG_EVENTS_TABLE}', 'workspace_id'),
147
+ ('{KSADK_PG_EVENTS_TABLE}', 'id'),
148
+ ('{KSADK_PG_EVENTS_TABLE}', 'session_id'),
149
+ ('{KSADK_PG_EVENTS_TABLE}', 'author'),
150
+ ('{KSADK_PG_EVENTS_TABLE}', 'event_type'),
151
+ ('{KSADK_PG_EVENTS_TABLE}', 'content_json'),
152
+ ('{KSADK_PG_EVENTS_TABLE}', 'timestamp'),
153
+ ('{KSADK_PG_EVENTS_TABLE}', 'state_delta_json'),
154
+ ('{KSADK_PG_EVENTS_TABLE}', 'seq_id'),
155
+ ('{KSADK_PG_EVENTS_TABLE}', 'invocation_id'),
156
+ ('{KSADK_PG_EVENTS_TABLE}', 'metadata_json'),
157
+ ('{KSADK_PG_STATES_TABLE}', 'namespace'),
158
+ ('{KSADK_PG_STATES_TABLE}', 'tenant_id'),
159
+ ('{KSADK_PG_STATES_TABLE}', 'workspace_id'),
160
+ ('{KSADK_PG_STATES_TABLE}', 'scope'),
161
+ ('{KSADK_PG_STATES_TABLE}', 'agent_id'),
162
+ ('{KSADK_PG_STATES_TABLE}', 'user_id'),
163
+ ('{KSADK_PG_STATES_TABLE}', 'session_id'),
164
+ ('{KSADK_PG_STATES_TABLE}', 'state_json'),
165
+ ('{KSADK_PG_STATES_TABLE}', 'version'),
166
+ ('{KSADK_PG_STATES_TABLE}', 'updated_at')
167
+ ) AS required(table_name, column_name)
168
+ WHERE NOT EXISTS (
169
+ SELECT 1
170
+ FROM pg_attribute AS attribute_row
171
+ WHERE attribute_row.attrelid = to_regclass(required.table_name)
172
+ AND attribute_row.attname = required.column_name
173
+ AND NOT attribute_row.attisdropped
174
+ )
175
+ )
176
+ AND EXISTS (
177
+ SELECT 1
178
+ FROM pg_constraint AS constraint_row
179
+ WHERE constraint_row.conrelid = to_regclass('{KSADK_PG_SESSIONS_TABLE}')
180
+ AND constraint_row.contype = 'p'
181
+ AND pg_get_constraintdef(constraint_row.oid)
182
+ = 'PRIMARY KEY (namespace, id)'
183
+ )
184
+ AND EXISTS (
185
+ SELECT 1
186
+ FROM pg_constraint AS constraint_row
187
+ WHERE constraint_row.conrelid = to_regclass('{KSADK_PG_EVENTS_TABLE}')
188
+ AND constraint_row.contype = 'p'
189
+ AND pg_get_constraintdef(constraint_row.oid)
190
+ = 'PRIMARY KEY (namespace, id)'
191
+ )
192
+ AND EXISTS (
193
+ SELECT 1
194
+ FROM pg_constraint AS constraint_row
195
+ WHERE constraint_row.conrelid = to_regclass('{KSADK_PG_STATES_TABLE}')
196
+ AND constraint_row.contype = 'p'
197
+ AND pg_get_constraintdef(constraint_row.oid)
198
+ = 'PRIMARY KEY (namespace, scope, agent_id, user_id, session_id)'
199
+ )
200
+ AND EXISTS (
201
+ SELECT 1
202
+ FROM pg_constraint AS constraint_row
203
+ WHERE constraint_row.conrelid = to_regclass('{KSADK_PG_EVENTS_TABLE}')
204
+ AND constraint_row.contype = 'u'
205
+ AND pg_get_constraintdef(constraint_row.oid)
206
+ = 'UNIQUE (namespace, session_id, seq_id)'
207
+ )
208
+ AND EXISTS (
209
+ SELECT 1
210
+ FROM pg_constraint AS constraint_row
211
+ WHERE constraint_row.conrelid = to_regclass('{KSADK_PG_EVENTS_TABLE}')
212
+ AND constraint_row.contype = 'f'
213
+ AND pg_get_constraintdef(constraint_row.oid)
214
+ = concat(
215
+ 'FOREIGN KEY (namespace, session_id) REFERENCES ',
216
+ '{KSADK_PG_SESSIONS_TABLE}(namespace, id) ON DELETE CASCADE'
217
+ )
218
+ )
219
+ """))
220
+
221
+ @staticmethod
222
+ async def _create_core_schema(connection: Any) -> None:
223
+ await connection.execute(f"""
224
+ CREATE TABLE IF NOT EXISTS {KSADK_PG_SESSIONS_TABLE} (
225
+ namespace TEXT NOT NULL,
226
+ tenant_id TEXT NOT NULL DEFAULT 'default',
227
+ workspace_id TEXT NOT NULL DEFAULT 'default',
228
+ id TEXT NOT NULL,
229
+ agent_id TEXT NOT NULL,
230
+ user_id TEXT NOT NULL,
231
+ title TEXT NOT NULL DEFAULT '',
232
+ title_source TEXT NOT NULL DEFAULT '',
233
+ summary TEXT NOT NULL DEFAULT '',
234
+ first_prompt TEXT NOT NULL DEFAULT '',
235
+ last_prompt TEXT NOT NULL DEFAULT '',
236
+ state_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
237
+ created_at DOUBLE PRECISION NOT NULL,
238
+ updated_at DOUBLE PRECISION NOT NULL,
239
+ version INTEGER NOT NULL DEFAULT 0,
240
+ PRIMARY KEY (namespace, id)
241
+ );
242
+
243
+ CREATE TABLE IF NOT EXISTS {KSADK_PG_EVENTS_TABLE} (
244
+ namespace TEXT NOT NULL,
245
+ tenant_id TEXT NOT NULL DEFAULT 'default',
246
+ workspace_id TEXT NOT NULL DEFAULT 'default',
247
+ id TEXT NOT NULL,
248
+ session_id TEXT NOT NULL,
249
+ author TEXT NOT NULL,
250
+ event_type TEXT NOT NULL,
251
+ content_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
252
+ timestamp DOUBLE PRECISION NOT NULL,
253
+ state_delta_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
254
+ seq_id INTEGER NOT NULL,
255
+ invocation_id TEXT,
256
+ metadata_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
257
+ PRIMARY KEY (namespace, id),
258
+ UNIQUE (namespace, session_id, seq_id),
259
+ FOREIGN KEY (namespace, session_id)
260
+ REFERENCES {KSADK_PG_SESSIONS_TABLE}(namespace, id)
261
+ ON DELETE CASCADE
262
+ );
263
+
264
+ CREATE INDEX IF NOT EXISTS idx_ksadk_pg_events_session_seq
265
+ ON {KSADK_PG_EVENTS_TABLE} (namespace, session_id, seq_id);
266
+
267
+ CREATE INDEX IF NOT EXISTS idx_ksadk_pg_events_session_invocation_seq
268
+ ON {KSADK_PG_EVENTS_TABLE} (namespace, session_id, invocation_id, seq_id);
269
+
270
+ CREATE INDEX IF NOT EXISTS idx_ksadk_pg_events_session_ts
271
+ ON {KSADK_PG_EVENTS_TABLE} (namespace, session_id, timestamp, id);
272
+
273
+ CREATE INDEX IF NOT EXISTS idx_ksadk_pg_sessions_agent_updated
274
+ ON {KSADK_PG_SESSIONS_TABLE} (namespace, agent_id, updated_at DESC, id);
275
+
276
+ CREATE TABLE IF NOT EXISTS {KSADK_PG_STATES_TABLE} (
277
+ namespace TEXT NOT NULL,
278
+ tenant_id TEXT NOT NULL DEFAULT 'default',
279
+ workspace_id TEXT NOT NULL DEFAULT 'default',
280
+ scope TEXT NOT NULL,
281
+ agent_id TEXT NOT NULL,
282
+ user_id TEXT NOT NULL DEFAULT '',
283
+ session_id TEXT NOT NULL DEFAULT '',
284
+ state_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
285
+ version INTEGER NOT NULL DEFAULT 0,
286
+ updated_at DOUBLE PRECISION NOT NULL,
287
+ PRIMARY KEY (namespace, scope, agent_id, user_id, session_id)
288
+ );
289
+
290
+ ALTER TABLE {KSADK_PG_SESSIONS_TABLE}
291
+ ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
292
+ ALTER TABLE {KSADK_PG_SESSIONS_TABLE}
293
+ ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
294
+ ALTER TABLE {KSADK_PG_EVENTS_TABLE}
295
+ ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
296
+ ALTER TABLE {KSADK_PG_EVENTS_TABLE}
297
+ ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
298
+ ALTER TABLE {KSADK_PG_STATES_TABLE}
299
+ ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
300
+ ALTER TABLE {KSADK_PG_STATES_TABLE}
301
+ ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
302
+ """)
303
+
304
+
305
+ __all__ = ["_PostgresSchemaMixin"]
@@ -0,0 +1,15 @@
1
+ """Postgres session 存储的表/视图常量(纯移动自 postgres_service,行为不变)。"""
2
+
3
+ KSADK_PG_SESSIONS_TABLE = "ksadk_sessions"
4
+ KSADK_PG_EVENTS_TABLE = "ksadk_events"
5
+ KSADK_PG_STATES_TABLE = "ksadk_states"
6
+ PG_READABLE_EVENTS_VIEW = "ksadk_session_events_readable"
7
+ _PG_SCHEMA_ADVISORY_LOCK_KEY = 0x4B5341444B53444B
8
+
9
+ __all__ = [
10
+ "KSADK_PG_EVENTS_TABLE",
11
+ "KSADK_PG_SESSIONS_TABLE",
12
+ "KSADK_PG_STATES_TABLE",
13
+ "PG_READABLE_EVENTS_VIEW",
14
+ "_PG_SCHEMA_ADVISORY_LOCK_KEY",
15
+ ]
ksadk/sessions/base.py CHANGED
@@ -5,7 +5,25 @@ import time
5
5
  import uuid
6
6
  from dataclasses import dataclass, field
7
7
  from datetime import datetime
8
- from typing import Any, Optional
8
+ from typing import Any, Literal, Optional, TypeAlias
9
+
10
+ SessionEventSeqBinding: TypeAlias = Literal["runtime_event.seq", "session_event.seq"]
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class SessionServiceStorageCapabilities:
15
+ """Typed storage guarantees required by canonical event persistence."""
16
+
17
+ atomic_seq_bindings: frozenset[SessionEventSeqBinding] = frozenset()
18
+ indexed_event_lookup: bool = False
19
+ indexed_invocation_lookup: bool = False
20
+
21
+
22
+ CANONICAL_EVENT_STORAGE_CAPABILITIES = SessionServiceStorageCapabilities(
23
+ atomic_seq_bindings=frozenset({"runtime_event.seq", "session_event.seq"}),
24
+ indexed_event_lookup=True,
25
+ indexed_invocation_lookup=True,
26
+ )
9
27
 
10
28
 
11
29
  def generate_id() -> str:
@@ -47,6 +65,47 @@ class SessionEvent:
47
65
  seq_id: int = 0
48
66
  invocation_id: Optional[str] = None
49
67
  metadata: dict[str, Any] = field(default_factory=dict)
68
+ seq_binding: SessionEventSeqBinding | None = None
69
+
70
+ def bind_seq_id(self, seq_id: int) -> None:
71
+ """Bind a store-assigned cursor into an explicitly declared content field.
72
+
73
+ Most session events only need the physical ``seq_id`` column. A typed
74
+ event envelope may additionally declare ``runtime_event.seq`` through
75
+ the transient ``seq_binding`` capability so the JSON fact and carrier
76
+ are written atomically with the same cursor. The binding is consumed
77
+ before persistence and never appears in public metadata or content.
78
+ """
79
+
80
+ self.seq_id = int(seq_id)
81
+ binding = self.seq_binding
82
+ self.seq_binding = None
83
+ if binding is None:
84
+ return
85
+ if binding == "session_event.seq":
86
+ envelope = self.content.get("session_event")
87
+ if not isinstance(envelope, dict):
88
+ raise ValueError("session_event.seq binding requires session_event content")
89
+ envelope = dict(envelope)
90
+ envelope["seq"] = self.seq_id
91
+ self.content = {**self.content, "session_event": envelope}
92
+ return
93
+ if binding != "runtime_event.seq":
94
+ raise ValueError(f"unsupported SessionEvent seq binding {binding!r}")
95
+ runtime_event = self.content.get("runtime_event")
96
+ if not isinstance(runtime_event, dict):
97
+ raise ValueError("runtime_event.seq binding requires runtime_event content")
98
+ runtime_event = dict(runtime_event)
99
+ runtime_event["seq"] = self.seq_id
100
+ content = {**self.content, "runtime_event": runtime_event}
101
+ # Keep the embedded generic envelope dump consistent with the same
102
+ # cursor when both carriers are present.
103
+ envelope = content.get("session_event")
104
+ if isinstance(envelope, dict):
105
+ envelope = dict(envelope)
106
+ envelope["seq"] = self.seq_id
107
+ content["session_event"] = envelope
108
+ self.content = content
50
109
 
51
110
  @classmethod
52
111
  def from_dict(
@@ -251,6 +310,8 @@ def _infer_event_type(payload: dict[str, Any]) -> str:
251
310
 
252
311
 
253
312
  class BaseSessionService(abc.ABC):
313
+ storage_capabilities = SessionServiceStorageCapabilities()
314
+
254
315
  @abc.abstractmethod
255
316
  async def create_session(
256
317
  self,
@@ -309,8 +370,26 @@ class BaseSessionService(abc.ABC):
309
370
 
310
371
  @abc.abstractmethod
311
372
  async def append_event(self, session_id: str, event: SessionEvent) -> SessionEvent:
373
+ """Append an event with a backend-unique ID and session-unique cursor."""
312
374
  raise NotImplementedError
313
375
 
376
+ async def get_event_by_id(self, session_id: str, event_id: str) -> Optional[SessionEvent]:
377
+ """Indexed physical-id lookup for idempotent event insertion."""
378
+
379
+ raise NotImplementedError("session backend does not support indexed event lookup")
380
+
381
+ async def get_events_by_invocation_id(
382
+ self,
383
+ session_id: str,
384
+ invocation_id: str,
385
+ *,
386
+ after_seq_id: Optional[int] = None,
387
+ before_seq_id: Optional[int] = None,
388
+ ) -> list[SessionEvent]:
389
+ """Indexed invocation read used by canonical run replay/recovery."""
390
+
391
+ raise NotImplementedError("session backend does not support indexed invocation lookup")
392
+
314
393
  @abc.abstractmethod
315
394
  async def get_events(
316
395
  self,
@@ -6,12 +6,23 @@ import time
6
6
  from typing import Optional
7
7
 
8
8
  from ksadk.ids import new_session_id
9
- from ksadk.sessions.base import BaseSessionService, Session, SessionEvent, SessionState, generate_id
9
+ from ksadk.sessions.base import (
10
+ CANONICAL_EVENT_STORAGE_CAPABILITIES,
11
+ BaseSessionService,
12
+ Session,
13
+ SessionEvent,
14
+ SessionState,
15
+ generate_id,
16
+ )
10
17
 
11
18
 
12
19
  class InMemorySessionService(BaseSessionService):
20
+ storage_capabilities = CANONICAL_EVENT_STORAGE_CAPABILITIES
21
+
13
22
  def __init__(self):
14
23
  self._sessions: dict[str, Session] = {}
24
+ self._events_by_id: dict[str, SessionEvent] = {}
25
+ self._events_by_invocation: dict[tuple[str, str], list[SessionEvent]] = {}
15
26
  self._states: dict[tuple[str, str, str, str], SessionState] = {}
16
27
  self._lock = asyncio.Lock()
17
28
 
@@ -91,6 +102,10 @@ class InMemorySessionService(BaseSessionService):
91
102
  session = self._sessions.pop(session_id, None)
92
103
  if not session:
93
104
  return False
105
+ for event in session.events:
106
+ self._events_by_id.pop(event.id, None)
107
+ if event.invocation_id is not None:
108
+ self._events_by_invocation.pop((session_id, event.invocation_id), None)
94
109
  self._states.pop(
95
110
  self._state_key(
96
111
  "session",
@@ -135,12 +150,25 @@ class InMemorySessionService(BaseSessionService):
135
150
  if not session:
136
151
  raise ValueError(f"Session {session_id} not found")
137
152
 
153
+ # Match the durable Local/Postgres physical primary-key contract.
154
+ # Canonical RuntimeEvent storage relies on a deterministic
155
+ # session+event storage id so concurrent insert losers cannot
156
+ # allocate another seq. Auto-generated ids retain their existing
157
+ # behavior because SessionEvent always supplies a fresh id.
158
+ if event.id in self._events_by_id:
159
+ raise ValueError(f"SessionEvent id {event.id!r} already exists")
160
+
138
161
  stored = copy.deepcopy(event)
139
162
  stored.session_id = session_id
140
- stored.seq_id = len(session.events) + 1
163
+ stored.bind_seq_id(len(session.events) + 1)
141
164
  if not stored.id:
142
165
  stored.id = generate_id()
143
166
  session.events.append(stored)
167
+ self._events_by_id[stored.id] = stored
168
+ if stored.invocation_id is not None:
169
+ self._events_by_invocation.setdefault(
170
+ (session_id, stored.invocation_id), []
171
+ ).append(stored)
144
172
  session.updated_at = time.time()
145
173
 
146
174
  if stored.state_delta:
@@ -165,6 +193,29 @@ class InMemorySessionService(BaseSessionService):
165
193
 
166
194
  return copy.deepcopy(stored)
167
195
 
196
+ async def get_event_by_id(self, session_id: str, event_id: str) -> Optional[SessionEvent]:
197
+ async with self._lock:
198
+ event = self._events_by_id.get(event_id)
199
+ if event is None or event.session_id != session_id:
200
+ return None
201
+ return copy.deepcopy(event)
202
+
203
+ async def get_events_by_invocation_id(
204
+ self,
205
+ session_id: str,
206
+ invocation_id: str,
207
+ *,
208
+ after_seq_id: Optional[int] = None,
209
+ before_seq_id: Optional[int] = None,
210
+ ) -> list[SessionEvent]:
211
+ async with self._lock:
212
+ events = list(self._events_by_invocation.get((session_id, invocation_id), ()))
213
+ if after_seq_id is not None:
214
+ events = [event for event in events if event.seq_id > after_seq_id]
215
+ if before_seq_id is not None:
216
+ events = [event for event in events if event.seq_id < before_seq_id]
217
+ return copy.deepcopy(events)
218
+
168
219
  async def get_events(
169
220
  self,
170
221
  session_id: str,