agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
  2. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
  3. ksadk/a2a/_space_client_events.py +381 -0
  4. ksadk/a2a/event_adapter.py +156 -64
  5. ksadk/a2a/executor.py +179 -63
  6. ksadk/a2a/space_client.py +6 -333
  7. ksadk/a2ui/core.py +222 -53
  8. ksadk/agui/_agent_helpers.py +243 -0
  9. ksadk/agui/a2ui_projection.py +12 -5
  10. ksadk/agui/agent.py +443 -259
  11. ksadk/api/client.py +525 -27
  12. ksadk/builders/code_builder.py +284 -8
  13. ksadk/builders/container_builder.py +8 -1
  14. ksadk/builders/managed_runtime_builder.py +39 -35
  15. ksadk/cli/__init__.py +17 -0
  16. ksadk/cli/cmd_dashboard.py +15 -1
  17. ksadk/cli/cmd_deploy.py +10 -2
  18. ksadk/cli/cmd_eval.py +66 -9
  19. ksadk/cli/cmd_evalset.py +284 -0
  20. ksadk/cli/cmd_files.py +5 -1
  21. ksadk/cli/cmd_hermes.py +1 -126
  22. ksadk/cli/cmd_invoke.py +28 -38
  23. ksadk/cli/cmd_managed_runtime.py +95 -0
  24. ksadk/cli/cmd_observe.py +85 -0
  25. ksadk/cli/cmd_openclaw.py +1 -435
  26. ksadk/cli/cmd_replay.py +28 -4
  27. ksadk/cli/cmd_studio.py +99 -8
  28. ksadk/cli/cmd_web.py +10 -2
  29. ksadk/cli/hermes_env.py +151 -0
  30. ksadk/cli/invoke_payload.py +49 -0
  31. ksadk/cli/openclaw_env.py +458 -0
  32. ksadk/codex/client.py +180 -30
  33. ksadk/codex/runtime.py +428 -326
  34. ksadk/configs/env_registry.py +66 -12
  35. ksadk/configs/env_registry_pcm.py +181 -0
  36. ksadk/configs/env_var_spec.py +18 -0
  37. ksadk/configs/global_config.py +5 -0
  38. ksadk/context_engine/__init__.py +98 -0
  39. ksadk/context_engine/assembler.py +176 -0
  40. ksadk/context_engine/baseline.py +419 -0
  41. ksadk/context_engine/cache_observability.py +228 -0
  42. ksadk/context_engine/capabilities.py +443 -0
  43. ksadk/context_engine/contributors.py +344 -0
  44. ksadk/context_engine/hosted_pipeline.py +417 -0
  45. ksadk/context_engine/models.py +117 -0
  46. ksadk/context_engine/planner.py +698 -0
  47. ksadk/context_engine/policies.py +319 -0
  48. ksadk/context_engine/projection.py +31 -0
  49. ksadk/context_engine/shadow_plan.py +266 -0
  50. ksadk/context_engine/tokenizer.py +164 -0
  51. ksadk/conversations/context.py +126 -6
  52. ksadk/conversations/message_projection.py +292 -28
  53. ksadk/conversations/model_context.py +49 -3
  54. ksadk/conversations/runtime_compaction.py +207 -5
  55. ksadk/conversations/runtime_input.py +184 -2
  56. ksadk/conversations/runtime_invocation.py +81 -3
  57. ksadk/conversations/runtime_observability.py +141 -0
  58. ksadk/conversations/runtime_payloads.py +42 -0
  59. ksadk/conversations/runtime_preparation.py +272 -2
  60. ksadk/conversations/runtime_resume.py +20 -1
  61. ksadk/conversations/runtime_stream_events.py +94 -9
  62. ksadk/conversations/semantic_summary.py +311 -1
  63. ksadk/conversations/session_lock.py +51 -0
  64. ksadk/deployment/env_forward.py +72 -0
  65. ksadk/deployment/managed_runtime.py +5 -0
  66. ksadk/deployment/providers/serverless.py +143 -69
  67. ksadk/evaluation/__init__.py +32 -0
  68. ksadk/evaluation/a2a_adapter.py +9 -1
  69. ksadk/evaluation/adapters.py +18 -5
  70. ksadk/evaluation/agent_eval_client.py +395 -0
  71. ksadk/evaluation/cloud_binding.py +80 -0
  72. ksadk/evaluation/cloud_converter.py +194 -0
  73. ksadk/evaluation/cloud_service.py +199 -0
  74. ksadk/evaluation/contracts.py +73 -4
  75. ksadk/evaluation/evaluators.py +183 -17
  76. ksadk/evaluation/evidence.py +258 -0
  77. ksadk/evaluation/executor.py +31 -6
  78. ksadk/evaluation/local_adapter.py +550 -0
  79. ksadk/evaluation/service_env.py +27 -0
  80. ksadk/evaluation/studio_build_adapter.py +253 -0
  81. ksadk/evaluation/target.py +15 -6
  82. ksadk/events/__init__.py +13 -13
  83. ksadk/events/_v1_compat/__init__.py +1 -0
  84. ksadk/events/_v1_compat/models.py +299 -0
  85. ksadk/events/_v1_compat/parser.py +247 -0
  86. ksadk/events/_v1_compat/projection.py +753 -0
  87. ksadk/events/adapters/__init__.py +34 -0
  88. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  89. ksadk/events/adapters/_a2a_support.py +275 -0
  90. ksadk/events/adapters/_codex_interactions.py +375 -0
  91. ksadk/events/adapters/_codex_items.py +801 -0
  92. ksadk/events/adapters/_codex_validators.py +311 -0
  93. ksadk/events/adapters/_langgraph_support.py +785 -0
  94. ksadk/events/adapters/a2a.py +841 -0
  95. ksadk/events/adapters/adk.py +503 -0
  96. ksadk/events/adapters/codex.py +717 -0
  97. ksadk/events/adapters/langgraph.py +745 -0
  98. ksadk/events/canonical.py +440 -0
  99. ksadk/events/canonical_replay.py +497 -0
  100. ksadk/events/canonical_store.py +468 -0
  101. ksadk/events/cold_recovery.py +257 -0
  102. ksadk/events/content.py +89 -0
  103. ksadk/events/identity.py +86 -0
  104. ksadk/events/pipeline.py +455 -0
  105. ksadk/events/projections.py +66 -0
  106. ksadk/events/reducer.py +661 -0
  107. ksadk/events/replay.py +3 -36
  108. ksadk/events/runtime_event.py +20 -265
  109. ksadk/events/session_event.py +324 -0
  110. ksadk/events/store.py +3 -316
  111. ksadk/events/v1_compat.py +41 -0
  112. ksadk/harness/runtime.py +160 -57
  113. ksadk/identity/resolver.py +4 -3
  114. ksadk/interaction/__init__.py +28 -0
  115. ksadk/interaction/contracts.py +136 -0
  116. ksadk/interaction/ledger.py +189 -0
  117. ksadk/interaction/provider.py +122 -0
  118. ksadk/interaction/providers/__init__.py +52 -0
  119. ksadk/interaction/providers/adk.py +40 -0
  120. ksadk/interaction/providers/codex.py +94 -0
  121. ksadk/interaction/providers/langgraph.py +58 -0
  122. ksadk/kernel/__init__.py +117 -0
  123. ksadk/kernel/authorization.py +258 -0
  124. ksadk/kernel/bootstrap.py +1074 -0
  125. ksadk/kernel/contract_fingerprints.py +61 -0
  126. ksadk/kernel/contracts.py +362 -0
  127. ksadk/kernel/control.py +219 -0
  128. ksadk/kernel/errors.py +79 -0
  129. ksadk/kernel/ingress.py +1102 -0
  130. ksadk/kernel/mapping.py +111 -0
  131. ksadk/kernel/memory_store.py +1133 -0
  132. ksadk/kernel/postgres_store.py +1756 -0
  133. ksadk/kernel/recovery.py +452 -0
  134. ksadk/kernel/runtime_identity.py +103 -0
  135. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  136. ksadk/kernel/sqlite_store.py +1410 -0
  137. ksadk/kernel/state.py +145 -0
  138. ksadk/kernel/store.py +232 -0
  139. ksadk/kernel/worker.py +953 -0
  140. ksadk/knowledge_base/client.py +7 -0
  141. ksadk/knowledge_base/service.py +32 -5
  142. ksadk/memory/__init__.py +61 -0
  143. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  144. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  145. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  146. ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
  147. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  148. ksadk/memory/coordinator.py +461 -0
  149. ksadk/memory/events.py +202 -0
  150. ksadk/memory/extraction.py +228 -0
  151. ksadk/memory/ltm_backend_factory.py +16 -3
  152. ksadk/memory/models.py +316 -0
  153. ksadk/memory/policy.py +215 -0
  154. ksadk/memory/provider.py +47 -0
  155. ksadk/memory/provider_adapter.py +159 -0
  156. ksadk/memory/provider_resolver.py +71 -0
  157. ksadk/memory/providers/__init__.py +5 -0
  158. ksadk/memory/providers/local_sqlite.py +490 -0
  159. ksadk/memory/resolved_policy.py +145 -0
  160. ksadk/memory/service.py +188 -6
  161. ksadk/model_proxy/bootstrap.py +16 -9
  162. ksadk/model_proxy/detect.py +202 -9
  163. ksadk/model_proxy/namespace.py +39 -15
  164. ksadk/model_proxy/server.py +24 -5
  165. ksadk/model_proxy/transform.py +60 -2
  166. ksadk/observability/__init__.py +25 -0
  167. ksadk/observability/session_log.py +420 -0
  168. ksadk/observability/trajectory.py +105 -0
  169. ksadk/prompts/__init__.py +71 -0
  170. ksadk/prompts/compiler.py +215 -0
  171. ksadk/prompts/models.py +82 -0
  172. ksadk/prompts/projection.py +89 -0
  173. ksadk/prompts/resolved.py +137 -0
  174. ksadk/prompts/sources.py +233 -0
  175. ksadk/runners/_langgraph_runner_streams.py +822 -0
  176. ksadk/runners/adk_runner.py +5 -5
  177. ksadk/runners/base_runner.py +16 -0
  178. ksadk/runners/factory.py +1 -2
  179. ksadk/runners/langgraph_runner.py +198 -437
  180. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  181. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  182. ksadk/runtime/adapter.py +118 -2
  183. ksadk/runtime/conversation_execution.py +316 -182
  184. ksadk/runtime/executor.py +144 -3
  185. ksadk/runtime/factory.py +193 -7
  186. ksadk/runtime/hosted_finalizer.py +268 -0
  187. ksadk/runtime/launch.py +14 -1
  188. ksadk/runtime/preprocessing.py +25 -3
  189. ksadk/runtime/runner_adapter.py +288 -508
  190. ksadk/runtime/usage.py +33 -0
  191. ksadk/sandbox/backends/e2b.py +35 -2
  192. ksadk/server/composition.py +8 -0
  193. ksadk/server/factory.py +69 -6
  194. ksadk/server/routes/kernel_ingress.py +258 -0
  195. ksadk/server/routes/openai_compat.py +88 -8
  196. ksadk/server/routes/projection.py +35 -20
  197. ksadk/server/routes/run.py +94 -0
  198. ksadk/server/routes/sessions.py +2 -0
  199. ksadk/server/routes/streaming.py +5 -2
  200. ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  201. ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
  202. ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  203. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  204. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  205. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  206. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  207. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  208. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  209. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  210. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  211. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  212. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  213. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  214. ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  215. ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  216. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  217. ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  218. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  219. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  220. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  221. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  222. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  223. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  224. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  225. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  226. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  227. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  228. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  229. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  230. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  231. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  232. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  233. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  234. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  235. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  236. ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
  237. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  238. ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
  239. ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
  240. ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
  241. ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
  242. ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
  243. ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
  244. ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
  245. ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
  246. ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
  247. ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
  248. ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
  249. ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
  250. ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
  251. ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
  252. ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
  253. ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
  254. ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
  255. ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
  256. ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
  257. ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-ngtN0DJB.js} +1 -1
  258. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  259. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  260. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  261. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  262. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  263. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  264. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  265. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  266. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  267. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  268. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  269. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  270. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  271. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  272. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  273. ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-BHjG8b-J.js} +1 -1
  274. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  275. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  276. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  277. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  278. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  279. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  280. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  281. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  282. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  283. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  284. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  285. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  286. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  287. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  288. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  289. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  290. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  291. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  292. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  293. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  294. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  295. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  296. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  297. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  298. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  299. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  300. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  301. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  302. ksadk/server/static/index.html +2 -2
  303. ksadk/sessions/__init__.py +26 -9
  304. ksadk/sessions/_local_service_sync.py +688 -0
  305. ksadk/sessions/_local_tables.py +21 -0
  306. ksadk/sessions/_postgres_schema.py +305 -0
  307. ksadk/sessions/_postgres_tables.py +15 -0
  308. ksadk/sessions/base.py +80 -1
  309. ksadk/sessions/in_memory.py +53 -2
  310. ksadk/sessions/local_service.py +63 -604
  311. ksadk/sessions/postgres_service.py +58 -148
  312. ksadk/sessions/resilient.py +35 -1
  313. ksadk/studio/api.py +577 -25
  314. ksadk/studio/api_contracts.py +114 -5
  315. ksadk/studio/api_memory_routes.py +82 -0
  316. ksadk/studio/authoring.py +252 -27
  317. ksadk/studio/authoring_coordinator.py +799 -67
  318. ksadk/studio/builder.py +88 -11
  319. ksadk/studio/capabilities.py +17 -0
  320. ksadk/studio/cloud.py +1916 -95
  321. ksadk/studio/codex_agent_service.py +125 -14
  322. ksadk/studio/codex_authoring.py +469 -0
  323. ksadk/studio/codex_builder.py +138 -25
  324. ksadk/studio/codex_manifest.py +51 -22
  325. ksadk/studio/codex_run.py +46 -3
  326. ksadk/studio/compiler.py +1 -0
  327. ksadk/studio/contracts.py +114 -3
  328. ksadk/studio/event_store.py +25 -95
  329. ksadk/studio/framework_run.py +231 -3
  330. ksadk/studio/hosted_kernel.py +317 -0
  331. ksadk/studio/manifest_resolver.py +131 -0
  332. ksadk/studio/model_client.py +95 -9
  333. ksadk/studio/model_profile_service.py +1 -1
  334. ksadk/studio/operations.py +37 -5
  335. ksadk/studio/otel_trace.py +348 -42
  336. ksadk/studio/pcm_memory.py +85 -0
  337. ksadk/studio/repository.py +23 -2
  338. ksadk/studio/resource_catalog.py +43 -0
  339. ksadk/studio/run_service.py +563 -137
  340. ksadk/studio/runtime_source.py +42 -16
  341. ksadk/studio/service.py +1180 -72
  342. ksadk/studio/shared_web.py +32 -22
  343. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  344. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  345. ksadk/studio/static/index.html +2 -2
  346. ksadk/studio/templates.py +100 -8
  347. ksadk/studio/validator.py +19 -0
  348. ksadk/studio/workspace.py +30 -32
  349. ksadk/tracing/setup.py +304 -3
  350. ksadk/version.py +1 -1
  351. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  352. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  353. ksadk/events/parser.py +0 -191
  354. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  355. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
  356. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
  357. ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
  358. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
  359. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
  360. ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
  361. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
  362. ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
  363. ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
  364. ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
  365. ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
  366. ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
  367. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
  368. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
  369. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
  370. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  371. ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
  372. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  373. ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
  374. ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
  375. ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
  376. ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
  377. ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
  378. ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
  379. ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
  380. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
  381. ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
  382. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
  383. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
  384. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
  385. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  386. ksadk/server/static/assets/index-R52pJJvg.js +0 -177
  387. ksadk/server/static/assets/index-jJr3_955.css +0 -2
  388. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
  389. ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
  390. ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
  391. ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
  392. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
  393. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
  394. ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
  395. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
  396. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
  397. ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
  398. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
  399. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
  400. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
  401. ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
  402. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
  404. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
  405. ksadk/studio/evaluation.py +0 -192
  406. ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
  407. ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
  408. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
  409. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  410. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  411. {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
ksadk/memory/policy.py ADDED
@@ -0,0 +1,215 @@
1
+ """Memory 写入策略、敏感信息拒绝与冲突解决(方案 §10.4 / §19)。
2
+
3
+ 策略与阈值必须属于 ``MemoryPolicy``,不能硬编码在 Runner(方案 §10.4 末)。Candidate 进入
4
+ Provider 前必须执行 Secret/PII 检查;硬拒绝标签(api_key/secret_key/access_key/cookie/
5
+ auth_header/signed_url/dsn/token/binary)一律 ``reject``,不写入长期记忆(方案 §19)。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import re
12
+ from dataclasses import dataclass, field
13
+ from typing import Literal
14
+
15
+ from ksadk.memory.models import MemoryCandidate, MemoryOperation, MemoryRecord, SensitiveLabel
16
+
17
+ # 硬拒绝敏感标签:出现任一即 reject,绝不写入(方案 §19)。
18
+ HARD_REJECT_LABELS: frozenset[SensitiveLabel] = frozenset(
19
+ {
20
+ "api_key",
21
+ "secret_key",
22
+ "access_key",
23
+ "cookie",
24
+ "auth_header",
25
+ "signed_url",
26
+ "dsn",
27
+ "token",
28
+ "binary",
29
+ }
30
+ )
31
+
32
+ PolicyDecision = Literal["commit", "pending", "reject"]
33
+
34
+
35
+ @dataclass(frozen=True)
36
+ class MemoryPolicyThresholds:
37
+ """候选写入阈值(方案 §10.4 初始值)。
38
+
39
+ 阈值属于 Policy,不硬编码在 Runner。可由部署/配置覆盖。
40
+ """
41
+
42
+ explicit_user_request: float = 0.60
43
+ verified_tool_fact: float = 0.80
44
+ implicit_preference: float = 0.85
45
+ implicit_preference_min_observations: int = 2
46
+ episode_importance: float = 0.70
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ class MemoryEvaluation:
51
+ """对单个 Candidate 的策略判定结果。"""
52
+
53
+ decision: PolicyDecision
54
+ operation: MemoryOperation
55
+ reason: str
56
+ new_version: int | None = None
57
+ conflicts_with: list[str] = field(default_factory=list)
58
+
59
+
60
+ # 敏感信息正则(best-effort,方案 §19)。只做写入前拦截,不做完整 DLP。
61
+ _SECRET_PATTERNS: tuple[tuple[re.Pattern[str], SensitiveLabel], ...] = (
62
+ (re.compile(r"(?i)api[_-]?key\s*[:=]\s*\S+"), "api_key"),
63
+ (re.compile(r"(?i)secret[_-]?key\s*[:=]\s*\S+"), "secret_key"),
64
+ (re.compile(r"(?i)access[_-]?key\s*[:=]\s*\S+"), "access_key"),
65
+ (re.compile(r"(?i)AKIA[0-9A-Z]{16}"), "access_key"),
66
+ (re.compile(r"(?i)cookie\s*[:=]\s*\S+"), "cookie"),
67
+ (re.compile(r"(?i)authorization\s*[:=]\s*bearer\s+\S+"), "auth_header"),
68
+ (
69
+ re.compile(r"https?://\S+?(?:X-Amz-Signature|X-Amz-Security-Token|signed)=", re.I),
70
+ "signed_url",
71
+ ),
72
+ (re.compile(r"(?i)(postgres|mysql|mongodb|redis)://\S+:\S+@\S+"), "dsn"),
73
+ (re.compile(r"(?i)sk-[A-Za-z0-9]{20,}"), "token"),
74
+ )
75
+
76
+
77
+ def detect_sensitive_labels(
78
+ content: str, candidate_labels: list[SensitiveLabel]
79
+ ) -> list[SensitiveLabel]:
80
+ """对 Candidate 正文做敏感信息检测(方案 §19)。
81
+
82
+ 先采纳 Candidate 自带的 ``sensitive_labels``,再用正则做 best-effort 补检。任一硬拒绝
83
+ 标签命中即整体拒绝。
84
+ """
85
+ labels: set[SensitiveLabel] = set()
86
+ for label in candidate_labels:
87
+ if label and label != "none":
88
+ labels.add(label)
89
+ text = str(content or "")
90
+ for pattern, label in _SECRET_PATTERNS:
91
+ if pattern.search(text):
92
+ labels.add(label)
93
+ # 二进制特征:大量非文本/重复字节不做完整检测,仅按显式标签处理。
94
+ return sorted(labels)
95
+
96
+
97
+ def _content_hash(content: str) -> str:
98
+ return "sha256:" + hashlib.sha256(str(content or "").encode("utf-8")).hexdigest()
99
+
100
+
101
+ @dataclass(frozen=True)
102
+ class MemoryPolicy:
103
+ """写入策略与冲突解决(方案 §10.4)。
104
+
105
+ 无状态、可复用。``evaluate`` 不接触 Provider;commit 由 Coordinator 执行。
106
+ """
107
+
108
+ thresholds: MemoryPolicyThresholds = field(default_factory=MemoryPolicyThresholds)
109
+
110
+ def evaluate(
111
+ self,
112
+ candidate: MemoryCandidate,
113
+ *,
114
+ existing: MemoryRecord | None = None,
115
+ observations: int = 1,
116
+ ) -> MemoryEvaluation:
117
+ """评估单个 Candidate(方案 §10.4 决策表)。
118
+
119
+ - 硬拒绝敏感标签 → ``reject``(绝不写入)。
120
+ - 用户明确"记住"(reason 含 explicit)→ 同步 propose,达阈值 commit。
121
+ - 用户明确"忘掉"(operation=delete)→ 解析目标删除;歧义时不猜测 → reject。
122
+ - 一次性当前任务状态 / 模型猜测 → 留 Session,不写 → ``reject``
123
+ (reason 标 ``not_durable``)。
124
+ - 与旧事实冲突 → ``update``/``supersede``,不覆盖历史来源。
125
+ """
126
+ labels = detect_sensitive_labels(candidate.content, list(candidate.sensitive_labels))
127
+ hard_hit = any(label in HARD_REJECT_LABELS for label in labels)
128
+ if hard_hit or candidate.is_hard_rejected():
129
+ return MemoryEvaluation(
130
+ decision="reject",
131
+ operation="ignore",
132
+ reason=f"sensitive_label_rejected:{','.join(labels) or 'explicit'}",
133
+ conflicts_with=list(candidate.conflicts_with),
134
+ )
135
+
136
+ if candidate.operation == "delete":
137
+ # 删除需明确目标;reason 为空或含 "ambiguous" 时不猜测(方案 §10.4)。
138
+ if not candidate.conflicts_with and not candidate.reason.strip():
139
+ return MemoryEvaluation(
140
+ decision="reject",
141
+ operation="ignore",
142
+ reason="delete_without_target",
143
+ )
144
+ return MemoryEvaluation(
145
+ decision="commit",
146
+ operation="delete",
147
+ reason="explicit_delete",
148
+ conflicts_with=list(candidate.conflicts_with),
149
+ )
150
+
151
+ # 一次性当前任务状态 / 模型猜测不写长期记忆(方案 §10.4)。
152
+ reason_lc = candidate.reason.lower()
153
+ if "model_guess" in reason_lc or "transient" in reason_lc or "current_plan" in reason_lc:
154
+ return MemoryEvaluation(
155
+ decision="reject",
156
+ operation="ignore",
157
+ reason="not_durable",
158
+ )
159
+
160
+ # 阈值判定(方案 §10.4 初始阈值)。
161
+ threshold = self._threshold_for(candidate, observations)
162
+ if candidate.confidence < threshold:
163
+ return MemoryEvaluation(
164
+ decision="pending",
165
+ operation=candidate.operation,
166
+ reason=f"below_threshold:{candidate.confidence:.2f}<{threshold:.2f}",
167
+ )
168
+
169
+ # 冲突:update/supersede,不覆盖历史来源(方案 §10.4)。
170
+ if existing is not None and candidate.operation != "add":
171
+ return MemoryEvaluation(
172
+ decision="commit",
173
+ operation="update",
174
+ reason="conflict_supersede",
175
+ new_version=existing.version + 1,
176
+ conflicts_with=[existing.memory_id],
177
+ )
178
+
179
+ return MemoryEvaluation(
180
+ decision="commit",
181
+ operation=candidate.operation,
182
+ reason="threshold_met",
183
+ new_version=1,
184
+ )
185
+
186
+ def _threshold_for(self, candidate: MemoryCandidate, observations: int) -> float:
187
+ t = self.thresholds
188
+ reason_lc = candidate.reason.lower()
189
+ if "explicit" in reason_lc or "user_request" in reason_lc:
190
+ return t.explicit_user_request
191
+ if "tool_fact" in reason_lc or "verified" in reason_lc:
192
+ return t.verified_tool_fact
193
+ if candidate.memory_type == "episode":
194
+ return t.episode_importance
195
+ # implicit preference
196
+ if observations < t.implicit_preference_min_observations:
197
+ # 观察次数不足,抬高到 implicit 阈值且要求更多观察 → pending。
198
+ return float("inf")
199
+ return t.implicit_preference
200
+
201
+
202
+ def content_hash(content: str) -> str:
203
+ """暴露给 Coordinator/Provider 的稳定 content hash。"""
204
+ return _content_hash(content)
205
+
206
+
207
+ __all__ = [
208
+ "HARD_REJECT_LABELS",
209
+ "MemoryEvaluation",
210
+ "MemoryPolicy",
211
+ "MemoryPolicyThresholds",
212
+ "PolicyDecision",
213
+ "content_hash",
214
+ "detect_sensitive_labels",
215
+ ]
@@ -0,0 +1,47 @@
1
+ """MemoryProvider Protocol 与能力声明(方案 §10.5)。
2
+
3
+ Provider 合同是本地与云端一致性的运行时边界:本地用 SQLite Provider,云端用 HTTP/SDK
4
+ Provider,二者共用同一套契约测试(方案 §17.4)。``expected_version`` 用于并发更新乐观锁,
5
+ 避免多个 Run 并发更新同一偏好时静默覆盖。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Protocol
11
+
12
+ from ksadk.memory.models import (
13
+ CoreMemoryRequest,
14
+ MemoryCapabilities,
15
+ MemoryDeleteRequest,
16
+ MemoryDeleteResult,
17
+ MemoryRecord,
18
+ MemorySearchRequest,
19
+ MemorySearchResult,
20
+ )
21
+
22
+
23
+ class MemoryProvider(Protocol):
24
+ """平台长期记忆 Provider 合同(方案 §10.5)。
25
+
26
+ 实现必须按 ``scope`` 隔离;``scope_id`` 由可信 Principal/Runtime Projection 决定,
27
+ 不能信任用户自行提交的 scope_id(方案 §19)。异常路径不得把错误文本塞进检索结果正文。
28
+ """
29
+
30
+ def capabilities(self) -> MemoryCapabilities: ...
31
+
32
+ def search(self, request: MemorySearchRequest) -> MemorySearchResult: ...
33
+
34
+ def get(self, memory_id: str) -> MemoryRecord | None: ...
35
+
36
+ def upsert(
37
+ self, record: MemoryRecord, *, expected_version: int | None
38
+ ) -> MemoryRecord: ...
39
+
40
+ def delete(self, request: MemoryDeleteRequest) -> MemoryDeleteResult: ...
41
+
42
+ def list_core(self, request: CoreMemoryRequest) -> list[MemoryRecord]: ...
43
+
44
+
45
+ __all__ = [
46
+ "MemoryProvider",
47
+ ]
@@ -0,0 +1,159 @@
1
+ """Memory Provider Adapter —— 统一不同 Provider 接口为 MemoryProvider Protocol(方案 §2)。
2
+
3
+ 不同后端接口不统一:
4
+ - SqliteMemoryProvider: upsert/search/delete(MemoryProvider Protocol)
5
+ - BaseLongTermMemoryBackend: save_memory/search_memory
6
+ - LongTermMemoryService: save_event_strings/search_entries
7
+
8
+ 本模块把它们统一适配为 MemoryCoordinator 可消费的接口。
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Any
14
+
15
+ from ksadk.memory.models import (
16
+ MemoryDeleteRequest,
17
+ MemoryDeleteResult,
18
+ MemoryRecord,
19
+ MemorySearchRequest,
20
+ MemorySearchResult,
21
+ )
22
+
23
+
24
+ class LegacyMemoryAdapter:
25
+ """把 BaseLongTermMemoryBackend / LongTermMemoryService 适配为 MemoryProvider Protocol。
26
+
27
+ save_memory → upsert(每条 event_string 构造 MemoryRecord)
28
+ search_memory → search(返回 MemorySearchResult)
29
+ """
30
+
31
+ def __init__(self, backend: Any) -> None:
32
+ self._backend = backend
33
+ self.last_error = getattr(backend, "last_error", "")
34
+
35
+ def capabilities(self):
36
+ from ksadk.memory.models import MemoryCapabilities
37
+
38
+ return MemoryCapabilities(
39
+ semantic_search=False,
40
+ keyword_search=True,
41
+ metadata_filter=False,
42
+ versioned_update=False,
43
+ hard_delete=False,
44
+ ttl=False,
45
+ max_record_chars=8192,
46
+ )
47
+
48
+ def search(self, request: MemorySearchRequest) -> MemorySearchResult:
49
+ """统一 search:用 search_memory/search_entries 取原始字符串列表。"""
50
+ import time
51
+
52
+ start = time.monotonic()
53
+ try:
54
+ # BaseLongTermMemoryBackend.search_memory
55
+ if hasattr(self._backend, "search_memory"):
56
+ entries = self._backend.search_memory(
57
+ user_id=request.scopes[0][1] if request.scopes else "",
58
+ query=request.query,
59
+ top_k=request.top_k,
60
+ )
61
+ # LongTermMemoryService.search_entries
62
+ elif hasattr(self._backend, "search_entries"):
63
+ entries = self._backend.search_entries(
64
+ user_id=request.scopes[0][1] if request.scopes else "",
65
+ query=request.query,
66
+ top_k=request.top_k,
67
+ )
68
+ else:
69
+ entries = []
70
+ except Exception: # noqa: BLE001
71
+ return MemorySearchResult(
72
+ status="failed",
73
+ records=[],
74
+ error_code="provider_error",
75
+ provider=type(self._backend).__name__,
76
+ latency_ms=int((time.monotonic() - start) * 1000),
77
+ accounting_accuracy="opaque",
78
+ )
79
+
80
+ # 转为 MemoryRecord 列表
81
+ records: list[MemoryRecord] = []
82
+ for i, entry in enumerate(entries):
83
+ records.append(
84
+ MemoryRecord(
85
+ memory_id=f"legacy_{i}",
86
+ tenant_id="local",
87
+ workspace_id="local",
88
+ scope="user",
89
+ scope_id=request.scopes[0][1] if request.scopes else "",
90
+ memory_type="fact",
91
+ content=entry,
92
+ summary=entry[:200],
93
+ status="active",
94
+ confidence=0.8,
95
+ importance=0.5,
96
+ valid_from="",
97
+ valid_to="",
98
+ expires_at="",
99
+ source_session_id="",
100
+ source_event_ids=[],
101
+ source_seq_range=None,
102
+ content_hash=f"sha256:{hash(entry) & 0xFFFFFFFFFFFFFFFF:016x}",
103
+ version=1,
104
+ )
105
+ )
106
+ return MemorySearchResult(
107
+ status="ok",
108
+ records=records,
109
+ error_code=None,
110
+ provider=type(self._backend).__name__,
111
+ latency_ms=int((time.monotonic() - start) * 1000),
112
+ accounting_accuracy="estimated",
113
+ )
114
+
115
+ def upsert(self, record: MemoryRecord, *, expected_version: int | None) -> MemoryRecord:
116
+ """统一 upsert:用 save_memory/save_event_strings。"""
117
+ import json
118
+
119
+ event_str = json.dumps(
120
+ {"parts": [{"text": record.content}], "metadata": record.metadata},
121
+ ensure_ascii=False,
122
+ )
123
+ success = True
124
+ if hasattr(self._backend, "save_memory"):
125
+ success = bool(
126
+ self._backend.save_memory(user_id=record.scope_id, event_strings=[event_str])
127
+ )
128
+ elif hasattr(self._backend, "save_event_strings"):
129
+ success = bool(
130
+ self._backend.save_event_strings(user_id=record.scope_id, event_strings=[event_str])
131
+ )
132
+ if not success:
133
+ raise RuntimeError(
134
+ f"Memory Provider save returned False: {type(self._backend).__name__}"
135
+ )
136
+ return record
137
+
138
+ def delete(self, request: MemoryDeleteRequest) -> MemoryDeleteResult:
139
+ return MemoryDeleteResult(status="ok", deleted=False, error_code="not_supported")
140
+
141
+ def list_core(self, request) -> list[MemoryRecord]:
142
+ return []
143
+
144
+
145
+ def adapt_as_memory_provider(obj: Any) -> Any:
146
+ """把任意后端适配为 MemoryProvider Protocol 兼容对象。
147
+
148
+ - 已经是 MemoryProvider Protocol(有 upsert/search)→ 原样返回
149
+ - BaseLongTermMemoryBackend / LongTermMemoryService → LegacyMemoryAdapter
150
+ """
151
+ # 已经兼容 MemoryProvider Protocol
152
+ if hasattr(obj, "upsert") and hasattr(obj, "search"):
153
+ return obj
154
+
155
+ # 需要适配
156
+ return LegacyMemoryAdapter(obj)
157
+
158
+
159
+ __all__ = ["LegacyMemoryAdapter", "adapt_as_memory_provider"]
@@ -0,0 +1,71 @@
1
+ """MemoryProviderResolver —— 根据 providerRef 解析真实 Memory Provider(方案 §2)。
2
+
3
+ providerRef 值映射:
4
+ "local-default" → 持久 SQLite(resolve_default_memory_provider)
5
+ "local-sqlite" → 同上
6
+ "local-inmemory" → InMemoryLTMBackend(测试用)
7
+ "http" → HttpLTMBackend(需 KSADK_LTM_HTTP_URL/TOKEN)
8
+ "sdk" → SdkLTMBackend(需 AK/SK + namespace)
9
+ "longterm-service" → LongTermMemoryService.from_env()
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import Protocol
15
+
16
+
17
+ class MemoryProviderLike(Protocol):
18
+ def search_memory(self, user_id: str, query: str, top_k: int = 5, **kwargs) -> list[str]: ...
19
+ def save_memory(self, user_id: str, event_strings: list[str], **kwargs) -> bool: ...
20
+
21
+
22
+ def resolve_memory_provider(provider_ref: str) -> MemoryProviderLike:
23
+ """根据 providerRef 解析真实 Memory Provider。
24
+
25
+ providerRef 值映射:
26
+ "local-default" / "local-sqlite" → 持久 SQLite
27
+ "local-inmemory" → InMemoryLTMBackend(测试用)
28
+ "http" → HttpLTMBackend(需 KSADK_LTM_HTTP_URL/TOKEN)
29
+ "sdk" → SdkLTMBackend(需 AK/SK + namespace)
30
+ "longterm-service" → LongTermMemoryService.from_env()
31
+ 其他 → fallback 到持久 SQLite(兼容旧 AgentVersion)
32
+ """
33
+ ref = str(provider_ref or "").strip().lower()
34
+
35
+ if ref in ("local-inmemory", "inmemory"):
36
+ from ksadk.memory.adk.backends.inmemory_ltm_backend import (
37
+ InMemoryLTMBackend,
38
+ )
39
+
40
+ return InMemoryLTMBackend()
41
+
42
+ if ref in ("http",):
43
+ import os
44
+
45
+ from ksadk.memory.adk.backends.http_ltm_backend import HttpLTMBackend
46
+
47
+ return HttpLTMBackend(
48
+ index="ksadk",
49
+ base_url=os.environ.get("KSADK_LTM_HTTP_URL", ""),
50
+ token=os.environ.get("KSADK_LTM_HTTP_TOKEN", ""),
51
+ )
52
+
53
+ if ref in ("sdk",):
54
+ from ksadk.memory.adk.backends.sdk_ltm_backend import SdkLTMBackend
55
+
56
+ return SdkLTMBackend(index="ksadk")
57
+
58
+ if ref in ("longterm-service",):
59
+ from ksadk.memory.service import LongTermMemoryService
60
+
61
+ return LongTermMemoryService.from_env()
62
+
63
+ # 默认:持久 SQLite(local-default / local-sqlite / 未知 ref)
64
+ from ksadk.memory.providers.local_sqlite import (
65
+ resolve_default_memory_provider,
66
+ )
67
+
68
+ return resolve_default_memory_provider()
69
+
70
+
71
+ __all__ = ["MemoryProviderLike", "resolve_memory_provider"]
@@ -0,0 +1,5 @@
1
+ """Memory Provider 实现入口。"""
2
+
3
+ from ksadk.memory.providers.local_sqlite import SqliteMemoryProvider
4
+
5
+ __all__ = ["SqliteMemoryProvider"]