agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.3__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.3.dist-info}/METADATA +25 -12
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/RECORD +421 -232
- ksadk/_build_provenance.json +1 -0
- 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 +247 -0
- ksadk/agui/a2ui_projection.py +12 -5
- ksadk/agui/agent.py +443 -259
- ksadk/api/client.py +528 -27
- ksadk/builders/code_builder.py +284 -8
- ksadk/builders/container_builder.py +8 -1
- ksadk/builders/managed_runtime_builder.py +42 -35
- ksadk/cli/__init__.py +23 -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_plugin.py +657 -0
- 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 +475 -331
- ksadk/configs/env_registry.py +94 -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/configs/settings.py +9 -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 +409 -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 +19 -0
- ksadk/conversations/context.py +230 -30
- ksadk/conversations/contracts.py +266 -0
- ksadk/conversations/message_projection.py +308 -26
- ksadk/conversations/model_context.py +49 -3
- ksadk/conversations/projector.py +616 -0
- ksadk/conversations/reducer.py +98 -0
- 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 +755 -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 +907 -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/__init__.py +45 -35
- ksadk/harness/runtime.py +220 -58
- 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 +62 -0
- ksadk/kernel/contracts.py +370 -0
- ksadk/kernel/control.py +220 -0
- ksadk/kernel/errors.py +79 -0
- ksadk/kernel/ingress.py +1123 -0
- ksadk/kernel/mapping.py +111 -0
- ksadk/kernel/memory_store.py +1134 -0
- ksadk/kernel/postgres_store.py +1757 -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 +1411 -0
- ksadk/kernel/state.py +145 -0
- ksadk/kernel/store.py +232 -0
- ksadk/kernel/worker.py +964 -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 +497 -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/plugins/__init__.py +167 -0
- ksadk/plugins/bridges/__init__.py +45 -0
- ksadk/plugins/bridges/codex.py +552 -0
- ksadk/plugins/bridges/dsh.py +1116 -0
- ksadk/plugins/builtins.py +747 -0
- ksadk/plugins/bundle.py +246 -0
- ksadk/plugins/bundle_security.py +167 -0
- ksadk/plugins/composition.py +529 -0
- ksadk/plugins/context_contributor.py +437 -0
- ksadk/plugins/contracts.py +451 -0
- ksadk/plugins/dsh_toolchain.py +935 -0
- ksadk/plugins/ecosystem_bridge.py +1105 -0
- ksadk/plugins/ecosystem_probe.py +191 -0
- ksadk/plugins/host.py +724 -0
- ksadk/plugins/providers/__init__.py +85 -0
- ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
- ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
- ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
- ksadk/plugins/providers/codex.py +722 -0
- ksadk/plugins/providers/codex_dsh.py +83 -0
- ksadk/plugins/providers/dsh.py +951 -0
- ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
- ksadk/plugins/providers/harness.py +627 -0
- ksadk/plugins/providers/harness_dsh.py +91 -0
- ksadk/plugins/providers/legacy.py +215 -0
- ksadk/plugins/providers/legacy_catalog.py +100 -0
- ksadk/plugins/providers/shipped_dsh.py +370 -0
- ksadk/plugins/resolver.py +331 -0
- ksadk/plugins/subagent_providers/__init__.py +12 -0
- ksadk/plugins/subagent_providers/codex.py +443 -0
- ksadk/plugins/subagents.py +333 -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 +797 -0
- ksadk/runtime/adapter.py +119 -2
- ksadk/runtime/conversation_execution.py +316 -182
- ksadk/runtime/executor.py +144 -3
- ksadk/runtime/factory.py +268 -8
- ksadk/runtime/framework_adapters.py +18 -0
- ksadk/runtime/hosted_finalizer.py +268 -0
- ksadk/runtime/launch.py +14 -1
- ksadk/runtime/preprocessing.py +25 -3
- ksadk/runtime/runner_adapter.py +293 -508
- ksadk/runtime/usage.py +33 -0
- ksadk/sandbox/__init__.py +2 -1
- ksadk/sandbox/backends/e2b.py +35 -2
- ksadk/sandbox/factory.py +72 -0
- ksadk/scheduler/__init__.py +18 -0
- ksadk/scheduler/calendar.py +102 -0
- ksadk/scheduler/contracts.py +254 -0
- ksadk/scheduler/dispatcher.py +129 -0
- ksadk/scheduler/engine.py +416 -0
- ksadk/scheduler/sqlite_store.py +563 -0
- 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-10GPXIJ6.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-BXk1l-G1.js} +4 -4
- ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
- ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-D9uB55Oh.js} +4 -4
- ksadk/server/static/assets/MermaidBlock--OEYoXIJ.js +312 -0
- ksadk/server/static/assets/NativeTerminalPanel-DrEe1syq.js +1 -0
- ksadk/server/static/assets/abnfDiagram-VCTEODGH-eeTFJLvo.js +1 -0
- ksadk/server/static/assets/arc-S3ZNbIAd.js +1 -0
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +1 -0
- ksadk/server/static/assets/architectureDiagram-5GKGNRK7-CRjgEJDX.js +36 -0
- ksadk/server/static/assets/blockDiagram-NRAW4CY4-C7bsBoNH.js +129 -0
- ksadk/server/static/assets/c4Diagram-UCG6FXSJ-BX3c33Ob.js +38 -0
- ksadk/server/static/assets/channel-s354Yo6o.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +1 -0
- ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-bZ7ws-8m.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-D2r0pvhY.js} +1 -1
- ksadk/server/static/assets/chunk-G27WJ6UU-CZwF3oUP.js +231 -0
- ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-DigFYCML.js} +1 -1
- ksadk/server/static/assets/chunk-LCL6LL3I-CnorGV5q.js +206 -0
- ksadk/server/static/assets/chunk-POPQ4Y6H-CexntQA-.js +1 -0
- ksadk/server/static/assets/chunk-RHFEMEQ7-CHTC7UxA.js +168 -0
- ksadk/server/static/assets/chunk-SVP7TREG-BC1EWt_-.js +88 -0
- ksadk/server/static/assets/chunk-XXDRQBXY-BTG24xN0.js +1 -0
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-CkonRdAS.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +1 -0
- ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-DEOCBe15.js +62 -0
- ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
- ksadk/server/static/assets/dagre-3AP2YEHR-DBThPuLa.js +4 -0
- ksadk/server/static/assets/dagre-ClTPrTht.js +1 -0
- ksadk/server/static/assets/diagram-S7CK7UJ4-DsZHrnpJ.js +30 -0
- ksadk/server/static/assets/diagram-UQ7AKVKN-BJR4nhVr.js +41 -0
- ksadk/server/static/assets/diagram-VSXAHHWV-xzcERX0a.js +3 -0
- ksadk/server/static/assets/diagram-VX7I27RA-tn2xM1xu.js +24 -0
- ksadk/server/static/assets/diagram-Z3DM3KII-BZPGBkw5.js +24 -0
- ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-4zN1_tq5.js} +1 -1
- ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-8VWI-2bZ.js} +1 -1
- ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-B-46q3Hk.js} +1 -1
- ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-B0gdk4rl.js} +1 -1
- ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-B1oWRmrH.js} +1 -1
- ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-BI1qQH4n.js} +1 -1
- ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-BJLUwH6W.js} +1 -1
- ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Bbwqa8TG.js} +1 -1
- ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-Btyo4vX4.js} +1 -1
- ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-C71CsujO.js} +1 -1
- ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-CXpH_Rdd.js} +1 -1
- ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-Cq4OL6nO.js} +1 -1
- ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-D1V3f1B4.js} +1 -1
- ksadk/server/static/assets/{dist-fhOuWds5.js → dist-DJmCPRVB.js} +1 -1
- ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DQAB0qn_.js} +2 -2
- ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DUwKa_l6.js} +1 -1
- ksadk/server/static/assets/dist-DdRBIceA.js +1 -0
- ksadk/server/static/assets/{dist-DWKByxWV.js → dist-DfGFrb0v.js} +1 -1
- ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-DjhwGUgZ.js} +1 -1
- ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-DyqV4fL4.js} +1 -1
- ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-M67Hwu0n.js} +1 -1
- ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-u8tVH5Ak.js} +1 -1
- ksadk/server/static/assets/ebnfDiagram-PWID7BFC-DVfMsLge.js +1 -0
- ksadk/server/static/assets/erDiagram-SSCWMZ5O-CWEZSYaw.js +99 -0
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +1 -0
- ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-TWIxoyYL.js +292 -0
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +1 -0
- ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-DDh2hd2S.js +106 -0
- ksadk/server/static/assets/index-B2k_urY8.js +241 -0
- ksadk/server/static/assets/index-ILPt6IWF.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +1 -0
- ksadk/server/static/assets/infoDiagram-RXCK75RN-CgoyWiDR.js +2 -0
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-CyRIu_om.js} +6 -6
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DN5JXHzN.js} +6 -6
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-CNP3ui66.js} +10 -10
- ksadk/server/static/assets/katex-DWEzQy1d.js +257 -0
- ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-C-qHp7d2.js} +1 -1
- ksadk/server/static/assets/mermaid-parser.core-Cl-K943T.js +166 -0
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-D5DB5mYm.js} +29 -29
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +1 -0
- ksadk/server/static/assets/pegDiagram-XKGWAZYB-BQVc9ia_.js +1 -0
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +1 -0
- ksadk/server/static/assets/pieDiagram-E7YTZNPT-B6UCAvtY.js +39 -0
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-mIr2d3eb.js} +6 -6
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +1 -0
- ksadk/server/static/assets/railroadDiagram-O6MQD6OU-Dt3FFDmK.js +1 -0
- ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-Cz_vQtgF.js +84 -0
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-wlO1TsH5.js} +7 -7
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-CHRbElYq.js} +10 -10
- ksadk/server/static/assets/sizeCapture-X5ZJPWSS-DXX54iyO.js +1 -0
- ksadk/server/static/assets/stateDiagram-HBIQ2CUA-Dp_lw9II.js +1 -0
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +1 -0
- ksadk/server/static/assets/swimlanes-XN3QIQJK-D8O5UlLG.js +1 -0
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +8 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-8mfKcxvG.js} +7 -7
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +1 -0
- ksadk/server/static/assets/vennDiagram-4TSXK5OY-EnNl0DE7.js +34 -0
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +1 -0
- ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DBu5fbYr.js +78 -0
- ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-BSVXs4IY.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/service_client.py +48 -0
- ksadk/studio/agent_lifecycle.py +26 -20
- ksadk/studio/api.py +1063 -69
- ksadk/studio/api_catalog_routes.py +5 -0
- ksadk/studio/api_contracts.py +148 -6
- ksadk/studio/api_memory_routes.py +82 -0
- ksadk/studio/api_plugin_routes.py +480 -0
- ksadk/studio/attachment_store.py +187 -0
- ksadk/studio/authoring.py +259 -28
- ksadk/studio/authoring_coordinator.py +809 -67
- ksadk/studio/builder.py +197 -40
- ksadk/studio/capabilities.py +17 -0
- ksadk/studio/cloud.py +1920 -95
- ksadk/studio/codex_agent_service.py +137 -15
- ksadk/studio/codex_authoring.py +469 -0
- ksadk/studio/codex_builder.py +177 -25
- ksadk/studio/codex_manifest.py +71 -22
- ksadk/studio/codex_run.py +59 -4
- ksadk/studio/compatibility_report.py +445 -0
- ksadk/studio/compiler.py +7 -1
- ksadk/studio/contracts.py +234 -4
- ksadk/studio/dsh_provider_registration.py +768 -0
- ksadk/studio/event_store.py +79 -101
- ksadk/studio/framework_run.py +264 -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 +47 -5
- ksadk/studio/otel_trace.py +348 -42
- ksadk/studio/pcm_memory.py +85 -0
- ksadk/studio/plugin_composition.py +301 -0
- ksadk/studio/plugin_kernel_adapter.py +128 -0
- ksadk/studio/plugin_runtime.py +652 -0
- ksadk/studio/repository.py +23 -2
- ksadk/studio/resource_catalog.py +49 -1
- ksadk/studio/run_service.py +1266 -202
- ksadk/studio/runtime_source.py +51 -17
- ksadk/studio/scheduler_runtime.py +374 -0
- ksadk/studio/scheduler_service.py +211 -0
- ksadk/studio/service.py +1815 -117
- ksadk/studio/shared_web.py +199 -50
- ksadk/studio/soul.py +52 -0
- ksadk/studio/static/assets/index-DXs1Eq4M.css +1 -0
- ksadk/studio/static/assets/index-DeDqwTsD.js +283 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/studio/templates.py +100 -8
- ksadk/studio/validator.py +20 -1
- ksadk/studio/workspace.py +31 -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_runtime_common/workspace_files/path_utils.py +41 -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.3.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.3.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,40 +28,94 @@ 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
|
+
"""
|
|
46
|
+
return self.append_many(run_id, [(event_type, data)])[0]
|
|
47
|
+
|
|
48
|
+
def append_many(
|
|
49
|
+
self,
|
|
50
|
+
run_id: str,
|
|
51
|
+
entries: list[tuple[str, dict[str, Any]]],
|
|
52
|
+
) -> list[RunEvent]:
|
|
53
|
+
"""Persist one logical Studio transition with a single file replace."""
|
|
40
54
|
record, events = self._read(run_id)
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
appended: list[RunEvent] = []
|
|
56
|
+
for event_type, data in entries:
|
|
57
|
+
event = RunEvent(
|
|
58
|
+
id=len(events) + 1,
|
|
59
|
+
run_id=run_id,
|
|
60
|
+
type=event_type,
|
|
61
|
+
data=data,
|
|
62
|
+
)
|
|
63
|
+
events.append(event)
|
|
64
|
+
appended.append(event)
|
|
65
|
+
if appended:
|
|
66
|
+
self._write(record, events)
|
|
67
|
+
return appended
|
|
68
|
+
|
|
69
|
+
def append_interaction_resolution(
|
|
70
|
+
self,
|
|
71
|
+
run_id: str,
|
|
72
|
+
*,
|
|
73
|
+
resolved_type: str,
|
|
74
|
+
resolved_data: dict[str, Any],
|
|
75
|
+
action_data: dict[str, Any],
|
|
76
|
+
) -> tuple[RunEvent, RunEvent, dict[str, Any]]:
|
|
77
|
+
"""Atomically persist a terminal interaction and its replay receipt."""
|
|
78
|
+
record, events = self._read(run_id)
|
|
79
|
+
resolution_event_id = len(events) + 1
|
|
80
|
+
action_event_id = resolution_event_id + 1
|
|
81
|
+
receipt = {
|
|
82
|
+
"runId": run_id,
|
|
83
|
+
"interactionId": str(action_data.get("interactionId") or ""),
|
|
84
|
+
"status": "resolved",
|
|
85
|
+
"revision": int(action_data.get("revision") or 0),
|
|
86
|
+
"resolutionEventId": resolution_event_id,
|
|
87
|
+
"eventId": action_event_id,
|
|
88
|
+
}
|
|
89
|
+
resolved = RunEvent(
|
|
90
|
+
id=resolution_event_id,
|
|
91
|
+
run_id=run_id,
|
|
92
|
+
type=resolved_type,
|
|
93
|
+
data=resolved_data,
|
|
94
|
+
)
|
|
95
|
+
action = RunEvent(
|
|
96
|
+
id=action_event_id,
|
|
43
97
|
run_id=run_id,
|
|
44
|
-
type=
|
|
45
|
-
data=
|
|
98
|
+
type="a2ui.action",
|
|
99
|
+
data={**action_data, "receipt": receipt},
|
|
46
100
|
)
|
|
47
|
-
events.
|
|
101
|
+
events.extend((resolved, action))
|
|
48
102
|
self._write(record, events)
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
def get(self, run_id: str) -> RunRecord:
|
|
52
|
-
record, _ = self._read(run_id)
|
|
53
|
-
return record
|
|
103
|
+
return resolved, action, receipt
|
|
54
104
|
|
|
55
105
|
def events(self, run_id: str, *, after: int = 0) -> list[RunEvent]:
|
|
56
106
|
_, events = self._read(run_id)
|
|
57
107
|
return [event for event in events if event.id > after]
|
|
58
108
|
|
|
109
|
+
def get(self, run_id: str) -> RunRecord:
|
|
110
|
+
record, _ = self._read(run_id)
|
|
111
|
+
return record
|
|
112
|
+
|
|
59
113
|
def list_runs(
|
|
60
114
|
self,
|
|
61
115
|
*,
|
|
62
116
|
session_id: str | None = None,
|
|
63
117
|
agent_id: str | None = None,
|
|
64
|
-
) ->
|
|
118
|
+
) -> list[RunRecord]:
|
|
65
119
|
records: list[RunRecord] = []
|
|
66
120
|
directory = self.workspace.resolve(".agentkit/runs")
|
|
67
121
|
for path in sorted(directory.glob("run_*.json")):
|
|
@@ -126,82 +180,6 @@ class RunEventStore:
|
|
|
126
180
|
deleted += 1
|
|
127
181
|
return deleted
|
|
128
182
|
|
|
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
183
|
def trace(self, trace_id: str) -> dict:
|
|
206
184
|
return self.trace_store.get_trace_view(trace_id)
|
|
207
185
|
|
|
@@ -253,14 +231,14 @@ class RunEventStore:
|
|
|
253
231
|
status=status,
|
|
254
232
|
)
|
|
255
233
|
|
|
256
|
-
def _read(self, run_id: str) -> tuple[RunRecord,
|
|
234
|
+
def _read(self, run_id: str) -> tuple[RunRecord, list[RunEvent]]:
|
|
257
235
|
path = self._path(run_id)
|
|
258
236
|
if not path.is_file():
|
|
259
237
|
raise not_found("run", run_id)
|
|
260
238
|
try:
|
|
261
239
|
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
262
240
|
record = RunRecord.model_validate(payload["record"])
|
|
263
|
-
events = [RunEvent.model_validate(item) for item in payload
|
|
241
|
+
events = [RunEvent.model_validate(item) for item in payload.get("events", [])]
|
|
264
242
|
return record, events
|
|
265
243
|
except (OSError, ValueError, KeyError, ValidationError) as exc:
|
|
266
244
|
raise StudioError(
|
|
@@ -270,15 +248,15 @@ class RunEventStore:
|
|
|
270
248
|
details={"id": run_id},
|
|
271
249
|
) from exc
|
|
272
250
|
|
|
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
|
-
],
|
|
251
|
+
def _write(self, record: RunRecord, events: list[RunEvent] | None = None) -> None:
|
|
252
|
+
payload: dict[str, Any] = {
|
|
253
|
+
"record": record.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
279
254
|
}
|
|
255
|
+
if events is not None:
|
|
256
|
+
payload["events"] = [
|
|
257
|
+
event.model_dump(by_alias=True, exclude_none=True, mode="json") for event in events
|
|
258
|
+
]
|
|
280
259
|
self.workspace.atomic_write_text(
|
|
281
260
|
self._path(record.id),
|
|
282
261
|
json.dumps(payload, ensure_ascii=False, sort_keys=True, indent=2) + "\n",
|
|
283
262
|
)
|
|
284
|
-
self.trace_store.sync(record, events)
|
ksadk/studio/framework_run.py
CHANGED
|
@@ -2,10 +2,16 @@
|
|
|
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
|
|
11
|
+
from ksadk.plugins.bundle_security import BundleSecurityError, assert_bundle_security
|
|
8
12
|
from ksadk.runtime import RuntimeLaunchContext
|
|
13
|
+
from ksadk.studio.capabilities import compute_bundle_digest
|
|
14
|
+
from ksadk.studio.contracts import BundleManifest
|
|
9
15
|
from ksadk.studio.errors import StudioError
|
|
10
16
|
from ksadk.studio.repository import BuildRepository
|
|
11
17
|
from ksadk.studio.run_service import StudioRunSpec
|
|
@@ -13,7 +19,79 @@ from ksadk.studio.workspace import Workspace
|
|
|
13
19
|
from ksadk.tools.gateway import normalize_tool_approval_mode
|
|
14
20
|
|
|
15
21
|
|
|
22
|
+
def _resolved_prompt_ownership(resolved: Any) -> str:
|
|
23
|
+
"""从 resolved-agent-spec.json 的 context 块读 prompt_ownership。
|
|
24
|
+
|
|
25
|
+
resolved spec 由 ContractModel 以 ``by_alias=True`` 序列化,alias_generator 为
|
|
26
|
+
camelCase,故字段名为 ``promptOwnership``;``populate_by_name`` 仅作用于输入,JSON
|
|
27
|
+
输出仍为 alias。此处 camelCase 与 snake 两种写法都查,稳妥兼容。非 dict / 缺失时
|
|
28
|
+
返回空串(== framework 默认,不接管 Runner 输入)。
|
|
29
|
+
"""
|
|
30
|
+
if not isinstance(resolved, dict):
|
|
31
|
+
return ""
|
|
32
|
+
context = resolved.get("context")
|
|
33
|
+
if not isinstance(context, dict):
|
|
34
|
+
return ""
|
|
35
|
+
return str(
|
|
36
|
+
context.get("promptOwnership")
|
|
37
|
+
or context.get("prompt_ownership")
|
|
38
|
+
or context.get("ownership")
|
|
39
|
+
or ""
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _resolved_context_engine_rollout(resolved: Any) -> str:
|
|
44
|
+
"""读取 AgentVersion 固化的 Context Engine rollout。"""
|
|
45
|
+
if not isinstance(resolved, dict):
|
|
46
|
+
return ""
|
|
47
|
+
context = resolved.get("context")
|
|
48
|
+
if not isinstance(context, dict):
|
|
49
|
+
return ""
|
|
50
|
+
rollout = context.get("rollout")
|
|
51
|
+
if not isinstance(rollout, dict):
|
|
52
|
+
return ""
|
|
53
|
+
return str(rollout.get("contextEngine") or rollout.get("context_engine") or "")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _resolved_memory_recall_enabled(resolved: Any) -> bool | None:
|
|
57
|
+
"""读取 AgentVersion 的 Memory 召回开关;缺失时保留旧环境策略。"""
|
|
58
|
+
if not isinstance(resolved, dict):
|
|
59
|
+
return None
|
|
60
|
+
memory = resolved.get("memory")
|
|
61
|
+
if not isinstance(memory, dict) or "enabled" not in memory:
|
|
62
|
+
return None
|
|
63
|
+
enabled = bool(memory.get("enabled"))
|
|
64
|
+
recall = memory.get("recall")
|
|
65
|
+
if isinstance(recall, dict) and "enabled" in recall:
|
|
66
|
+
enabled = enabled and bool(recall.get("enabled"))
|
|
67
|
+
context = resolved.get("context")
|
|
68
|
+
contributors = context.get("contributors") if isinstance(context, dict) else None
|
|
69
|
+
if isinstance(contributors, dict):
|
|
70
|
+
explicit = contributors.get("memoryRecall", contributors.get("memory_recall"))
|
|
71
|
+
if explicit is not None:
|
|
72
|
+
enabled = enabled and bool(explicit)
|
|
73
|
+
return enabled
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _resolved_memory_write_rollout(resolved: Any) -> str:
|
|
77
|
+
"""读取 AgentVersion 固化的 Memory 写入 rollout。"""
|
|
78
|
+
if not isinstance(resolved, dict):
|
|
79
|
+
return ""
|
|
80
|
+
context = resolved.get("context")
|
|
81
|
+
if not isinstance(context, dict):
|
|
82
|
+
return ""
|
|
83
|
+
rollout = context.get("rollout")
|
|
84
|
+
if not isinstance(rollout, dict):
|
|
85
|
+
return ""
|
|
86
|
+
return str(rollout.get("memoryWrite") or rollout.get("memory_write") or "")
|
|
87
|
+
|
|
88
|
+
|
|
16
89
|
class FrameworkRunSpecResolver:
|
|
90
|
+
# manifest.json 是 bundle 自身的描述文件,不进入 manifest.files 清单
|
|
91
|
+
# (builder 在扫描文件列表之后才写它),校验时排除。checksums.txt 在本仓
|
|
92
|
+
# bundle 格式中是 manifest 声明的普通成员,参与校验。
|
|
93
|
+
_BUNDLE_META_FILES = frozenset({"manifest.json"})
|
|
94
|
+
|
|
17
95
|
def __init__(
|
|
18
96
|
self,
|
|
19
97
|
workspace: Workspace,
|
|
@@ -43,6 +121,11 @@ class FrameworkRunSpecResolver:
|
|
|
43
121
|
raise StudioError("BUILD_NOT_READY", "Build 尚未生成制品", status_code=409)
|
|
44
122
|
artifact_root = self.workspace.resolve(build.artifact_path, must_exist=True).parent
|
|
45
123
|
bundle_root = artifact_root / "agent-bundle"
|
|
124
|
+
self._verify_bundle_integrity(bundle_root, expected_bundle_digest=build.bundle_digest)
|
|
125
|
+
# v1 artifacts predate the no-literal-secret Bundle admission rule and
|
|
126
|
+
# must stay runnable. Every v2 bundle is checked again before local
|
|
127
|
+
# execution, including an externally restored but integrity-valid ZIP.
|
|
128
|
+
self._verify_bundle_security(bundle_root)
|
|
46
129
|
project_dir = bundle_root / "runtime"
|
|
47
130
|
if not project_dir.is_dir():
|
|
48
131
|
raise StudioError(
|
|
@@ -67,13 +150,38 @@ class FrameworkRunSpecResolver:
|
|
|
67
150
|
instructions = resolved.get("instructions") if isinstance(resolved, dict) else {}
|
|
68
151
|
request_config = {
|
|
69
152
|
"base_instructions": str((instructions or {}).get("system") or ""),
|
|
153
|
+
# Preserve system/task as separate PCM sources while keeping the
|
|
154
|
+
# framework runner's existing base_instructions projection.
|
|
155
|
+
"agent_system": str((instructions or {}).get("system") or ""),
|
|
156
|
+
"agent_task": str((instructions or {}).get("task") or ""),
|
|
157
|
+
**(
|
|
158
|
+
{"prompt_integration_mode": "ksadk_hosted"}
|
|
159
|
+
if _resolved_prompt_ownership(resolved) == "ksadk"
|
|
160
|
+
else {}
|
|
161
|
+
),
|
|
162
|
+
"context_engine_rollout": _resolved_context_engine_rollout(resolved),
|
|
163
|
+
"memory_recall_enabled": _resolved_memory_recall_enabled(resolved),
|
|
164
|
+
"memory_write_rollout": _resolved_memory_write_rollout(resolved),
|
|
165
|
+
"memory_enabled": _resolved_memory_enabled(resolved),
|
|
166
|
+
"memory_write_mode": _resolved_memory_write_mode(resolved),
|
|
167
|
+
"flush_before_compaction": _resolved_memory_flush_before_compaction(resolved),
|
|
168
|
+
"provider_ref": _resolved_memory_provider_ref(resolved),
|
|
70
169
|
"entry_point": detection.entry_point,
|
|
71
170
|
"agent_variable": detection.agent_variable,
|
|
72
171
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
172
|
+
# AgentVersion 的 ContextSpec 预算传到 Planner(方案 §8.2)
|
|
173
|
+
context_spec = resolved.get("context") if isinstance(resolved, dict) else {}
|
|
174
|
+
if isinstance(context_spec, dict):
|
|
175
|
+
max_input = context_spec.get("maxInputTokens") or context_spec.get("max_input_tokens")
|
|
176
|
+
reserve_output = context_spec.get("reserveOutputTokens") or context_spec.get(
|
|
177
|
+
"reserve_output_tokens"
|
|
76
178
|
)
|
|
179
|
+
if max_input is not None:
|
|
180
|
+
request_config["max_input_tokens"] = int(max_input)
|
|
181
|
+
if reserve_output is not None:
|
|
182
|
+
request_config["reserve_output_tokens"] = int(reserve_output)
|
|
183
|
+
if approval_mode:
|
|
184
|
+
request_config["tool_approval_mode"] = normalize_tool_approval_mode(approval_mode)
|
|
77
185
|
return StudioRunSpec(
|
|
78
186
|
launch_context=RuntimeLaunchContext(
|
|
79
187
|
runtime_type=runtime_type,
|
|
@@ -110,5 +218,158 @@ class FrameworkRunSpecResolver:
|
|
|
110
218
|
)
|
|
111
219
|
return selected
|
|
112
220
|
|
|
221
|
+
def _verify_bundle_integrity(
|
|
222
|
+
self,
|
|
223
|
+
bundle_dir: Path,
|
|
224
|
+
*,
|
|
225
|
+
expected_bundle_digest: str = "",
|
|
226
|
+
) -> None:
|
|
227
|
+
"""加载前校验 bundle 未被篡改:manifest 自身摘要、与 Build 记录一致、
|
|
228
|
+
文件清单无增删、每个文件 sha256/size 匹配。"""
|
|
229
|
+
try:
|
|
230
|
+
manifest = BundleManifest.model_validate_json(
|
|
231
|
+
(bundle_dir / "manifest.json").read_text(encoding="utf-8")
|
|
232
|
+
)
|
|
233
|
+
except (OSError, ValueError) as exc:
|
|
234
|
+
raise StudioError(
|
|
235
|
+
"BUILD_ARTIFACT_INVALID",
|
|
236
|
+
"Build 缺少有效的 Bundle Manifest",
|
|
237
|
+
status_code=500,
|
|
238
|
+
) from exc
|
|
239
|
+
if manifest.bundle_digest != compute_bundle_digest(manifest):
|
|
240
|
+
raise StudioError(
|
|
241
|
+
"BUILD_ARTIFACT_INVALID",
|
|
242
|
+
"Bundle Manifest 摘要不匹配,Bundle 可能已被篡改",
|
|
243
|
+
status_code=500,
|
|
244
|
+
details={"bundleDigest": manifest.bundle_digest},
|
|
245
|
+
)
|
|
246
|
+
if expected_bundle_digest and manifest.bundle_digest != expected_bundle_digest:
|
|
247
|
+
raise StudioError(
|
|
248
|
+
"BUILD_ARTIFACT_INVALID",
|
|
249
|
+
"Bundle 与 Build 记录的摘要不一致,Bundle 可能已被篡改",
|
|
250
|
+
status_code=500,
|
|
251
|
+
details={
|
|
252
|
+
"expected": expected_bundle_digest,
|
|
253
|
+
"actual": manifest.bundle_digest,
|
|
254
|
+
},
|
|
255
|
+
)
|
|
256
|
+
declared = {entry.path for entry in manifest.files}
|
|
257
|
+
actual: dict[str, Path] = {}
|
|
258
|
+
for path in bundle_dir.rglob("*"):
|
|
259
|
+
if not path.is_file():
|
|
260
|
+
continue
|
|
261
|
+
relative = path.relative_to(bundle_dir).as_posix()
|
|
262
|
+
if relative in self._BUNDLE_META_FILES:
|
|
263
|
+
continue
|
|
264
|
+
actual[relative] = path
|
|
265
|
+
extra = sorted(set(actual) - declared)
|
|
266
|
+
if extra:
|
|
267
|
+
raise StudioError(
|
|
268
|
+
"BUILD_ARTIFACT_INVALID",
|
|
269
|
+
"Bundle 含未在 Manifest 中声明的文件",
|
|
270
|
+
status_code=500,
|
|
271
|
+
details={"extraFiles": extra},
|
|
272
|
+
)
|
|
273
|
+
for entry in manifest.files:
|
|
274
|
+
file_path = actual.get(entry.path)
|
|
275
|
+
if file_path is None:
|
|
276
|
+
raise StudioError(
|
|
277
|
+
"BUILD_ARTIFACT_INVALID",
|
|
278
|
+
"Bundle 缺少 Manifest 声明的文件",
|
|
279
|
+
status_code=500,
|
|
280
|
+
details={"missingFile": entry.path},
|
|
281
|
+
)
|
|
282
|
+
content = file_path.read_bytes()
|
|
283
|
+
actual_sha = f"sha256:{hashlib.sha256(content).hexdigest()}"
|
|
284
|
+
if actual_sha != entry.sha256:
|
|
285
|
+
raise StudioError(
|
|
286
|
+
"BUILD_ARTIFACT_INVALID",
|
|
287
|
+
"Bundle 文件摘要不匹配",
|
|
288
|
+
status_code=500,
|
|
289
|
+
details={
|
|
290
|
+
"path": entry.path,
|
|
291
|
+
"expected": entry.sha256,
|
|
292
|
+
"actual": actual_sha,
|
|
293
|
+
},
|
|
294
|
+
)
|
|
295
|
+
if len(content) != entry.size:
|
|
296
|
+
raise StudioError(
|
|
297
|
+
"BUILD_ARTIFACT_INVALID",
|
|
298
|
+
"Bundle 文件大小不匹配",
|
|
299
|
+
status_code=500,
|
|
300
|
+
details={
|
|
301
|
+
"path": entry.path,
|
|
302
|
+
"expected": entry.size,
|
|
303
|
+
"actual": len(content),
|
|
304
|
+
},
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def _verify_bundle_security(bundle_dir: Path) -> None:
|
|
309
|
+
try:
|
|
310
|
+
manifest = BundleManifest.model_validate_json(
|
|
311
|
+
(bundle_dir / "manifest.json").read_text(encoding="utf-8")
|
|
312
|
+
)
|
|
313
|
+
except (OSError, ValueError):
|
|
314
|
+
# Integrity verification reports the canonical error for a malformed
|
|
315
|
+
# manifest; do not mask it with a second diagnostic path.
|
|
316
|
+
return
|
|
317
|
+
if manifest.bundle_format != "agentkit.bundle/v2":
|
|
318
|
+
return
|
|
319
|
+
try:
|
|
320
|
+
assert_bundle_security(bundle_dir)
|
|
321
|
+
except BundleSecurityError as exc:
|
|
322
|
+
raise StudioError(
|
|
323
|
+
"BUILD_ARTIFACT_INVALID",
|
|
324
|
+
"Bundle 包含不允许的明文凭证或本机路径",
|
|
325
|
+
status_code=422,
|
|
326
|
+
details={
|
|
327
|
+
"securityFindings": [
|
|
328
|
+
{
|
|
329
|
+
"path": finding.path,
|
|
330
|
+
"kind": finding.kind,
|
|
331
|
+
**({"field": finding.field} if finding.field else {}),
|
|
332
|
+
}
|
|
333
|
+
for finding in exc.findings
|
|
334
|
+
]
|
|
335
|
+
},
|
|
336
|
+
) from exc
|
|
337
|
+
|
|
113
338
|
|
|
114
339
|
__all__ = ["FrameworkRunSpecResolver"]
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _resolved_memory_enabled(resolved: Any) -> bool:
|
|
343
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
344
|
+
return bool(memory.get("enabled", False)) if isinstance(memory, dict) else False
|
|
345
|
+
|
|
346
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
347
|
+
if not isinstance(memory, dict) or not memory.get("enabled", False):
|
|
348
|
+
return False
|
|
349
|
+
recall = memory.get("recall", {})
|
|
350
|
+
return bool(recall.get("enabled", True)) if isinstance(recall, dict) else True
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def _resolved_memory_write_mode(resolved: Any) -> str:
|
|
354
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
355
|
+
write = memory.get("write", {}) if isinstance(memory, dict) else {}
|
|
356
|
+
return (
|
|
357
|
+
str(write.get("mode", "candidate") or "candidate")
|
|
358
|
+
if isinstance(write, dict)
|
|
359
|
+
else "candidate"
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def _resolved_memory_flush_before_compaction(resolved: Any) -> bool:
|
|
364
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
365
|
+
write = memory.get("write", {}) if isinstance(memory, dict) else {}
|
|
366
|
+
return bool(write.get("flushBeforeCompaction", True)) if isinstance(write, dict) else True
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _resolved_memory_provider_ref(resolved: Any) -> str:
|
|
370
|
+
memory = resolved.get("memory") if isinstance(resolved, dict) else {}
|
|
371
|
+
return (
|
|
372
|
+
str(memory.get("providerRef", "local-default") or "local-default")
|
|
373
|
+
if isinstance(memory, dict)
|
|
374
|
+
else "local-default"
|
|
375
|
+
)
|