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,469 @@
|
|
|
1
|
+
"""Codex-authored conversation proposals.
|
|
2
|
+
|
|
3
|
+
veadk ``intelligent_development`` 模式的移植:每轮对话创建请求背后是一个真实的
|
|
4
|
+
Codex 会话——Codex 在沙箱工作区把 Agent Draft Patch 写成
|
|
5
|
+
``.agentkit/authoring/<request_id>/agentkit.yaml`` 文件,产物经过与 chat 链路完全
|
|
6
|
+
相同的 ``parse_conversation_proposal`` 验证器校验;校验失败把错误作为下一轮消息
|
|
7
|
+
喂回同一个 Codex thread 让它改写文件(最多 ``max_retries`` 轮)。相对 chat 模型
|
|
8
|
+
直接输出 JSON,文件产物 + 错误回喂显著降低非法 JSON 残缺 patch 的比例。
|
|
9
|
+
|
|
10
|
+
Codex 不可用(SDK 缺失、二进制缺失、turn 超时)时抛
|
|
11
|
+
``CodexAuthoringUnavailableError``,由 coordinator 降级回 chat 链路。
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import json
|
|
18
|
+
import logging
|
|
19
|
+
import re
|
|
20
|
+
import shutil
|
|
21
|
+
import time
|
|
22
|
+
from dataclasses import dataclass, field
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any, Callable
|
|
25
|
+
from uuid import uuid4
|
|
26
|
+
|
|
27
|
+
import yaml # type: ignore[import-untyped]
|
|
28
|
+
|
|
29
|
+
from ksadk.studio.authoring import AgentAuthoringService, ConversationProposal
|
|
30
|
+
from ksadk.studio.contracts import ResolvedModel, Usage
|
|
31
|
+
from ksadk.studio.errors import StudioError
|
|
32
|
+
from ksadk.studio.workspace import Workspace
|
|
33
|
+
|
|
34
|
+
LOGGER = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
#: 单个 Codex turn 的执行超时;超时视为 codex 不可用并降级 chat 链。
|
|
37
|
+
DEFAULT_TURN_TIMEOUT_SECONDS = 240.0
|
|
38
|
+
#: 校验失败后的最大改写轮数(首轮之外)。
|
|
39
|
+
DEFAULT_MAX_RETRIES = 3
|
|
40
|
+
#: 失败产物目录保留数量,供诊断;成功目录立即清理。
|
|
41
|
+
_MAX_FAILED_DIRECTORIES = 5
|
|
42
|
+
_REQUEST_DIR_PREFIX = "codex-req-"
|
|
43
|
+
|
|
44
|
+
_MANIFEST_FILENAME = "agentkit.yaml"
|
|
45
|
+
|
|
46
|
+
_BUILDER_SCHEMA = """\
|
|
47
|
+
你是 AgentKit Studio 的 Agent 配置编写器。你的唯一任务是把一份 Agent Draft Patch
|
|
48
|
+
写成 YAML 文件(不是输出到对话里)。文件必须写到指定路径,使用合法 YAML,根节点
|
|
49
|
+
是一个 JSON/YAML 对象,字段如下:
|
|
50
|
+
|
|
51
|
+
- name: 字符串,Agent 展示名(1-128 字符)
|
|
52
|
+
- slug: 字符串,小写字母数字与连字符(1-63 字符)
|
|
53
|
+
- runtimeType: 只能是 codex、adk、langgraph
|
|
54
|
+
- description: 字符串,可为空(最长 1024)
|
|
55
|
+
- spec: 完整 AgentSpec 对象,可包含:
|
|
56
|
+
- instructions(必须):包含 system(系统提示词)与 task(任务提示词)两个字符串
|
|
57
|
+
- runtime:对象,必须包含 type 字段(与 runtimeType 相同的值:codex/adk/langgraph),
|
|
58
|
+
不要写 provider;adk/langgraph 可加 projectPath/entryPoint/agentVariable
|
|
59
|
+
- execution、context、memory、security、evaluation:按需
|
|
60
|
+
|
|
61
|
+
完整示例(输出必须严格遵循此结构,字段名一字不差):
|
|
62
|
+
|
|
63
|
+
name: 每日科技新闻摘要
|
|
64
|
+
slug: daily-tech-news-summary
|
|
65
|
+
runtimeType: codex
|
|
66
|
+
description: 每天早晨抓取科技新闻源并生成中文简报
|
|
67
|
+
spec:
|
|
68
|
+
instructions:
|
|
69
|
+
system: 你是一名资深科技编辑,擅长从多条新闻中提炼要点。
|
|
70
|
+
task: 汇总当日科技新闻,按重要性排序输出中文简报,每条含标题与一句话摘要。
|
|
71
|
+
runtime:
|
|
72
|
+
type: codex
|
|
73
|
+
|
|
74
|
+
注意:
|
|
75
|
+
- 示例中的 name/slug/description/instructions 值必须替换为符合用户
|
|
76
|
+
对话的内容,不要照抄示例文字。
|
|
77
|
+
- 模型 Profile、模型参数、Tool、MCP、Skill、凭证、端点和资源 ID 是 Studio 的
|
|
78
|
+
受控输入,严禁写入 model、bindings 或 capabilities。需要它们时只在
|
|
79
|
+
instructions/task 中描述语义用途,Studio 会在确认前注入已选资源。
|
|
80
|
+
|
|
81
|
+
规则:
|
|
82
|
+
0. 硬性要求:你必须在本轮实际调用 apply_patch 工具把完整 patch 写入目标文件,
|
|
83
|
+
然后才能结束回复。只在回复文本里描述计划、或只在回复中给出 YAML/JSON 内容
|
|
84
|
+
(包括 Markdown 代码块)而没有实际写文件,都视为本轮失败。
|
|
85
|
+
1. 必须用写文件工具把完整 patch 写入指定路径;不要只在回复中输出内容。
|
|
86
|
+
2. 不要输出 Markdown 代码块包裹的 YAML 作为最终答案,文件本身就是产物。
|
|
87
|
+
3. 首轮必须包含全部顶层字段;后续轮次(已有草稿时)输出完整合并后的新版本。
|
|
88
|
+
4. 不得编造 Tool、MCP、Skill、模型、模型参数、资源 ID、凭证或端点;这些由
|
|
89
|
+
Studio 的资源选择器和策略层注入。
|
|
90
|
+
5. 只做配置编写,不要创建其他文件、不要执行无关命令。
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class CodexAuthoringUnavailableError(RuntimeError):
|
|
95
|
+
"""Codex authoring 后端不可用(缺依赖/二进制、超时),调用方应降级。"""
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass
|
|
99
|
+
class CodexAuthoringResult:
|
|
100
|
+
proposal: ConversationProposal
|
|
101
|
+
usage: Usage
|
|
102
|
+
attempts: int
|
|
103
|
+
final_message: str
|
|
104
|
+
request_id: str
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass
|
|
108
|
+
class _TurnOutcome:
|
|
109
|
+
final_message: str
|
|
110
|
+
usage: Usage = field(default_factory=Usage)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _sanitize_request_id(request_id: str | None) -> str:
|
|
114
|
+
candidate = str(request_id or "").strip()
|
|
115
|
+
if re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}", candidate):
|
|
116
|
+
return candidate
|
|
117
|
+
return uuid4().hex
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _extract_usage(params: dict[str, Any]) -> dict[str, int] | None:
|
|
121
|
+
usage = params.get("tokenUsage") or params.get("token_usage")
|
|
122
|
+
if not isinstance(usage, dict):
|
|
123
|
+
return None
|
|
124
|
+
last = usage.get("last")
|
|
125
|
+
if not isinstance(last, dict):
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
def metric(camel: str, snake: str) -> int:
|
|
129
|
+
value = last.get(camel, last.get(snake, 0))
|
|
130
|
+
try:
|
|
131
|
+
return max(0, int(value)) # type: ignore[arg-type]
|
|
132
|
+
except (TypeError, ValueError):
|
|
133
|
+
return 0
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
"input_tokens": metric("inputTokens", "input_tokens"),
|
|
137
|
+
"output_tokens": metric("outputTokens", "output_tokens"),
|
|
138
|
+
"total_tokens": metric("totalTokens", "total_tokens"),
|
|
139
|
+
"cached_input_tokens": metric("cachedInputTokens", "cached_input_tokens"),
|
|
140
|
+
"reasoning_output_tokens": metric("reasoningOutputTokens", "reasoning_output_tokens"),
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class CodexAuthoringExecutor:
|
|
145
|
+
"""让真实 Codex 会话在工作区文件里编写 Agent Draft Patch。"""
|
|
146
|
+
|
|
147
|
+
def __init__(
|
|
148
|
+
self,
|
|
149
|
+
workspace: Workspace,
|
|
150
|
+
credential_resolver: Any,
|
|
151
|
+
*,
|
|
152
|
+
client_factory: Callable[[dict[str, str]], Any] | None = None,
|
|
153
|
+
turn_timeout_seconds: float = DEFAULT_TURN_TIMEOUT_SECONDS,
|
|
154
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
155
|
+
) -> None:
|
|
156
|
+
self.workspace = workspace
|
|
157
|
+
self.root = workspace.resolve(".agentkit/authoring")
|
|
158
|
+
self.credentials = credential_resolver
|
|
159
|
+
self._client_factory = client_factory
|
|
160
|
+
self._turn_timeout_seconds = turn_timeout_seconds
|
|
161
|
+
self._max_retries = max(0, int(max_retries))
|
|
162
|
+
|
|
163
|
+
# ------------------------------------------------------------------
|
|
164
|
+
# Availability probe
|
|
165
|
+
# ------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
def probe(self) -> None:
|
|
168
|
+
"""Fail fast when the Codex backend cannot run on this host.
|
|
169
|
+
|
|
170
|
+
Raises ``CodexAuthoringUnavailableError`` so the coordinator can
|
|
171
|
+
silently fall back to the chat chain.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
import openai_codex # type: ignore[import-not-found] # noqa: F401
|
|
176
|
+
except ImportError as exc:
|
|
177
|
+
raise CodexAuthoringUnavailableError(
|
|
178
|
+
"openai-codex SDK 未安装 (pip install 'ksadk[codex]')"
|
|
179
|
+
) from exc
|
|
180
|
+
try:
|
|
181
|
+
from codex_cli_bin import (
|
|
182
|
+
bundled_codex_path, # type: ignore[import-not-found, import-untyped]
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
binary = Path(str(bundled_codex_path()))
|
|
186
|
+
except (ImportError, OSError) as exc:
|
|
187
|
+
raise CodexAuthoringUnavailableError("本地 Codex 平台二进制不可用") from exc
|
|
188
|
+
if not binary.exists():
|
|
189
|
+
raise CodexAuthoringUnavailableError(f"Codex 二进制不存在: {binary}")
|
|
190
|
+
|
|
191
|
+
# ------------------------------------------------------------------
|
|
192
|
+
# Authoring flow
|
|
193
|
+
# ------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
async def compose(
|
|
196
|
+
self,
|
|
197
|
+
*,
|
|
198
|
+
messages: list[dict[str, str]],
|
|
199
|
+
model: ResolvedModel,
|
|
200
|
+
base: ConversationProposal | None = None,
|
|
201
|
+
request_id: str | None = None,
|
|
202
|
+
) -> CodexAuthoringResult:
|
|
203
|
+
normalized_request_id = _sanitize_request_id(request_id)
|
|
204
|
+
request_dir = self.workspace.resolve(
|
|
205
|
+
Path(".agentkit/authoring")
|
|
206
|
+
/ f"{_REQUEST_DIR_PREFIX}{normalized_request_id}"
|
|
207
|
+
)
|
|
208
|
+
shutil.rmtree(request_dir, ignore_errors=True)
|
|
209
|
+
request_dir.mkdir(parents=True, exist_ok=True)
|
|
210
|
+
manifest_path = request_dir / _MANIFEST_FILENAME
|
|
211
|
+
|
|
212
|
+
env = self._codex_env(model)
|
|
213
|
+
client = self._create_client(env)
|
|
214
|
+
usage_total: dict[str, int] = {}
|
|
215
|
+
attempts = 0
|
|
216
|
+
validation_error = ""
|
|
217
|
+
last_message = ""
|
|
218
|
+
try:
|
|
219
|
+
thread_id = await client.start_thread(
|
|
220
|
+
{
|
|
221
|
+
"cwd": str(request_dir),
|
|
222
|
+
"sandbox": "workspace-write",
|
|
223
|
+
"approval_mode": "deny_all",
|
|
224
|
+
"model": model.model,
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
prompt = self._builder_prompt(messages, base=base, manifest_path=manifest_path)
|
|
228
|
+
for attempt in range(self._max_retries + 1):
|
|
229
|
+
attempts = attempt + 1
|
|
230
|
+
if validation_error:
|
|
231
|
+
prompt = self._correction_prompt(manifest_path, validation_error)
|
|
232
|
+
outcome = await self._run_turn(client, thread_id, prompt)
|
|
233
|
+
last_message = outcome.final_message
|
|
234
|
+
for key, value in outcome.usage.model_dump().items():
|
|
235
|
+
if key in {"reported", "source"}:
|
|
236
|
+
continue
|
|
237
|
+
usage_total[key] = usage_total.get(key, 0) + int(value or 0)
|
|
238
|
+
content = self._read_manifest(manifest_path)
|
|
239
|
+
if content is None:
|
|
240
|
+
# 兜底:部分模型不调用写文件工具,把 YAML/JSON 直接输出在
|
|
241
|
+
# agentMessage 里;从 ```yaml/```json 代码块恢复并落盘,
|
|
242
|
+
# 再走正常校验链,避免整轮作废。
|
|
243
|
+
recovered = self._recover_manifest_from_message(last_message)
|
|
244
|
+
if recovered is not None:
|
|
245
|
+
LOGGER.warning(
|
|
246
|
+
"codex authoring attempt %d wrote no manifest; recovered "
|
|
247
|
+
"fenced block from agent message: requestId=%s",
|
|
248
|
+
attempts,
|
|
249
|
+
normalized_request_id,
|
|
250
|
+
)
|
|
251
|
+
try:
|
|
252
|
+
manifest_path.write_text(recovered, encoding="utf-8")
|
|
253
|
+
content = recovered
|
|
254
|
+
except OSError:
|
|
255
|
+
LOGGER.warning(
|
|
256
|
+
"codex authoring fallback write failed: requestId=%s",
|
|
257
|
+
normalized_request_id,
|
|
258
|
+
)
|
|
259
|
+
if content is not None:
|
|
260
|
+
# Codex 习惯写 YAML;parse_conversation_proposal 的 JSON 提取器
|
|
261
|
+
# 遇到 YAML 里游离的 `{}` 会误解析成空 patch,这里先归一成 JSON。
|
|
262
|
+
try:
|
|
263
|
+
yaml_payload = yaml.safe_load(content)
|
|
264
|
+
except yaml.YAMLError:
|
|
265
|
+
yaml_payload = None
|
|
266
|
+
if isinstance(yaml_payload, dict):
|
|
267
|
+
content = json.dumps(yaml_payload, ensure_ascii=False)
|
|
268
|
+
if content is None:
|
|
269
|
+
validation_error = (
|
|
270
|
+
f"{_MANIFEST_FILENAME} 文件不存在或为空;你上一轮没有写文件,"
|
|
271
|
+
f"必须调用 apply_patch 工具(*** Begin Patch … Add File … "
|
|
272
|
+
f"*** End Patch)把完整 patch 写入 {manifest_path},"
|
|
273
|
+
"禁止只在回复文本中输出内容或 Markdown 代码块"
|
|
274
|
+
)
|
|
275
|
+
LOGGER.warning(
|
|
276
|
+
"codex authoring attempt %d produced no manifest: requestId=%s",
|
|
277
|
+
attempts,
|
|
278
|
+
normalized_request_id,
|
|
279
|
+
)
|
|
280
|
+
continue
|
|
281
|
+
try:
|
|
282
|
+
proposal = AgentAuthoringService.parse_conversation_proposal(content, base=base)
|
|
283
|
+
except StudioError as exc:
|
|
284
|
+
validation_error = str(exc.details.get("reason") or exc.message)
|
|
285
|
+
LOGGER.warning(
|
|
286
|
+
"codex authoring attempt %d invalid: requestId=%s reason=%s",
|
|
287
|
+
attempts,
|
|
288
|
+
normalized_request_id,
|
|
289
|
+
validation_error,
|
|
290
|
+
)
|
|
291
|
+
continue
|
|
292
|
+
self._cleanup_request_dir(request_dir, success=True)
|
|
293
|
+
return CodexAuthoringResult(
|
|
294
|
+
proposal=proposal,
|
|
295
|
+
usage=Usage(**usage_total, reported=True, source="codex-authoring"),
|
|
296
|
+
attempts=attempts,
|
|
297
|
+
final_message=last_message,
|
|
298
|
+
request_id=normalized_request_id,
|
|
299
|
+
)
|
|
300
|
+
raise StudioError(
|
|
301
|
+
"AUTHORING_MODEL_OUTPUT_INVALID",
|
|
302
|
+
"Codex 会话没有产出合法的 Agent Draft Patch",
|
|
303
|
+
status_code=502,
|
|
304
|
+
details={
|
|
305
|
+
"validationError": validation_error,
|
|
306
|
+
"attemptedCorrections": attempts - 1,
|
|
307
|
+
"requestId": normalized_request_id,
|
|
308
|
+
},
|
|
309
|
+
)
|
|
310
|
+
finally:
|
|
311
|
+
try:
|
|
312
|
+
await client.close()
|
|
313
|
+
except Exception: # pragma: no cover - defensive close
|
|
314
|
+
LOGGER.debug("codex authoring client close failed", exc_info=True)
|
|
315
|
+
self._cleanup_request_dir(request_dir, success=False)
|
|
316
|
+
|
|
317
|
+
# ------------------------------------------------------------------
|
|
318
|
+
# Internals
|
|
319
|
+
# ------------------------------------------------------------------
|
|
320
|
+
|
|
321
|
+
def _create_client(self, env: dict[str, str]) -> Any:
|
|
322
|
+
if self._client_factory is not None:
|
|
323
|
+
return self._client_factory(env)
|
|
324
|
+
try:
|
|
325
|
+
from openai_codex import CodexConfig # type: ignore[import-not-found]
|
|
326
|
+
|
|
327
|
+
from ksadk.codex.client import AsyncCodexClient
|
|
328
|
+
except ImportError as exc:
|
|
329
|
+
raise CodexAuthoringUnavailableError(
|
|
330
|
+
"openai-codex SDK 未安装 (pip install 'ksadk[codex]')"
|
|
331
|
+
) from exc
|
|
332
|
+
return AsyncCodexClient(CodexConfig(env=env))
|
|
333
|
+
|
|
334
|
+
def _codex_env(self, model: ResolvedModel) -> dict[str, str]:
|
|
335
|
+
env: dict[str, str] = {}
|
|
336
|
+
try:
|
|
337
|
+
credential = self.credentials.resolve(model.credential_ref)
|
|
338
|
+
env["OPENAI_API_KEY"] = credential
|
|
339
|
+
except StudioError:
|
|
340
|
+
raise CodexAuthoringUnavailableError(f"无法解析模型凭证引用: {model.credential_ref}")
|
|
341
|
+
base_url = str(model.endpoint_url or "").rstrip("/")
|
|
342
|
+
for suffix in ("/chat/completions", "/responses"):
|
|
343
|
+
if base_url.endswith(suffix):
|
|
344
|
+
base_url = base_url[: -len(suffix)]
|
|
345
|
+
if base_url:
|
|
346
|
+
env["OPENAI_BASE_URL"] = base_url
|
|
347
|
+
env["OPENAI_API_BASE"] = base_url
|
|
348
|
+
env["OPENAI_MODEL_NAME"] = model.model
|
|
349
|
+
return env
|
|
350
|
+
|
|
351
|
+
def _builder_prompt(
|
|
352
|
+
self,
|
|
353
|
+
messages: list[dict[str, str]],
|
|
354
|
+
*,
|
|
355
|
+
base: ConversationProposal | None,
|
|
356
|
+
manifest_path: Path,
|
|
357
|
+
) -> str:
|
|
358
|
+
parts = [_BUILDER_SCHEMA, f"\n目标文件路径(绝对路径):{manifest_path}\n"]
|
|
359
|
+
if base is not None:
|
|
360
|
+
current = base.model_dump(by_alias=True, mode="json", exclude_none=True)
|
|
361
|
+
parts.append(
|
|
362
|
+
"当前已有草稿(作为起点,必须合并用户最新要求后输出完整新版本):\n"
|
|
363
|
+
+ yaml.safe_dump(current, allow_unicode=True, sort_keys=False)
|
|
364
|
+
)
|
|
365
|
+
transcript = "\n".join(
|
|
366
|
+
f"{str(item.get('role') or 'user')}: {str(item.get('content') or '').strip()}"
|
|
367
|
+
for item in messages
|
|
368
|
+
)
|
|
369
|
+
parts.append(f"用户对话(最后一条 user 消息是最新要求,必须优先满足):\n{transcript}\n")
|
|
370
|
+
parts.append("现在把完整的 Agent Draft Patch 写入目标文件。")
|
|
371
|
+
parts.append(
|
|
372
|
+
"写入方式要求:沙箱外命令已被审批策略拒绝,不要尝试 shell 重定向"
|
|
373
|
+
"(如 cat > file 或 echo > file)——它们会被静默拒绝导致文件不存在。"
|
|
374
|
+
"必须使用 apply_patch 工具(*** Begin Patch … Add File: <绝对路径> … "
|
|
375
|
+
"*** End Patch)把完整 YAML 内容写为目标文件。"
|
|
376
|
+
)
|
|
377
|
+
return "\n".join(parts)
|
|
378
|
+
|
|
379
|
+
@staticmethod
|
|
380
|
+
def _correction_prompt(manifest_path: Path, validation_error: str) -> str:
|
|
381
|
+
return (
|
|
382
|
+
f"你写入的 {_MANIFEST_FILENAME} 未通过 Agent Draft Patch 校验。\n"
|
|
383
|
+
f"校验错误细节如下,请逐条修正后重写文件 {manifest_path}(完整内容,"
|
|
384
|
+
"不是增量补丁):\n"
|
|
385
|
+
f"{validation_error}"
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
async def _run_turn(self, client: Any, thread_id: str, prompt: str) -> _TurnOutcome:
|
|
389
|
+
message_parts: list[str] = []
|
|
390
|
+
usage = Usage()
|
|
391
|
+
event_counts: dict[str, int] = {}
|
|
392
|
+
started = time.monotonic()
|
|
393
|
+
try:
|
|
394
|
+
# asyncio.timeout 是 3.11+;项目基线 3.10,用 wait_for 包装整轮消费。
|
|
395
|
+
async def _consume() -> None:
|
|
396
|
+
nonlocal usage
|
|
397
|
+
async for event in client.run_turn(thread_id, prompt):
|
|
398
|
+
if not isinstance(event, dict):
|
|
399
|
+
continue
|
|
400
|
+
method = str(event.get("method") or "")
|
|
401
|
+
event_counts[method] = event_counts.get(method, 0) + 1
|
|
402
|
+
params = event.get("params") or {}
|
|
403
|
+
if not isinstance(params, dict):
|
|
404
|
+
continue
|
|
405
|
+
if method == "item/agentMessage/delta":
|
|
406
|
+
message_parts.append(str(params.get("delta") or ""))
|
|
407
|
+
elif method == "thread/tokenUsage/updated":
|
|
408
|
+
metrics = _extract_usage(params)
|
|
409
|
+
if metrics:
|
|
410
|
+
usage = Usage(
|
|
411
|
+
**metrics, # type: ignore[arg-type]
|
|
412
|
+
reported=True,
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
await asyncio.wait_for(_consume(), timeout=self._turn_timeout_seconds)
|
|
416
|
+
except asyncio.TimeoutError as exc:
|
|
417
|
+
raise CodexAuthoringUnavailableError(
|
|
418
|
+
f"Codex authoring turn 超时({self._turn_timeout_seconds:.0f}s)"
|
|
419
|
+
) from exc
|
|
420
|
+
LOGGER.info("codex authoring turn finished in %.2fs", time.monotonic() - started)
|
|
421
|
+
# 事件 method 分布:诊断"模型只回话不调工具"(无 item/*command* 事件)等
|
|
422
|
+
# 失败模式的关键证据,debug 级别避免常态噪音。
|
|
423
|
+
LOGGER.debug("codex authoring turn events: %s", dict(sorted(event_counts.items())))
|
|
424
|
+
return _TurnOutcome(final_message="".join(message_parts), usage=usage)
|
|
425
|
+
|
|
426
|
+
_FENCED_BLOCK_RE = re.compile(r"```[A-Za-z0-9_-]*[ \t]*\r?\n(.*?)```", re.DOTALL)
|
|
427
|
+
|
|
428
|
+
@classmethod
|
|
429
|
+
def _recover_manifest_from_message(cls, message: str) -> str | None:
|
|
430
|
+
"""从 agentMessage 文本里恢复 patch:优先围栏代码块,其次裸 JSON 对象。"""
|
|
431
|
+
|
|
432
|
+
text = str(message or "").strip()
|
|
433
|
+
if not text:
|
|
434
|
+
return None
|
|
435
|
+
for match in cls._FENCED_BLOCK_RE.finditer(text):
|
|
436
|
+
block = match.group(1).strip()
|
|
437
|
+
if block:
|
|
438
|
+
return block
|
|
439
|
+
if text.startswith("{") and text.endswith("}"):
|
|
440
|
+
return text
|
|
441
|
+
return None
|
|
442
|
+
|
|
443
|
+
@staticmethod
|
|
444
|
+
def _read_manifest(manifest_path: Path) -> str | None:
|
|
445
|
+
try:
|
|
446
|
+
content = manifest_path.read_text(encoding="utf-8")
|
|
447
|
+
except OSError:
|
|
448
|
+
return None
|
|
449
|
+
return content or None
|
|
450
|
+
|
|
451
|
+
def _cleanup_request_dir(self, request_dir: Path, *, success: bool) -> None:
|
|
452
|
+
if success:
|
|
453
|
+
shutil.rmtree(request_dir, ignore_errors=True)
|
|
454
|
+
return
|
|
455
|
+
if not request_dir.exists():
|
|
456
|
+
return
|
|
457
|
+
failed = sorted(
|
|
458
|
+
(path for path in self.root.glob(f"{_REQUEST_DIR_PREFIX}*") if path.is_dir()),
|
|
459
|
+
key=lambda path: path.stat().st_mtime,
|
|
460
|
+
)
|
|
461
|
+
while len(failed) > _MAX_FAILED_DIRECTORIES:
|
|
462
|
+
shutil.rmtree(failed.pop(0), ignore_errors=True)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
__all__ = [
|
|
466
|
+
"CodexAuthoringExecutor",
|
|
467
|
+
"CodexAuthoringResult",
|
|
468
|
+
"CodexAuthoringUnavailableError",
|
|
469
|
+
]
|