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.
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
- ksadk/a2a/_space_client_events.py +381 -0
- ksadk/a2a/event_adapter.py +156 -64
- ksadk/a2a/executor.py +179 -63
- ksadk/a2a/space_client.py +6 -333
- ksadk/a2ui/core.py +222 -53
- ksadk/agui/_agent_helpers.py +243 -0
- ksadk/agui/a2ui_projection.py +12 -5
- ksadk/agui/agent.py +443 -259
- ksadk/api/client.py +525 -27
- ksadk/builders/code_builder.py +284 -8
- ksadk/builders/container_builder.py +8 -1
- ksadk/builders/managed_runtime_builder.py +39 -35
- ksadk/cli/__init__.py +17 -0
- ksadk/cli/cmd_dashboard.py +15 -1
- ksadk/cli/cmd_deploy.py +10 -2
- ksadk/cli/cmd_eval.py +66 -9
- ksadk/cli/cmd_evalset.py +284 -0
- ksadk/cli/cmd_files.py +5 -1
- ksadk/cli/cmd_hermes.py +1 -126
- ksadk/cli/cmd_invoke.py +28 -38
- ksadk/cli/cmd_managed_runtime.py +95 -0
- ksadk/cli/cmd_observe.py +85 -0
- ksadk/cli/cmd_openclaw.py +1 -435
- ksadk/cli/cmd_replay.py +28 -4
- ksadk/cli/cmd_studio.py +99 -8
- ksadk/cli/cmd_web.py +10 -2
- ksadk/cli/hermes_env.py +151 -0
- ksadk/cli/invoke_payload.py +49 -0
- ksadk/cli/openclaw_env.py +458 -0
- ksadk/codex/client.py +180 -30
- ksadk/codex/runtime.py +428 -326
- ksadk/configs/env_registry.py +66 -12
- ksadk/configs/env_registry_pcm.py +181 -0
- ksadk/configs/env_var_spec.py +18 -0
- ksadk/configs/global_config.py +5 -0
- 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/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 +184 -2
- ksadk/conversations/runtime_invocation.py +81 -3
- ksadk/conversations/runtime_observability.py +141 -0
- ksadk/conversations/runtime_payloads.py +42 -0
- ksadk/conversations/runtime_preparation.py +272 -2
- ksadk/conversations/runtime_resume.py +20 -1
- ksadk/conversations/runtime_stream_events.py +94 -9
- 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 +5 -0
- ksadk/deployment/providers/serverless.py +143 -69
- ksadk/evaluation/__init__.py +32 -0
- ksadk/evaluation/a2a_adapter.py +9 -1
- ksadk/evaluation/adapters.py +18 -5
- 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 +73 -4
- ksadk/evaluation/evaluators.py +183 -17
- ksadk/evaluation/evidence.py +258 -0
- ksadk/evaluation/executor.py +31 -6
- ksadk/evaluation/local_adapter.py +550 -0
- ksadk/evaluation/service_env.py +27 -0
- ksadk/evaluation/studio_build_adapter.py +253 -0
- ksadk/evaluation/target.py +15 -6
- 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 -265
- ksadk/events/session_event.py +324 -0
- ksadk/events/store.py +3 -316
- ksadk/events/v1_compat.py +41 -0
- ksadk/harness/runtime.py +160 -57
- 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 +7 -0
- ksadk/knowledge_base/service.py +32 -5
- 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 +384 -2
- ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
- 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 +188 -6
- ksadk/model_proxy/bootstrap.py +16 -9
- ksadk/model_proxy/detect.py +202 -9
- ksadk/model_proxy/namespace.py +39 -15
- ksadk/model_proxy/server.py +24 -5
- ksadk/model_proxy/transform.py +60 -2
- 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 +5 -5
- ksadk/runners/base_runner.py +16 -0
- ksadk/runners/factory.py +1 -2
- ksadk/runners/langgraph_runner.py +198 -437
- ksadk/runtime/_runner_adapter/__init__.py +1 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
- ksadk/runtime/adapter.py +118 -2
- ksadk/runtime/conversation_execution.py +316 -182
- ksadk/runtime/executor.py +144 -3
- ksadk/runtime/factory.py +193 -7
- ksadk/runtime/hosted_finalizer.py +268 -0
- ksadk/runtime/launch.py +14 -1
- ksadk/runtime/preprocessing.py +25 -3
- ksadk/runtime/runner_adapter.py +288 -508
- ksadk/runtime/usage.py +33 -0
- ksadk/sandbox/backends/e2b.py +35 -2
- ksadk/server/composition.py +8 -0
- ksadk/server/factory.py +69 -6
- ksadk/server/routes/kernel_ingress.py +258 -0
- ksadk/server/routes/openai_compat.py +88 -8
- ksadk/server/routes/projection.py +35 -20
- ksadk/server/routes/run.py +94 -0
- ksadk/server/routes/sessions.py +2 -0
- ksadk/server/routes/streaming.py +5 -2
- ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
- ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.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-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
- ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
- ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.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-ChNs_Mdk.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-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
- ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
- ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
- ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
- ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
- ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
- ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
- ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
- ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
- ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
- ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
- ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
- ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
- ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
- ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
- ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
- ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
- ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
- ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
- ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
- ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
- ksadk/server/static/assets/{dist-CmZHzlwZ.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-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
- ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
- ksadk/server/static/assets/{linear-hdBcYzM8.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-Bjy_2v4_.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-BmkRbwCg.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-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.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-DEz24vV0.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/studio/api.py +577 -25
- ksadk/studio/api_contracts.py +114 -5
- ksadk/studio/api_memory_routes.py +82 -0
- ksadk/studio/authoring.py +252 -27
- ksadk/studio/authoring_coordinator.py +799 -67
- ksadk/studio/builder.py +88 -11
- ksadk/studio/capabilities.py +17 -0
- ksadk/studio/cloud.py +1916 -95
- ksadk/studio/codex_agent_service.py +125 -14
- ksadk/studio/codex_authoring.py +469 -0
- ksadk/studio/codex_builder.py +138 -25
- ksadk/studio/codex_manifest.py +51 -22
- ksadk/studio/codex_run.py +46 -3
- ksadk/studio/compiler.py +1 -0
- ksadk/studio/contracts.py +114 -3
- ksadk/studio/event_store.py +25 -95
- ksadk/studio/framework_run.py +231 -3
- ksadk/studio/hosted_kernel.py +317 -0
- ksadk/studio/manifest_resolver.py +131 -0
- ksadk/studio/model_client.py +95 -9
- ksadk/studio/model_profile_service.py +1 -1
- ksadk/studio/operations.py +37 -5
- ksadk/studio/otel_trace.py +348 -42
- ksadk/studio/pcm_memory.py +85 -0
- ksadk/studio/repository.py +23 -2
- ksadk/studio/resource_catalog.py +43 -0
- ksadk/studio/run_service.py +563 -137
- ksadk/studio/runtime_source.py +42 -16
- ksadk/studio/service.py +1180 -72
- ksadk/studio/shared_web.py +32 -22
- ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
- ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/studio/templates.py +100 -8
- ksadk/studio/validator.py +19 -0
- ksadk/studio/workspace.py +30 -32
- ksadk/tracing/setup.py +304 -3
- ksadk/version.py +1 -1
- ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
- ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
- ksadk/events/parser.py +0 -191
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
- ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
- ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
- ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
- ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
- ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
- ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
- ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
- ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
- ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
- ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
- ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
- ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
- ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
- ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
- ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
- ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
- ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
- ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
- ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
- ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
- ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
- ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
- ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
- ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
- ksadk/server/static/assets/index-R52pJJvg.js +0 -177
- ksadk/server/static/assets/index-jJr3_955.css +0 -2
- ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
- ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
- ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
- ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
- ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
- ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
- ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
- ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
- ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
- ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
- ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
- ksadk/studio/evaluation.py +0 -192
- ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
- ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""TokenCounter 协议与启发式实现。
|
|
2
|
+
|
|
3
|
+
对齐方案 8.9。实现顺序应是 provider 官方 tokenizer → 兼容 tokenizer → CJK+ASCII
|
|
4
|
+
启发式。第一个 PR 只落地启发式实现(复用现有 ``estimate_text_tokens``),并记录所用
|
|
5
|
+
tokenizer 名称;只有 heuristic 可用时由调用方自行加安全系数。tiktoken/provider
|
|
6
|
+
tokenizer 接入留后续 PR。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
from typing import Any, Protocol, Sequence
|
|
13
|
+
|
|
14
|
+
HEURISTIC_TOKENIZER_NAME = "heuristic_cjk_ascii"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TokenCounter(Protocol):
|
|
18
|
+
"""token 计数协议。"""
|
|
19
|
+
|
|
20
|
+
name: str
|
|
21
|
+
|
|
22
|
+
def count_text(self, text: str, *, model: str | None = None) -> int: ...
|
|
23
|
+
|
|
24
|
+
def count_messages(self, messages: Sequence[Any], *, model: str | None = None) -> int: ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class HeuristicTokenCounter:
|
|
28
|
+
"""复用 ``ksadk.conversations.model_context.estimate_text_tokens`` 的启发式计数器。
|
|
29
|
+
|
|
30
|
+
CJK 字符按约 1.5 token,其他按 4 chars ~= 1 token。不是真实 tokenizer,但比纯英文
|
|
31
|
+
口径更接近本地中文使用体验。第一个 PR 的 shadow ContextPlan 只用它做可观测估算,
|
|
32
|
+
不进任何决策路径。
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
name = HEURISTIC_TOKENIZER_NAME
|
|
36
|
+
|
|
37
|
+
def count_text(self, text: str, *, model: str | None = None) -> int:
|
|
38
|
+
from ksadk.conversations.model_context import estimate_text_tokens
|
|
39
|
+
|
|
40
|
+
return estimate_text_tokens(text)
|
|
41
|
+
|
|
42
|
+
def count_messages(self, messages: Sequence[Any], *, model: str | None = None) -> int:
|
|
43
|
+
from ksadk.conversations.model_context import estimate_text_tokens
|
|
44
|
+
|
|
45
|
+
total = 0
|
|
46
|
+
for message in messages:
|
|
47
|
+
total += self._count_message(message, estimate_text_tokens)
|
|
48
|
+
return total
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def _count_message(message: Any, estimator: Any) -> int:
|
|
52
|
+
if isinstance(message, str):
|
|
53
|
+
return estimator(message)
|
|
54
|
+
if isinstance(message, dict):
|
|
55
|
+
total = 0
|
|
56
|
+
for key in ("content", "text", "output"):
|
|
57
|
+
value = message.get(key)
|
|
58
|
+
if isinstance(value, str):
|
|
59
|
+
total += estimator(value)
|
|
60
|
+
elif isinstance(value, list):
|
|
61
|
+
for part in value:
|
|
62
|
+
if isinstance(part, dict):
|
|
63
|
+
text = part.get("text") or part.get("content")
|
|
64
|
+
if isinstance(text, str):
|
|
65
|
+
total += estimator(text)
|
|
66
|
+
elif isinstance(part, str):
|
|
67
|
+
total += estimator(part)
|
|
68
|
+
role = message.get("role")
|
|
69
|
+
if isinstance(role, str):
|
|
70
|
+
total += estimator(role)
|
|
71
|
+
return total
|
|
72
|
+
# LangChain/BaseMessage 风格对象:尽量取 content。
|
|
73
|
+
content = getattr(message, "content", None)
|
|
74
|
+
if isinstance(content, str):
|
|
75
|
+
return estimator(content)
|
|
76
|
+
if isinstance(content, list):
|
|
77
|
+
total = 0
|
|
78
|
+
for part in content:
|
|
79
|
+
if isinstance(part, dict):
|
|
80
|
+
text = part.get("text") or part.get("content")
|
|
81
|
+
if isinstance(text, str):
|
|
82
|
+
total += estimator(text)
|
|
83
|
+
elif isinstance(part, str):
|
|
84
|
+
total += estimator(part)
|
|
85
|
+
return total
|
|
86
|
+
return estimator(str(message))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
_DEFAULT_COUNTER: HeuristicTokenCounter | None = None
|
|
90
|
+
_PROVIDER_COUNTER: "TokenCounter | None" = None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class _TiktokenTokenCounter:
|
|
94
|
+
"""tiktoken 兼容 tokenizer(方案 §8.9 实现顺序 2)。
|
|
95
|
+
|
|
96
|
+
用于 OpenAI cl100k_base/o200k 系模型;非该系模型回退到 heuristic。``name`` 记录实际
|
|
97
|
+
tokenizer,供 ContextPlan ``tokenizer`` 字段如实标注。
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
def __init__(self, encoding_name: str = "cl100k_base") -> None:
|
|
101
|
+
try:
|
|
102
|
+
import tiktoken # type: ignore
|
|
103
|
+
|
|
104
|
+
self._enc = tiktoken.get_encoding(encoding_name)
|
|
105
|
+
self._encoding_name = encoding_name
|
|
106
|
+
except Exception: # noqa: BLE001
|
|
107
|
+
self._enc = None
|
|
108
|
+
self._encoding_name = encoding_name
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def name(self) -> str:
|
|
112
|
+
if self._enc is None:
|
|
113
|
+
return HEURISTIC_TOKENIZER_NAME
|
|
114
|
+
return f"tiktoken:{self._encoding_name}"
|
|
115
|
+
|
|
116
|
+
def count_text(self, text: str, *, model: str | None = None) -> int:
|
|
117
|
+
if self._enc is None:
|
|
118
|
+
return HeuristicTokenCounter().count_text(text)
|
|
119
|
+
try:
|
|
120
|
+
return len(self._enc.encode(str(text or "")))
|
|
121
|
+
except Exception: # noqa: BLE001
|
|
122
|
+
return HeuristicTokenCounter().count_text(text)
|
|
123
|
+
|
|
124
|
+
def count_messages(self, messages: Sequence[Any], *, model: str | None = None) -> int:
|
|
125
|
+
total = 0
|
|
126
|
+
for message in messages:
|
|
127
|
+
total += HeuristicTokenCounter._count_message(message, self.count_text)
|
|
128
|
+
return total
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _provider_counter_enabled() -> bool:
|
|
132
|
+
"""是否启用 provider/兼容 tokenizer(方案 §8.9)。
|
|
133
|
+
|
|
134
|
+
默认 **关闭**(保持 heuristic baseline,不静默改变既有计数口径——方案 §8.9 "先观测后接管");
|
|
135
|
+
显式 ``KSADK_TOKENIZER_PROVIDER=auto|tiktoken`` 才尝试 tiktoken,不可用时回退 heuristic。
|
|
136
|
+
"""
|
|
137
|
+
raw = str(os.environ.get("KSADK_TOKENIZER_PROVIDER", "") or "").strip().lower()
|
|
138
|
+
return raw in ("auto", "tiktoken")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def get_default_token_counter() -> TokenCounter:
|
|
142
|
+
"""返回进程级默认 TokenCounter(方案 §8.9)。
|
|
143
|
+
|
|
144
|
+
优先 provider/兼容 tokenizer(``KSADK_TOKENIZER_PROVIDER=auto`` 时尝试 tiktoken,不可用
|
|
145
|
+
回退 heuristic);``auto`` 之外显式 ``heuristic`` 则只用启发式。名称如实记录,偏差监控由
|
|
146
|
+
调用方按 model 维度做(方案 §8.9 末)。
|
|
147
|
+
"""
|
|
148
|
+
global _PROVIDER_COUNTER
|
|
149
|
+
if _provider_counter_enabled() and _PROVIDER_COUNTER is None:
|
|
150
|
+
_PROVIDER_COUNTER = _TiktokenTokenCounter()
|
|
151
|
+
if _PROVIDER_COUNTER is not None and _provider_counter_enabled():
|
|
152
|
+
return _PROVIDER_COUNTER
|
|
153
|
+
global _DEFAULT_COUNTER
|
|
154
|
+
if _DEFAULT_COUNTER is None:
|
|
155
|
+
_DEFAULT_COUNTER = HeuristicTokenCounter()
|
|
156
|
+
return _DEFAULT_COUNTER
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def set_default_token_counter(counter: TokenCounter | None) -> None:
|
|
160
|
+
"""测试/注入用:覆盖默认 counter。``None`` 恢复自动解析。"""
|
|
161
|
+
global _PROVIDER_COUNTER, _DEFAULT_COUNTER
|
|
162
|
+
_PROVIDER_COUNTER = counter
|
|
163
|
+
if counter is None:
|
|
164
|
+
_DEFAULT_COUNTER = None
|
ksadk/conversations/context.py
CHANGED
|
@@ -6,6 +6,11 @@ from collections.abc import Mapping, Sequence
|
|
|
6
6
|
from typing import Any, Dict, Iterable, List
|
|
7
7
|
|
|
8
8
|
from ksadk.sessions.base import SessionEvent
|
|
9
|
+
from ksadk.tools.result_budget import (
|
|
10
|
+
ToolResultBudget,
|
|
11
|
+
budget_tool_output,
|
|
12
|
+
default_tool_result_budget,
|
|
13
|
+
)
|
|
9
14
|
|
|
10
15
|
CANONICAL_EVENT_TYPES = {
|
|
11
16
|
"user_message",
|
|
@@ -34,11 +39,23 @@ TRANSCRIPT_EVENT_TYPES = {
|
|
|
34
39
|
"context_checkpoint",
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
_RUNTIME_PLACEHOLDER_EVENT_TYPES = {
|
|
43
|
+
"tool_call",
|
|
44
|
+
"tool_result",
|
|
45
|
+
"approval_request",
|
|
46
|
+
"approval_response",
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
DATA_URL_RE = re.compile(r"data:(?P<mime>[A-Za-z0-9.+-]+/[A-Za-z0-9.+-]+);base64,[A-Za-z0-9+/=_-]+")
|
|
38
50
|
BASE64_FIELD_RE = re.compile(
|
|
39
51
|
r"(?P<prefix>['\"](?P<field>file_data|data|bytes|base64)['\"]\s*:\s*['\"])(?P<value>[A-Za-z0-9+/=_-]{512,})(?P<suffix>['\"])",
|
|
40
52
|
re.IGNORECASE,
|
|
41
53
|
)
|
|
54
|
+
_CORRECTION_MARKER_RE = re.compile(
|
|
55
|
+
r"(?:修正|更正|改为|更新为|最新(?:的)?|废弃|作废|不再使用|不是.+而是|不要|不得|禁止)"
|
|
56
|
+
)
|
|
57
|
+
_LATEST_USER_INSTRUCTION_MAX_CHARS = 8192
|
|
58
|
+
_CORRECTION_SUMMARY_MAX_CHARS = 2048
|
|
42
59
|
|
|
43
60
|
|
|
44
61
|
def sanitize_event_text_for_context(text: Any) -> str:
|
|
@@ -55,8 +72,7 @@ def sanitize_event_text_for_context(text: Any) -> str:
|
|
|
55
72
|
value = DATA_URL_RE.sub(_replace_data_url, value)
|
|
56
73
|
value = BASE64_FIELD_RE.sub(
|
|
57
74
|
lambda match: (
|
|
58
|
-
f"{match.group('prefix')}[base64 {match.group('field')} omitted]"
|
|
59
|
-
f"{match.group('suffix')}"
|
|
75
|
+
f"{match.group('prefix')}[base64 {match.group('field')} omitted]{match.group('suffix')}"
|
|
60
76
|
),
|
|
61
77
|
value,
|
|
62
78
|
)
|
|
@@ -146,6 +162,70 @@ def _stringify_part_text(value: Any) -> str:
|
|
|
146
162
|
return str(value)
|
|
147
163
|
|
|
148
164
|
|
|
165
|
+
def budget_tool_result_for_event(
|
|
166
|
+
*,
|
|
167
|
+
tool_name: str,
|
|
168
|
+
tool_output: Any,
|
|
169
|
+
tool_call_id: str | None,
|
|
170
|
+
enabled: bool,
|
|
171
|
+
budget: ToolResultBudget | None = None,
|
|
172
|
+
) -> tuple[str, dict[str, Any]]:
|
|
173
|
+
"""PR C:tool_result 落 SessionEvent 前的单项预算(ksadk_hosted 门控)。
|
|
174
|
+
|
|
175
|
+
返回 ``(session_event_text, metadata_extras)``:
|
|
176
|
+
|
|
177
|
+
- ``enabled=False`` → ``(str(tool_output), {})``:与旧
|
|
178
|
+
``text=str(tool_output)`` **字节级一致**,非ksadk_hosted / framework / native
|
|
179
|
+
路径零行为变更。
|
|
180
|
+
- ``enabled=True``:先 ``_stringify_part_text`` 干净渲染(已预算的 toolset dict →
|
|
181
|
+
``"preview\\n[persisted-output] path (mime)"``;裸串 → 原串),再若仍超 ``max_chars`` 则
|
|
182
|
+
``budget_tool_output`` 落盘+截断,``text = "preview\\n[persisted-output] path (mime)"``,
|
|
183
|
+
``extras = {"tool_result_budget": {truncated, original_chars, preview_chars, persisted}}``。
|
|
184
|
+
未超阈值 → ``(rendered, {})``。
|
|
185
|
+
|
|
186
|
+
**不碰 ``metadata.tool_output``**:调用方保留原值(UI/Responses 读取方不受影响,
|
|
187
|
+
会话存储节省留后续)。
|
|
188
|
+
只 bound 进 ``content.parts[0].text``——即下一轮 ``extract_event_text`` → ``payload["history"]``
|
|
189
|
+
→ 模型输入的那条 text。已预算 dict 经 ``_stringify_part_text`` 渲染后必小于阈值,不重复落盘。
|
|
190
|
+
"""
|
|
191
|
+
if not enabled:
|
|
192
|
+
return str(tool_output), {}
|
|
193
|
+
active = budget or default_tool_result_budget()
|
|
194
|
+
rendered = _stringify_part_text(tool_output)
|
|
195
|
+
if len(rendered) <= active.max_chars:
|
|
196
|
+
return rendered, {}
|
|
197
|
+
budgeted = budget_tool_output(
|
|
198
|
+
tool_name=tool_name,
|
|
199
|
+
field_name="output",
|
|
200
|
+
value=tool_output,
|
|
201
|
+
metadata={"tool_call_id": tool_call_id or ""},
|
|
202
|
+
budget=active,
|
|
203
|
+
)
|
|
204
|
+
preview = str(budgeted.get("output") or "")
|
|
205
|
+
persisted = budgeted.get("persisted")
|
|
206
|
+
if not isinstance(persisted, Mapping) or not persisted.get("path"):
|
|
207
|
+
# 无落盘(不应发生,但兜底)→ 退回 rendered 截断标记,不谎报 persisted。
|
|
208
|
+
marker = f"\n[truncated {len(rendered) - active.max_chars} chars]"
|
|
209
|
+
return (rendered[: active.max_chars] + marker), {
|
|
210
|
+
"tool_result_budget": {
|
|
211
|
+
"truncated": True,
|
|
212
|
+
"original_chars": int(budgeted.get("original_chars") or len(rendered)),
|
|
213
|
+
"preview_chars": active.max_chars,
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
mime_type = persisted.get("mime_type") or "text/plain"
|
|
217
|
+
text = f"{preview}\n[persisted-output] {persisted['path']} ({mime_type})"
|
|
218
|
+
extras = {
|
|
219
|
+
"tool_result_budget": {
|
|
220
|
+
"truncated": bool(budgeted.get("truncated")),
|
|
221
|
+
"original_chars": int(budgeted.get("original_chars") or 0),
|
|
222
|
+
"preview_chars": int(budgeted.get("preview_chars") or len(preview)),
|
|
223
|
+
"persisted": dict(persisted),
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return text, extras
|
|
227
|
+
|
|
228
|
+
|
|
149
229
|
def build_request_history(messages: Iterable[Dict[str, Any]]) -> List[Dict[str, str]]:
|
|
150
230
|
history: List[Dict[str, str]] = []
|
|
151
231
|
for message in messages or []:
|
|
@@ -191,14 +271,16 @@ def summarize_event_groups(
|
|
|
191
271
|
) -> str:
|
|
192
272
|
"""把要折叠的旧轮次压成一段 checkpoint 文本。
|
|
193
273
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
274
|
+
extractive fallback:结构化骨架 + 有界保留错误修正和最新长 user 指令。
|
|
275
|
+
无摘要模型时,关键修正可能位于长消息尾部,也可能不是最后一条 user 消息;
|
|
276
|
+
因此跨消息提取修正,并在预算上限内保留最新长指令首尾(方案 §9.4)。
|
|
197
277
|
"""
|
|
198
278
|
lines: List[str] = []
|
|
199
279
|
if previous_summary:
|
|
200
280
|
lines.append(previous_summary)
|
|
201
281
|
lines.append("Earlier conversation summary:")
|
|
282
|
+
last_user_text = ""
|
|
283
|
+
correction_snippets: list[str] = []
|
|
202
284
|
for group in groups:
|
|
203
285
|
snippets: List[str] = []
|
|
204
286
|
for event in group:
|
|
@@ -216,9 +298,34 @@ def summarize_event_groups(
|
|
|
216
298
|
role = "assistant"
|
|
217
299
|
else:
|
|
218
300
|
role = "user"
|
|
301
|
+
last_user_text = text
|
|
302
|
+
for sentence in re.split(r"[\n。;;]+", text):
|
|
303
|
+
normalized = sentence.strip()
|
|
304
|
+
if normalized and _CORRECTION_MARKER_RE.search(normalized):
|
|
305
|
+
correction_snippets.append(normalized[:512])
|
|
219
306
|
snippets.append(f"{role}: {text[:180]}")
|
|
220
307
|
if snippets:
|
|
221
308
|
lines.append(" | ".join(snippets))
|
|
309
|
+
# 修正不一定是 compact 范围内最后一条 user 消息;单独形成结构化段,供
|
|
310
|
+
# Working State 确定性解析。总量有界,避免用“保留完整”重新撑爆上下文。
|
|
311
|
+
if correction_snippets:
|
|
312
|
+
unique: list[str] = []
|
|
313
|
+
for snippet in correction_snippets:
|
|
314
|
+
if snippet not in unique:
|
|
315
|
+
unique.append(snippet)
|
|
316
|
+
correction_text = ";".join(unique[-8:])[-_CORRECTION_SUMMARY_MAX_CHARS:]
|
|
317
|
+
lines.append(f"错误修正:{correction_text}")
|
|
318
|
+
# 末尾追加最新 user 指令的有界首尾内容。短消息已在摘要骨架里,不重复。
|
|
319
|
+
if last_user_text and len(last_user_text) > 180:
|
|
320
|
+
preserved = last_user_text
|
|
321
|
+
if len(preserved) > _LATEST_USER_INSTRUCTION_MAX_CHARS:
|
|
322
|
+
half = _LATEST_USER_INSTRUCTION_MAX_CHARS // 2
|
|
323
|
+
preserved = (
|
|
324
|
+
preserved[:half]
|
|
325
|
+
+ "\n...[中间内容因上下文预算省略]...\n"
|
|
326
|
+
+ preserved[-half:]
|
|
327
|
+
)
|
|
328
|
+
lines.append(f"最新用户指令(有界保留): {preserved}")
|
|
222
329
|
return "\n".join(line for line in lines if line).strip()
|
|
223
330
|
|
|
224
331
|
|
|
@@ -235,6 +342,7 @@ def project_model_messages(
|
|
|
235
342
|
3. tool/approval/attachment 仍保留成可解释的文本占位,避免状态丢失。
|
|
236
343
|
"""
|
|
237
344
|
projected: List[Dict[str, str]] = []
|
|
345
|
+
placeholder_flags: list[bool] = []
|
|
238
346
|
compacted_until = compacted_until_seq_id(events)
|
|
239
347
|
checkpoint = next(
|
|
240
348
|
(
|
|
@@ -253,6 +361,7 @@ def project_model_messages(
|
|
|
253
361
|
"content": summary_text,
|
|
254
362
|
}
|
|
255
363
|
)
|
|
364
|
+
placeholder_flags.append(False)
|
|
256
365
|
|
|
257
366
|
for event in events:
|
|
258
367
|
event_type = canonical_event_type(
|
|
@@ -291,10 +400,17 @@ def project_model_messages(
|
|
|
291
400
|
else:
|
|
292
401
|
role = "user"
|
|
293
402
|
|
|
294
|
-
|
|
403
|
+
is_placeholder = event_type in _RUNTIME_PLACEHOLDER_EVENT_TYPES
|
|
404
|
+
if (
|
|
405
|
+
projected
|
|
406
|
+
and projected[-1]["role"] == role
|
|
407
|
+
and not placeholder_flags[-1]
|
|
408
|
+
and not is_placeholder
|
|
409
|
+
):
|
|
295
410
|
projected[-1]["content"] = f"{projected[-1]['content']}\n{text}".strip()
|
|
296
411
|
else:
|
|
297
412
|
projected.append({"role": role, "content": text})
|
|
413
|
+
placeholder_flags.append(is_placeholder)
|
|
298
414
|
|
|
299
415
|
return projected
|
|
300
416
|
|
|
@@ -430,6 +546,10 @@ def project_responses_history(events: List[SessionEvent]) -> List[dict[str, Any]
|
|
|
430
546
|
from a text summary. Events without a reliable call id fall back to the
|
|
431
547
|
existing explanatory message representation instead of emitting an invalid
|
|
432
548
|
``function_call_output`` item.
|
|
549
|
+
|
|
550
|
+
公开承诺(契约声明见 ``ksadk/events/projections.py``):仅 OpenAI Responses
|
|
551
|
+
input item 形态(``type``/``call_id``/``output``/role 消息);内部不保证
|
|
552
|
+
compacted 前缀的重放方式与占位消息的具体措辞。
|
|
433
553
|
"""
|
|
434
554
|
projected: List[dict[str, Any]] = []
|
|
435
555
|
projected_call_ids: set[str] = set()
|