agentengine-sdk-python 0.8.2__py3-none-any.whl → 0.8.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/METADATA +18 -25
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/RECORD +224 -169
- ksadk/_build_provenance.json +1 -0
- ksadk/agui/_agent_helpers.py +4 -0
- ksadk/api/client.py +3 -0
- ksadk/builders/managed_runtime_builder.py +3 -0
- ksadk/cli/__init__.py +6 -0
- ksadk/cli/cmd_plugin.py +657 -0
- ksadk/codex/runtime.py +50 -8
- ksadk/configs/env_registry.py +31 -3
- ksadk/configs/settings.py +9 -0
- ksadk/context_engine/contributors.py +73 -8
- ksadk/conversations/__init__.py +19 -0
- ksadk/conversations/context.py +104 -24
- ksadk/conversations/contracts.py +266 -0
- ksadk/conversations/message_projection.py +19 -1
- ksadk/conversations/projector.py +616 -0
- ksadk/conversations/reducer.py +98 -0
- ksadk/events/_v1_compat/projection.py +2 -0
- ksadk/events/adapters/codex.py +190 -0
- ksadk/harness/__init__.py +45 -35
- ksadk/harness/runtime.py +60 -1
- ksadk/kernel/contract_fingerprints.py +5 -4
- ksadk/kernel/contracts.py +8 -0
- ksadk/kernel/control.py +1 -0
- ksadk/kernel/ingress.py +21 -0
- ksadk/kernel/memory_store.py +1 -0
- ksadk/kernel/postgres_store.py +1 -0
- ksadk/kernel/sqlite_store.py +1 -0
- ksadk/kernel/worker.py +11 -0
- ksadk/memory/providers/local_sqlite.py +7 -0
- ksadk/plugins/__init__.py +167 -0
- ksadk/plugins/bridges/__init__.py +45 -0
- ksadk/plugins/bridges/codex.py +552 -0
- ksadk/plugins/bridges/dsh.py +1116 -0
- ksadk/plugins/builtins.py +747 -0
- ksadk/plugins/bundle.py +246 -0
- ksadk/plugins/bundle_security.py +167 -0
- ksadk/plugins/composition.py +529 -0
- ksadk/plugins/context_contributor.py +437 -0
- ksadk/plugins/contracts.py +451 -0
- ksadk/plugins/dsh_toolchain.py +935 -0
- ksadk/plugins/ecosystem_bridge.py +1105 -0
- ksadk/plugins/ecosystem_probe.py +191 -0
- ksadk/plugins/host.py +724 -0
- ksadk/plugins/providers/__init__.py +85 -0
- ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
- ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
- ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
- ksadk/plugins/providers/codex.py +722 -0
- ksadk/plugins/providers/codex_dsh.py +83 -0
- ksadk/plugins/providers/dsh.py +951 -0
- ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
- ksadk/plugins/providers/harness.py +627 -0
- ksadk/plugins/providers/harness_dsh.py +91 -0
- ksadk/plugins/providers/legacy.py +215 -0
- ksadk/plugins/providers/legacy_catalog.py +100 -0
- ksadk/plugins/providers/shipped_dsh.py +370 -0
- ksadk/plugins/resolver.py +331 -0
- ksadk/plugins/subagent_providers/__init__.py +12 -0
- ksadk/plugins/subagent_providers/codex.py +443 -0
- ksadk/plugins/subagents.py +333 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +51 -42
- ksadk/runtime/adapter.py +1 -0
- ksadk/runtime/factory.py +76 -2
- ksadk/runtime/framework_adapters.py +18 -0
- ksadk/runtime/runner_adapter.py +5 -0
- ksadk/sandbox/__init__.py +2 -1
- ksadk/sandbox/factory.py +72 -0
- ksadk/scheduler/__init__.py +18 -0
- ksadk/scheduler/calendar.py +102 -0
- ksadk/scheduler/contracts.py +254 -0
- ksadk/scheduler/dispatcher.py +129 -0
- ksadk/scheduler/engine.py +416 -0
- ksadk/scheduler/sqlite_store.py +563 -0
- ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-10GPXIJ6.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-BXk1l-G1.js} +1 -1
- ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-D9uB55Oh.js} +1 -1
- ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock--OEYoXIJ.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-DrEe1syq.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-eeTFJLvo.js} +1 -1
- ksadk/server/static/assets/{arc-C4FzinUA.js → arc-S3ZNbIAd.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-CRjgEJDX.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-C7bsBoNH.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-BX3c33Ob.js} +1 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-bZ7ws-8m.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-D2r0pvhY.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-CZwF3oUP.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-DigFYCML.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-CnorGV5q.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CexntQA-.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-CHTC7UxA.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-BC1EWt_-.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-BTG24xN0.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-CkonRdAS.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-DEOCBe15.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-DBThPuLa.js} +1 -1
- ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-ClTPrTht.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-DsZHrnpJ.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-BJR4nhVr.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-xzcERX0a.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-tn2xM1xu.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-BZPGBkw5.js} +1 -1
- ksadk/server/static/assets/{dist-ClxGviKw.js → dist-4zN1_tq5.js} +1 -1
- ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-8VWI-2bZ.js} +1 -1
- ksadk/server/static/assets/{dist-BX8z72IC.js → dist-B-46q3Hk.js} +1 -1
- ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-B0gdk4rl.js} +1 -1
- ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-B1oWRmrH.js} +1 -1
- ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-BI1qQH4n.js} +1 -1
- ksadk/server/static/assets/{dist-dydu68Fl.js → dist-BJLUwH6W.js} +1 -1
- ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-Bbwqa8TG.js} +1 -1
- ksadk/server/static/assets/{dist-CttYUqzS.js → dist-Btyo4vX4.js} +1 -1
- ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C71CsujO.js} +1 -1
- ksadk/server/static/assets/{dist-dDdADKFA.js → dist-CXpH_Rdd.js} +1 -1
- ksadk/server/static/assets/{dist-CSh_DE14.js → dist-Cq4OL6nO.js} +1 -1
- ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-D1V3f1B4.js} +1 -1
- ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-DJmCPRVB.js} +1 -1
- ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-DQAB0qn_.js} +1 -1
- ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DUwKa_l6.js} +1 -1
- ksadk/server/static/assets/{dist-B7seoj3d.js → dist-DdRBIceA.js} +1 -1
- ksadk/server/static/assets/{dist-BytlxIDT.js → dist-DfGFrb0v.js} +1 -1
- ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-DjhwGUgZ.js} +1 -1
- ksadk/server/static/assets/{dist-W-TIVntx.js → dist-DyqV4fL4.js} +1 -1
- ksadk/server/static/assets/{dist-DUX-id_F.js → dist-M67Hwu0n.js} +1 -1
- ksadk/server/static/assets/{dist-DmldrHd_.js → dist-u8tVH5Ak.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-DVfMsLge.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CWEZSYaw.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-TWIxoyYL.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-DDh2hd2S.js} +1 -1
- ksadk/server/static/assets/index-B2k_urY8.js +241 -0
- ksadk/server/static/assets/index-ILPt6IWF.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CgoyWiDR.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CyRIu_om.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-DN5JXHzN.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CNP3ui66.js} +1 -1
- ksadk/server/static/assets/{katex-vFWytM5c.js → katex-DWEzQy1d.js} +1 -1
- ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-C-qHp7d2.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-Cl-K943T.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-D5DB5mYm.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-BQVc9ia_.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-B6UCAvtY.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-mIr2d3eb.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-Dt3FFDmK.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-Cz_vQtgF.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-wlO1TsH5.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-CHRbElYq.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DXX54iyO.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-Dp_lw9II.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-D8O5UlLG.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-8mfKcxvG.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-EnNl0DE7.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-DBu5fbYr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-BSVXs4IY.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/skills/service_client.py +48 -0
- ksadk/studio/agent_lifecycle.py +26 -20
- ksadk/studio/api.py +513 -71
- ksadk/studio/api_catalog_routes.py +5 -0
- ksadk/studio/api_contracts.py +34 -1
- ksadk/studio/api_plugin_routes.py +480 -0
- ksadk/studio/attachment_store.py +187 -0
- ksadk/studio/authoring.py +10 -4
- ksadk/studio/authoring_coordinator.py +12 -2
- ksadk/studio/builder.py +123 -43
- ksadk/studio/cloud.py +4 -0
- ksadk/studio/codex_agent_service.py +12 -1
- ksadk/studio/codex_builder.py +54 -15
- ksadk/studio/codex_manifest.py +21 -1
- ksadk/studio/codex_run.py +16 -4
- ksadk/studio/compatibility_report.py +445 -0
- ksadk/studio/compiler.py +6 -1
- ksadk/studio/contracts.py +123 -4
- ksadk/studio/dsh_provider_registration.py +768 -0
- ksadk/studio/event_store.py +54 -6
- ksadk/studio/framework_run.py +37 -4
- ksadk/studio/hosted_kernel.py +1 -1
- ksadk/studio/operations.py +12 -2
- ksadk/studio/plugin_composition.py +301 -0
- ksadk/studio/plugin_kernel_adapter.py +128 -0
- ksadk/studio/plugin_runtime.py +652 -0
- ksadk/studio/resource_catalog.py +6 -1
- ksadk/studio/run_service.py +713 -75
- ksadk/studio/runtime_source.py +9 -1
- ksadk/studio/scheduler_runtime.py +374 -0
- ksadk/studio/scheduler_service.py +211 -0
- ksadk/studio/service.py +672 -82
- ksadk/studio/shared_web.py +167 -28
- ksadk/studio/soul.py +52 -0
- ksadk/studio/static/assets/index-DXs1Eq4M.css +1 -0
- ksadk/studio/static/assets/index-DeDqwTsD.js +283 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/studio/validator.py +1 -1
- ksadk/studio/workspace.py +1 -0
- ksadk/version.py +1 -1
- ksadk_runtime_common/workspace_files/path_utils.py +41 -0
- ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +0 -1
- ksadk/server/static/assets/channel-4cQHKtx1.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +0 -1
- ksadk/server/static/assets/index-8ipRcQ-M.js +0 -240
- ksadk/server/static/assets/index-ByFCqjlh.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +0 -1
- ksadk/studio/static/assets/index-BLpcdrgW.css +0 -1
- ksadk/studio/static/assets/index-CYekR2Xv.js +0 -260
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/top_level.txt +0 -0
ksadk/codex/runtime.py
CHANGED
|
@@ -107,11 +107,13 @@ class CodexRuntimeAdapter(RuntimeAdapter):
|
|
|
107
107
|
*,
|
|
108
108
|
sandbox_read_only: bool = True,
|
|
109
109
|
turn_timeout_seconds: Optional[float] = None,
|
|
110
|
+
bound_skill_paths: Mapping[str, str] | None = None,
|
|
110
111
|
) -> None:
|
|
111
112
|
super().__init__(_CodexAsBaseRuntime(client))
|
|
112
113
|
self._client = client
|
|
113
114
|
self._sandbox_read_only = sandbox_read_only
|
|
114
115
|
self._turn_timeout_seconds = turn_timeout_seconds
|
|
116
|
+
self._bound_skill_paths = dict(bound_skill_paths or {})
|
|
115
117
|
self._threads: dict[str, _CodexThread] = {}
|
|
116
118
|
self._requests: dict[str, StartRequest] = {}
|
|
117
119
|
self._known_threads: set[str] = set()
|
|
@@ -147,6 +149,7 @@ class CodexRuntimeAdapter(RuntimeAdapter):
|
|
|
147
149
|
goal=RuntimeCapability(supported=True, mode="native"),
|
|
148
150
|
loop=_unavailable("codex_loop_requires_run_control_spec"),
|
|
149
151
|
plan=RuntimeCapability(supported=True, mode="native"),
|
|
152
|
+
interaction_mode="live_submit",
|
|
150
153
|
)
|
|
151
154
|
|
|
152
155
|
# ---- 六动词 ----
|
|
@@ -154,6 +157,25 @@ class CodexRuntimeAdapter(RuntimeAdapter):
|
|
|
154
157
|
async def start(self, request: StartRequest) -> RunHandle:
|
|
155
158
|
# 新 thread 由后端分配真实 thread_id(thread_start);metadata 携带的 thread_id
|
|
156
159
|
# 表示接入既有 thread(resume 语义,run_turn 时按 resume 接入)。
|
|
160
|
+
if self._bound_skill_paths:
|
|
161
|
+
skills = request.config.get("skills") if request.config else None
|
|
162
|
+
if isinstance(skills, list):
|
|
163
|
+
projected_skills = []
|
|
164
|
+
for item in skills:
|
|
165
|
+
if not isinstance(item, dict):
|
|
166
|
+
continue
|
|
167
|
+
name = str(item.get("name") or "").strip()
|
|
168
|
+
projected_skills.append(
|
|
169
|
+
{
|
|
170
|
+
**item,
|
|
171
|
+
"path": self._bound_skill_paths.get(
|
|
172
|
+
name, str(item.get("path") or "")
|
|
173
|
+
),
|
|
174
|
+
}
|
|
175
|
+
)
|
|
176
|
+
request = request.model_copy(
|
|
177
|
+
update={"config": {**request.config, "skills": projected_skills}}
|
|
178
|
+
)
|
|
157
179
|
provided = request.metadata.get("thread_id")
|
|
158
180
|
if provided:
|
|
159
181
|
thread_id = str(provided)
|
|
@@ -353,23 +375,43 @@ class CodexRuntimeAdapter(RuntimeAdapter):
|
|
|
353
375
|
)
|
|
354
376
|
|
|
355
377
|
async def close(self, handle: RunHandle) -> None:
|
|
378
|
+
self._do_not_persist.add(handle.run_id)
|
|
379
|
+
await self.close_all()
|
|
380
|
+
|
|
381
|
+
async def close_all(self) -> None:
|
|
382
|
+
"""Dispose every thread and the activation-owned App Server process.
|
|
383
|
+
|
|
384
|
+
One ``CodexRuntimeAdapter`` owns one client transport. Closing any
|
|
385
|
+
attached Kernel handle therefore closes the transport as a unit; this
|
|
386
|
+
additive helper also lets a draining AgentProvider clean up a runtime
|
|
387
|
+
that has been created but not started yet.
|
|
388
|
+
"""
|
|
389
|
+
|
|
356
390
|
if self._closed:
|
|
357
391
|
return
|
|
358
392
|
self._closed = True
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
393
|
+
threads = tuple(self._threads.values())
|
|
394
|
+
active_threads = tuple(
|
|
395
|
+
thread for thread in threads if thread.streaming and not thread.done
|
|
396
|
+
)
|
|
397
|
+
for thread in active_threads:
|
|
363
398
|
thread.interrupt_event.set()
|
|
364
399
|
try:
|
|
365
|
-
|
|
400
|
+
for thread in active_threads:
|
|
366
401
|
await self._client.interrupt_active_turn(thread.thread_id)
|
|
367
402
|
finally:
|
|
368
403
|
# AsyncCodex.close owns terminate/wait/kill for the app-server child.
|
|
369
404
|
await self._client.close()
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
405
|
+
thread_ids = {
|
|
406
|
+
*self._known_threads,
|
|
407
|
+
*self._threads,
|
|
408
|
+
*self._requests,
|
|
409
|
+
}
|
|
410
|
+
self._do_not_persist.update(thread_ids)
|
|
411
|
+
self._threads.clear()
|
|
412
|
+
self._requests.clear()
|
|
413
|
+
self._known_threads.clear()
|
|
414
|
+
self._pending_cancels.clear()
|
|
373
415
|
|
|
374
416
|
# ---- stream → RuntimeEvent(phase 翻译 + 中断竞速) ----
|
|
375
417
|
|
ksadk/configs/env_registry.py
CHANGED
|
@@ -232,6 +232,28 @@ _ENV_VAR_REGISTRY_ITEMS: tuple[EnvVarSpec, ...] = (
|
|
|
232
232
|
"Isolate native Codex state under the project workspace; set to 0 for debugging only.",
|
|
233
233
|
"1",
|
|
234
234
|
),
|
|
235
|
+
EnvVarSpec(
|
|
236
|
+
"KSADK_DSH_BIN",
|
|
237
|
+
"plugins",
|
|
238
|
+
(
|
|
239
|
+
"Optional absolute path to the managed DSH command; must match the pinned "
|
|
240
|
+
"toolchain version."
|
|
241
|
+
),
|
|
242
|
+
),
|
|
243
|
+
EnvVarSpec(
|
|
244
|
+
"KSADK_DSH_HOME",
|
|
245
|
+
"plugins",
|
|
246
|
+
(
|
|
247
|
+
"Directory containing the isolated DSH Profile; defaults to .agentkit/dsh-home "
|
|
248
|
+
"in the workspace."
|
|
249
|
+
),
|
|
250
|
+
),
|
|
251
|
+
EnvVarSpec(
|
|
252
|
+
"KSADK_DSH_PROFILE",
|
|
253
|
+
"plugins",
|
|
254
|
+
"DSH Profile name used by Studio and the plugin bridge.",
|
|
255
|
+
"studio",
|
|
256
|
+
),
|
|
235
257
|
EnvVarSpec(
|
|
236
258
|
"KSADK_STUDIO_NO_SECURITY",
|
|
237
259
|
"studio",
|
|
@@ -356,7 +378,10 @@ _ENV_VAR_REGISTRY_ITEMS: tuple[EnvVarSpec, ...] = (
|
|
|
356
378
|
EnvVarSpec(
|
|
357
379
|
"KSADK_LANGGRAPH_AUTO_CHECKPOINT",
|
|
358
380
|
"sessions",
|
|
359
|
-
|
|
381
|
+
(
|
|
382
|
+
"Allow a hosted LangGraph runner to rebuild a factory-exported graph with the "
|
|
383
|
+
"managed PostgreSQL saver."
|
|
384
|
+
),
|
|
360
385
|
"false",
|
|
361
386
|
),
|
|
362
387
|
EnvVarSpec(
|
|
@@ -640,7 +665,10 @@ _ENV_VAR_REGISTRY_ITEMS: tuple[EnvVarSpec, ...] = (
|
|
|
640
665
|
EnvVarSpec(
|
|
641
666
|
"KSADK_AGENT_KERNEL",
|
|
642
667
|
"kernel",
|
|
643
|
-
|
|
668
|
+
(
|
|
669
|
+
"Opt in to Agent Kernel ingress locally; managed deployment may use "
|
|
670
|
+
"AGENT_KERNEL_ENABLED instead."
|
|
671
|
+
),
|
|
644
672
|
"false",
|
|
645
673
|
),
|
|
646
674
|
EnvVarSpec("KSADK_SESSION_PATH", "sessions", "Conversation local SQLite database path."),
|
|
@@ -810,7 +838,7 @@ _ENV_VAR_REGISTRY_ITEMS: tuple[EnvVarSpec, ...] = (
|
|
|
810
838
|
"KSADK_WEB_VERSION",
|
|
811
839
|
"web",
|
|
812
840
|
"Published KsADK Web npm version used for a reproducible wheel build.",
|
|
813
|
-
"0.3.
|
|
841
|
+
"0.3.4",
|
|
814
842
|
),
|
|
815
843
|
EnvVarSpec(
|
|
816
844
|
"KSADK_WORKING_SET_MAX_FILES",
|
ksadk/configs/settings.py
CHANGED
|
@@ -628,3 +628,12 @@ def setup_environment(agent_path: Path | str):
|
|
|
628
628
|
setup_proxy_redirect_if_enabled()
|
|
629
629
|
except Exception: # noqa: BLE001 代理可选,失败不影响主流程(默认关时本就不触发)
|
|
630
630
|
pass
|
|
631
|
+
|
|
632
|
+
# 5. 沙箱控制面 URL 内网探测:在 Pod 内探测 198 公共服务网内网地址,
|
|
633
|
+
# 可达则覆盖 E2B_API_URL 为内网域名,private_only 节点也能访问沙箱控制面。
|
|
634
|
+
try:
|
|
635
|
+
from ksadk.sandbox import setup_sandbox_api_url_if_needed
|
|
636
|
+
|
|
637
|
+
setup_sandbox_api_url_if_needed()
|
|
638
|
+
except Exception: # noqa: BLE001 沙箱可选,失败不影响主流程
|
|
639
|
+
pass
|
|
@@ -24,6 +24,14 @@ logger = logging.getLogger(__name__)
|
|
|
24
24
|
ContributorFailureMode = Literal["skip", "warn", "fail"]
|
|
25
25
|
ContributorCacheability = Literal["stable", "turn", "none"]
|
|
26
26
|
|
|
27
|
+
_TRUST_RANK: dict[ContextTrustLevel, int] = {
|
|
28
|
+
"untrusted": 0,
|
|
29
|
+
"user": 1,
|
|
30
|
+
"resource": 2,
|
|
31
|
+
"developer": 3,
|
|
32
|
+
"platform": 4,
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
|
|
28
36
|
@dataclass(frozen=True)
|
|
29
37
|
class ContributorCapabilities:
|
|
@@ -131,13 +139,15 @@ class WorkspaceRulesContributor(ContextContributor):
|
|
|
131
139
|
return []
|
|
132
140
|
items: list[ContextItem] = []
|
|
133
141
|
for index, section in enumerate(sections):
|
|
142
|
+
raw_tokens = section.metadata.get("tokens", 0)
|
|
143
|
+
tokens = int(raw_tokens) if isinstance(raw_tokens, (int, str)) else 0
|
|
134
144
|
items.append(
|
|
135
145
|
_make_item(
|
|
136
146
|
contributor_id=self.capabilities.contributor_id,
|
|
137
147
|
trust_level=self.capabilities.trust_level,
|
|
138
148
|
kind="resource_manifest",
|
|
139
149
|
content=section.content,
|
|
140
|
-
tokens=
|
|
150
|
+
tokens=tokens or 1,
|
|
141
151
|
source=section.source,
|
|
142
152
|
metadata={"path": section.metadata.get("path"), "kind": "rule_file"},
|
|
143
153
|
)
|
|
@@ -267,6 +277,60 @@ class ContributionResult:
|
|
|
267
277
|
warnings: tuple[str, ...]
|
|
268
278
|
|
|
269
279
|
|
|
280
|
+
def _admit_contribution_items(
|
|
281
|
+
contributor: ContextContributor,
|
|
282
|
+
items: object,
|
|
283
|
+
) -> tuple[list[ContextItem], str | None]:
|
|
284
|
+
"""Validate one Contributor result and enforce its declared token ceiling.
|
|
285
|
+
|
|
286
|
+
A Contributor is an untrusted capability boundary. It cannot promote an
|
|
287
|
+
item above the trust level granted at registration, mark context as
|
|
288
|
+
required, return duplicate identities, or make the Host confuse token
|
|
289
|
+
counts with list indexes. Items that do not fit the declared budget are
|
|
290
|
+
deterministically omitted while later, smaller items may still fit.
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
if not isinstance(items, list) or not all(isinstance(item, ContextItem) for item in items):
|
|
294
|
+
raise TypeError("ContextContributor must return a list of ContextItem values")
|
|
295
|
+
|
|
296
|
+
capabilities = contributor.capabilities
|
|
297
|
+
if capabilities.max_tokens < 0:
|
|
298
|
+
raise ValueError("ContextContributor max_tokens cannot be negative")
|
|
299
|
+
if capabilities.timeout_ms <= 0:
|
|
300
|
+
raise ValueError("ContextContributor timeout_ms must be positive")
|
|
301
|
+
|
|
302
|
+
admitted: list[ContextItem] = []
|
|
303
|
+
seen_ids: set[str] = set()
|
|
304
|
+
used_tokens = 0
|
|
305
|
+
omitted = 0
|
|
306
|
+
maximum_trust = _TRUST_RANK[capabilities.trust_level]
|
|
307
|
+
for item in items:
|
|
308
|
+
if not item.item_id or item.item_id in seen_ids:
|
|
309
|
+
raise ValueError("ContextContributor item ids must be non-empty and unique")
|
|
310
|
+
seen_ids.add(item.item_id)
|
|
311
|
+
if item.required:
|
|
312
|
+
raise ValueError("ContextContributor cannot mark context as required")
|
|
313
|
+
if _TRUST_RANK[item.trust_level] > maximum_trust:
|
|
314
|
+
raise ValueError(
|
|
315
|
+
"ContextContributor cannot elevate item trust above its registered level"
|
|
316
|
+
)
|
|
317
|
+
if item.estimated_tokens < 0:
|
|
318
|
+
raise ValueError("ContextContributor estimated_tokens cannot be negative")
|
|
319
|
+
if used_tokens + item.estimated_tokens > capabilities.max_tokens:
|
|
320
|
+
omitted += 1
|
|
321
|
+
continue
|
|
322
|
+
admitted.append(item)
|
|
323
|
+
used_tokens += item.estimated_tokens
|
|
324
|
+
|
|
325
|
+
warning = None
|
|
326
|
+
if omitted:
|
|
327
|
+
warning = (
|
|
328
|
+
f"{contributor.id()}: omitted {omitted} context item(s) that exceeded "
|
|
329
|
+
f"the {capabilities.max_tokens}-token contributor budget"
|
|
330
|
+
)
|
|
331
|
+
return admitted, warning
|
|
332
|
+
|
|
333
|
+
|
|
270
334
|
async def run_contributors(
|
|
271
335
|
contributors: Sequence[ContextContributor],
|
|
272
336
|
request: ContextContributionRequest,
|
|
@@ -284,24 +348,25 @@ async def run_contributors(
|
|
|
284
348
|
async def _run_one(c: ContextContributor) -> tuple[str, list[ContextItem], str, str | None]:
|
|
285
349
|
timeout = max(c.capabilities.timeout_ms, 1) / 1000.0
|
|
286
350
|
try:
|
|
287
|
-
|
|
351
|
+
raw_items = await asyncio.wait_for(c.contribute(request), timeout=timeout)
|
|
352
|
+
items, budget_warning = _admit_contribution_items(c, raw_items)
|
|
288
353
|
except asyncio.TimeoutError:
|
|
289
354
|
return c.id(), [], "timeout", f"{c.id()}: timeout"
|
|
290
355
|
except Exception as exc: # noqa: BLE001
|
|
291
356
|
if c.capabilities.failure_mode == "fail":
|
|
292
357
|
raise
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
items = items[: c.capabilities.max_tokens] # best-effort 限条数
|
|
297
|
-
return c.id(), items, "ok", None
|
|
358
|
+
warning = f"{c.id()}: {exc}" if c.capabilities.failure_mode == "warn" else None
|
|
359
|
+
return c.id(), [], "error", warning
|
|
360
|
+
return c.id(), items, "ok", budget_warning
|
|
298
361
|
|
|
299
362
|
results = await asyncio.gather(*[_run_one(c) for c in contributors], return_exceptions=True)
|
|
300
363
|
all_items: list[ContextItem] = []
|
|
301
364
|
status: dict[str, str] = {}
|
|
302
365
|
warnings: list[str] = []
|
|
303
366
|
for contributor, r in zip(contributors, results):
|
|
304
|
-
if isinstance(r,
|
|
367
|
+
if isinstance(r, BaseException):
|
|
368
|
+
if isinstance(r, asyncio.CancelledError):
|
|
369
|
+
raise r
|
|
305
370
|
if contributor.capabilities.failure_mode == "fail":
|
|
306
371
|
raise r
|
|
307
372
|
warnings.append(f"{contributor.id()}: {r}")
|
ksadk/conversations/__init__.py
CHANGED
|
@@ -11,6 +11,25 @@ def _exports(module: str, *names: str) -> dict[str, tuple[str, str]]:
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
_EXPORTS = {
|
|
14
|
+
**_exports(
|
|
15
|
+
"ksadk.conversations.contracts",
|
|
16
|
+
"ConversationCapability",
|
|
17
|
+
"ConversationInput",
|
|
18
|
+
"ConversationAttachmentPart",
|
|
19
|
+
"ConversationItem",
|
|
20
|
+
"ConversationSurface",
|
|
21
|
+
"ConversationTextPart",
|
|
22
|
+
"validate_conversation_input",
|
|
23
|
+
"validate_surface_input",
|
|
24
|
+
),
|
|
25
|
+
**_exports(
|
|
26
|
+
"ksadk.conversations.projector",
|
|
27
|
+
"project_conversation_item",
|
|
28
|
+
),
|
|
29
|
+
**_exports(
|
|
30
|
+
"ksadk.conversations.reducer",
|
|
31
|
+
"ConversationItemReducer",
|
|
32
|
+
),
|
|
14
33
|
**_exports(
|
|
15
34
|
"ksadk.conversations.attachments",
|
|
16
35
|
"decode_inline_data",
|
ksadk/conversations/context.py
CHANGED
|
@@ -5,6 +5,8 @@ import re
|
|
|
5
5
|
from collections.abc import Mapping, Sequence
|
|
6
6
|
from typing import Any, Dict, Iterable, List
|
|
7
7
|
|
|
8
|
+
from ksadk.events.canonical import ItemCompleted, parse_runtime_event
|
|
9
|
+
from ksadk.events.content import TextContent
|
|
8
10
|
from ksadk.sessions.base import SessionEvent
|
|
9
11
|
from ksadk.tools.result_budget import (
|
|
10
12
|
ToolResultBudget,
|
|
@@ -99,6 +101,60 @@ def extract_event_text(event: SessionEvent) -> str:
|
|
|
99
101
|
)
|
|
100
102
|
|
|
101
103
|
|
|
104
|
+
def _canonical_completed_message(
|
|
105
|
+
event: SessionEvent,
|
|
106
|
+
) -> tuple[str, str, tuple[str, str]] | None:
|
|
107
|
+
"""Return one canonical assistant message without flattening its identity.
|
|
108
|
+
|
|
109
|
+
Canonical RuntimeEvents are persisted inside the existing ``SessionEvent``
|
|
110
|
+
carrier. Legacy transcript projection only inspects carrier-level fields,
|
|
111
|
+
so an ``item.completed`` message otherwise disappears from the next turn's
|
|
112
|
+
history. The canonical event id and ``(scope_id, item_id)`` are both kept:
|
|
113
|
+
replays are idempotent, while equal text from different items remains
|
|
114
|
+
distinct.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
raw = (event.content or {}).get("runtime_event")
|
|
118
|
+
if not isinstance(raw, Mapping):
|
|
119
|
+
return None
|
|
120
|
+
try:
|
|
121
|
+
canonical = parse_runtime_event(dict(raw))
|
|
122
|
+
except (TypeError, ValueError):
|
|
123
|
+
return None
|
|
124
|
+
if (
|
|
125
|
+
not isinstance(canonical, ItemCompleted)
|
|
126
|
+
or canonical.item_kind != "message"
|
|
127
|
+
or event.event_type != canonical.event_type
|
|
128
|
+
):
|
|
129
|
+
return None
|
|
130
|
+
text = sanitize_event_text_for_context(
|
|
131
|
+
"".join(
|
|
132
|
+
part.text for part in canonical.snapshot.parts if isinstance(part, TextContent)
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
if not text:
|
|
136
|
+
return None
|
|
137
|
+
return canonical.event_id, text, (canonical.scope_id, canonical.item_id)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _transcript_event_projection(
|
|
141
|
+
event: SessionEvent,
|
|
142
|
+
) -> tuple[str, str, tuple[str, tuple[str, str]] | None]:
|
|
143
|
+
canonical_message = _canonical_completed_message(event)
|
|
144
|
+
if canonical_message is not None:
|
|
145
|
+
event_id, text, item_identity = canonical_message
|
|
146
|
+
return "assistant_message", text, (event_id, item_identity)
|
|
147
|
+
return (
|
|
148
|
+
canonical_event_type(
|
|
149
|
+
event.event_type,
|
|
150
|
+
author=event.author,
|
|
151
|
+
role=str((event.content or {}).get("role") or ""),
|
|
152
|
+
),
|
|
153
|
+
extract_event_text(event),
|
|
154
|
+
None,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
102
158
|
def canonical_event_type(
|
|
103
159
|
event_type: str | None,
|
|
104
160
|
*,
|
|
@@ -276,6 +332,8 @@ def summarize_event_groups(
|
|
|
276
332
|
因此跨消息提取修正,并在预算上限内保留最新长指令首尾(方案 §9.4)。
|
|
277
333
|
"""
|
|
278
334
|
lines: List[str] = []
|
|
335
|
+
seen_canonical_event_ids: set[str] = set()
|
|
336
|
+
seen_canonical_items: set[tuple[str, str]] = set()
|
|
279
337
|
if previous_summary:
|
|
280
338
|
lines.append(previous_summary)
|
|
281
339
|
lines.append("Earlier conversation summary:")
|
|
@@ -284,14 +342,18 @@ def summarize_event_groups(
|
|
|
284
342
|
for group in groups:
|
|
285
343
|
snippets: List[str] = []
|
|
286
344
|
for event in group:
|
|
287
|
-
event_type =
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
345
|
+
event_type, text, canonical_identity = _transcript_event_projection(event)
|
|
346
|
+
if canonical_identity is not None:
|
|
347
|
+
event_id, item_identity = canonical_identity
|
|
348
|
+
if (
|
|
349
|
+
event_id in seen_canonical_event_ids
|
|
350
|
+
or item_identity in seen_canonical_items
|
|
351
|
+
):
|
|
352
|
+
continue
|
|
353
|
+
seen_canonical_event_ids.add(event_id)
|
|
354
|
+
seen_canonical_items.add(item_identity)
|
|
292
355
|
if event_type not in TRANSCRIPT_EVENT_TYPES or event_type == "context_checkpoint":
|
|
293
356
|
continue
|
|
294
|
-
text = extract_event_text(event)
|
|
295
357
|
if not text:
|
|
296
358
|
continue
|
|
297
359
|
if event_type in {"assistant_message", "tool_call"}:
|
|
@@ -343,6 +405,9 @@ def project_model_messages(
|
|
|
343
405
|
"""
|
|
344
406
|
projected: List[Dict[str, str]] = []
|
|
345
407
|
placeholder_flags: list[bool] = []
|
|
408
|
+
identity_boundary_flags: list[bool] = []
|
|
409
|
+
seen_canonical_event_ids: set[str] = set()
|
|
410
|
+
seen_canonical_items: set[tuple[str, str]] = set()
|
|
346
411
|
compacted_until = compacted_until_seq_id(events)
|
|
347
412
|
checkpoint = next(
|
|
348
413
|
(
|
|
@@ -362,21 +427,26 @@ def project_model_messages(
|
|
|
362
427
|
}
|
|
363
428
|
)
|
|
364
429
|
placeholder_flags.append(False)
|
|
430
|
+
identity_boundary_flags.append(False)
|
|
365
431
|
|
|
366
432
|
for event in events:
|
|
367
|
-
event_type =
|
|
368
|
-
event.event_type,
|
|
369
|
-
author=event.author,
|
|
370
|
-
role=str((event.content or {}).get("role") or ""),
|
|
371
|
-
)
|
|
433
|
+
event_type, text, canonical_identity = _transcript_event_projection(event)
|
|
372
434
|
if event.seq_id <= compacted_until and event_type != "context_checkpoint":
|
|
373
435
|
continue
|
|
374
436
|
if event_type not in TRANSCRIPT_EVENT_TYPES:
|
|
375
437
|
continue
|
|
376
438
|
if event_type in {"context_checkpoint", "compaction_boundary"}:
|
|
377
439
|
continue
|
|
440
|
+
if canonical_identity is not None:
|
|
441
|
+
event_id, item_identity = canonical_identity
|
|
442
|
+
if (
|
|
443
|
+
event_id in seen_canonical_event_ids
|
|
444
|
+
or item_identity in seen_canonical_items
|
|
445
|
+
):
|
|
446
|
+
continue
|
|
447
|
+
seen_canonical_event_ids.add(event_id)
|
|
448
|
+
seen_canonical_items.add(item_identity)
|
|
378
449
|
|
|
379
|
-
text = extract_event_text(event)
|
|
380
450
|
if not text:
|
|
381
451
|
continue
|
|
382
452
|
|
|
@@ -405,12 +475,15 @@ def project_model_messages(
|
|
|
405
475
|
projected
|
|
406
476
|
and projected[-1]["role"] == role
|
|
407
477
|
and not placeholder_flags[-1]
|
|
478
|
+
and not identity_boundary_flags[-1]
|
|
408
479
|
and not is_placeholder
|
|
480
|
+
and canonical_identity is None
|
|
409
481
|
):
|
|
410
482
|
projected[-1]["content"] = f"{projected[-1]['content']}\n{text}".strip()
|
|
411
483
|
else:
|
|
412
484
|
projected.append({"role": role, "content": text})
|
|
413
485
|
placeholder_flags.append(is_placeholder)
|
|
486
|
+
identity_boundary_flags.append(canonical_identity is not None)
|
|
414
487
|
|
|
415
488
|
return projected
|
|
416
489
|
|
|
@@ -553,6 +626,8 @@ def project_responses_history(events: List[SessionEvent]) -> List[dict[str, Any]
|
|
|
553
626
|
"""
|
|
554
627
|
projected: List[dict[str, Any]] = []
|
|
555
628
|
projected_call_ids: set[str] = set()
|
|
629
|
+
seen_canonical_event_ids: set[str] = set()
|
|
630
|
+
seen_canonical_items: set[tuple[str, str]] = set()
|
|
556
631
|
compacted_until = compacted_until_seq_id(events)
|
|
557
632
|
checkpoint = next(
|
|
558
633
|
(
|
|
@@ -568,17 +643,22 @@ def project_responses_history(events: List[SessionEvent]) -> List[dict[str, Any]
|
|
|
568
643
|
projected.append(summary_message)
|
|
569
644
|
|
|
570
645
|
for event in events:
|
|
571
|
-
event_type =
|
|
572
|
-
event.event_type,
|
|
573
|
-
author=event.author,
|
|
574
|
-
role=str((event.content or {}).get("role") or ""),
|
|
575
|
-
)
|
|
646
|
+
event_type, text, canonical_identity = _transcript_event_projection(event)
|
|
576
647
|
if event.seq_id <= compacted_until and event_type != "context_checkpoint":
|
|
577
648
|
continue
|
|
578
649
|
if event_type not in TRANSCRIPT_EVENT_TYPES:
|
|
579
650
|
continue
|
|
580
651
|
if event_type in {"context_checkpoint", "compaction_boundary"}:
|
|
581
652
|
continue
|
|
653
|
+
if canonical_identity is not None:
|
|
654
|
+
event_id, item_identity = canonical_identity
|
|
655
|
+
if (
|
|
656
|
+
event_id in seen_canonical_event_ids
|
|
657
|
+
or item_identity in seen_canonical_items
|
|
658
|
+
):
|
|
659
|
+
continue
|
|
660
|
+
seen_canonical_event_ids.add(event_id)
|
|
661
|
+
seen_canonical_items.add(item_identity)
|
|
582
662
|
|
|
583
663
|
if event_type == "tool_call":
|
|
584
664
|
item = _response_tool_call_item(event)
|
|
@@ -586,25 +666,25 @@ def project_responses_history(events: List[SessionEvent]) -> List[dict[str, Any]
|
|
|
586
666
|
projected.append(item)
|
|
587
667
|
projected_call_ids.add(str(item["call_id"]))
|
|
588
668
|
continue
|
|
589
|
-
message = _responses_message("assistant", f"[tool_call] {
|
|
669
|
+
message = _responses_message("assistant", f"[tool_call] {text}")
|
|
590
670
|
elif event_type == "tool_result":
|
|
591
671
|
item = _response_tool_output_item(event)
|
|
592
672
|
if item and str(item["call_id"]) in projected_call_ids:
|
|
593
673
|
projected.append(item)
|
|
594
674
|
continue
|
|
595
|
-
message = _responses_message("user", f"[tool_result] {
|
|
675
|
+
message = _responses_message("user", f"[tool_result] {text}")
|
|
596
676
|
elif event_type == "assistant_message":
|
|
597
|
-
message = _responses_message("assistant",
|
|
677
|
+
message = _responses_message("assistant", text)
|
|
598
678
|
elif event_type == "approval_request":
|
|
599
679
|
message = _responses_message(
|
|
600
|
-
"assistant", f"[approval_request] {
|
|
680
|
+
"assistant", f"[approval_request] {text}"
|
|
601
681
|
)
|
|
602
682
|
elif event_type == "approval_response":
|
|
603
|
-
message = _responses_message("user", f"[approval_response] {
|
|
683
|
+
message = _responses_message("user", f"[approval_response] {text}")
|
|
604
684
|
elif event_type == "attachment_ref":
|
|
605
|
-
message = _responses_message("user", f"[attachment] {
|
|
685
|
+
message = _responses_message("user", f"[attachment] {text}")
|
|
606
686
|
else:
|
|
607
|
-
message = _responses_message("user",
|
|
687
|
+
message = _responses_message("user", text)
|
|
608
688
|
if message:
|
|
609
689
|
projected.append(message)
|
|
610
690
|
|