agentengine-sdk-python 0.8.0__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.
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
- agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
- ksadk/a2a/__init__.py +2 -0
- ksadk/a2a/_space_client_events.py +381 -0
- ksadk/a2a/bootstrap.py +0 -2
- ksadk/a2a/card.py +6 -111
- ksadk/a2a/control_plane.py +239 -1
- ksadk/a2a/event_adapter.py +156 -64
- ksadk/a2a/executor.py +195 -172
- ksadk/a2a/routes.py +12 -5
- ksadk/a2a/server.py +1 -8
- ksadk/a2a/service_env.py +33 -0
- ksadk/a2a/space_client.py +43 -349
- ksadk/a2a_card.py +101 -0
- ksadk/a2ui/core.py +222 -53
- ksadk/agui/_agent_helpers.py +243 -0
- ksadk/agui/a2ui_projection.py +12 -5
- ksadk/agui/agent.py +474 -275
- ksadk/agui/config.py +11 -5
- ksadk/agui/routes.py +7 -15
- ksadk/api/client.py +530 -40
- ksadk/api/environment.py +27 -0
- ksadk/builders/code_builder.py +352 -53
- ksadk/builders/container_builder.py +71 -44
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +2 -2
- ksadk/builders/managed_runtime_builder.py +60 -28
- ksadk/cli/__init__.py +25 -0
- ksadk/cli/cmd_a2a.py +18 -31
- ksadk/cli/cmd_create.py +13 -26
- ksadk/cli/cmd_dashboard.py +15 -1
- ksadk/cli/cmd_deploy.py +28 -3
- ksadk/cli/cmd_eval.py +443 -0
- ksadk/cli/cmd_evalset.py +284 -0
- ksadk/cli/cmd_files.py +5 -1
- ksadk/cli/cmd_hermes.py +137 -163
- ksadk/cli/cmd_invoke.py +28 -38
- ksadk/cli/cmd_launch.py +12 -0
- ksadk/cli/cmd_managed_runtime.py +95 -0
- ksadk/cli/cmd_observe.py +85 -0
- ksadk/cli/cmd_openclaw.py +85 -479
- ksadk/cli/cmd_replay.py +28 -4
- ksadk/cli/cmd_run.py +29 -67
- ksadk/cli/cmd_studio.py +201 -0
- ksadk/cli/cmd_web.py +15 -6
- ksadk/cli/dry_run.py +2 -1
- ksadk/cli/env_options.py +83 -0
- ksadk/cli/global_options.py +3 -1
- ksadk/cli/hermes_env.py +151 -0
- ksadk/cli/invoke_payload.py +49 -0
- ksadk/cli/network_options.py +7 -5
- ksadk/cli/openclaw_env.py +458 -0
- ksadk/cli/runtime_bootstrap.py +51 -0
- ksadk/cli/ui.py +6 -0
- ksadk/cli/workflow_common.py +5 -5
- ksadk/codex/__init__.py +3 -3
- ksadk/codex/client.py +833 -49
- ksadk/codex/phase.py +1 -1
- ksadk/codex/runtime.py +720 -127
- ksadk/common/kop_client.py +232 -0
- ksadk/configs/__init__.py +1 -3
- ksadk/configs/env_registry.py +244 -45
- ksadk/configs/env_registry_pcm.py +181 -0
- ksadk/configs/env_var_spec.py +18 -0
- ksadk/configs/global_config.py +6 -1
- ksadk/configs/settings.py +5 -108
- ksadk/context_engine/__init__.py +98 -0
- ksadk/context_engine/assembler.py +176 -0
- ksadk/context_engine/baseline.py +419 -0
- ksadk/context_engine/cache_observability.py +228 -0
- ksadk/context_engine/capabilities.py +443 -0
- ksadk/context_engine/contributors.py +344 -0
- ksadk/context_engine/hosted_pipeline.py +417 -0
- ksadk/context_engine/models.py +117 -0
- ksadk/context_engine/planner.py +698 -0
- ksadk/context_engine/policies.py +319 -0
- ksadk/context_engine/projection.py +31 -0
- ksadk/context_engine/shadow_plan.py +266 -0
- ksadk/context_engine/tokenizer.py +164 -0
- ksadk/conversations/__init__.py +85 -94
- ksadk/conversations/context.py +126 -6
- ksadk/conversations/message_projection.py +292 -28
- ksadk/conversations/model_context.py +49 -3
- ksadk/conversations/runtime_compaction.py +207 -5
- ksadk/conversations/runtime_input.py +193 -3
- ksadk/conversations/runtime_invocation.py +81 -3
- ksadk/conversations/runtime_observability.py +157 -4
- ksadk/conversations/runtime_payloads.py +42 -0
- ksadk/conversations/runtime_preparation.py +280 -2
- ksadk/conversations/runtime_resume.py +71 -32
- ksadk/conversations/runtime_stream_events.py +94 -9
- ksadk/conversations/runtime_streaming.py +175 -22
- ksadk/conversations/semantic_summary.py +311 -1
- ksadk/conversations/session_lock.py +51 -0
- ksadk/deployment/env_forward.py +72 -0
- ksadk/deployment/managed_runtime.py +38 -0
- ksadk/deployment/manager.py +24 -8
- ksadk/deployment/providers/serverless.py +228 -92
- ksadk/evaluation/__init__.py +116 -0
- ksadk/evaluation/a2a_adapter.py +452 -0
- ksadk/evaluation/adapters.py +67 -0
- ksadk/evaluation/agent_eval_client.py +395 -0
- ksadk/evaluation/cloud_binding.py +80 -0
- ksadk/evaluation/cloud_converter.py +194 -0
- ksadk/evaluation/cloud_service.py +199 -0
- ksadk/evaluation/contracts.py +478 -0
- ksadk/evaluation/evalset.py +351 -0
- ksadk/evaluation/evaluators.py +627 -0
- ksadk/evaluation/evidence.py +258 -0
- ksadk/evaluation/executor.py +143 -0
- ksadk/evaluation/local_adapter.py +550 -0
- ksadk/evaluation/service_env.py +27 -0
- ksadk/evaluation/storage.py +68 -0
- ksadk/evaluation/studio_build_adapter.py +253 -0
- ksadk/evaluation/target.py +82 -0
- ksadk/events/__init__.py +13 -13
- ksadk/events/_v1_compat/__init__.py +1 -0
- ksadk/events/_v1_compat/models.py +299 -0
- ksadk/events/_v1_compat/parser.py +247 -0
- ksadk/events/_v1_compat/projection.py +753 -0
- ksadk/events/adapters/__init__.py +34 -0
- ksadk/events/adapters/_a2a_snapshot.py +622 -0
- ksadk/events/adapters/_a2a_support.py +275 -0
- ksadk/events/adapters/_codex_interactions.py +375 -0
- ksadk/events/adapters/_codex_items.py +801 -0
- ksadk/events/adapters/_codex_validators.py +311 -0
- ksadk/events/adapters/_langgraph_support.py +785 -0
- ksadk/events/adapters/a2a.py +841 -0
- ksadk/events/adapters/adk.py +503 -0
- ksadk/events/adapters/codex.py +717 -0
- ksadk/events/adapters/langgraph.py +745 -0
- ksadk/events/canonical.py +440 -0
- ksadk/events/canonical_replay.py +497 -0
- ksadk/events/canonical_store.py +468 -0
- ksadk/events/cold_recovery.py +257 -0
- ksadk/events/content.py +89 -0
- ksadk/events/identity.py +86 -0
- ksadk/events/pipeline.py +455 -0
- ksadk/events/projections.py +66 -0
- ksadk/events/reducer.py +661 -0
- ksadk/events/replay.py +3 -36
- ksadk/events/runtime_event.py +20 -256
- ksadk/events/session_event.py +324 -0
- ksadk/events/store.py +3 -316
- ksadk/events/v1_compat.py +41 -0
- ksadk/harness/__init__.py +3 -2
- ksadk/harness/app.py +114 -123
- ksadk/harness/config.py +1 -1
- ksadk/harness/runtime.py +467 -0
- ksadk/hermes_terminal.py +5 -0
- ksadk/identity/resolver.py +4 -3
- ksadk/interaction/__init__.py +28 -0
- ksadk/interaction/contracts.py +136 -0
- ksadk/interaction/ledger.py +189 -0
- ksadk/interaction/provider.py +122 -0
- ksadk/interaction/providers/__init__.py +52 -0
- ksadk/interaction/providers/adk.py +40 -0
- ksadk/interaction/providers/codex.py +94 -0
- ksadk/interaction/providers/langgraph.py +58 -0
- ksadk/kernel/__init__.py +117 -0
- ksadk/kernel/authorization.py +258 -0
- ksadk/kernel/bootstrap.py +1074 -0
- ksadk/kernel/contract_fingerprints.py +61 -0
- ksadk/kernel/contracts.py +362 -0
- ksadk/kernel/control.py +219 -0
- ksadk/kernel/errors.py +79 -0
- ksadk/kernel/ingress.py +1102 -0
- ksadk/kernel/mapping.py +111 -0
- ksadk/kernel/memory_store.py +1133 -0
- ksadk/kernel/postgres_store.py +1756 -0
- ksadk/kernel/recovery.py +452 -0
- ksadk/kernel/runtime_identity.py +103 -0
- ksadk/kernel/sql/001_agent_kernel.sql +120 -0
- ksadk/kernel/sqlite_store.py +1410 -0
- ksadk/kernel/state.py +145 -0
- ksadk/kernel/store.py +232 -0
- ksadk/kernel/worker.py +953 -0
- ksadk/knowledge_base/client.py +22 -4
- ksadk/knowledge_base/service.py +32 -5
- ksadk/managed_a2a_card.py +160 -0
- ksadk/managed_runtime.py +16 -9
- ksadk/memory/__init__.py +61 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
- ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
- ksadk/memory/adk/backends/sdk_ltm_backend.py +394 -5
- ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
- ksadk/memory/adk/long_term_memory.py +3 -2
- ksadk/memory/coordinator.py +461 -0
- ksadk/memory/events.py +202 -0
- ksadk/memory/extraction.py +228 -0
- ksadk/memory/ltm_backend_factory.py +16 -3
- ksadk/memory/models.py +316 -0
- ksadk/memory/policy.py +215 -0
- ksadk/memory/provider.py +47 -0
- ksadk/memory/provider_adapter.py +159 -0
- ksadk/memory/provider_resolver.py +71 -0
- ksadk/memory/providers/__init__.py +5 -0
- ksadk/memory/providers/local_sqlite.py +490 -0
- ksadk/memory/resolved_policy.py +145 -0
- ksadk/memory/service.py +198 -8
- ksadk/memory/tool.py +4 -0
- ksadk/model_proxy/bootstrap.py +16 -9
- ksadk/model_proxy/config.py +22 -1
- ksadk/model_proxy/detect.py +202 -9
- ksadk/model_proxy/namespace.py +67 -15
- ksadk/model_proxy/server.py +168 -6
- ksadk/model_proxy/transform.py +105 -3
- ksadk/observability/__init__.py +25 -0
- ksadk/observability/session_log.py +420 -0
- ksadk/observability/trajectory.py +105 -0
- ksadk/prompts/__init__.py +71 -0
- ksadk/prompts/compiler.py +215 -0
- ksadk/prompts/models.py +82 -0
- ksadk/prompts/projection.py +89 -0
- ksadk/prompts/resolved.py +137 -0
- ksadk/prompts/sources.py +233 -0
- ksadk/runners/_langgraph_runner_streams.py +822 -0
- ksadk/runners/adk_runner.py +14 -31
- ksadk/runners/base_runner.py +44 -3
- ksadk/runners/factory.py +3 -3
- ksadk/runners/langgraph_runner.py +252 -433
- ksadk/runners/utils/__init__.py +0 -10
- ksadk/runners/utils/loader.py +16 -0
- ksadk/runtime/__init__.py +67 -41
- ksadk/runtime/_runner_adapter/__init__.py +1 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
- ksadk/runtime/adapter.py +199 -16
- ksadk/runtime/conversation_execution.py +687 -0
- ksadk/runtime/executor.py +392 -0
- ksadk/runtime/factory.py +342 -0
- ksadk/runtime/framework_adapters.py +6 -12
- ksadk/runtime/hosted_finalizer.py +268 -0
- ksadk/runtime/launch.py +61 -0
- ksadk/runtime/preprocessing.py +49 -14
- ksadk/runtime/runner_adapter.py +330 -391
- ksadk/runtime/runner_loading.py +36 -0
- ksadk/runtime/usage.py +33 -0
- ksadk/sandbox/backends/e2b.py +36 -3
- ksadk/server/__init__.py +39 -4
- ksadk/server/app.py +18 -492
- ksadk/server/composition.py +36 -2
- ksadk/server/factory.py +210 -149
- ksadk/server/routes/common.py +15 -46
- ksadk/server/routes/control.py +13 -9
- ksadk/server/routes/kernel_ingress.py +258 -0
- ksadk/server/routes/misc.py +10 -33
- ksadk/server/routes/models.py +14 -6
- ksadk/server/routes/openai_compat.py +129 -27
- ksadk/server/routes/projection.py +84 -16
- ksadk/server/routes/run.py +347 -460
- ksadk/server/routes/sessions.py +37 -40
- ksadk/server/routes/streaming.py +52 -7
- ksadk/server/routes/workspace.py +54 -21
- ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
- ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
- ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
- ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
- ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
- ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
- ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
- ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
- ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
- ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
- ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
- ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
- ksadk/server/static/assets/{chunk-FMBD7UC4-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
- ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
- ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
- ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
- ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
- ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
- ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
- ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-CX3yotHq.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
- ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
- ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
- ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
- ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
- ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
- ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
- ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
- ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
- ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
- ksadk/server/static/assets/{dist-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
- ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
- ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
- ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
- ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
- ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
- ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
- ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
- ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
- ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
- ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
- ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
- ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
- ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
- ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
- ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
- ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
- ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
- ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
- ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
- ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
- ksadk/server/static/assets/{dist-C99THtIA.js → dist-ngtN0DJB.js} +1 -1
- ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
- ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
- ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
- ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
- ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
- ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
- ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
- ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
- ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
- ksadk/server/static/assets/{linear-CvMBw9cA.js → linear-BHjG8b-J.js} +1 -1
- ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-CSAQxEAe.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
- ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
- ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
- ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
- ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-CxIR4JXI.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
- ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
- ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
- ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
- ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
- ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
- ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-jqoYs3jQ.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
- ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
- ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
- ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
- ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
- ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
- ksadk/server/static/index.html +2 -2
- ksadk/sessions/__init__.py +26 -9
- ksadk/sessions/_local_service_sync.py +688 -0
- ksadk/sessions/_local_tables.py +21 -0
- ksadk/sessions/_postgres_schema.py +305 -0
- ksadk/sessions/_postgres_tables.py +15 -0
- ksadk/sessions/base.py +80 -1
- ksadk/sessions/in_memory.py +53 -2
- ksadk/sessions/local_service.py +63 -604
- ksadk/sessions/postgres_service.py +58 -148
- ksadk/sessions/resilient.py +35 -1
- ksadk/skills/runtime/backends/e2b.py +1 -1
- ksadk/skills/service_client.py +13 -3
- ksadk/studio/__init__.py +5 -0
- ksadk/studio/agent_avatar_assets.py +120 -0
- ksadk/studio/agent_lifecycle.py +51 -0
- ksadk/studio/api.py +1598 -0
- ksadk/studio/api_catalog_routes.py +324 -0
- ksadk/studio/api_contracts.py +286 -0
- ksadk/studio/api_helpers.py +132 -0
- ksadk/studio/api_memory_routes.py +82 -0
- ksadk/studio/authoring.py +749 -0
- ksadk/studio/authoring_coordinator.py +1017 -0
- ksadk/studio/builder.py +397 -0
- ksadk/studio/capabilities.py +368 -0
- ksadk/studio/cloud.py +2099 -0
- ksadk/studio/codex_agent_service.py +694 -0
- ksadk/studio/codex_authoring.py +469 -0
- ksadk/studio/codex_builder.py +437 -0
- ksadk/studio/codex_manifest.py +307 -0
- ksadk/studio/codex_run.py +395 -0
- ksadk/studio/compiler.py +190 -0
- ksadk/studio/contracts.py +755 -0
- ksadk/studio/errors.py +47 -0
- ksadk/studio/event_store.py +214 -0
- ksadk/studio/framework_run.py +342 -0
- ksadk/studio/hosted_kernel.py +317 -0
- ksadk/studio/identifiers.py +33 -0
- ksadk/studio/manifest_resolver.py +131 -0
- ksadk/studio/mcp_runtime.py +229 -0
- ksadk/studio/model_client.py +629 -0
- ksadk/studio/model_profile_service.py +214 -0
- ksadk/studio/operations.py +275 -0
- ksadk/studio/otel_trace.py +1060 -0
- ksadk/studio/pagination.py +182 -0
- ksadk/studio/pcm_memory.py +85 -0
- ksadk/studio/python_tool_inspection.py +183 -0
- ksadk/studio/repository.py +327 -0
- ksadk/studio/resource_catalog.py +1260 -0
- ksadk/studio/run_service.py +1133 -0
- ksadk/studio/runtime_catalog.py +74 -0
- ksadk/studio/runtime_source.py +365 -0
- ksadk/studio/service.py +2249 -0
- ksadk/studio/shared_web.py +1004 -0
- ksadk/studio/skill_discovery.py +628 -0
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
- ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
- ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
- ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
- ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- ksadk/studio/static/index.html +15 -0
- ksadk/studio/templates.py +722 -0
- ksadk/studio/validator.py +265 -0
- ksadk/studio/workspace.py +135 -0
- ksadk/tools/gateway.py +9 -0
- ksadk/toolsets/__init__.py +27 -1
- ksadk/toolsets/a2a.py +426 -0
- ksadk/tracing/__init__.py +19 -21
- ksadk/tracing/setup.py +317 -403
- ksadk/tracing/span_utils.py +0 -44
- ksadk/version.py +1 -1
- ksadk_runtime_common/memory_backend/registry.py +56 -56
- ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
- ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
- ksadk_runtime_common/workspace_files/router.py +8 -2
- agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
- ksadk/a2a/card_builder.py +0 -64
- ksadk/a2a/client.py +0 -309
- ksadk/events/parser.py +0 -191
- ksadk/harness/runner.py +0 -211
- ksadk/runners/codex_runner.py +0 -132
- ksadk/runners/utils/langfuse.py +0 -230
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
- ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
- ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
- ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
- ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
- ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
- ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
- ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
- ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
- ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
- ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
- ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
- ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
- ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
- ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
- ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
- ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
- ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
- ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
- ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
- ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
- ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
- ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
- ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
- ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
- ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
- ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
- ksadk/server/static/assets/katex-DATssjp1.js +0 -265
- ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
- ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
- ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
- ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
- ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
- ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
- ksadk/tracing/exporters/langfuse_exporter.py +0 -460
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
|
@@ -2,15 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
使用简单的内存字典存储和文本匹配检索。
|
|
4
4
|
数据在进程退出后丢失,仅适用于开发和测试场景。
|
|
5
|
+
|
|
6
|
+
扩展协议(技术改造方案 §7.3):内存实现结构化检索与 update/delete,
|
|
7
|
+
用于本地开发和 fake 场景下的契约验证;不声明 flush/session_status 能力
|
|
8
|
+
(没有后台提取过程,写入即"可见")。
|
|
9
|
+
|
|
10
|
+
兼容设计:_storage 保存原始事件字符串不改写,search_memory 返回原始
|
|
11
|
+
字符串列表(保留旧契约,§7.5);结构化能力通过平行 ID 索引提供。
|
|
5
12
|
"""
|
|
6
13
|
|
|
14
|
+
import json
|
|
7
15
|
import logging
|
|
16
|
+
import uuid
|
|
8
17
|
from collections import defaultdict
|
|
9
|
-
from typing import List
|
|
18
|
+
from typing import List, Set
|
|
10
19
|
|
|
11
20
|
from pydantic import PrivateAttr
|
|
12
21
|
|
|
13
|
-
from ksadk.memory.adk.backends.base_ltm_backend import
|
|
22
|
+
from ksadk.memory.adk.backends.base_ltm_backend import (
|
|
23
|
+
CAP_ADD,
|
|
24
|
+
CAP_DELETE,
|
|
25
|
+
CAP_SEARCH,
|
|
26
|
+
CAP_STRUCTURED_SEARCH,
|
|
27
|
+
CAP_UPDATE,
|
|
28
|
+
BaseLongTermMemoryBackend,
|
|
29
|
+
)
|
|
30
|
+
from ksadk.memory.models import (
|
|
31
|
+
LongTermMemoryRecord,
|
|
32
|
+
MemoryMutationResult,
|
|
33
|
+
)
|
|
14
34
|
|
|
15
35
|
logger = logging.getLogger(__name__)
|
|
16
36
|
|
|
@@ -30,6 +50,12 @@ class InMemoryLTMBackend(BaseLongTermMemoryBackend):
|
|
|
30
50
|
"""
|
|
31
51
|
|
|
32
52
|
_storage: defaultdict[str, list[str]] = PrivateAttr(default_factory=lambda: defaultdict(list))
|
|
53
|
+
# memory_id -> 原始事件字符串(不改写 _storage,保留旧 search_memory 契约)。
|
|
54
|
+
_entry_ids: dict[str, str] = PrivateAttr(default_factory=dict)
|
|
55
|
+
# (user_id) -> {memory_id -> 原始事件字符串},用于快速定位与更新/删除。
|
|
56
|
+
_user_entry_index: defaultdict[str, dict[str, str]] = PrivateAttr(
|
|
57
|
+
default_factory=lambda: defaultdict(dict)
|
|
58
|
+
)
|
|
33
59
|
|
|
34
60
|
def model_post_init(self, __context) -> None:
|
|
35
61
|
# {user_id: [event_string, ...]}
|
|
@@ -40,7 +66,11 @@ class InMemoryLTMBackend(BaseLongTermMemoryBackend):
|
|
|
40
66
|
if not event_strings:
|
|
41
67
|
return True
|
|
42
68
|
|
|
43
|
-
|
|
69
|
+
for entry in event_strings:
|
|
70
|
+
memory_id = f"mem-{uuid.uuid4().hex[:12]}"
|
|
71
|
+
self._entry_ids[memory_id] = entry
|
|
72
|
+
self._user_entry_index[user_id][memory_id] = entry
|
|
73
|
+
self._storage[user_id].append(entry)
|
|
44
74
|
logger.debug(
|
|
45
75
|
f"Saved {len(event_strings)} events for user={user_id}, "
|
|
46
76
|
f"total={len(self._storage[user_id])}"
|
|
@@ -88,3 +118,106 @@ class InMemoryLTMBackend(BaseLongTermMemoryBackend):
|
|
|
88
118
|
f"found {len(results)} results from {len(user_memories)} total"
|
|
89
119
|
)
|
|
90
120
|
return results
|
|
121
|
+
|
|
122
|
+
# ---- 扩展协议实现(§7.3) ----
|
|
123
|
+
|
|
124
|
+
def capabilities(self) -> Set[str]:
|
|
125
|
+
return {
|
|
126
|
+
CAP_SEARCH,
|
|
127
|
+
CAP_ADD,
|
|
128
|
+
CAP_STRUCTURED_SEARCH,
|
|
129
|
+
CAP_UPDATE,
|
|
130
|
+
CAP_DELETE,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
def search_records(
|
|
134
|
+
self, user_id: str, query: str, top_k: int = 5, **kwargs
|
|
135
|
+
) -> List[LongTermMemoryRecord]:
|
|
136
|
+
"""结构化检索:复用关键词匹配,返回稳定生成的本地 ID。"""
|
|
137
|
+
entries = self.search_memory(user_id, query, top_k=top_k)
|
|
138
|
+
records: List[LongTermMemoryRecord] = []
|
|
139
|
+
for entry in entries:
|
|
140
|
+
memory_id = self._find_entry_id(user_id, entry)
|
|
141
|
+
if memory_id is None:
|
|
142
|
+
continue
|
|
143
|
+
records.append(
|
|
144
|
+
LongTermMemoryRecord(
|
|
145
|
+
memory_id=memory_id,
|
|
146
|
+
content=self._entry_text(entry),
|
|
147
|
+
score=None,
|
|
148
|
+
user_id=user_id,
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
return records
|
|
152
|
+
|
|
153
|
+
def update_memory(
|
|
154
|
+
self,
|
|
155
|
+
*,
|
|
156
|
+
user_id: str,
|
|
157
|
+
memory_id: str,
|
|
158
|
+
content: str,
|
|
159
|
+
**kwargs,
|
|
160
|
+
) -> MemoryMutationResult:
|
|
161
|
+
user_index = self._user_entry_index.get(user_id, {})
|
|
162
|
+
old_entry = user_index.get(memory_id)
|
|
163
|
+
if old_entry is None:
|
|
164
|
+
return MemoryMutationResult(ok=False, memory_id=memory_id, status="not_found")
|
|
165
|
+
new_entry = json.dumps(
|
|
166
|
+
{"role": "user", "parts": [{"text": content}]}, ensure_ascii=False
|
|
167
|
+
)
|
|
168
|
+
memories = self._storage[user_id]
|
|
169
|
+
for i, entry in enumerate(memories):
|
|
170
|
+
if entry is old_entry:
|
|
171
|
+
memories[i] = new_entry
|
|
172
|
+
break
|
|
173
|
+
self._entry_ids[memory_id] = new_entry
|
|
174
|
+
user_index[memory_id] = new_entry
|
|
175
|
+
return MemoryMutationResult(
|
|
176
|
+
ok=True,
|
|
177
|
+
memory_id=memory_id,
|
|
178
|
+
new_memory_id=memory_id,
|
|
179
|
+
status="updated",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
def delete_memory(
|
|
183
|
+
self,
|
|
184
|
+
*,
|
|
185
|
+
user_id: str,
|
|
186
|
+
memory_id: str,
|
|
187
|
+
**kwargs,
|
|
188
|
+
) -> MemoryMutationResult:
|
|
189
|
+
user_index = self._user_entry_index.get(user_id, {})
|
|
190
|
+
entry = user_index.pop(memory_id, None)
|
|
191
|
+
if entry is None:
|
|
192
|
+
return MemoryMutationResult(
|
|
193
|
+
ok=True, memory_id=memory_id, status="already_absent", message="目标记忆已不存在"
|
|
194
|
+
)
|
|
195
|
+
self._entry_ids.pop(memory_id, None)
|
|
196
|
+
memories = self._storage.get(user_id, [])
|
|
197
|
+
try:
|
|
198
|
+
memories.remove(entry)
|
|
199
|
+
except ValueError:
|
|
200
|
+
pass
|
|
201
|
+
return MemoryMutationResult(ok=True, memory_id=memory_id, status="deleted")
|
|
202
|
+
|
|
203
|
+
def _find_entry_id(self, user_id: str, entry: str) -> str | None:
|
|
204
|
+
"""根据原始条目定位 memory_id(反向查表)。"""
|
|
205
|
+
for memory_id, stored in self._user_entry_index.get(user_id, {}).items():
|
|
206
|
+
if stored is entry or stored == entry:
|
|
207
|
+
return memory_id
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
# ---- 内部工具 ----
|
|
211
|
+
|
|
212
|
+
@staticmethod
|
|
213
|
+
def _entry_text(entry: str) -> str:
|
|
214
|
+
"""提取事件字符串里的正文(兼容 JSON 事件与纯文本)。"""
|
|
215
|
+
try:
|
|
216
|
+
payload = json.loads(entry)
|
|
217
|
+
except (json.JSONDecodeError, TypeError):
|
|
218
|
+
return entry
|
|
219
|
+
if isinstance(payload, dict):
|
|
220
|
+
parts = payload.get("parts")
|
|
221
|
+
if isinstance(parts, list) and parts and isinstance(parts[0], dict):
|
|
222
|
+
return str(parts[0].get("text", entry))
|
|
223
|
+
return entry
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
环境变量:
|
|
10
10
|
KSADK_LTM_BACKEND: sdk
|
|
11
|
-
KSADK_LTM_ACCESS_KEY: AK (可选,默认取 KSYUN_ACCESS_KEY)
|
|
12
|
-
KSADK_LTM_SECRET_KEY: SK (可选,默认取 KSYUN_SECRET_KEY)
|
|
11
|
+
KSADK_LTM_ACCESS_KEY: AK (可选,默认取 KSYUN_ACCESS_KEY / KSYUN_ACCESS_KEY_ID)
|
|
12
|
+
KSADK_LTM_SECRET_KEY: SK (可选,默认取 KSYUN_SECRET_KEY / KSYUN_SECRET_ACCESS_KEY)
|
|
13
|
+
KSADK_LTM_SESSION_TOKEN: STS 临时会话 token (可选,默认取 KSYUN_SESSION_TOKEN)
|
|
13
14
|
KSADK_LTM_REGION: 区域 (默认 cn-beijing-6)
|
|
14
15
|
KSADK_LTM_ENDPOINT: API 端点 (默认 aicp.api.ksyun.com)
|
|
15
16
|
KSADK_LTM_SCHEME: http/https (默认 https)
|
|
@@ -20,18 +21,41 @@
|
|
|
20
21
|
|
|
21
22
|
import json
|
|
22
23
|
import logging
|
|
24
|
+
import re
|
|
23
25
|
import time
|
|
24
26
|
import uuid
|
|
25
|
-
from typing import Any
|
|
27
|
+
from typing import Any, List, Set
|
|
26
28
|
|
|
27
29
|
from pydantic import ConfigDict, Field
|
|
28
30
|
|
|
29
|
-
from ksadk.memory.adk.backends.base_ltm_backend import
|
|
31
|
+
from ksadk.memory.adk.backends.base_ltm_backend import (
|
|
32
|
+
CAP_ADD,
|
|
33
|
+
CAP_DELETE,
|
|
34
|
+
CAP_FLUSH,
|
|
35
|
+
CAP_SEARCH,
|
|
36
|
+
CAP_SESSION_STATUS,
|
|
37
|
+
CAP_STRUCTURED_SEARCH,
|
|
38
|
+
CAP_UPDATE,
|
|
39
|
+
BaseLongTermMemoryBackend,
|
|
40
|
+
)
|
|
41
|
+
from ksadk.memory.models import (
|
|
42
|
+
LongTermMemoryRecord,
|
|
43
|
+
MemoryExtractionStatus,
|
|
44
|
+
MemoryMutationResult,
|
|
45
|
+
map_session_state,
|
|
46
|
+
)
|
|
30
47
|
|
|
31
48
|
logger = logging.getLogger(__name__)
|
|
32
49
|
|
|
33
50
|
DEFAULT_SCENE_ID = "_sys_general"
|
|
34
51
|
|
|
52
|
+
# "记忆不存在"识别模式(方案 §17.4:准确错误码待真实 fixture 固化,
|
|
53
|
+
# 首版按保守中英文模式匹配,fixture 到位后收敛为精确匹配)。
|
|
54
|
+
_NOT_EXIST_RE = re.compile(
|
|
55
|
+
r"not[ _]?exist|does not exist|memory.*不存在|记忆不存在|记忆已被删除|resourcenotfound|notfound",
|
|
56
|
+
re.IGNORECASE,
|
|
57
|
+
)
|
|
58
|
+
|
|
35
59
|
|
|
36
60
|
class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
37
61
|
"""金山云 AICP 记忆库 SDK 后端
|
|
@@ -42,6 +66,7 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
42
66
|
Attributes:
|
|
43
67
|
access_key: 访问密钥 ID (AK)
|
|
44
68
|
secret_key: 访问密钥 (SK)
|
|
69
|
+
session_token: STS 临时会话 token
|
|
45
70
|
region: API 区域
|
|
46
71
|
endpoint: API 端点
|
|
47
72
|
scheme: http 或 https
|
|
@@ -64,6 +89,7 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
64
89
|
|
|
65
90
|
access_key: str = ""
|
|
66
91
|
secret_key: str = ""
|
|
92
|
+
session_token: str = ""
|
|
67
93
|
region: str = "cn-beijing-6"
|
|
68
94
|
endpoint: str = "aicp.api.ksyun.com"
|
|
69
95
|
scheme: str = "https"
|
|
@@ -137,7 +163,9 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
137
163
|
"Ensure kingsoftcloud-sdk-python>=1.5.8.94 is installed."
|
|
138
164
|
)
|
|
139
165
|
|
|
140
|
-
cred = credential.Credential(
|
|
166
|
+
cred = credential.Credential(
|
|
167
|
+
self.access_key, self.secret_key, self.session_token or None
|
|
168
|
+
)
|
|
141
169
|
|
|
142
170
|
http_profile = HttpProfile()
|
|
143
171
|
http_profile.endpoint = self.endpoint
|
|
@@ -240,6 +268,8 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
240
268
|
params["AgentId"] = agent_id
|
|
241
269
|
if session_id:
|
|
242
270
|
params["SessionId"] = session_id
|
|
271
|
+
if metadata.get("flush") is True or kwargs.get("flush") is True:
|
|
272
|
+
params["Flush"] = True
|
|
243
273
|
|
|
244
274
|
logger.info(
|
|
245
275
|
f"CreateMemorySdk: memory_collection_id={memory_collection_id}, "
|
|
@@ -322,6 +352,365 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
322
352
|
logger.error(f"QueryMemorySdk failed: {e}")
|
|
323
353
|
return []
|
|
324
354
|
|
|
355
|
+
# ------------------------------------------------------------------
|
|
356
|
+
# 结构化扩展协议(方案 §7.3/§7.4):走通用 client.call 通道。
|
|
357
|
+
# kingsoftcloud-sdk-python 1.5.8.101 的 AICP client 未提供
|
|
358
|
+
# ListMemories/UpdateMemory/DeleteMemory 类型化方法(§7.4.2)。
|
|
359
|
+
# 所有解析对已确认 schema 严格校验;未知结构 fail closed,不伪造结果。
|
|
360
|
+
# ------------------------------------------------------------------
|
|
361
|
+
|
|
362
|
+
def search_records(
|
|
363
|
+
self, user_id: str, query: str, top_k: int = 5, **kwargs
|
|
364
|
+
) -> List[LongTermMemoryRecord]:
|
|
365
|
+
"""QueryMemorySdk 结构化检索:返回带服务端 MemoryId 的记录。
|
|
366
|
+
|
|
367
|
+
按已确认 schema(§7.4.1)从 ``Data[].Memories[]`` 解析
|
|
368
|
+
MemoryId / Memory / Score / OccurredStart / OccurredEnd。
|
|
369
|
+
缺少 MemoryId 的条目跳过(无法支撑后续 mutation)。
|
|
370
|
+
未知响应结构返回空列表(fail closed)。
|
|
371
|
+
"""
|
|
372
|
+
client = self._get_client()
|
|
373
|
+
memory_collection_id = self._effective_memory_collection_id()
|
|
374
|
+
params = {
|
|
375
|
+
"MemoryCollectionId": memory_collection_id,
|
|
376
|
+
"AgentUserId": user_id,
|
|
377
|
+
"Query": query,
|
|
378
|
+
"Limit": top_k,
|
|
379
|
+
"SceneId": self._effective_scene_id(),
|
|
380
|
+
}
|
|
381
|
+
response = client.call("QueryMemorySdk", params, options={"IsPostJson": True})
|
|
382
|
+
records = self._parse_query_records_response(response, user_id=user_id)
|
|
383
|
+
logger.info(
|
|
384
|
+
f"QueryMemorySdk structured: user={user_id}, records={len(records)}"
|
|
385
|
+
)
|
|
386
|
+
return records
|
|
387
|
+
|
|
388
|
+
def list_memory_records(
|
|
389
|
+
self,
|
|
390
|
+
*,
|
|
391
|
+
user_id: str,
|
|
392
|
+
query: str = "",
|
|
393
|
+
page: int = 1,
|
|
394
|
+
page_size: int = 20,
|
|
395
|
+
) -> List[LongTermMemoryRecord]:
|
|
396
|
+
"""ListMemories:精确确认提取完成后的可见性 / 取得当前 MemoryId。
|
|
397
|
+
|
|
398
|
+
按已确认 schema(§7.4.1)从顶层 ``MemoryList[]`` 解析。
|
|
399
|
+
未知响应结构返回空列表(fail closed,不宣称可见)。
|
|
400
|
+
"""
|
|
401
|
+
client = self._get_client()
|
|
402
|
+
params: dict[str, Any] = {
|
|
403
|
+
"MemoryCollectionId": self._effective_memory_collection_id(),
|
|
404
|
+
"AgentUserId": user_id,
|
|
405
|
+
"Page": page,
|
|
406
|
+
"PageSize": page_size,
|
|
407
|
+
}
|
|
408
|
+
if query:
|
|
409
|
+
params["Query"] = query
|
|
410
|
+
response = client.call("ListMemories", params, options={"IsPostJson": True})
|
|
411
|
+
records = self._parse_list_memories_response(response, user_id=user_id)
|
|
412
|
+
logger.info(f"ListMemories: user={user_id}, records={len(records)}")
|
|
413
|
+
return records
|
|
414
|
+
|
|
415
|
+
def update_memory(
|
|
416
|
+
self,
|
|
417
|
+
*,
|
|
418
|
+
user_id: str,
|
|
419
|
+
memory_id: str,
|
|
420
|
+
content: str,
|
|
421
|
+
**kwargs,
|
|
422
|
+
) -> MemoryMutationResult:
|
|
423
|
+
"""UpdateMemory:按 ID 原地更新正文,解析 new_memory_id。
|
|
424
|
+
|
|
425
|
+
Update 不幂等:重复调用会重复触发(§17.7),由上层控制重试。
|
|
426
|
+
"记忆不存在"按 not_found 归一(§7.4.1,错误码待 fixture 收敛)。
|
|
427
|
+
"""
|
|
428
|
+
client = self._get_client()
|
|
429
|
+
params = {
|
|
430
|
+
"MemoryCollectionId": self._effective_memory_collection_id(),
|
|
431
|
+
"MemoryId": memory_id,
|
|
432
|
+
"Content": content,
|
|
433
|
+
"AgentUserId": user_id,
|
|
434
|
+
}
|
|
435
|
+
try:
|
|
436
|
+
response = client.call("UpdateMemory", params, options={"IsPostJson": True})
|
|
437
|
+
except Exception as exc:
|
|
438
|
+
if self._is_not_exist_error(exc):
|
|
439
|
+
return MemoryMutationResult(
|
|
440
|
+
ok=False,
|
|
441
|
+
memory_id=memory_id,
|
|
442
|
+
status="not_found",
|
|
443
|
+
message="目标记忆不存在",
|
|
444
|
+
)
|
|
445
|
+
self.last_error = str(exc)
|
|
446
|
+
logger.error("UpdateMemory failed: %s", type(exc).__name__)
|
|
447
|
+
return MemoryMutationResult(
|
|
448
|
+
ok=False,
|
|
449
|
+
memory_id=memory_id,
|
|
450
|
+
status="failed",
|
|
451
|
+
message="记忆更新失败",
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
data = self._parse_json_response(response)
|
|
455
|
+
response_memory_id = self._parse_new_memory_id(data)
|
|
456
|
+
new_memory_id = response_memory_id
|
|
457
|
+
if not response_memory_id or response_memory_id == memory_id:
|
|
458
|
+
# The service can merge an edited memory into another record while
|
|
459
|
+
# returning no new ID (or echoing the old one). Do not expose that
|
|
460
|
+
# stale handle to callers: confirm the current handle by listing
|
|
461
|
+
# records whose final content exactly matches the update.
|
|
462
|
+
try:
|
|
463
|
+
matches = [
|
|
464
|
+
record
|
|
465
|
+
for record in self.list_memory_records(
|
|
466
|
+
user_id=user_id,
|
|
467
|
+
query=content,
|
|
468
|
+
page=1,
|
|
469
|
+
page_size=100,
|
|
470
|
+
)
|
|
471
|
+
if record.content.strip() == content.strip()
|
|
472
|
+
]
|
|
473
|
+
except Exception as exc:
|
|
474
|
+
logger.warning(
|
|
475
|
+
"ListMemories failed while reconciling updated memory ID: %s",
|
|
476
|
+
type(exc).__name__,
|
|
477
|
+
)
|
|
478
|
+
matches = []
|
|
479
|
+
unique_ids = {record.memory_id for record in matches}
|
|
480
|
+
new_memory_id = unique_ids.pop() if len(unique_ids) == 1 else ""
|
|
481
|
+
|
|
482
|
+
if new_memory_id and new_memory_id != memory_id:
|
|
483
|
+
message = f"更新成功,新记忆 ID: {new_memory_id}"
|
|
484
|
+
elif new_memory_id == memory_id:
|
|
485
|
+
message = "更新成功,记忆 ID 未变化"
|
|
486
|
+
else:
|
|
487
|
+
message = "更新成功,但未能唯一确认更新后的记忆 ID,请重新搜索后再操作"
|
|
488
|
+
return MemoryMutationResult(
|
|
489
|
+
ok=True,
|
|
490
|
+
memory_id=memory_id,
|
|
491
|
+
new_memory_id=new_memory_id,
|
|
492
|
+
status="updated",
|
|
493
|
+
message=message,
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
def delete_memory(
|
|
497
|
+
self,
|
|
498
|
+
*,
|
|
499
|
+
user_id: str,
|
|
500
|
+
memory_id: str,
|
|
501
|
+
**kwargs,
|
|
502
|
+
) -> MemoryMutationResult:
|
|
503
|
+
"""DeleteMemory:按 ID 软删除。
|
|
504
|
+
|
|
505
|
+
重复删除返回"记忆不存在",归一为 already_absent,
|
|
506
|
+
与首次成功 deleted 分开审计(§7.4)。
|
|
507
|
+
"""
|
|
508
|
+
client = self._get_client()
|
|
509
|
+
params = {
|
|
510
|
+
"MemoryCollectionId": self._effective_memory_collection_id(),
|
|
511
|
+
"MemoryId": memory_id,
|
|
512
|
+
"AgentUserId": user_id,
|
|
513
|
+
}
|
|
514
|
+
try:
|
|
515
|
+
client.call("DeleteMemory", params, options={"IsPostJson": True})
|
|
516
|
+
except Exception as exc:
|
|
517
|
+
if self._is_not_exist_error(exc):
|
|
518
|
+
return MemoryMutationResult(
|
|
519
|
+
ok=True,
|
|
520
|
+
memory_id=memory_id,
|
|
521
|
+
status="already_absent",
|
|
522
|
+
message="目标记忆已不存在(可能已删除)",
|
|
523
|
+
)
|
|
524
|
+
self.last_error = str(exc)
|
|
525
|
+
logger.error("DeleteMemory failed: %s", type(exc).__name__)
|
|
526
|
+
return MemoryMutationResult(
|
|
527
|
+
ok=False,
|
|
528
|
+
memory_id=memory_id,
|
|
529
|
+
status="failed",
|
|
530
|
+
message="记忆删除失败",
|
|
531
|
+
)
|
|
532
|
+
return MemoryMutationResult(
|
|
533
|
+
ok=True,
|
|
534
|
+
memory_id=memory_id,
|
|
535
|
+
status="deleted",
|
|
536
|
+
message="已删除",
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
def get_extraction_status(
|
|
540
|
+
self,
|
|
541
|
+
*,
|
|
542
|
+
user_id: str,
|
|
543
|
+
session_id: str,
|
|
544
|
+
) -> MemoryExtractionStatus:
|
|
545
|
+
"""ListSessions 查询 Session 后台提取状态(§7.7)。
|
|
546
|
+
|
|
547
|
+
State 映射 0/50/100/-50/-100;未找到 Session 返回 unknown。
|
|
548
|
+
searchable 需 Service 层结合 ListMemories 确认后置位。
|
|
549
|
+
"""
|
|
550
|
+
item = self.get_session_status(user_id=user_id, session_id=session_id)
|
|
551
|
+
if not isinstance(item, dict):
|
|
552
|
+
return MemoryExtractionStatus(
|
|
553
|
+
session_id=session_id,
|
|
554
|
+
state=None,
|
|
555
|
+
status="unknown",
|
|
556
|
+
message="Session 状态未知",
|
|
557
|
+
)
|
|
558
|
+
state = item.get("State")
|
|
559
|
+
state_int = int(state) if isinstance(state, (int, float, str)) and str(state).lstrip("-").isdigit() else None
|
|
560
|
+
status = map_session_state(state_int)
|
|
561
|
+
message = {
|
|
562
|
+
"queued": "排队中",
|
|
563
|
+
"extracting": "提取中",
|
|
564
|
+
"extracted": "提取完成",
|
|
565
|
+
"duplicate_skipped": "内容重复,已跳过提取",
|
|
566
|
+
"failed": "提取失败,可稍后重新明确保存",
|
|
567
|
+
}.get(status, "状态未知")
|
|
568
|
+
return MemoryExtractionStatus(
|
|
569
|
+
session_id=session_id,
|
|
570
|
+
state=state_int,
|
|
571
|
+
status=status,
|
|
572
|
+
message=message,
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
def capabilities(self) -> Set[str]:
|
|
576
|
+
return {
|
|
577
|
+
CAP_SEARCH,
|
|
578
|
+
CAP_ADD,
|
|
579
|
+
CAP_FLUSH,
|
|
580
|
+
CAP_STRUCTURED_SEARCH,
|
|
581
|
+
CAP_UPDATE,
|
|
582
|
+
CAP_DELETE,
|
|
583
|
+
CAP_SESSION_STATUS,
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
@staticmethod
|
|
587
|
+
def _is_not_exist_error(exc: Exception) -> bool:
|
|
588
|
+
"""识别"记忆不存在"类错误。
|
|
589
|
+
|
|
590
|
+
§17.4:准确错误码/结构待真实 fixture 固化;首版按保守模式匹配
|
|
591
|
+
code/message,fixture 到位后收敛为精确匹配。
|
|
592
|
+
"""
|
|
593
|
+
text = " ".join(
|
|
594
|
+
str(part) for part in (getattr(exc, "code", ""), str(exc)) if part
|
|
595
|
+
)
|
|
596
|
+
return bool(_NOT_EXIST_RE.search(text))
|
|
597
|
+
|
|
598
|
+
@staticmethod
|
|
599
|
+
def _parse_new_memory_id(data: Any) -> str:
|
|
600
|
+
"""从 UpdateMemory 响应解析 new_memory_id(§7.4.1)。
|
|
601
|
+
|
|
602
|
+
兼容 snake/camel 两种命名;都不存在时返回空串,由调用方通过
|
|
603
|
+
ListMemories 核验当前句柄,不能据此推断 ID 未变化。
|
|
604
|
+
"""
|
|
605
|
+
if not isinstance(data, dict):
|
|
606
|
+
return ""
|
|
607
|
+
for key in ("new_memory_id", "NewMemoryId", "NewMemoryID"):
|
|
608
|
+
value = data.get(key)
|
|
609
|
+
if isinstance(value, str) and value.strip():
|
|
610
|
+
return value.strip()
|
|
611
|
+
nested = data.get("Data")
|
|
612
|
+
if isinstance(nested, dict):
|
|
613
|
+
for key in ("new_memory_id", "NewMemoryId", "NewMemoryID"):
|
|
614
|
+
value = nested.get(key)
|
|
615
|
+
if isinstance(value, str) and value.strip():
|
|
616
|
+
return value.strip()
|
|
617
|
+
return ""
|
|
618
|
+
|
|
619
|
+
def _parse_query_records_response(
|
|
620
|
+
self, response: Any, *, user_id: str
|
|
621
|
+
) -> List[LongTermMemoryRecord]:
|
|
622
|
+
"""严格解析 QueryMemorySdk 结构化响应:Data[].Memories[]。"""
|
|
623
|
+
try:
|
|
624
|
+
data = self._parse_json_response(response)
|
|
625
|
+
except (json.JSONDecodeError, TypeError):
|
|
626
|
+
logger.error("QueryMemorySdk records: invalid JSON response")
|
|
627
|
+
return []
|
|
628
|
+
if not isinstance(data, dict):
|
|
629
|
+
logger.error("QueryMemorySdk records: unexpected payload type")
|
|
630
|
+
return []
|
|
631
|
+
items = data.get("Data")
|
|
632
|
+
if not isinstance(items, list):
|
|
633
|
+
logger.warning(
|
|
634
|
+
"QueryMemorySdk records: unknown schema, keys=%s; fail closed",
|
|
635
|
+
list(data.keys()),
|
|
636
|
+
)
|
|
637
|
+
return []
|
|
638
|
+
records: List[LongTermMemoryRecord] = []
|
|
639
|
+
for item in items:
|
|
640
|
+
memories = item.get("Memories") if isinstance(item, dict) else None
|
|
641
|
+
if not isinstance(memories, list):
|
|
642
|
+
continue
|
|
643
|
+
for memory in memories:
|
|
644
|
+
record = self._record_from_item(memory, user_id=user_id)
|
|
645
|
+
if record is not None:
|
|
646
|
+
records.append(record)
|
|
647
|
+
return records
|
|
648
|
+
|
|
649
|
+
def _parse_list_memories_response(
|
|
650
|
+
self, response: Any, *, user_id: str
|
|
651
|
+
) -> List[LongTermMemoryRecord]:
|
|
652
|
+
"""严格解析 ListMemories 响应:顶层 MemoryList[](§7.4.1)。"""
|
|
653
|
+
try:
|
|
654
|
+
data = self._parse_json_response(response)
|
|
655
|
+
except (json.JSONDecodeError, TypeError):
|
|
656
|
+
logger.error("ListMemories: invalid JSON response")
|
|
657
|
+
return []
|
|
658
|
+
if not isinstance(data, dict):
|
|
659
|
+
logger.error("ListMemories: unexpected payload type")
|
|
660
|
+
return []
|
|
661
|
+
items = data.get("MemoryList")
|
|
662
|
+
if not isinstance(items, list):
|
|
663
|
+
logger.warning(
|
|
664
|
+
"ListMemories: unknown schema, keys=%s; fail closed",
|
|
665
|
+
list(data.keys()),
|
|
666
|
+
)
|
|
667
|
+
return []
|
|
668
|
+
records: List[LongTermMemoryRecord] = []
|
|
669
|
+
for item in items:
|
|
670
|
+
record = self._record_from_item(item, user_id=user_id)
|
|
671
|
+
if record is not None:
|
|
672
|
+
records.append(record)
|
|
673
|
+
return records
|
|
674
|
+
|
|
675
|
+
def _record_from_item(
|
|
676
|
+
self, item: Any, *, user_id: str
|
|
677
|
+
) -> LongTermMemoryRecord | None:
|
|
678
|
+
"""将单个记忆条目解析为 LongTermMemoryRecord。
|
|
679
|
+
|
|
680
|
+
缺少 MemoryId 或正文的条目返回 None(无法支撑 mutation,fail closed)。
|
|
681
|
+
"""
|
|
682
|
+
if not isinstance(item, dict):
|
|
683
|
+
return None
|
|
684
|
+
memory_id = item.get("MemoryId")
|
|
685
|
+
content = item.get("Memory")
|
|
686
|
+
if not isinstance(memory_id, str) or not memory_id.strip():
|
|
687
|
+
logger.warning("memory item without MemoryId skipped")
|
|
688
|
+
return None
|
|
689
|
+
if not isinstance(content, str) or not content.strip():
|
|
690
|
+
logger.warning("memory item without content skipped")
|
|
691
|
+
return None
|
|
692
|
+
score = item.get("Score")
|
|
693
|
+
parsed_score: float | None = None
|
|
694
|
+
if isinstance(score, (int, float)):
|
|
695
|
+
parsed_score = float(score)
|
|
696
|
+
metadata: dict[str, Any] = {}
|
|
697
|
+
for key in ("OccurredStart", "OccurredEnd"):
|
|
698
|
+
value = item.get(key)
|
|
699
|
+
if value is not None:
|
|
700
|
+
metadata[key] = value
|
|
701
|
+
agent_user_id = item.get("AgentUserId")
|
|
702
|
+
if isinstance(agent_user_id, str) and agent_user_id:
|
|
703
|
+
metadata["AgentUserId"] = agent_user_id
|
|
704
|
+
return LongTermMemoryRecord(
|
|
705
|
+
memory_id=memory_id.strip(),
|
|
706
|
+
content=content.strip(),
|
|
707
|
+
score=parsed_score,
|
|
708
|
+
user_id=user_id,
|
|
709
|
+
created_at=item.get("CreatedAt") if isinstance(item.get("CreatedAt"), str) else None,
|
|
710
|
+
updated_at=item.get("UpdatedAt") if isinstance(item.get("UpdatedAt"), str) else None,
|
|
711
|
+
metadata=metadata,
|
|
712
|
+
)
|
|
713
|
+
|
|
325
714
|
def get_session_status(
|
|
326
715
|
self,
|
|
327
716
|
*,
|