agentengine-sdk-python 0.8.0__py3-none-any.whl → 0.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
- agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
- ksadk/a2a/__init__.py +2 -0
- ksadk/a2a/_space_client_events.py +381 -0
- ksadk/a2a/bootstrap.py +0 -2
- ksadk/a2a/card.py +6 -111
- ksadk/a2a/control_plane.py +239 -1
- ksadk/a2a/event_adapter.py +156 -64
- ksadk/a2a/executor.py +195 -172
- ksadk/a2a/routes.py +12 -5
- ksadk/a2a/server.py +1 -8
- ksadk/a2a/service_env.py +33 -0
- ksadk/a2a/space_client.py +43 -349
- ksadk/a2a_card.py +101 -0
- ksadk/a2ui/core.py +222 -53
- ksadk/agui/_agent_helpers.py +243 -0
- ksadk/agui/a2ui_projection.py +12 -5
- ksadk/agui/agent.py +474 -275
- ksadk/agui/config.py +11 -5
- ksadk/agui/routes.py +7 -15
- ksadk/api/client.py +530 -40
- ksadk/api/environment.py +27 -0
- ksadk/builders/code_builder.py +352 -53
- ksadk/builders/container_builder.py +71 -44
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +2 -2
- ksadk/builders/managed_runtime_builder.py +60 -28
- ksadk/cli/__init__.py +25 -0
- ksadk/cli/cmd_a2a.py +18 -31
- ksadk/cli/cmd_create.py +13 -26
- ksadk/cli/cmd_dashboard.py +15 -1
- ksadk/cli/cmd_deploy.py +28 -3
- ksadk/cli/cmd_eval.py +443 -0
- ksadk/cli/cmd_evalset.py +284 -0
- ksadk/cli/cmd_files.py +5 -1
- ksadk/cli/cmd_hermes.py +137 -163
- ksadk/cli/cmd_invoke.py +28 -38
- ksadk/cli/cmd_launch.py +12 -0
- ksadk/cli/cmd_managed_runtime.py +95 -0
- ksadk/cli/cmd_observe.py +85 -0
- ksadk/cli/cmd_openclaw.py +85 -479
- ksadk/cli/cmd_replay.py +28 -4
- ksadk/cli/cmd_run.py +29 -67
- ksadk/cli/cmd_studio.py +201 -0
- ksadk/cli/cmd_web.py +15 -6
- ksadk/cli/dry_run.py +2 -1
- ksadk/cli/env_options.py +83 -0
- ksadk/cli/global_options.py +3 -1
- ksadk/cli/hermes_env.py +151 -0
- ksadk/cli/invoke_payload.py +49 -0
- ksadk/cli/network_options.py +7 -5
- ksadk/cli/openclaw_env.py +458 -0
- ksadk/cli/runtime_bootstrap.py +51 -0
- ksadk/cli/ui.py +6 -0
- ksadk/cli/workflow_common.py +5 -5
- ksadk/codex/__init__.py +3 -3
- ksadk/codex/client.py +833 -49
- ksadk/codex/phase.py +1 -1
- ksadk/codex/runtime.py +720 -127
- ksadk/common/kop_client.py +232 -0
- ksadk/configs/__init__.py +1 -3
- ksadk/configs/env_registry.py +244 -45
- ksadk/configs/env_registry_pcm.py +181 -0
- ksadk/configs/env_var_spec.py +18 -0
- ksadk/configs/global_config.py +6 -1
- ksadk/configs/settings.py +5 -108
- ksadk/context_engine/__init__.py +98 -0
- ksadk/context_engine/assembler.py +176 -0
- ksadk/context_engine/baseline.py +419 -0
- ksadk/context_engine/cache_observability.py +228 -0
- ksadk/context_engine/capabilities.py +443 -0
- ksadk/context_engine/contributors.py +344 -0
- ksadk/context_engine/hosted_pipeline.py +417 -0
- ksadk/context_engine/models.py +117 -0
- ksadk/context_engine/planner.py +698 -0
- ksadk/context_engine/policies.py +319 -0
- ksadk/context_engine/projection.py +31 -0
- ksadk/context_engine/shadow_plan.py +266 -0
- ksadk/context_engine/tokenizer.py +164 -0
- ksadk/conversations/__init__.py +85 -94
- ksadk/conversations/context.py +126 -6
- ksadk/conversations/message_projection.py +292 -28
- ksadk/conversations/model_context.py +49 -3
- ksadk/conversations/runtime_compaction.py +207 -5
- ksadk/conversations/runtime_input.py +193 -3
- ksadk/conversations/runtime_invocation.py +81 -3
- ksadk/conversations/runtime_observability.py +157 -4
- ksadk/conversations/runtime_payloads.py +42 -0
- ksadk/conversations/runtime_preparation.py +280 -2
- ksadk/conversations/runtime_resume.py +71 -32
- ksadk/conversations/runtime_stream_events.py +94 -9
- ksadk/conversations/runtime_streaming.py +175 -22
- ksadk/conversations/semantic_summary.py +311 -1
- ksadk/conversations/session_lock.py +51 -0
- ksadk/deployment/env_forward.py +72 -0
- ksadk/deployment/managed_runtime.py +38 -0
- ksadk/deployment/manager.py +24 -8
- ksadk/deployment/providers/serverless.py +228 -92
- ksadk/evaluation/__init__.py +116 -0
- ksadk/evaluation/a2a_adapter.py +452 -0
- ksadk/evaluation/adapters.py +67 -0
- ksadk/evaluation/agent_eval_client.py +395 -0
- ksadk/evaluation/cloud_binding.py +80 -0
- ksadk/evaluation/cloud_converter.py +194 -0
- ksadk/evaluation/cloud_service.py +199 -0
- ksadk/evaluation/contracts.py +478 -0
- ksadk/evaluation/evalset.py +351 -0
- ksadk/evaluation/evaluators.py +627 -0
- ksadk/evaluation/evidence.py +258 -0
- ksadk/evaluation/executor.py +143 -0
- ksadk/evaluation/local_adapter.py +550 -0
- ksadk/evaluation/service_env.py +27 -0
- ksadk/evaluation/storage.py +68 -0
- ksadk/evaluation/studio_build_adapter.py +253 -0
- ksadk/evaluation/target.py +82 -0
- ksadk/events/__init__.py +13 -13
- ksadk/events/_v1_compat/__init__.py +1 -0
- ksadk/events/_v1_compat/models.py +299 -0
- ksadk/events/_v1_compat/parser.py +247 -0
- ksadk/events/_v1_compat/projection.py +753 -0
- ksadk/events/adapters/__init__.py +34 -0
- ksadk/events/adapters/_a2a_snapshot.py +622 -0
- ksadk/events/adapters/_a2a_support.py +275 -0
- ksadk/events/adapters/_codex_interactions.py +375 -0
- ksadk/events/adapters/_codex_items.py +801 -0
- ksadk/events/adapters/_codex_validators.py +311 -0
- ksadk/events/adapters/_langgraph_support.py +785 -0
- ksadk/events/adapters/a2a.py +841 -0
- ksadk/events/adapters/adk.py +503 -0
- ksadk/events/adapters/codex.py +717 -0
- ksadk/events/adapters/langgraph.py +745 -0
- ksadk/events/canonical.py +440 -0
- ksadk/events/canonical_replay.py +497 -0
- ksadk/events/canonical_store.py +468 -0
- ksadk/events/cold_recovery.py +257 -0
- ksadk/events/content.py +89 -0
- ksadk/events/identity.py +86 -0
- ksadk/events/pipeline.py +455 -0
- ksadk/events/projections.py +66 -0
- ksadk/events/reducer.py +661 -0
- ksadk/events/replay.py +3 -36
- ksadk/events/runtime_event.py +20 -256
- ksadk/events/session_event.py +324 -0
- ksadk/events/store.py +3 -316
- ksadk/events/v1_compat.py +41 -0
- ksadk/harness/__init__.py +3 -2
- ksadk/harness/app.py +114 -123
- ksadk/harness/config.py +1 -1
- ksadk/harness/runtime.py +467 -0
- ksadk/hermes_terminal.py +5 -0
- ksadk/identity/resolver.py +4 -3
- ksadk/interaction/__init__.py +28 -0
- ksadk/interaction/contracts.py +136 -0
- ksadk/interaction/ledger.py +189 -0
- ksadk/interaction/provider.py +122 -0
- ksadk/interaction/providers/__init__.py +52 -0
- ksadk/interaction/providers/adk.py +40 -0
- ksadk/interaction/providers/codex.py +94 -0
- ksadk/interaction/providers/langgraph.py +58 -0
- ksadk/kernel/__init__.py +117 -0
- ksadk/kernel/authorization.py +258 -0
- ksadk/kernel/bootstrap.py +1074 -0
- ksadk/kernel/contract_fingerprints.py +61 -0
- ksadk/kernel/contracts.py +362 -0
- ksadk/kernel/control.py +219 -0
- ksadk/kernel/errors.py +79 -0
- ksadk/kernel/ingress.py +1102 -0
- ksadk/kernel/mapping.py +111 -0
- ksadk/kernel/memory_store.py +1133 -0
- ksadk/kernel/postgres_store.py +1756 -0
- ksadk/kernel/recovery.py +452 -0
- ksadk/kernel/runtime_identity.py +103 -0
- ksadk/kernel/sql/001_agent_kernel.sql +120 -0
- ksadk/kernel/sqlite_store.py +1410 -0
- ksadk/kernel/state.py +145 -0
- ksadk/kernel/store.py +232 -0
- ksadk/kernel/worker.py +953 -0
- ksadk/knowledge_base/client.py +22 -4
- ksadk/knowledge_base/service.py +32 -5
- ksadk/managed_a2a_card.py +160 -0
- ksadk/managed_runtime.py +16 -9
- ksadk/memory/__init__.py +61 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
- ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
- ksadk/memory/adk/backends/sdk_ltm_backend.py +394 -5
- ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
- ksadk/memory/adk/long_term_memory.py +3 -2
- ksadk/memory/coordinator.py +461 -0
- ksadk/memory/events.py +202 -0
- ksadk/memory/extraction.py +228 -0
- ksadk/memory/ltm_backend_factory.py +16 -3
- ksadk/memory/models.py +316 -0
- ksadk/memory/policy.py +215 -0
- ksadk/memory/provider.py +47 -0
- ksadk/memory/provider_adapter.py +159 -0
- ksadk/memory/provider_resolver.py +71 -0
- ksadk/memory/providers/__init__.py +5 -0
- ksadk/memory/providers/local_sqlite.py +490 -0
- ksadk/memory/resolved_policy.py +145 -0
- ksadk/memory/service.py +198 -8
- ksadk/memory/tool.py +4 -0
- ksadk/model_proxy/bootstrap.py +16 -9
- ksadk/model_proxy/config.py +22 -1
- ksadk/model_proxy/detect.py +202 -9
- ksadk/model_proxy/namespace.py +67 -15
- ksadk/model_proxy/server.py +168 -6
- ksadk/model_proxy/transform.py +105 -3
- ksadk/observability/__init__.py +25 -0
- ksadk/observability/session_log.py +420 -0
- ksadk/observability/trajectory.py +105 -0
- ksadk/prompts/__init__.py +71 -0
- ksadk/prompts/compiler.py +215 -0
- ksadk/prompts/models.py +82 -0
- ksadk/prompts/projection.py +89 -0
- ksadk/prompts/resolved.py +137 -0
- ksadk/prompts/sources.py +233 -0
- ksadk/runners/_langgraph_runner_streams.py +822 -0
- ksadk/runners/adk_runner.py +14 -31
- ksadk/runners/base_runner.py +44 -3
- ksadk/runners/factory.py +3 -3
- ksadk/runners/langgraph_runner.py +252 -433
- ksadk/runners/utils/__init__.py +0 -10
- ksadk/runners/utils/loader.py +16 -0
- ksadk/runtime/__init__.py +67 -41
- ksadk/runtime/_runner_adapter/__init__.py +1 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
- ksadk/runtime/adapter.py +199 -16
- ksadk/runtime/conversation_execution.py +687 -0
- ksadk/runtime/executor.py +392 -0
- ksadk/runtime/factory.py +342 -0
- ksadk/runtime/framework_adapters.py +6 -12
- ksadk/runtime/hosted_finalizer.py +268 -0
- ksadk/runtime/launch.py +61 -0
- ksadk/runtime/preprocessing.py +49 -14
- ksadk/runtime/runner_adapter.py +330 -391
- ksadk/runtime/runner_loading.py +36 -0
- ksadk/runtime/usage.py +33 -0
- ksadk/sandbox/backends/e2b.py +36 -3
- ksadk/server/__init__.py +39 -4
- ksadk/server/app.py +18 -492
- ksadk/server/composition.py +36 -2
- ksadk/server/factory.py +210 -149
- ksadk/server/routes/common.py +15 -46
- ksadk/server/routes/control.py +13 -9
- ksadk/server/routes/kernel_ingress.py +258 -0
- ksadk/server/routes/misc.py +10 -33
- ksadk/server/routes/models.py +14 -6
- ksadk/server/routes/openai_compat.py +129 -27
- ksadk/server/routes/projection.py +84 -16
- ksadk/server/routes/run.py +347 -460
- ksadk/server/routes/sessions.py +37 -40
- ksadk/server/routes/streaming.py +52 -7
- ksadk/server/routes/workspace.py +54 -21
- ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
- ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
- ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
- ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
- ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
- ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
- ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
- ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
- ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
- ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
- ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
- ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
- ksadk/server/static/assets/{chunk-FMBD7UC4-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
- ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
- ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
- ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
- ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
- ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
- ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
- ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-CX3yotHq.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
- ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
- ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
- ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
- ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
- ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
- ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
- ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
- ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
- ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
- ksadk/server/static/assets/{dist-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
- ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
- ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
- ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
- ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
- ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
- ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
- ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
- ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
- ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
- ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
- ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
- ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
- ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
- ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
- ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
- ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
- ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
- ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
- ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
- ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
- ksadk/server/static/assets/{dist-C99THtIA.js → dist-ngtN0DJB.js} +1 -1
- ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
- ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
- ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
- ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
- ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
- ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
- ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
- ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
- ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
- ksadk/server/static/assets/{linear-CvMBw9cA.js → linear-BHjG8b-J.js} +1 -1
- ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-CSAQxEAe.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
- ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
- ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
- ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
- ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-CxIR4JXI.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
- ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
- ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
- ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
- ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
- ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
- ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-jqoYs3jQ.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
- ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
- ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
- ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
- ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
- ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
- ksadk/server/static/index.html +2 -2
- ksadk/sessions/__init__.py +26 -9
- ksadk/sessions/_local_service_sync.py +688 -0
- ksadk/sessions/_local_tables.py +21 -0
- ksadk/sessions/_postgres_schema.py +305 -0
- ksadk/sessions/_postgres_tables.py +15 -0
- ksadk/sessions/base.py +80 -1
- ksadk/sessions/in_memory.py +53 -2
- ksadk/sessions/local_service.py +63 -604
- ksadk/sessions/postgres_service.py +58 -148
- ksadk/sessions/resilient.py +35 -1
- ksadk/skills/runtime/backends/e2b.py +1 -1
- ksadk/skills/service_client.py +13 -3
- ksadk/studio/__init__.py +5 -0
- ksadk/studio/agent_avatar_assets.py +120 -0
- ksadk/studio/agent_lifecycle.py +51 -0
- ksadk/studio/api.py +1598 -0
- ksadk/studio/api_catalog_routes.py +324 -0
- ksadk/studio/api_contracts.py +286 -0
- ksadk/studio/api_helpers.py +132 -0
- ksadk/studio/api_memory_routes.py +82 -0
- ksadk/studio/authoring.py +749 -0
- ksadk/studio/authoring_coordinator.py +1017 -0
- ksadk/studio/builder.py +397 -0
- ksadk/studio/capabilities.py +368 -0
- ksadk/studio/cloud.py +2099 -0
- ksadk/studio/codex_agent_service.py +694 -0
- ksadk/studio/codex_authoring.py +469 -0
- ksadk/studio/codex_builder.py +437 -0
- ksadk/studio/codex_manifest.py +307 -0
- ksadk/studio/codex_run.py +395 -0
- ksadk/studio/compiler.py +190 -0
- ksadk/studio/contracts.py +755 -0
- ksadk/studio/errors.py +47 -0
- ksadk/studio/event_store.py +214 -0
- ksadk/studio/framework_run.py +342 -0
- ksadk/studio/hosted_kernel.py +317 -0
- ksadk/studio/identifiers.py +33 -0
- ksadk/studio/manifest_resolver.py +131 -0
- ksadk/studio/mcp_runtime.py +229 -0
- ksadk/studio/model_client.py +629 -0
- ksadk/studio/model_profile_service.py +214 -0
- ksadk/studio/operations.py +275 -0
- ksadk/studio/otel_trace.py +1060 -0
- ksadk/studio/pagination.py +182 -0
- ksadk/studio/pcm_memory.py +85 -0
- ksadk/studio/python_tool_inspection.py +183 -0
- ksadk/studio/repository.py +327 -0
- ksadk/studio/resource_catalog.py +1260 -0
- ksadk/studio/run_service.py +1133 -0
- ksadk/studio/runtime_catalog.py +74 -0
- ksadk/studio/runtime_source.py +365 -0
- ksadk/studio/service.py +2249 -0
- ksadk/studio/shared_web.py +1004 -0
- ksadk/studio/skill_discovery.py +628 -0
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
- ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
- ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
- ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
- ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- ksadk/studio/static/index.html +15 -0
- ksadk/studio/templates.py +722 -0
- ksadk/studio/validator.py +265 -0
- ksadk/studio/workspace.py +135 -0
- ksadk/tools/gateway.py +9 -0
- ksadk/toolsets/__init__.py +27 -1
- ksadk/toolsets/a2a.py +426 -0
- ksadk/tracing/__init__.py +19 -21
- ksadk/tracing/setup.py +317 -403
- ksadk/tracing/span_utils.py +0 -44
- ksadk/version.py +1 -1
- ksadk_runtime_common/memory_backend/registry.py +56 -56
- ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
- ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
- ksadk_runtime_common/workspace_files/router.py +8 -2
- agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
- ksadk/a2a/card_builder.py +0 -64
- ksadk/a2a/client.py +0 -309
- ksadk/events/parser.py +0 -191
- ksadk/harness/runner.py +0 -211
- ksadk/runners/codex_runner.py +0 -132
- ksadk/runners/utils/langfuse.py +0 -230
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
- ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
- ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
- ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
- ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
- ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
- ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
- ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
- ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
- ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
- ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
- ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
- ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
- ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
- ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
- ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
- ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
- ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
- ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
- ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
- ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
- ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
- ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
- ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
- ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
- ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
- ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
- ksadk/server/static/assets/katex-DATssjp1.js +0 -265
- ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
- ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
- ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
- ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
- ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
- ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
- ksadk/tracing/exporters/langfuse_exporter.py +0 -460
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
"""Resolve an immutable Codex build into a canonical StudioRunSpec."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import zipfile
|
|
7
|
+
from typing import Any, cast
|
|
8
|
+
|
|
9
|
+
import yaml # type: ignore[import-untyped]
|
|
10
|
+
|
|
11
|
+
from ksadk.configs import ModelConfig
|
|
12
|
+
from ksadk.runtime import RuntimeLaunchContext
|
|
13
|
+
from ksadk.studio.codex_builder import CodexBuildRepository
|
|
14
|
+
from ksadk.studio.codex_manifest import CodexAgentManifest, CodexManifestRepository
|
|
15
|
+
from ksadk.studio.contracts import ModelSpec
|
|
16
|
+
from ksadk.studio.errors import StudioError
|
|
17
|
+
from ksadk.studio.run_service import StudioRunSpec
|
|
18
|
+
from ksadk.studio.workspace import Workspace
|
|
19
|
+
from ksadk.tools.gateway import normalize_tool_approval_mode
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CodexRunSpecResolver:
|
|
23
|
+
"""Validate a build snapshot without creating another Runtime abstraction."""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
workspace: Workspace,
|
|
28
|
+
*,
|
|
29
|
+
build_repository: CodexBuildRepository | None = None,
|
|
30
|
+
manifest_repository: CodexManifestRepository | None = None,
|
|
31
|
+
credential_resolver: Any = None,
|
|
32
|
+
resource_catalog: Any = None,
|
|
33
|
+
draft_repository: Any = None,
|
|
34
|
+
) -> None:
|
|
35
|
+
self.workspace = workspace
|
|
36
|
+
self.builds = build_repository or CodexBuildRepository(workspace)
|
|
37
|
+
self.manifests = manifest_repository or CodexManifestRepository(workspace)
|
|
38
|
+
self.credentials = credential_resolver
|
|
39
|
+
self.catalog = resource_catalog
|
|
40
|
+
self.drafts = draft_repository
|
|
41
|
+
|
|
42
|
+
def resolve(
|
|
43
|
+
self,
|
|
44
|
+
build_id: str,
|
|
45
|
+
*,
|
|
46
|
+
model: str | None = None,
|
|
47
|
+
sandbox: str | None = None,
|
|
48
|
+
approval_mode: str | None = None,
|
|
49
|
+
) -> StudioRunSpec:
|
|
50
|
+
build = self.builds.get(build_id)
|
|
51
|
+
current = self.manifests.load(build.agent_name)
|
|
52
|
+
if build.manifest_sha256 != current.manifest_sha256:
|
|
53
|
+
raise StudioError(
|
|
54
|
+
"CODEX_BUILD_STALE",
|
|
55
|
+
"agentengine.yaml 已修改,请重新构建后再运行",
|
|
56
|
+
status_code=409,
|
|
57
|
+
details={
|
|
58
|
+
"buildManifestSha256": build.manifest_sha256,
|
|
59
|
+
"currentManifestSha256": current.manifest_sha256,
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
manifest = self._load_build_manifest(build.artifact_path)
|
|
63
|
+
selected_model = self._select_model(manifest, model)
|
|
64
|
+
project_dir = self.workspace.root.resolve()
|
|
65
|
+
skills = self._skill_inputs(manifest)
|
|
66
|
+
codex_overrides = self._mcp_overrides(manifest)
|
|
67
|
+
approval_profile = normalize_tool_approval_mode(approval_mode) if approval_mode else ""
|
|
68
|
+
sandbox, approval = self._resolve_sandbox(
|
|
69
|
+
manifest,
|
|
70
|
+
override=sandbox,
|
|
71
|
+
approval_mode=approval_profile or None,
|
|
72
|
+
)
|
|
73
|
+
if sandbox == "workspace-write":
|
|
74
|
+
# workspace-write 默认断网;MCP/搜索类工具需要显式放行网络
|
|
75
|
+
codex_overrides = [*codex_overrides, "sandbox_workspace_write.network_access=true"]
|
|
76
|
+
launch_config: dict[str, Any] = {
|
|
77
|
+
"sandbox_read_only": sandbox == "read-only",
|
|
78
|
+
"sandbox": sandbox,
|
|
79
|
+
"approval_mode": approval,
|
|
80
|
+
}
|
|
81
|
+
if codex_overrides:
|
|
82
|
+
launch_config["codex_overrides"] = codex_overrides
|
|
83
|
+
runtime_env = {
|
|
84
|
+
**self._resolve_model_env(build, manifest, selected_model),
|
|
85
|
+
**self._resolve_mcp_env(manifest),
|
|
86
|
+
}
|
|
87
|
+
if runtime_env:
|
|
88
|
+
launch_config["env"] = runtime_env
|
|
89
|
+
agent_task = str(manifest.task_prompt or "").strip()
|
|
90
|
+
# PCM 策略从不可变 Manifest 读取(方案 §5.1:Build 锁定后 sidecar 修改不影响旧 Build)
|
|
91
|
+
# manifest.context/memory 由 _manifest() 从 AgentSpec 写入,随 Build 进入 Artifact
|
|
92
|
+
resolved_context = manifest.context
|
|
93
|
+
resolved_memory = manifest.memory
|
|
94
|
+
base_instructions = manifest.prompt
|
|
95
|
+
if agent_task:
|
|
96
|
+
base_instructions = f"{manifest.prompt}\n\n{agent_task}"
|
|
97
|
+
request_config: dict[str, Any] = {
|
|
98
|
+
# Codex 原生只接收 base_instructions,因此运行前合并;PCM 证据仍使用下面
|
|
99
|
+
# 两个独立来源生成 agent_identity / agent_policy 的分段 hash。
|
|
100
|
+
"base_instructions": base_instructions,
|
|
101
|
+
"agent_system": manifest.prompt,
|
|
102
|
+
"agent_task": agent_task,
|
|
103
|
+
"cwd": str(project_dir),
|
|
104
|
+
"skills": skills,
|
|
105
|
+
"sandbox_read_only": sandbox == "read-only",
|
|
106
|
+
"sandbox": sandbox,
|
|
107
|
+
"approval_mode": approval,
|
|
108
|
+
"summary": "auto",
|
|
109
|
+
# Studio sessions resume the same native Codex thread across turns.
|
|
110
|
+
"ephemeral": False,
|
|
111
|
+
# PCM 配置(方案 §5.1):从 Manifest 读取预算和 rollout
|
|
112
|
+
"max_input_tokens": resolved_context.max_input_tokens if resolved_context else None,
|
|
113
|
+
"reserve_output_tokens": (
|
|
114
|
+
resolved_context.reserve_output_tokens if resolved_context else None
|
|
115
|
+
),
|
|
116
|
+
"context_engine_rollout": (
|
|
117
|
+
resolved_context.rollout.context_engine if resolved_context else None
|
|
118
|
+
),
|
|
119
|
+
"memory_recall_enabled": (resolved_memory.recall.enabled if resolved_memory else None),
|
|
120
|
+
"memory_recall_top_k": resolved_memory.recall.top_k if resolved_memory else None,
|
|
121
|
+
"memory_recall_max_tokens": (
|
|
122
|
+
resolved_memory.recall.max_tokens if resolved_memory else None
|
|
123
|
+
),
|
|
124
|
+
"memory_recall_min_score": (
|
|
125
|
+
resolved_memory.recall.min_score if resolved_memory else None
|
|
126
|
+
),
|
|
127
|
+
"memory_write_rollout": (
|
|
128
|
+
resolved_context.rollout.memory_write if resolved_context else None
|
|
129
|
+
),
|
|
130
|
+
"memory_enabled": resolved_memory.enabled if resolved_memory else False,
|
|
131
|
+
"memory_write_mode": resolved_memory.write.mode if resolved_memory else "candidate",
|
|
132
|
+
"flush_before_compaction": (
|
|
133
|
+
resolved_memory.write.flush_before_compaction if resolved_memory else True
|
|
134
|
+
),
|
|
135
|
+
"provider_ref": resolved_memory.provider_ref if resolved_memory else "local-default",
|
|
136
|
+
}
|
|
137
|
+
if approval_profile:
|
|
138
|
+
request_config["tool_approval_mode"] = approval_profile
|
|
139
|
+
return StudioRunSpec(
|
|
140
|
+
launch_context=RuntimeLaunchContext(
|
|
141
|
+
runtime_type="codex",
|
|
142
|
+
project_dir=project_dir,
|
|
143
|
+
config=launch_config,
|
|
144
|
+
),
|
|
145
|
+
build_id=build.id,
|
|
146
|
+
agent_id=manifest.name,
|
|
147
|
+
model=selected_model,
|
|
148
|
+
request_config=request_config,
|
|
149
|
+
manifest_sha256=build.manifest_sha256,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def _resolve_model_env(
|
|
153
|
+
self,
|
|
154
|
+
build: Any,
|
|
155
|
+
manifest: CodexAgentManifest,
|
|
156
|
+
selected_model: str,
|
|
157
|
+
) -> dict[str, str]:
|
|
158
|
+
resolver = self.credentials
|
|
159
|
+
if resolver is None:
|
|
160
|
+
from ksadk.studio.model_client import CredentialResolver
|
|
161
|
+
|
|
162
|
+
resolver = CredentialResolver(self.workspace)
|
|
163
|
+
self.credentials = resolver
|
|
164
|
+
profile = self._resolve_model_profile(build, manifest, selected_model)
|
|
165
|
+
credential_ref = profile.credential_ref if profile else "env://OPENAI_API_KEY"
|
|
166
|
+
try:
|
|
167
|
+
credential = resolver.resolve(credential_ref)
|
|
168
|
+
except StudioError:
|
|
169
|
+
return {}
|
|
170
|
+
base_url = (
|
|
171
|
+
self._model_base_url(profile)
|
|
172
|
+
if profile is not None
|
|
173
|
+
else ModelConfig().api_base.rstrip("/")
|
|
174
|
+
)
|
|
175
|
+
return {
|
|
176
|
+
"OPENAI_API_KEY": credential,
|
|
177
|
+
"OPENAI_BASE_URL": base_url,
|
|
178
|
+
"OPENAI_API_BASE": base_url,
|
|
179
|
+
"OPENAI_MODEL_NAME": selected_model,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
def _resolve_model_profile(
|
|
183
|
+
self,
|
|
184
|
+
build: Any,
|
|
185
|
+
manifest: CodexAgentManifest,
|
|
186
|
+
selected_model: str,
|
|
187
|
+
) -> ModelSpec | None:
|
|
188
|
+
# New build records own an immutable connection snapshot. An empty
|
|
189
|
+
# mapping explicitly means this build uses the process/workspace
|
|
190
|
+
# default connection; only legacy records may consult live Catalog
|
|
191
|
+
# state for backward compatibility.
|
|
192
|
+
snapshots = getattr(build, "model_profiles", None)
|
|
193
|
+
if snapshots is not None:
|
|
194
|
+
payload = snapshots.get(selected_model)
|
|
195
|
+
return ModelSpec.model_validate(payload) if payload is not None else None
|
|
196
|
+
|
|
197
|
+
if self.catalog is None:
|
|
198
|
+
from ksadk.studio.resource_catalog import LocalResourceCatalog
|
|
199
|
+
|
|
200
|
+
self.catalog = LocalResourceCatalog(self.workspace)
|
|
201
|
+
if self.drafts is None:
|
|
202
|
+
from ksadk.studio.codex_agent_service import CodexDraftRepository
|
|
203
|
+
|
|
204
|
+
self.drafts = CodexDraftRepository(self.workspace)
|
|
205
|
+
|
|
206
|
+
draft = self.drafts.get(manifest.name)
|
|
207
|
+
if draft is not None:
|
|
208
|
+
bindings = draft.spec.bindings
|
|
209
|
+
resource_ids = list(bindings.model_profile_ids)
|
|
210
|
+
if not resource_ids and bindings.model_profile_id:
|
|
211
|
+
resource_ids = [bindings.model_profile_id]
|
|
212
|
+
for resource_id in resource_ids:
|
|
213
|
+
try:
|
|
214
|
+
descriptor = self.catalog.get(resource_id)
|
|
215
|
+
profile = ModelSpec.model_validate(descriptor.contract)
|
|
216
|
+
except (StudioError, ValueError):
|
|
217
|
+
continue
|
|
218
|
+
if profile.model == selected_model:
|
|
219
|
+
return profile
|
|
220
|
+
|
|
221
|
+
matches: list[ModelSpec] = []
|
|
222
|
+
for descriptor in self.catalog.list(kind="model", limit=500):
|
|
223
|
+
try:
|
|
224
|
+
profile = ModelSpec.model_validate(descriptor.contract)
|
|
225
|
+
except ValueError:
|
|
226
|
+
continue
|
|
227
|
+
if profile.model == selected_model:
|
|
228
|
+
matches.append(profile)
|
|
229
|
+
return matches[0] if len(matches) == 1 else None
|
|
230
|
+
|
|
231
|
+
@staticmethod
|
|
232
|
+
def _model_base_url(profile: ModelSpec) -> str:
|
|
233
|
+
raw = str(profile.base_url or profile.endpoint_url or "").rstrip("/")
|
|
234
|
+
for suffix in ("/chat/completions", "/responses"):
|
|
235
|
+
if raw.endswith(suffix):
|
|
236
|
+
return raw[: -len(suffix)]
|
|
237
|
+
return raw
|
|
238
|
+
|
|
239
|
+
@staticmethod
|
|
240
|
+
def _mcp_overrides(manifest: CodexAgentManifest) -> list[str]:
|
|
241
|
+
"""Translate bound MCP servers into codex --config overrides."""
|
|
242
|
+
overrides: list[str] = []
|
|
243
|
+
for server in manifest.mcp_servers or []:
|
|
244
|
+
name = str(server.get("name") or "").strip()
|
|
245
|
+
url = str(server.get("url") or "").strip()
|
|
246
|
+
if not name or not url:
|
|
247
|
+
continue
|
|
248
|
+
overrides.append(f"mcp_servers.{name}.url={url}")
|
|
249
|
+
env_key = str(server.get("env_key") or "").strip()
|
|
250
|
+
if env_key:
|
|
251
|
+
overrides.append(f"mcp_servers.{name}.bearer_token_env_var={env_key}")
|
|
252
|
+
return overrides
|
|
253
|
+
|
|
254
|
+
def _resolve_mcp_env(self, manifest: CodexAgentManifest) -> dict[str, str]:
|
|
255
|
+
"""把 manifest 中 MCP 的 env_key 解析为真实值,注入 codex 子进程环境。
|
|
256
|
+
|
|
257
|
+
codex app-server 的 bearer_token_env_var 直接读子进程环境变量,不经过
|
|
258
|
+
Studio 的凭证解析链(session → 工作区 secrets.env → 环境变量),必须在
|
|
259
|
+
启动前完成解析。缺凭证时快速失败并指出具体引用。
|
|
260
|
+
"""
|
|
261
|
+
env: dict[str, str] = {}
|
|
262
|
+
for server in manifest.mcp_servers or []:
|
|
263
|
+
env_key = str(server.get("env_key") or "").strip()
|
|
264
|
+
if not env_key:
|
|
265
|
+
continue
|
|
266
|
+
if env_key in env:
|
|
267
|
+
continue
|
|
268
|
+
resolver = self.credentials
|
|
269
|
+
if resolver is None:
|
|
270
|
+
from ksadk.studio.model_client import CredentialResolver
|
|
271
|
+
|
|
272
|
+
resolver = CredentialResolver(self.workspace)
|
|
273
|
+
self.credentials = resolver
|
|
274
|
+
try:
|
|
275
|
+
env[env_key] = resolver.resolve(f"env://{env_key}")
|
|
276
|
+
except Exception as exc:
|
|
277
|
+
raise StudioError(
|
|
278
|
+
"MCP_CREDENTIAL_MISSING",
|
|
279
|
+
f"MCP Server「{server.get('name')}」需要凭证 {env_key},"
|
|
280
|
+
"请先在 MCP 页连接时保存该环境变量的值",
|
|
281
|
+
status_code=422,
|
|
282
|
+
details={
|
|
283
|
+
"server": str(server.get("name") or ""),
|
|
284
|
+
"reference": f"env://{env_key}",
|
|
285
|
+
},
|
|
286
|
+
) from exc
|
|
287
|
+
return env
|
|
288
|
+
|
|
289
|
+
@staticmethod
|
|
290
|
+
def _resolve_sandbox(
|
|
291
|
+
manifest: CodexAgentManifest,
|
|
292
|
+
override: str | None = None,
|
|
293
|
+
approval_mode: str | None = None,
|
|
294
|
+
) -> tuple[str, str]:
|
|
295
|
+
"""Resolve (sandbox, approval_mode): per-run override > manifest > env > default.
|
|
296
|
+
|
|
297
|
+
UI 4 档: read_only / workspace_write / workspace_write_auto / full_access
|
|
298
|
+
"""
|
|
299
|
+
presets = {
|
|
300
|
+
"read_only": ("read-only", "deny_all"),
|
|
301
|
+
"read-only": ("read-only", "deny_all"),
|
|
302
|
+
"workspace_write": ("workspace-write", "deny_all"),
|
|
303
|
+
"workspace-write": ("workspace-write", "deny_all"),
|
|
304
|
+
"workspace_write_auto": ("workspace-write", "auto_review"),
|
|
305
|
+
"workspace-write-auto": ("workspace-write", "auto_review"),
|
|
306
|
+
"full_access": ("full-access", "deny_all"),
|
|
307
|
+
"full-access": ("full-access", "deny_all"),
|
|
308
|
+
}
|
|
309
|
+
approval_presets = {
|
|
310
|
+
"ask": ("workspace-write", "manual"),
|
|
311
|
+
"risk": ("workspace-write", "auto_review"),
|
|
312
|
+
"full": ("full-access", "deny_all"),
|
|
313
|
+
}
|
|
314
|
+
if approval_mode:
|
|
315
|
+
return approval_presets[normalize_tool_approval_mode(approval_mode)]
|
|
316
|
+
raw = (
|
|
317
|
+
(override or os.environ.get("KSADK_CODEX_SANDBOX") or manifest.sandbox or "read_only")
|
|
318
|
+
.strip()
|
|
319
|
+
.lower()
|
|
320
|
+
)
|
|
321
|
+
return presets.get(raw, ("read-only", "deny_all"))
|
|
322
|
+
|
|
323
|
+
def _skill_inputs(self, manifest: CodexAgentManifest) -> list[dict[str, str]]:
|
|
324
|
+
"""Resolve bound skill resource ids to codex SkillInput wire dicts."""
|
|
325
|
+
if not manifest.skills:
|
|
326
|
+
return []
|
|
327
|
+
skills_root = self.workspace.resolve("capabilities/skills")
|
|
328
|
+
inputs: list[dict[str, str]] = []
|
|
329
|
+
for sid in manifest.skills:
|
|
330
|
+
name = self._skill_name_from_id(sid)
|
|
331
|
+
if not name:
|
|
332
|
+
continue
|
|
333
|
+
skill_dir = skills_root / name
|
|
334
|
+
if not skill_dir.is_dir():
|
|
335
|
+
continue
|
|
336
|
+
inputs.append({"name": name, "path": str(skill_dir.resolve())})
|
|
337
|
+
return inputs
|
|
338
|
+
|
|
339
|
+
@staticmethod
|
|
340
|
+
def _skill_name_from_id(resource_id: str) -> str:
|
|
341
|
+
parts = str(resource_id).split(":")
|
|
342
|
+
if len(parts) >= 4 and parts[0] == "skill":
|
|
343
|
+
return parts[2]
|
|
344
|
+
if len(parts) == 2:
|
|
345
|
+
return parts[1]
|
|
346
|
+
return ""
|
|
347
|
+
|
|
348
|
+
@staticmethod
|
|
349
|
+
def _select_model(manifest: CodexAgentManifest, requested: str | None) -> str:
|
|
350
|
+
selected = str(requested or manifest.model).strip()
|
|
351
|
+
if selected not in manifest.allowed_models:
|
|
352
|
+
raise StudioError(
|
|
353
|
+
"MODEL_NOT_BOUND",
|
|
354
|
+
"请求模型未绑定到当前 Agent Build",
|
|
355
|
+
status_code=422,
|
|
356
|
+
details={
|
|
357
|
+
"model": selected,
|
|
358
|
+
"allowedModels": list(manifest.allowed_models),
|
|
359
|
+
},
|
|
360
|
+
)
|
|
361
|
+
environment_allowlist = {
|
|
362
|
+
item.strip()
|
|
363
|
+
for item in os.environ.get("AGENTENGINE_MODEL_ALLOWLIST", "").split(",")
|
|
364
|
+
if item.strip()
|
|
365
|
+
}
|
|
366
|
+
if environment_allowlist and selected not in environment_allowlist:
|
|
367
|
+
raise StudioError(
|
|
368
|
+
"MODEL_NOT_AVAILABLE",
|
|
369
|
+
"请求模型不在当前运行环境的模型白名单中",
|
|
370
|
+
status_code=422,
|
|
371
|
+
details={"model": selected},
|
|
372
|
+
)
|
|
373
|
+
return selected
|
|
374
|
+
|
|
375
|
+
def _load_build_manifest(self, artifact_path: str) -> CodexAgentManifest:
|
|
376
|
+
archive_path = self.workspace.resolve(artifact_path, must_exist=True)
|
|
377
|
+
try:
|
|
378
|
+
if archive_path.suffix == ".zip":
|
|
379
|
+
# Compatibility for historical local audit receipts. New
|
|
380
|
+
# YAML-only builds keep the declaration as a plain immutable
|
|
381
|
+
# file, so they cannot be mistaken for a user-code package.
|
|
382
|
+
with zipfile.ZipFile(archive_path) as archive:
|
|
383
|
+
payload = yaml.safe_load(archive.read("agentengine.yaml"))
|
|
384
|
+
else:
|
|
385
|
+
payload = yaml.safe_load(archive_path.read_bytes())
|
|
386
|
+
return cast(CodexAgentManifest, CodexAgentManifest.model_validate(payload))
|
|
387
|
+
except (OSError, KeyError, ValueError, zipfile.BadZipFile) as exc:
|
|
388
|
+
raise StudioError(
|
|
389
|
+
"CODEX_BUILD_INVALID",
|
|
390
|
+
"Codex Build 缺少有效的 agentengine.yaml",
|
|
391
|
+
status_code=500,
|
|
392
|
+
) from exc
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
__all__ = ["CodexRunSpecResolver"]
|
ksadk/studio/compiler.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""Deterministic compilation from AgentDraft to ResolvedAgentSpec."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
from ksadk.studio.capabilities import (
|
|
10
|
+
CapabilityResolver,
|
|
11
|
+
LocalCapabilityResolver,
|
|
12
|
+
canonical_json,
|
|
13
|
+
sha256_digest,
|
|
14
|
+
)
|
|
15
|
+
from ksadk.studio.contracts import (
|
|
16
|
+
AgentDraft,
|
|
17
|
+
CapabilitiesSpec,
|
|
18
|
+
ResolvedAgentSpec,
|
|
19
|
+
ResolvedCapabilities,
|
|
20
|
+
)
|
|
21
|
+
from ksadk.studio.errors import StudioError
|
|
22
|
+
from ksadk.studio.resource_catalog import LocalResourceCatalog
|
|
23
|
+
from ksadk.studio.validator import AgentValidator
|
|
24
|
+
from ksadk.studio.workspace import Workspace
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class CompileResult:
|
|
29
|
+
resolved: ResolvedAgentSpec
|
|
30
|
+
dependency_lock: dict[str, Any]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AgentCompiler:
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
workspace: Workspace,
|
|
37
|
+
*,
|
|
38
|
+
resolver: CapabilityResolver | None = None,
|
|
39
|
+
validator: AgentValidator | None = None,
|
|
40
|
+
catalog: LocalResourceCatalog | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
self.workspace = workspace
|
|
43
|
+
self.resolver = resolver or LocalCapabilityResolver(workspace)
|
|
44
|
+
self.validator = validator or AgentValidator()
|
|
45
|
+
self.catalog = catalog or LocalResourceCatalog(workspace)
|
|
46
|
+
|
|
47
|
+
def compile(self, draft: AgentDraft) -> CompileResult:
|
|
48
|
+
source_payload = draft.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
49
|
+
source_digest = sha256_digest(canonical_json(source_payload))
|
|
50
|
+
materialized = self._materialize_bindings(draft)
|
|
51
|
+
self.validator.validate(materialized, level="build", raise_on_error=True)
|
|
52
|
+
assert materialized.spec.model is not None
|
|
53
|
+
|
|
54
|
+
skills = [
|
|
55
|
+
self.resolver.resolve_skill(ref)
|
|
56
|
+
for ref in materialized.spec.capabilities.skills
|
|
57
|
+
if ref.enabled
|
|
58
|
+
]
|
|
59
|
+
mcp_servers = [
|
|
60
|
+
self.resolver.resolve_mcp(ref)
|
|
61
|
+
for ref in materialized.spec.capabilities.mcp_servers
|
|
62
|
+
if ref.enabled
|
|
63
|
+
]
|
|
64
|
+
tools = [
|
|
65
|
+
self.resolver.resolve_tool(tool)
|
|
66
|
+
for tool in materialized.spec.capabilities.tools
|
|
67
|
+
]
|
|
68
|
+
skills.sort(key=lambda item: (item["name"], item["version"], item["digest"]))
|
|
69
|
+
mcp_servers.sort(key=lambda item: (item["name"], item["version"], item["digest"]))
|
|
70
|
+
tools.sort(key=lambda item: (item.name, item.version, item.digest or ""))
|
|
71
|
+
|
|
72
|
+
resolved = ResolvedAgentSpec(
|
|
73
|
+
agent_id=draft.metadata.id,
|
|
74
|
+
source_revision=draft.metadata.revision,
|
|
75
|
+
instructions=materialized.spec.instructions,
|
|
76
|
+
model=self.resolver.resolve_model(materialized.spec.model),
|
|
77
|
+
capabilities=ResolvedCapabilities(
|
|
78
|
+
skills=skills,
|
|
79
|
+
mcp_servers=mcp_servers,
|
|
80
|
+
tools=tools,
|
|
81
|
+
),
|
|
82
|
+
execution=materialized.spec.execution,
|
|
83
|
+
context=materialized.spec.context,
|
|
84
|
+
memory=materialized.spec.memory,
|
|
85
|
+
security=materialized.spec.security,
|
|
86
|
+
evaluation=materialized.spec.evaluation,
|
|
87
|
+
source_digest=source_digest,
|
|
88
|
+
)
|
|
89
|
+
digest_payload = resolved.model_dump(
|
|
90
|
+
by_alias=True,
|
|
91
|
+
exclude={"resolved_digest"},
|
|
92
|
+
exclude_none=True,
|
|
93
|
+
mode="json",
|
|
94
|
+
)
|
|
95
|
+
resolved.resolved_digest = sha256_digest(canonical_json(digest_payload))
|
|
96
|
+
dependency_lock = {
|
|
97
|
+
"lockVersion": "agentkit.lock/v1",
|
|
98
|
+
"agentId": draft.metadata.id,
|
|
99
|
+
"sourceRevision": draft.metadata.revision,
|
|
100
|
+
"resolvedDigest": resolved.resolved_digest,
|
|
101
|
+
"model": resolved.model.model_dump(
|
|
102
|
+
by_alias=True,
|
|
103
|
+
exclude_none=True,
|
|
104
|
+
mode="json",
|
|
105
|
+
),
|
|
106
|
+
"skills": skills,
|
|
107
|
+
"mcpServers": mcp_servers,
|
|
108
|
+
"tools": [
|
|
109
|
+
tool.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
110
|
+
for tool in tools
|
|
111
|
+
],
|
|
112
|
+
}
|
|
113
|
+
return CompileResult(resolved=resolved, dependency_lock=dependency_lock)
|
|
114
|
+
|
|
115
|
+
def _materialize_bindings(self, draft: AgentDraft) -> AgentDraft:
|
|
116
|
+
bindings = draft.spec.bindings
|
|
117
|
+
if (
|
|
118
|
+
not bindings.model_profile_id
|
|
119
|
+
and not bindings.tools
|
|
120
|
+
and not bindings.mcp_servers
|
|
121
|
+
and not bindings.skills
|
|
122
|
+
):
|
|
123
|
+
return draft
|
|
124
|
+
materialized = draft.model_copy(deep=True)
|
|
125
|
+
model = self.catalog.resolve_model(bindings) or materialized.spec.model
|
|
126
|
+
if model is None:
|
|
127
|
+
raise StudioError(
|
|
128
|
+
"AGENT_MODEL_REQUIRED",
|
|
129
|
+
"必须选择一个可用的 Model Profile",
|
|
130
|
+
status_code=422,
|
|
131
|
+
field="spec.bindings.modelProfileId",
|
|
132
|
+
)
|
|
133
|
+
bound_tools, permissions = self.catalog.policy_preview(bindings)
|
|
134
|
+
bound_mcp_tools = self.catalog.resolve_mcp_tools(bindings)
|
|
135
|
+
capabilities = CapabilitiesSpec(
|
|
136
|
+
skills=[
|
|
137
|
+
*materialized.spec.capabilities.skills,
|
|
138
|
+
*self.catalog.resolve_skills(bindings),
|
|
139
|
+
],
|
|
140
|
+
mcp_servers=[
|
|
141
|
+
*materialized.spec.capabilities.mcp_servers,
|
|
142
|
+
*self.catalog.resolve_mcp_servers(bindings),
|
|
143
|
+
],
|
|
144
|
+
tools=[
|
|
145
|
+
*materialized.spec.capabilities.tools,
|
|
146
|
+
*bound_tools,
|
|
147
|
+
*bound_mcp_tools,
|
|
148
|
+
],
|
|
149
|
+
)
|
|
150
|
+
self._require_unique(
|
|
151
|
+
[item.name for item in capabilities.skills],
|
|
152
|
+
kind="Skill",
|
|
153
|
+
)
|
|
154
|
+
self._require_unique(
|
|
155
|
+
[item.name for item in capabilities.mcp_servers],
|
|
156
|
+
kind="MCP Server",
|
|
157
|
+
)
|
|
158
|
+
self._require_unique(
|
|
159
|
+
[item.name for item in capabilities.tools],
|
|
160
|
+
kind="Tool",
|
|
161
|
+
)
|
|
162
|
+
materialized.spec.model = model
|
|
163
|
+
materialized.spec.capabilities = capabilities
|
|
164
|
+
materialized.spec.security.allowed_permissions = sorted(
|
|
165
|
+
set(materialized.spec.security.allowed_permissions)
|
|
166
|
+
| set(permissions)
|
|
167
|
+
| {
|
|
168
|
+
permission
|
|
169
|
+
for tool in bound_mcp_tools
|
|
170
|
+
for permission in tool.permissions
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
endpoint = model.endpoint_url or model.base_url or ""
|
|
174
|
+
hostname = (urlparse(endpoint).hostname or "").lower().rstrip(".")
|
|
175
|
+
if hostname and materialized.spec.security.network.mode == "restricted":
|
|
176
|
+
materialized.spec.security.network.allowed_hosts = sorted(
|
|
177
|
+
set(materialized.spec.security.network.allowed_hosts) | {hostname}
|
|
178
|
+
)
|
|
179
|
+
return materialized
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def _require_unique(names: list[str], *, kind: str) -> None:
|
|
183
|
+
duplicates = sorted({name for name in names if names.count(name) > 1})
|
|
184
|
+
if duplicates:
|
|
185
|
+
raise StudioError(
|
|
186
|
+
"CAPABILITY_DUPLICATE",
|
|
187
|
+
f"{kind} binding 重复",
|
|
188
|
+
status_code=422,
|
|
189
|
+
details={"names": duplicates},
|
|
190
|
+
)
|