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
@@ -0,0 +1,228 @@
1
+ """Memory Candidate 抽取(方案 §9.2 / §10.3 / §10.4)。
2
+
3
+ 压缩前从 ``groups_to_compact`` 的事件里确定性提取记忆候选。首期只做确定性提取,不调用模型
4
+ (方案 §9.3:优先确定性提取;模型辅助可关闭):
5
+
6
+ - 用户显式"记住/remember/别忘了" → ``profile`` 候选(reason=explicit_user_request)。
7
+ - 工具返回的稳定事实(含 "确认/confirmed/最终/final" 字样)→ ``fact`` 候选(reason=tool_fact)。
8
+
9
+ 提取结果交 ``MemoryPolicy.evaluate`` 评估;secret/PII、一次性当前任务状态、模型猜测由 Policy
10
+ 拒绝(方案 §10.4)。本期不做 LLM 辅助抽取,避免把模型猜测写入长期记忆。
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import re
16
+ import uuid
17
+ from typing import Sequence
18
+
19
+ from ksadk.memory.models import MemoryCandidate, MemoryScope
20
+
21
+ # 显式记忆意图(中英)。
22
+ _EXPLICIT_PATTERNS: tuple[re.Pattern[str], ...] = (
23
+ re.compile(r"(?i)记住[::]?\s*(.+)"),
24
+ re.compile(r"(?i)别忘了[::]?\s*(.+)"),
25
+ re.compile(r"(?i)remember\s+(?:that\s+)?(.+)", re.IGNORECASE),
26
+ re.compile(r"(?i)请记[::]?\s*(.+)"),
27
+ )
28
+ # 明确纠正同一偏好槽位。首期只覆盖语义边界清晰的动作型偏好,避免把
29
+ # “喜欢音乐”和“喜欢运动”等无关事实误判为冲突。
30
+ _PREFERENCE_CORRECTION = re.compile(
31
+ r"(?P<prefix>(?:我|本人)?喜欢(?P<action>吃|喝|用|看|听|玩))"
32
+ r"(?:的)?(?:是)?\s*(?P<new>.+?)\s*(?:,|,)?\s*(?:而)?不是\s*"
33
+ r"(?P<old>.+?)(?:[。.!!]|$)",
34
+ re.IGNORECASE,
35
+ )
36
+ _PREFERENCE_SLOT = re.compile(r"(?:我|本人)?喜欢(?P<action>吃|喝|用|看|听|玩)")
37
+ _HOBBY_DECLARATION = re.compile(
38
+ r"(?:我|本人)?的?爱好(?P<correction>其实|现在|改)?(?:是|改成|变成)\s*(?P<value>.+?)"
39
+ r"(?:[。.!!]|$)",
40
+ re.IGNORECASE,
41
+ )
42
+ _IMPLICIT_PREFERENCE_PATTERNS: tuple[re.Pattern[str], ...] = (
43
+ re.compile(r"(?:我|本人)?的?偏好(?:是|为)\s*(.+?)(?:[。.!!]|$)", re.IGNORECASE),
44
+ re.compile(
45
+ r"(?:我|本人)?(?:平时)?(?:喜欢|习惯)(吃|喝|用|看|听|玩)\s*(.+?)(?:[。.!!]|$)",
46
+ re.IGNORECASE,
47
+ ),
48
+ )
49
+ # 工具稳定事实信号。
50
+ _FACT_SIGNALS = ("confirmed", "最终确认", "final", "verified", "确认成功")
51
+
52
+
53
+ def _event_text(event: any) -> str: # type: ignore[name-defined]
54
+ try:
55
+ from ksadk.conversations.context import extract_event_text
56
+
57
+ return extract_event_text(event)
58
+ except Exception: # noqa: BLE001
59
+ return str(getattr(event, "text", "") or "")
60
+
61
+
62
+ def derive_profile_slot_key(content: str) -> str:
63
+ """为边界明确的可变偏好生成稳定槽位;无法确定时返回空串。"""
64
+ if _HOBBY_DECLARATION.search(str(content or "")):
65
+ return "profile.preference.hobby"
66
+ match = _PREFERENCE_SLOT.search(str(content or ""))
67
+ if not match:
68
+ return ""
69
+ action = match.group("action")
70
+ labels = {
71
+ "吃": "food",
72
+ "喝": "drink",
73
+ "用": "tool",
74
+ "看": "viewing",
75
+ "听": "listening",
76
+ "玩": "activity",
77
+ }
78
+ return f"profile.preference.{labels[action]}"
79
+
80
+
81
+ def propose_memory_candidates(
82
+ events: Sequence[any], # type: ignore[name-defined]
83
+ *,
84
+ scope: MemoryScope = "user",
85
+ scope_id: str = "",
86
+ ) -> list[MemoryCandidate]:
87
+ """从待压缩事件提取记忆候选(方案 §9.2)。
88
+
89
+ 纯确定性、无 LLM。返回候选列表交 Coordinator flush;Policy 决定 commit/reject。
90
+ """
91
+ candidates: list[MemoryCandidate] = []
92
+ if not events:
93
+ return candidates
94
+ for event in events:
95
+ text = _event_text(event).strip()
96
+ if not text:
97
+ continue
98
+ event_type = getattr(event, "event_type", "") or ""
99
+ author = getattr(event, "author", "") or ""
100
+ seq = getattr(event, "seq_id", 0) or 0
101
+ event_id = getattr(event, "id", "") or f"evt_{seq}"
102
+
103
+ # 1. 用户显式记忆意图
104
+ if author == "user" or event_type == "user_message":
105
+ hobby = _HOBBY_DECLARATION.search(text)
106
+ if hobby and hobby.group("correction"):
107
+ new_value = hobby.group("value").strip().strip("。.,, ")
108
+ if new_value:
109
+ content = f"我的爱好是{new_value}"
110
+ candidates.append(
111
+ MemoryCandidate(
112
+ candidate_id=f"cand_{uuid.uuid4().hex[:16]}",
113
+ operation="update",
114
+ memory_type="profile",
115
+ scope=scope,
116
+ scope_id=scope_id,
117
+ content=content[:1000],
118
+ confidence=0.95,
119
+ importance=0.9,
120
+ source_event_ids=[event_id],
121
+ slot_key=derive_profile_slot_key(content),
122
+ reason="explicit_user_correction",
123
+ )
124
+ )
125
+ continue
126
+ correction = _PREFERENCE_CORRECTION.search(text)
127
+ if correction:
128
+ prefix = correction.group("prefix").strip()
129
+ new_value = correction.group("new").strip().strip("。.,, ")
130
+ if new_value:
131
+ content = f"{prefix}{new_value}"
132
+ candidates.append(
133
+ MemoryCandidate(
134
+ candidate_id=f"cand_{uuid.uuid4().hex[:16]}",
135
+ operation="update",
136
+ memory_type="profile",
137
+ scope=scope,
138
+ scope_id=scope_id,
139
+ content=content[:1000],
140
+ confidence=0.95,
141
+ importance=0.9,
142
+ source_event_ids=[event_id],
143
+ slot_key=derive_profile_slot_key(content),
144
+ reason="explicit_user_correction",
145
+ )
146
+ )
147
+ continue
148
+ for pattern in _EXPLICIT_PATTERNS:
149
+ m = pattern.search(text)
150
+ if m:
151
+ content = (m.group(1) or text).strip().strip("。.,,")
152
+ if not content:
153
+ continue
154
+ candidates.append(
155
+ MemoryCandidate(
156
+ candidate_id=f"cand_{uuid.uuid4().hex[:16]}",
157
+ operation="add",
158
+ memory_type="profile",
159
+ scope=scope,
160
+ scope_id=scope_id,
161
+ content=content[:1000],
162
+ confidence=0.9,
163
+ importance=0.8,
164
+ source_event_ids=[event_id],
165
+ slot_key=derive_profile_slot_key(content),
166
+ reason="explicit_user_request",
167
+ )
168
+ )
169
+ break
170
+ else:
171
+ # 隐式偏好只生成低置信候选;MemoryPolicy 仍要求达到观察次数阈值,
172
+ # explicit_only 模式也会过滤它,避免一次闲聊直接成为长期事实。
173
+ for pattern in _IMPLICIT_PREFERENCE_PATTERNS:
174
+ match = pattern.search(text)
175
+ if not match:
176
+ continue
177
+ content = match.group(0).strip().strip("。.,,")
178
+ candidates.append(
179
+ MemoryCandidate(
180
+ candidate_id=f"cand_{uuid.uuid4().hex[:16]}",
181
+ operation="add",
182
+ memory_type="profile",
183
+ scope=scope,
184
+ scope_id=scope_id,
185
+ content=content[:1000],
186
+ confidence=0.75,
187
+ importance=0.65,
188
+ source_event_ids=[event_id],
189
+ slot_key=derive_profile_slot_key(content),
190
+ reason="implicit_user_preference",
191
+ )
192
+ )
193
+ break
194
+
195
+ # 2. 工具稳定事实(assistant/tool 事件含确认信号)
196
+ if event_type in ("tool_result", "assistant_message") and any(
197
+ sig in text.lower() for sig in _FACT_SIGNALS
198
+ ):
199
+ candidates.append(
200
+ MemoryCandidate(
201
+ candidate_id=f"cand_{uuid.uuid4().hex[:16]}",
202
+ operation="add",
203
+ memory_type="fact",
204
+ scope=scope,
205
+ scope_id=scope_id,
206
+ content=text[:1000],
207
+ confidence=0.7,
208
+ importance=0.6,
209
+ source_event_ids=[event_id],
210
+ slot_key="",
211
+ reason="tool_fact",
212
+ )
213
+ )
214
+ return candidates
215
+
216
+
217
+ class MemoryExtractor:
218
+ """方案 §9.2 的 ``MemoryExtractor.propose()`` 接口封装。"""
219
+
220
+ def __init__(self, *, scope: MemoryScope = "user", scope_id: str = "") -> None:
221
+ self._scope = scope
222
+ self._scope_id = scope_id
223
+
224
+ def propose(self, events: Sequence[any]) -> list[MemoryCandidate]: # type: ignore[name-defined]
225
+ return propose_memory_candidates(events, scope=self._scope, scope_id=self._scope_id)
226
+
227
+
228
+ __all__ = ["MemoryExtractor", "derive_profile_slot_key", "propose_memory_candidates"]
@@ -5,9 +5,22 @@ from __future__ import annotations
5
5
 
6
6
  def get_long_term_memory_backend_cls(backend: str) -> type:
7
7
  if backend == "local":
8
- from ksadk.memory.adk.backends.inmemory_ltm_backend import InMemoryLTMBackend
9
-
10
- return InMemoryLTMBackend
8
+ # 优先用持久 SQLite(解决 InMemory 进程退出后数据丢失、recall 和 flush 不同库)。
9
+ # 设 KSADK_LTM_BACKEND=inmemory 可显式回退。
10
+ import os
11
+
12
+ if str(os.environ.get("KSADK_LTM_FORCE_INMEMORY", "")).strip().lower() in (
13
+ "1",
14
+ "true",
15
+ ):
16
+ from ksadk.memory.adk.backends.inmemory_ltm_backend import (
17
+ InMemoryLTMBackend,
18
+ )
19
+
20
+ return InMemoryLTMBackend
21
+ from ksadk.memory.adk.backends.sqlite_ltm_backend import SqliteLTMBackend
22
+
23
+ return SqliteLTMBackend
11
24
 
12
25
  if backend == "http":
13
26
  from ksadk.memory.adk.backends.http_ltm_backend import HttpLTMBackend
ksadk/memory/models.py ADDED
@@ -0,0 +1,316 @@
1
+ """长期记忆结构化模型、操作结果与稳定异常类型。
2
+
3
+ 按《Hermes × KsADK 长期记忆实时性与纠错能力技术改造方案》§7.1/§7.2/§7.8 设计:
4
+
5
+ - LongTermMemoryRecord: 结构化记忆记录(memory_id 来自服务端返回值)
6
+ - MemoryWriteResult: 写入受理结果(accepted + queued/failed)
7
+ - MemoryMutationResult: update/delete 结果(updated/deleted/already_absent/not_found/failed)
8
+ - MemoryExtractionStatus: 后台提取状态
9
+ (queued/extracting/extracted/duplicate_skipped/failed/unknown)
10
+ - MemoryOperationError 族: 稳定异常类型,供上层归一化处理
11
+
12
+ 设计要点:
13
+ - memory_id 不能由正文 hash 临时生成;大部分情况稳定,但融合/人工编辑可能变化,
14
+ 不能作为永久业务主键长期缓存。
15
+ - 写入受理(accepted)与提取状态(extraction status)使用不同类型,
16
+ 避免布尔值同时表示"请求成功"和"已经可检索"。
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass, field
22
+ from typing import Any, Literal
23
+
24
+ __all__ = [
25
+ "LongTermMemoryRecord",
26
+ "MemoryWriteResult",
27
+ "MemoryMutationResult",
28
+ "MemoryExtractionStatus",
29
+ "MemoryOperationError",
30
+ "MemoryNotFoundError",
31
+ "UnsupportedMemoryOperation",
32
+ "MemoryPermissionError",
33
+ "MemoryConflictError",
34
+ "SESSION_STATE_PENDING",
35
+ "SESSION_STATE_EXTRACTING",
36
+ "SESSION_STATE_EXTRACTED",
37
+ "SESSION_STATE_DUPLICATE_SKIPPED",
38
+ "SESSION_STATE_EXTRACT_FAILED",
39
+ "map_session_state",
40
+ ]
41
+
42
+ # ---- AICP ListSessions State 枚举(服务端已确认) ----
43
+ SESSION_STATE_PENDING = 0 # 待提取
44
+ SESSION_STATE_EXTRACTING = 50 # 提取中
45
+ SESSION_STATE_EXTRACTED = 100 # 提取成功
46
+ SESSION_STATE_DUPLICATE_SKIPPED = -50 # 重复跳过
47
+ SESSION_STATE_EXTRACT_FAILED = -100 # 提取失败
48
+
49
+
50
+ @dataclass(frozen=True)
51
+ class LongTermMemoryRecord:
52
+ """结构化长期记忆记录。
53
+
54
+ Attributes:
55
+ memory_id: 服务端返回的记忆 ID。大部分情况稳定,但系统融合或
56
+ 人工编辑可能改变 ID,不能作为永久业务主键长期缓存。
57
+ content: 记忆正文。
58
+ score: 相关度得分;后端没有 score 时为 None。
59
+ user_id: 归属用户 ID。
60
+ session_id: 来源 Session ID(后端能提供时)。
61
+ created_at: 创建时间(后端原始字符串,通常为 ISO 时间或毫秒时间戳)。
62
+ updated_at: 更新时间(后端原始字符串)。
63
+ metadata: 其他必要元数据。禁止放入 AK/SK、token、内部 endpoint 等敏感信息。
64
+ """
65
+
66
+ memory_id: str
67
+ content: str
68
+ score: float | None = None
69
+ user_id: str = ""
70
+ session_id: str = ""
71
+ created_at: str | None = None
72
+ updated_at: str | None = None
73
+ metadata: dict[str, Any] = field(default_factory=dict)
74
+
75
+
76
+ @dataclass(frozen=True)
77
+ class MemoryWriteResult:
78
+ """写入受理结果。
79
+
80
+ status 只表达受理层状态:queued(已入队)/ failed(受理失败)。
81
+ 后续提取进展用 MemoryExtractionStatus 查询,不在写入热路径等待。
82
+ """
83
+
84
+ accepted: bool
85
+ status: str # queued | failed
86
+ session_id: str = ""
87
+ message: str = ""
88
+
89
+
90
+ @dataclass(frozen=True)
91
+ class MemoryMutationResult:
92
+ """update/delete 操作结果。
93
+
94
+ status:
95
+ updated - 原地更新成功;new_memory_id 为服务端返回的新句柄
96
+ deleted - 软删除成功
97
+ already_absent - 目标已不存在(如重复删除),与 deleted 分开审计
98
+ not_found - 目标记录不存在
99
+ failed - 操作失败
100
+ """
101
+
102
+ ok: bool
103
+ memory_id: str
104
+ new_memory_id: str = ""
105
+ status: str = "" # updated | deleted | already_absent | not_found | failed
106
+ message: str = ""
107
+
108
+
109
+ @dataclass(frozen=True)
110
+ class MemoryExtractionStatus:
111
+ """后台提取状态查询结果。
112
+
113
+ status:
114
+ queued - 写请求已被服务端接受,等待后台处理
115
+ extracting - 后台已经开始提取
116
+ extracted - ListSessions.State=100,提取完成
117
+ duplicate_skipped- State=-50,本次内容因重复被跳过(不是系统失败)
118
+ failed - State=-100 或查询过程失败
119
+ unknown - 状态未知(如 Session 未在 ListSessions 返回中)
120
+
121
+ searchable 单独用布尔标志表达:State=100 后通过 ListMemories 确认目标
122
+ 记录可见时才为 True(见方案 §7.2:状态与 searchable 分离建模)。
123
+ """
124
+
125
+ session_id: str
126
+ state: int | None
127
+ status: str
128
+ searchable: bool = False
129
+ message: str = ""
130
+
131
+
132
+ def map_session_state(state: int | None) -> str:
133
+ """将 AICP Session State 映射为统一提取状态字符串。"""
134
+ mapping = {
135
+ SESSION_STATE_PENDING: "queued",
136
+ SESSION_STATE_EXTRACTING: "extracting",
137
+ SESSION_STATE_EXTRACTED: "extracted",
138
+ SESSION_STATE_DUPLICATE_SKIPPED: "duplicate_skipped",
139
+ SESSION_STATE_EXTRACT_FAILED: "failed",
140
+ }
141
+ if state is None:
142
+ return "unknown"
143
+ return mapping.get(int(state), "unknown")
144
+
145
+
146
+ # ---- 稳定异常类型(§7.8) ----
147
+
148
+
149
+ class MemoryOperationError(RuntimeError):
150
+ """长期记忆操作基础异常。子类供上层按类型归一化处理。"""
151
+
152
+
153
+ class MemoryNotFoundError(MemoryOperationError):
154
+ """目标记忆记录不存在。"""
155
+
156
+
157
+ class UnsupportedMemoryOperation(MemoryOperationError):
158
+ """当前 backend 不支持该操作。
159
+
160
+ 不支持某能力的 backend 必须显式抛出本异常(或返回 unsupported 结果),
161
+ 不能静默追加一条新记忆来模拟 update。
162
+ """
163
+
164
+
165
+ class MemoryPermissionError(MemoryOperationError):
166
+ """跨用户或越权访问记忆资源。"""
167
+
168
+
169
+ class MemoryConflictError(MemoryOperationError):
170
+ """并发修改冲突(如记录已被融合导致 ID 变化)。"""
171
+
172
+
173
+ # ---- PCM v2 数据模型(feature-prompt-context-optimize 分支)----
174
+ # 与 master 的 LongTermMemoryRecord 共存;PCM 模块用这些类型
175
+
176
+ MEMORY_MODEL_VERSION = "v1"
177
+
178
+ MemoryScope = Literal["user", "agent", "workspace", "org"]
179
+ MemoryType = Literal["profile", "fact", "episode"]
180
+ MemoryStatus = Literal["active", "superseded", "deleted", "expired"]
181
+ MemoryOperation = Literal["add", "update", "delete", "ignore"]
182
+ MemorySearchStatus = Literal["ok", "not_configured", "timeout", "unauthorized", "failed"]
183
+ SensitiveLabel = Literal[
184
+ "api_key",
185
+ "secret_key",
186
+ "access_key",
187
+ "cookie",
188
+ "auth_header",
189
+ "signed_url",
190
+ "dsn",
191
+ "pii",
192
+ "token",
193
+ "binary",
194
+ "none",
195
+ ]
196
+
197
+
198
+ @dataclass(frozen=True)
199
+ class MemoryRecord:
200
+ memory_id: str
201
+ tenant_id: str
202
+ workspace_id: str
203
+ scope: MemoryScope
204
+ scope_id: str
205
+ memory_type: MemoryType
206
+ content: str
207
+ summary: str
208
+ status: MemoryStatus
209
+ confidence: float
210
+ importance: float
211
+ valid_from: str
212
+ valid_to: str
213
+ expires_at: str
214
+ source_session_id: str
215
+ source_event_ids: list[str]
216
+ source_seq_range: tuple[int, int] | None
217
+ content_hash: str
218
+ version: int
219
+ metadata: dict[str, Any] = field(default_factory=dict)
220
+ created_at: str = ""
221
+ updated_at: str = ""
222
+
223
+ def is_active_now(self, *, now_iso: str = "") -> bool:
224
+ if self.status != "active":
225
+ return False
226
+ if self.expires_at and now_iso and self.expires_at < now_iso:
227
+ return False
228
+ if self.valid_to and now_iso and self.valid_to < now_iso:
229
+ return False
230
+ return True
231
+
232
+
233
+ @dataclass(frozen=True)
234
+ class MemoryCandidate:
235
+ candidate_id: str
236
+ operation: MemoryOperation
237
+ memory_type: MemoryType
238
+ scope: MemoryScope
239
+ scope_id: str
240
+ content: str
241
+ confidence: float
242
+ importance: float
243
+ source_event_ids: list[str]
244
+ conflicts_with: list[str] = field(default_factory=list)
245
+ sensitive_labels: list[SensitiveLabel] = field(default_factory=list)
246
+ reason: str = ""
247
+ slot_key: str = ""
248
+
249
+ def is_hard_rejected(self) -> bool:
250
+ return any(label != "none" for label in self.sensitive_labels)
251
+
252
+
253
+ @dataclass(frozen=True)
254
+ class MemorySearchRequest:
255
+ query: str
256
+ scopes: list[tuple[MemoryScope, str]]
257
+ memory_types: list[MemoryType]
258
+ top_k: int = 8
259
+ max_tokens: int = 4000
260
+ min_score: float = 0.45
261
+ as_of: str = ""
262
+ filters: dict[str, Any] = field(default_factory=dict)
263
+
264
+
265
+ @dataclass(frozen=True)
266
+ class MemorySearchResult:
267
+ status: MemorySearchStatus
268
+ records: list[MemoryRecord]
269
+ error_code: str | None
270
+ provider: str
271
+ latency_ms: int
272
+ accounting_accuracy: str
273
+ truncated_by_budget: bool = False
274
+
275
+
276
+ @dataclass(frozen=True)
277
+ class MemoryCapabilities:
278
+ semantic_search: bool
279
+ keyword_search: bool
280
+ metadata_filter: bool
281
+ versioned_update: bool
282
+ hard_delete: bool
283
+ ttl: bool
284
+ max_record_chars: int
285
+
286
+
287
+ @dataclass(frozen=True)
288
+ class CoreMemoryBlock:
289
+ name: str
290
+ description: str
291
+ content: str
292
+ max_tokens: int
293
+ writable: bool
294
+ source_memory_ids: list[str] = field(default_factory=list)
295
+
296
+
297
+ @dataclass(frozen=True)
298
+ class MemoryDeleteRequest:
299
+ memory_id: str
300
+ scope: MemoryScope
301
+ scope_id: str
302
+ hard: bool = False
303
+
304
+
305
+ @dataclass(frozen=True)
306
+ class MemoryDeleteResult:
307
+ status: MemorySearchStatus
308
+ deleted: bool
309
+ error_code: str | None = None
310
+
311
+
312
+ @dataclass(frozen=True)
313
+ class CoreMemoryRequest:
314
+ scopes: list[tuple[MemoryScope, str]]
315
+ max_blocks: int = 8
316
+ max_tokens: int = 4096