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
ksadk/studio/event_store.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Persistent local Run and
|
|
1
|
+
"""Persistent local Run record store and derived trace access."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -6,11 +6,11 @@ import json
|
|
|
6
6
|
import shutil
|
|
7
7
|
from datetime import datetime, timezone
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Any
|
|
10
10
|
|
|
11
11
|
from pydantic import ValidationError
|
|
12
12
|
|
|
13
|
-
from ksadk.studio.contracts import RunEvent, RunRecord
|
|
13
|
+
from ksadk.studio.contracts import RunEvent, RunRecord
|
|
14
14
|
from ksadk.studio.errors import StudioError, not_found
|
|
15
15
|
from ksadk.studio.otel_trace import OtlpTraceStore
|
|
16
16
|
from ksadk.studio.workspace import Workspace
|
|
@@ -28,15 +28,21 @@ class RunEventStore:
|
|
|
28
28
|
path = self._path(record.id)
|
|
29
29
|
if path.exists():
|
|
30
30
|
raise StudioError("RUN_ALREADY_EXISTS", "Run 已存在", status_code=409)
|
|
31
|
-
self._write(record
|
|
31
|
+
self._write(record)
|
|
32
32
|
return record
|
|
33
33
|
|
|
34
34
|
def save(self, record: RunRecord) -> RunRecord:
|
|
35
35
|
_, events = self._read(record.id)
|
|
36
|
-
self._write(record, events)
|
|
36
|
+
self._write(record, events or None)
|
|
37
37
|
return record
|
|
38
38
|
|
|
39
39
|
def append(self, run_id: str, event_type: str, data: dict) -> RunEvent:
|
|
40
|
+
"""Persist a Studio lifecycle RunEvent (run.created, memory.recall.projected, …).
|
|
41
|
+
|
|
42
|
+
These Studio-level events (as opposed to RuntimeEvents) are durably
|
|
43
|
+
stored in the run JSON so the Studio events timeline survives restarts.
|
|
44
|
+
Runs that never call ``append`` keep ``set(run_payload) == {"record"}``.
|
|
45
|
+
"""
|
|
40
46
|
record, events = self._read(run_id)
|
|
41
47
|
event = RunEvent(
|
|
42
48
|
id=len(events) + 1,
|
|
@@ -48,20 +54,20 @@ class RunEventStore:
|
|
|
48
54
|
self._write(record, events)
|
|
49
55
|
return event
|
|
50
56
|
|
|
51
|
-
def get(self, run_id: str) -> RunRecord:
|
|
52
|
-
record, _ = self._read(run_id)
|
|
53
|
-
return record
|
|
54
|
-
|
|
55
57
|
def events(self, run_id: str, *, after: int = 0) -> list[RunEvent]:
|
|
56
58
|
_, events = self._read(run_id)
|
|
57
59
|
return [event for event in events if event.id > after]
|
|
58
60
|
|
|
61
|
+
def get(self, run_id: str) -> RunRecord:
|
|
62
|
+
record, _ = self._read(run_id)
|
|
63
|
+
return record
|
|
64
|
+
|
|
59
65
|
def list_runs(
|
|
60
66
|
self,
|
|
61
67
|
*,
|
|
62
68
|
session_id: str | None = None,
|
|
63
69
|
agent_id: str | None = None,
|
|
64
|
-
) ->
|
|
70
|
+
) -> list[RunRecord]:
|
|
65
71
|
records: list[RunRecord] = []
|
|
66
72
|
directory = self.workspace.resolve(".agentkit/runs")
|
|
67
73
|
for path in sorted(directory.glob("run_*.json")):
|
|
@@ -126,82 +132,6 @@ class RunEventStore:
|
|
|
126
132
|
deleted += 1
|
|
127
133
|
return deleted
|
|
128
134
|
|
|
129
|
-
def recover_interrupted(self) -> int:
|
|
130
|
-
"""Reconcile non-terminal records left behind by a stopped Studio.
|
|
131
|
-
|
|
132
|
-
Events are persisted before the final RunRecord update. A browser
|
|
133
|
-
disconnect or process stop can therefore leave a terminal event next
|
|
134
|
-
to a stale ``RUNNING`` record. On startup the event log wins; a run
|
|
135
|
-
without any terminal event is explicitly marked interrupted because
|
|
136
|
-
its in-memory runtime task cannot survive a Studio restart.
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
recovered = 0
|
|
140
|
-
for record in self.list_runs():
|
|
141
|
-
if record.status not in {
|
|
142
|
-
RunStatus.CREATED,
|
|
143
|
-
RunStatus.RUNNING,
|
|
144
|
-
RunStatus.PAUSED,
|
|
145
|
-
RunStatus.WAITING_INPUT,
|
|
146
|
-
}:
|
|
147
|
-
continue
|
|
148
|
-
events = self.events(record.id)
|
|
149
|
-
terminal = next(
|
|
150
|
-
(
|
|
151
|
-
event
|
|
152
|
-
for event in reversed(events)
|
|
153
|
-
if event.type
|
|
154
|
-
in {
|
|
155
|
-
"run.completed",
|
|
156
|
-
"run.failed",
|
|
157
|
-
"run.cancelled",
|
|
158
|
-
"run.interrupted",
|
|
159
|
-
}
|
|
160
|
-
),
|
|
161
|
-
None,
|
|
162
|
-
)
|
|
163
|
-
if terminal is None:
|
|
164
|
-
terminal = self.append(
|
|
165
|
-
record.id,
|
|
166
|
-
"run.interrupted",
|
|
167
|
-
{
|
|
168
|
-
"status": "interrupted",
|
|
169
|
-
"reason": "studio_restarted",
|
|
170
|
-
},
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
if terminal.type == "run.completed":
|
|
174
|
-
record.status = RunStatus.COMPLETED
|
|
175
|
-
record.error = None
|
|
176
|
-
elif terminal.type == "run.failed":
|
|
177
|
-
record.status = RunStatus.FAILED
|
|
178
|
-
record.error = {
|
|
179
|
-
"code": "RUNTIME_RUN_FAILED",
|
|
180
|
-
"message": str(
|
|
181
|
-
terminal.data.get("error")
|
|
182
|
-
or terminal.data.get("message")
|
|
183
|
-
or "Agent 运行失败"
|
|
184
|
-
),
|
|
185
|
-
}
|
|
186
|
-
elif terminal.type == "run.cancelled":
|
|
187
|
-
record.status = RunStatus.CANCELLED
|
|
188
|
-
record.error = {"code": "RUN_CANCELLED", "message": "运行已取消"}
|
|
189
|
-
else:
|
|
190
|
-
record.status = RunStatus.INTERRUPTED
|
|
191
|
-
record.error = {
|
|
192
|
-
"code": "RUN_INTERRUPTED",
|
|
193
|
-
"message": "Studio 重启后无法重新 attach 上一次本地运行",
|
|
194
|
-
}
|
|
195
|
-
record.completed_at = terminal.created_at
|
|
196
|
-
if record.started_at is not None:
|
|
197
|
-
record.duration_ms = max(
|
|
198
|
-
0,
|
|
199
|
-
int((record.completed_at - record.started_at).total_seconds() * 1000),
|
|
200
|
-
)
|
|
201
|
-
self.save(record)
|
|
202
|
-
recovered += 1
|
|
203
|
-
return recovered
|
|
204
|
-
|
|
205
135
|
def trace(self, trace_id: str) -> dict:
|
|
206
136
|
return self.trace_store.get_trace_view(trace_id)
|
|
207
137
|
|
|
@@ -253,14 +183,14 @@ class RunEventStore:
|
|
|
253
183
|
status=status,
|
|
254
184
|
)
|
|
255
185
|
|
|
256
|
-
def _read(self, run_id: str) -> tuple[RunRecord,
|
|
186
|
+
def _read(self, run_id: str) -> tuple[RunRecord, list[RunEvent]]:
|
|
257
187
|
path = self._path(run_id)
|
|
258
188
|
if not path.is_file():
|
|
259
189
|
raise not_found("run", run_id)
|
|
260
190
|
try:
|
|
261
191
|
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
262
192
|
record = RunRecord.model_validate(payload["record"])
|
|
263
|
-
events = [RunEvent.model_validate(item) for item in payload
|
|
193
|
+
events = [RunEvent.model_validate(item) for item in payload.get("events", [])]
|
|
264
194
|
return record, events
|
|
265
195
|
except (OSError, ValueError, KeyError, ValidationError) as exc:
|
|
266
196
|
raise StudioError(
|
|
@@ -270,15 +200,15 @@ class RunEventStore:
|
|
|
270
200
|
details={"id": run_id},
|
|
271
201
|
) from exc
|
|
272
202
|
|
|
273
|
-
def _write(self, record: RunRecord, events:
|
|
274
|
-
payload = {
|
|
275
|
-
"record": record.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
276
|
-
"events": [
|
|
277
|
-
event.model_dump(by_alias=True, exclude_none=True, mode="json") for event in events
|
|
278
|
-
],
|
|
203
|
+
def _write(self, record: RunRecord, events: list[RunEvent] | None = None) -> None:
|
|
204
|
+
payload: dict[str, Any] = {
|
|
205
|
+
"record": record.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
279
206
|
}
|
|
207
|
+
if events is not None:
|
|
208
|
+
payload["events"] = [
|
|
209
|
+
event.model_dump(by_alias=True, exclude_none=True, mode="json") for event in events
|
|
210
|
+
]
|
|
280
211
|
self.workspace.atomic_write_text(
|
|
281
212
|
self._path(record.id),
|
|
282
213
|
json.dumps(payload, ensure_ascii=False, sort_keys=True, indent=2) + "\n",
|
|
283
214
|
)
|
|
284
|
-
self.trace_store.sync(record, events)
|
ksadk/studio/framework_run.py
CHANGED
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import hashlib
|
|
5
6
|
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
6
9
|
|
|
7
10
|
from ksadk.detection.detector import FrameworkDetector
|
|
8
11
|
from ksadk.runtime import RuntimeLaunchContext
|
|
12
|
+
from ksadk.studio.capabilities import compute_bundle_digest
|
|
13
|
+
from ksadk.studio.contracts import BundleManifest
|
|
9
14
|
from ksadk.studio.errors import StudioError
|
|
10
15
|
from ksadk.studio.repository import BuildRepository
|
|
11
16
|
from ksadk.studio.run_service import StudioRunSpec
|
|
@@ -13,7 +18,79 @@ from ksadk.studio.workspace import Workspace
|
|
|
13
18
|
from ksadk.tools.gateway import normalize_tool_approval_mode
|
|
14
19
|
|
|
15
20
|
|
|
21
|
+
def _resolved_prompt_ownership(resolved: Any) -> str:
|
|
22
|
+
"""从 resolved-agent-spec.json 的 context 块读 prompt_ownership。
|
|
23
|
+
|
|
24
|
+
resolved spec 由 ContractModel 以 ``by_alias=True`` 序列化,alias_generator 为
|
|
25
|
+
camelCase,故字段名为 ``promptOwnership``;``populate_by_name`` 仅作用于输入,JSON
|
|
26
|
+
输出仍为 alias。此处 camelCase 与 snake 两种写法都查,稳妥兼容。非 dict / 缺失时
|
|
27
|
+
返回空串(== framework 默认,不接管 Runner 输入)。
|
|
28
|
+
"""
|
|
29
|
+
if not isinstance(resolved, dict):
|
|
30
|
+
return ""
|
|
31
|
+
context = resolved.get("context")
|
|
32
|
+
if not isinstance(context, dict):
|
|
33
|
+
return ""
|
|
34
|
+
return str(
|
|
35
|
+
context.get("promptOwnership")
|
|
36
|
+
or context.get("prompt_ownership")
|
|
37
|
+
or context.get("ownership")
|
|
38
|
+
or ""
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _resolved_context_engine_rollout(resolved: Any) -> str:
|
|
43
|
+
"""读取 AgentVersion 固化的 Context Engine rollout。"""
|
|
44
|
+
if not isinstance(resolved, dict):
|
|
45
|
+
return ""
|
|
46
|
+
context = resolved.get("context")
|
|
47
|
+
if not isinstance(context, dict):
|
|
48
|
+
return ""
|
|
49
|
+
rollout = context.get("rollout")
|
|
50
|
+
if not isinstance(rollout, dict):
|
|
51
|
+
return ""
|
|
52
|
+
return str(rollout.get("contextEngine") or rollout.get("context_engine") or "")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _resolved_memory_recall_enabled(resolved: Any) -> bool | None:
|
|
56
|
+
"""读取 AgentVersion 的 Memory 召回开关;缺失时保留旧环境策略。"""
|
|
57
|
+
if not isinstance(resolved, dict):
|
|
58
|
+
return None
|
|
59
|
+
memory = resolved.get("memory")
|
|
60
|
+
if not isinstance(memory, dict) or "enabled" not in memory:
|
|
61
|
+
return None
|
|
62
|
+
enabled = bool(memory.get("enabled"))
|
|
63
|
+
recall = memory.get("recall")
|
|
64
|
+
if isinstance(recall, dict) and "enabled" in recall:
|
|
65
|
+
enabled = enabled and bool(recall.get("enabled"))
|
|
66
|
+
context = resolved.get("context")
|
|
67
|
+
contributors = context.get("contributors") if isinstance(context, dict) else None
|
|
68
|
+
if isinstance(contributors, dict):
|
|
69
|
+
explicit = contributors.get("memoryRecall", contributors.get("memory_recall"))
|
|
70
|
+
if explicit is not None:
|
|
71
|
+
enabled = enabled and bool(explicit)
|
|
72
|
+
return enabled
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _resolved_memory_write_rollout(resolved: Any) -> str:
|
|
76
|
+
"""读取 AgentVersion 固化的 Memory 写入 rollout。"""
|
|
77
|
+
if not isinstance(resolved, dict):
|
|
78
|
+
return ""
|
|
79
|
+
context = resolved.get("context")
|
|
80
|
+
if not isinstance(context, dict):
|
|
81
|
+
return ""
|
|
82
|
+
rollout = context.get("rollout")
|
|
83
|
+
if not isinstance(rollout, dict):
|
|
84
|
+
return ""
|
|
85
|
+
return str(rollout.get("memoryWrite") or rollout.get("memory_write") or "")
|
|
86
|
+
|
|
87
|
+
|
|
16
88
|
class FrameworkRunSpecResolver:
|
|
89
|
+
# manifest.json 是 bundle 自身的描述文件,不进入 manifest.files 清单
|
|
90
|
+
# (builder 在扫描文件列表之后才写它),校验时排除。checksums.txt 在本仓
|
|
91
|
+
# bundle 格式中是 manifest 声明的普通成员,参与校验。
|
|
92
|
+
_BUNDLE_META_FILES = frozenset({"manifest.json"})
|
|
93
|
+
|
|
17
94
|
def __init__(
|
|
18
95
|
self,
|
|
19
96
|
workspace: Workspace,
|
|
@@ -43,6 +120,9 @@ class FrameworkRunSpecResolver:
|
|
|
43
120
|
raise StudioError("BUILD_NOT_READY", "Build 尚未生成制品", status_code=409)
|
|
44
121
|
artifact_root = self.workspace.resolve(build.artifact_path, must_exist=True).parent
|
|
45
122
|
bundle_root = artifact_root / "agent-bundle"
|
|
123
|
+
self._verify_bundle_integrity(
|
|
124
|
+
bundle_root, expected_bundle_digest=build.bundle_digest
|
|
125
|
+
)
|
|
46
126
|
project_dir = bundle_root / "runtime"
|
|
47
127
|
if not project_dir.is_dir():
|
|
48
128
|
raise StudioError(
|
|
@@ -67,13 +147,38 @@ class FrameworkRunSpecResolver:
|
|
|
67
147
|
instructions = resolved.get("instructions") if isinstance(resolved, dict) else {}
|
|
68
148
|
request_config = {
|
|
69
149
|
"base_instructions": str((instructions or {}).get("system") or ""),
|
|
150
|
+
# Preserve system/task as separate PCM sources while keeping the
|
|
151
|
+
# framework runner's existing base_instructions projection.
|
|
152
|
+
"agent_system": str((instructions or {}).get("system") or ""),
|
|
153
|
+
"agent_task": str((instructions or {}).get("task") or ""),
|
|
154
|
+
**(
|
|
155
|
+
{"prompt_integration_mode": "ksadk_hosted"}
|
|
156
|
+
if _resolved_prompt_ownership(resolved) == "ksadk"
|
|
157
|
+
else {}
|
|
158
|
+
),
|
|
159
|
+
"context_engine_rollout": _resolved_context_engine_rollout(resolved),
|
|
160
|
+
"memory_recall_enabled": _resolved_memory_recall_enabled(resolved),
|
|
161
|
+
"memory_write_rollout": _resolved_memory_write_rollout(resolved),
|
|
162
|
+
"memory_enabled": _resolved_memory_enabled(resolved),
|
|
163
|
+
"memory_write_mode": _resolved_memory_write_mode(resolved),
|
|
164
|
+
"flush_before_compaction": _resolved_memory_flush_before_compaction(resolved),
|
|
165
|
+
"provider_ref": _resolved_memory_provider_ref(resolved),
|
|
70
166
|
"entry_point": detection.entry_point,
|
|
71
167
|
"agent_variable": detection.agent_variable,
|
|
72
168
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
169
|
+
# AgentVersion 的 ContextSpec 预算传到 Planner(方案 §8.2)
|
|
170
|
+
context_spec = resolved.get("context") if isinstance(resolved, dict) else {}
|
|
171
|
+
if isinstance(context_spec, dict):
|
|
172
|
+
max_input = context_spec.get("maxInputTokens") or context_spec.get("max_input_tokens")
|
|
173
|
+
reserve_output = context_spec.get("reserveOutputTokens") or context_spec.get(
|
|
174
|
+
"reserve_output_tokens"
|
|
76
175
|
)
|
|
176
|
+
if max_input is not None:
|
|
177
|
+
request_config["max_input_tokens"] = int(max_input)
|
|
178
|
+
if reserve_output is not None:
|
|
179
|
+
request_config["reserve_output_tokens"] = int(reserve_output)
|
|
180
|
+
if approval_mode:
|
|
181
|
+
request_config["tool_approval_mode"] = normalize_tool_approval_mode(approval_mode)
|
|
77
182
|
return StudioRunSpec(
|
|
78
183
|
launch_context=RuntimeLaunchContext(
|
|
79
184
|
runtime_type=runtime_type,
|
|
@@ -110,5 +215,128 @@ class FrameworkRunSpecResolver:
|
|
|
110
215
|
)
|
|
111
216
|
return selected
|
|
112
217
|
|
|
218
|
+
def _verify_bundle_integrity(
|
|
219
|
+
self,
|
|
220
|
+
bundle_dir: Path,
|
|
221
|
+
*,
|
|
222
|
+
expected_bundle_digest: str = "",
|
|
223
|
+
) -> None:
|
|
224
|
+
"""加载前校验 bundle 未被篡改:manifest 自身摘要、与 Build 记录一致、
|
|
225
|
+
文件清单无增删、每个文件 sha256/size 匹配。"""
|
|
226
|
+
try:
|
|
227
|
+
manifest = BundleManifest.model_validate_json(
|
|
228
|
+
(bundle_dir / "manifest.json").read_text(encoding="utf-8")
|
|
229
|
+
)
|
|
230
|
+
except (OSError, ValueError) as exc:
|
|
231
|
+
raise StudioError(
|
|
232
|
+
"BUILD_ARTIFACT_INVALID",
|
|
233
|
+
"Build 缺少有效的 Bundle Manifest",
|
|
234
|
+
status_code=500,
|
|
235
|
+
) from exc
|
|
236
|
+
if manifest.bundle_digest != compute_bundle_digest(manifest):
|
|
237
|
+
raise StudioError(
|
|
238
|
+
"BUILD_ARTIFACT_INVALID",
|
|
239
|
+
"Bundle Manifest 摘要不匹配,Bundle 可能已被篡改",
|
|
240
|
+
status_code=500,
|
|
241
|
+
details={"bundleDigest": manifest.bundle_digest},
|
|
242
|
+
)
|
|
243
|
+
if expected_bundle_digest and manifest.bundle_digest != expected_bundle_digest:
|
|
244
|
+
raise StudioError(
|
|
245
|
+
"BUILD_ARTIFACT_INVALID",
|
|
246
|
+
"Bundle 与 Build 记录的摘要不一致,Bundle 可能已被篡改",
|
|
247
|
+
status_code=500,
|
|
248
|
+
details={
|
|
249
|
+
"expected": expected_bundle_digest,
|
|
250
|
+
"actual": manifest.bundle_digest,
|
|
251
|
+
},
|
|
252
|
+
)
|
|
253
|
+
declared = {entry.path for entry in manifest.files}
|
|
254
|
+
actual: dict[str, Path] = {}
|
|
255
|
+
for path in bundle_dir.rglob("*"):
|
|
256
|
+
if not path.is_file():
|
|
257
|
+
continue
|
|
258
|
+
relative = path.relative_to(bundle_dir).as_posix()
|
|
259
|
+
if relative in self._BUNDLE_META_FILES:
|
|
260
|
+
continue
|
|
261
|
+
actual[relative] = path
|
|
262
|
+
extra = sorted(set(actual) - declared)
|
|
263
|
+
if extra:
|
|
264
|
+
raise StudioError(
|
|
265
|
+
"BUILD_ARTIFACT_INVALID",
|
|
266
|
+
"Bundle 含未在 Manifest 中声明的文件",
|
|
267
|
+
status_code=500,
|
|
268
|
+
details={"extraFiles": extra},
|
|
269
|
+
)
|
|
270
|
+
for entry in manifest.files:
|
|
271
|
+
file_path = actual.get(entry.path)
|
|
272
|
+
if file_path is None:
|
|
273
|
+
raise StudioError(
|
|
274
|
+
"BUILD_ARTIFACT_INVALID",
|
|
275
|
+
"Bundle 缺少 Manifest 声明的文件",
|
|
276
|
+
status_code=500,
|
|
277
|
+
details={"missingFile": entry.path},
|
|
278
|
+
)
|
|
279
|
+
content = file_path.read_bytes()
|
|
280
|
+
actual_sha = f"sha256:{hashlib.sha256(content).hexdigest()}"
|
|
281
|
+
if actual_sha != entry.sha256:
|
|
282
|
+
raise StudioError(
|
|
283
|
+
"BUILD_ARTIFACT_INVALID",
|
|
284
|
+
"Bundle 文件摘要不匹配",
|
|
285
|
+
status_code=500,
|
|
286
|
+
details={
|
|
287
|
+
"path": entry.path,
|
|
288
|
+
"expected": entry.sha256,
|
|
289
|
+
"actual": actual_sha,
|
|
290
|
+
},
|
|
291
|
+
)
|
|
292
|
+
if len(content) != entry.size:
|
|
293
|
+
raise StudioError(
|
|
294
|
+
"BUILD_ARTIFACT_INVALID",
|
|
295
|
+
"Bundle 文件大小不匹配",
|
|
296
|
+
status_code=500,
|
|
297
|
+
details={
|
|
298
|
+
"path": entry.path,
|
|
299
|
+
"expected": entry.size,
|
|
300
|
+
"actual": len(content),
|
|
301
|
+
},
|
|
302
|
+
)
|
|
303
|
+
|
|
113
304
|
|
|
114
305
|
__all__ = ["FrameworkRunSpecResolver"]
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def _resolved_memory_enabled(resolved: Any) -> bool:
|
|
309
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
310
|
+
return bool(memory.get("enabled", False)) if isinstance(memory, dict) else False
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
314
|
+
if not isinstance(memory, dict) or not memory.get("enabled", False):
|
|
315
|
+
return False
|
|
316
|
+
recall = memory.get("recall", {})
|
|
317
|
+
return bool(recall.get("enabled", True)) if isinstance(recall, dict) else True
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _resolved_memory_write_mode(resolved: Any) -> str:
|
|
321
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
322
|
+
write = memory.get("write", {}) if isinstance(memory, dict) else {}
|
|
323
|
+
return (
|
|
324
|
+
str(write.get("mode", "candidate") or "candidate")
|
|
325
|
+
if isinstance(write, dict)
|
|
326
|
+
else "candidate"
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _resolved_memory_flush_before_compaction(resolved: Any) -> bool:
|
|
331
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
332
|
+
write = memory.get("write", {}) if isinstance(memory, dict) else {}
|
|
333
|
+
return bool(write.get("flushBeforeCompaction", True)) if isinstance(write, dict) else True
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _resolved_memory_provider_ref(resolved: Any) -> str:
|
|
337
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
338
|
+
return (
|
|
339
|
+
str(memory.get("providerRef", "local-default") or "local-default")
|
|
340
|
+
if isinstance(memory, dict)
|
|
341
|
+
else "local-default"
|
|
342
|
+
)
|