agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.0__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.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +36 -20
- agentengine_sdk_python-0.8.0.dist-info/RECORD +578 -0
- ksadk/a2a/__init__.py +178 -11
- ksadk/a2a/bootstrap.py +334 -0
- ksadk/a2a/card.py +120 -0
- ksadk/a2a/context_store.py +203 -0
- ksadk/a2a/control_plane.py +818 -0
- ksadk/a2a/credential.py +99 -0
- ksadk/a2a/event_adapter.py +149 -0
- ksadk/a2a/executor.py +406 -89
- ksadk/a2a/external_transport.py +516 -0
- ksadk/a2a/identity.py +304 -0
- ksadk/a2a/ids.py +22 -0
- ksadk/a2a/langgraph.py +285 -0
- ksadk/a2a/resume_store.py +201 -0
- ksadk/a2a/routes.py +105 -0
- ksadk/a2a/server.py +107 -60
- ksadk/a2a/space_client.py +1101 -0
- ksadk/a2a/task_adapter.py +423 -0
- ksadk/a2a/task_event_dispatcher.py +167 -0
- ksadk/a2a/task_event_outbox.py +326 -0
- ksadk/a2a/task_store.py +206 -0
- ksadk/a2ui/__init__.py +27 -0
- ksadk/a2ui/core.py +186 -0
- ksadk/a2ui/models.py +166 -0
- ksadk/a2ui/renderer.py +198 -0
- ksadk/agui/__init__.py +9 -0
- ksadk/agui/a2ui_projection.py +92 -0
- ksadk/agui/agent.py +857 -0
- ksadk/agui/config.py +86 -0
- ksadk/agui/routes.py +55 -0
- ksadk/api/client.py +233 -191
- ksadk/builders/__init__.py +2 -0
- ksadk/builders/base.py +16 -14
- ksadk/builders/code_builder.py +318 -236
- ksadk/builders/container_builder.py +187 -167
- ksadk/builders/framework_requirements.py +29 -11
- ksadk/builders/ks3_uploader.py +58 -27
- ksadk/builders/managed_runtime_builder.py +145 -0
- ksadk/builders/mcp_builder.py +91 -92
- ksadk/builders/requirements_utils.py +1 -5
- ksadk/cli/__init__.py +89 -171
- ksadk/cli/cmd_a2a.py +254 -70
- ksadk/cli/cmd_agent.py +19 -5
- ksadk/cli/cmd_build.py +158 -29
- ksadk/cli/cmd_completion.py +47 -35
- ksadk/cli/cmd_config.py +267 -198
- ksadk/cli/cmd_create.py +500 -720
- ksadk/cli/cmd_dashboard.py +120 -45
- ksadk/cli/cmd_deploy.py +117 -58
- ksadk/cli/cmd_destroy.py +44 -14
- ksadk/cli/cmd_files.py +63 -24
- ksadk/cli/cmd_hermes.py +168 -89
- ksadk/cli/cmd_invoke.py +184 -122
- ksadk/cli/cmd_launch.py +64 -28
- ksadk/cli/cmd_mcp.py +98 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +483 -227
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +33 -10
- ksadk/cli/cmd_status.py +80 -31
- ksadk/cli/cmd_version.py +20 -13
- ksadk/cli/cmd_web.py +89 -13
- ksadk/cli/deploy_utils.py +20 -20
- ksadk/cli/dry_run.py +5 -3
- ksadk/cli/error_utils.py +37 -12
- ksadk/cli/global_options.py +1 -2
- ksadk/cli/local_runtime.py +1 -2
- ksadk/cli/model_catalog.py +6 -2
- ksadk/cli/network_options.py +34 -14
- ksadk/cli/resource_common.py +6 -2
- ksadk/cli/storage.py +0 -1
- ksadk/cli/ui.py +5 -3
- ksadk/cli/workflow_common.py +51 -17
- ksadk/codex/__init__.py +12 -0
- ksadk/codex/client.py +408 -0
- ksadk/codex/phase.py +143 -0
- ksadk/codex/runtime.py +449 -0
- ksadk/common/aicp_env.py +0 -1
- ksadk/common/auth.py +2 -2
- ksadk/common/constants.py +1 -3
- ksadk/common/llm_utils.py +17 -13
- ksadk/compat/__init__.py +5 -0
- ksadk/compat/adk_compat.py +200 -0
- ksadk/compat/copilotkit_a2ui.py +330 -0
- ksadk/configs/__init__.py +12 -12
- ksadk/configs/env_registry.py +500 -100
- ksadk/configs/global_config.py +2 -1
- ksadk/configs/settings.py +151 -124
- ksadk/conversations/__init__.py +7 -5
- ksadk/conversations/attachment_storage.py +16 -11
- ksadk/conversations/attachments.py +44 -36
- ksadk/conversations/compaction_pipeline.py +12 -12
- ksadk/conversations/compaction_prompt.py +9 -5
- ksadk/conversations/context.py +221 -6
- ksadk/conversations/message_projection.py +438 -51
- ksadk/conversations/model_context.py +12 -6
- ksadk/conversations/model_options.py +0 -1
- ksadk/conversations/normalize.py +20 -16
- ksadk/conversations/reasoning_markup.py +1 -1
- ksadk/conversations/runtime.py +339 -5255
- ksadk/conversations/runtime_compaction.py +333 -0
- ksadk/conversations/runtime_constants.py +27 -0
- ksadk/conversations/runtime_governance.py +185 -0
- ksadk/conversations/runtime_input.py +652 -0
- ksadk/conversations/runtime_invocation.py +395 -0
- ksadk/conversations/runtime_metadata.py +475 -0
- ksadk/conversations/runtime_observability.py +355 -0
- ksadk/conversations/runtime_payloads.py +272 -0
- ksadk/conversations/runtime_persistence.py +440 -0
- ksadk/conversations/runtime_preparation.py +418 -0
- ksadk/conversations/runtime_resume.py +816 -0
- ksadk/conversations/runtime_stream_events.py +902 -0
- ksadk/conversations/runtime_streaming.py +547 -0
- ksadk/conversations/semantic_summary.py +17 -5
- ksadk/conversations/session_title.py +6 -3
- ksadk/deployment/__init__.py +15 -16
- ksadk/deployment/agent_access.py +12 -23
- ksadk/deployment/base.py +51 -38
- ksadk/deployment/manager.py +63 -65
- ksadk/deployment/providers/serverless.py +309 -202
- ksadk/deployment/registry.py +38 -32
- ksadk/deployment/state.py +11 -11
- ksadk/deployment/ui_config.py +1 -1
- ksadk/detection/__init__.py +1 -1
- ksadk/detection/detector.py +146 -83
- ksadk/detection/mcp_detector.py +9 -6
- ksadk/events/__init__.py +25 -0
- ksadk/events/parser.py +191 -0
- ksadk/events/replay.py +37 -0
- ksadk/events/runtime_event.py +264 -0
- ksadk/events/store.py +317 -0
- ksadk/harness/__init__.py +34 -0
- ksadk/harness/app.py +278 -0
- ksadk/harness/config.py +181 -0
- ksadk/harness/reasoner.py +105 -0
- ksadk/harness/runner.py +211 -0
- ksadk/harness/sandbox.py +141 -0
- ksadk/harness/tools.py +222 -0
- ksadk/hermes_terminal.py +23 -12
- ksadk/identity/resolver.py +15 -9
- ksadk/ids.py +32 -0
- ksadk/knowledge_base/adk_tool.py +1 -1
- ksadk/knowledge_base/client.py +23 -29
- ksadk/managed_runtime.py +188 -0
- ksadk/markdown.py +5 -2
- ksadk/mcp_runtime/__init__.py +9 -6
- ksadk/memory/__init__.py +1 -1
- ksadk/memory/adk/__init__.py +2 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
- ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
- ksadk/memory/adk/backends/sdk_ltm_backend.py +26 -33
- ksadk/memory/adk/long_term_memory.py +31 -35
- ksadk/memory/adk/resilient_session_service.py +4 -5
- ksadk/memory/adk/short_term_memory.py +12 -21
- ksadk/memory/adk_tool.py +3 -2
- ksadk/memory/backends/base.py +19 -19
- ksadk/memory/backends/memory.py +24 -25
- ksadk/memory/backends/redis.py +31 -30
- ksadk/memory/langchain_tool.py +2 -1
- ksadk/memory/manager.py +52 -47
- ksadk/memory/service.py +10 -8
- ksadk/model_policy.py +15 -7
- ksadk/model_proxy/__init__.py +51 -0
- ksadk/model_proxy/bootstrap.py +80 -0
- ksadk/model_proxy/cache.py +165 -0
- ksadk/model_proxy/config.py +45 -0
- ksadk/model_proxy/demo_webui.py +115 -0
- ksadk/model_proxy/detect.py +145 -0
- ksadk/model_proxy/gate.py +68 -0
- ksadk/model_proxy/namespace.py +173 -0
- ksadk/model_proxy/protocol_proxy.py +22 -0
- ksadk/model_proxy/server.py +300 -0
- ksadk/model_proxy/transform.py +691 -0
- ksadk/openclaw_gateway.py +29 -14
- ksadk/runners/adk_runner.py +345 -120
- ksadk/runners/base_runner.py +46 -29
- ksadk/runners/codex_runner.py +132 -0
- ksadk/runners/deepagents_runner.py +0 -1
- ksadk/runners/factory.py +17 -5
- ksadk/runners/langchain_runner.py +29 -742
- ksadk/runners/langgraph_runner.py +352 -90
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +134 -33
- ksadk/runners/usage_accumulator.py +1 -0
- ksadk/runners/utils/langfuse.py +3 -3
- ksadk/runners/utils/loader.py +7 -7
- ksadk/runtime/__init__.py +41 -0
- ksadk/runtime/adapter.py +345 -0
- ksadk/runtime/framework_adapters.py +124 -0
- ksadk/runtime/preprocessing.py +118 -0
- ksadk/runtime/runner_adapter.py +873 -0
- ksadk/runtime_context.py +18 -3
- ksadk/runtime_state.py +0 -1
- ksadk/sandbox/__init__.py +4 -1
- ksadk/sandbox/backends/__init__.py +4 -1
- ksadk/sandbox/backends/e2b.py +13 -5
- ksadk/sandbox/backends/local_process.py +11 -3
- ksadk/sandbox/base.py +10 -15
- ksadk/sandbox/factory.py +14 -4
- ksadk/sandbox/registry.py +57 -6
- ksadk/server/api_models.py +15 -5
- ksadk/server/app.py +455 -3885
- ksadk/server/composition.py +21 -0
- ksadk/server/factory.py +624 -0
- ksadk/server/routes/__init__.py +1 -0
- ksadk/server/routes/checkpoint_resolution.py +116 -0
- ksadk/server/routes/common.py +713 -0
- ksadk/server/routes/control.py +327 -0
- ksadk/server/routes/dependencies.py +98 -0
- ksadk/server/routes/misc.py +448 -0
- ksadk/server/routes/models.py +443 -0
- ksadk/server/routes/openai_compat.py +207 -0
- ksadk/server/routes/projection.py +795 -0
- ksadk/server/routes/routers.py +52 -0
- ksadk/server/routes/run.py +726 -0
- ksadk/server/routes/sessions.py +649 -0
- ksadk/server/routes/streaming.py +223 -0
- ksadk/server/routes/workspace.py +381 -0
- ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-Cjnqt-8W.js} +1 -1
- ksadk/server/static/assets/CodeBlock-BqyqZfuB.js +9 -0
- ksadk/server/static/assets/MathMessageMarkdown-BpH7jiFM.js +8 -0
- ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +1 -0
- ksadk/server/static/assets/{arc-BA13sHc9.js → arc-CFKwSk_B.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
- ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-BK8paA20.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D98vPd-E.js} +1 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
- ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-6CVKuTAe.js} +1 -1
- ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-BUHRxvDG.js} +1 -1
- ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-BZ9n9AjO.js} +1 -1
- ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BibcG1V9.js} +1 -1
- ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-Bs-jQcRX.js} +1 -1
- ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-C2xjE7cO.js} +1 -1
- ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-C7-3jInC.js} +1 -1
- ksadk/server/static/assets/{dist-D-xOD048.js → dist-C99THtIA.js} +1 -1
- ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-CGcp2ex8.js} +1 -1
- ksadk/server/static/assets/{dist-DyOkZmze.js → dist-CVQRZjPu.js} +1 -1
- ksadk/server/static/assets/{dist-BssVmjIo.js → dist-Cf23NY4L.js} +1 -1
- ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-CgF3fj15.js} +1 -1
- ksadk/server/static/assets/{dist-2hInLS_J.js → dist-Cwt7koer.js} +1 -1
- ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-D82mtD2s.js} +1 -1
- ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-DF06ORQo.js} +1 -1
- ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-DHn6nBzr.js} +1 -1
- ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-Djgl2wVZ.js} +1 -1
- ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-DlzCRy0S.js} +1 -1
- ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-DqNnNFrw.js} +1 -1
- ksadk/server/static/assets/{dist-D57wnGWd.js → dist-DyvYLMW9.js} +1 -1
- ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-eoW6tZXA.js} +1 -1
- ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-ivOya1LD.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-DpCoB2g9.js} +1 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-9IKVFBVT.js} +1 -1
- ksadk/server/static/assets/index-QSwCHuB8.js +177 -0
- ksadk/server/static/assets/index-jOPmTOZH.css +2 -0
- ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +1 -0
- ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
- ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-DATssjp1.js} +1 -1
- ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-CvMBw9cA.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-CSAQxEAe.js} +1 -1
- ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +1 -0
- ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +1 -0
- ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-DGpd9yFG.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +1 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-jqoYs3jQ.js} +1 -1
- ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +1 -0
- ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-SkiH8GsK.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +111 -58
- ksadk/sessions/__init__.py +69 -19
- ksadk/sessions/base.py +31 -11
- ksadk/sessions/continuity.py +2 -3
- ksadk/sessions/in_memory.py +46 -2
- ksadk/sessions/local_service.py +148 -17
- ksadk/sessions/postgres_service.py +143 -25
- ksadk/sessions/resilient.py +36 -8
- ksadk/skills/models.py +17 -5
- ksadk/skills/package_store.py +5 -2
- ksadk/skills/runtime/agent.py +20 -5
- ksadk/skills/runtime/artifacts.py +1 -5
- ksadk/skills/runtime/backends/e2b.py +10 -4
- ksadk/skills/runtime/backends/local.py +15 -3
- ksadk/skills/runtime/base.py +1 -2
- ksadk/skills/runtime/executor.py +10 -3
- ksadk/skills/runtime/factory.py +4 -2
- ksadk/skills/runtime/loader.py +1 -2
- ksadk/skills/runtime/registry.py +15 -10
- ksadk/skills/runtime/request.py +3 -1
- ksadk/skills/service_client.py +38 -17
- ksadk/skills/tool_defs.py +15 -10
- ksadk/terminal_exec_policy.py +3 -4
- ksadk/tools/gateway.py +92 -15
- ksadk/tools/result_budget.py +12 -4
- ksadk/toolsets/__init__.py +134 -36
- ksadk/toolsets/platform.py +21 -5
- ksadk/toolsets/sandbox.py +82 -16
- ksadk/toolsets/skills.py +200 -39
- ksadk/toolsets/web.py +123 -26
- ksadk/toolsets/workspace.py +212 -101
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/exporters/langfuse_exporter.py +91 -76
- ksadk/tracing/setup.py +69 -53
- ksadk/tracing/span_utils.py +5 -2
- ksadk/tui/loop.py +78 -30
- ksadk/tui/stream_render.py +1 -0
- ksadk/ui_config.py +5 -3
- ksadk/version.py +1 -1
- ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
- agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
- ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
- ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
- ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
- ksadk/server/static/assets/channel-CTuydARX.js +0 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
- ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
- ksadk/server/static/assets/index-DAURbCsP.css +0 -1
- ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
- ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
- ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
- ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./mermaid-parser.core-
|
|
1
|
+
import{t as e}from"./mermaid-parser.core-mGAcEwcq.js";import{t}from"./chunk-4BX2VUAB-CsWIQRhc.js";import{An as n,Jt as r,N as i,Zt as a,_n as o,en as s,hn as c,in as l,kn as u,mn as d,mt as f,nn as p,on as m,rn as h,tn as g}from"./MermaidBlock-DWuxETaJ.js";var _=u((e,t)=>{let n=e<=1?e*100:e;if(n<0||n>100)throw Error(`${t} must be between 0-1 (decimal) or 0-100 (percentage). Received: ${e}`);return n},`toPercent`),v=u((e,t,n)=>({x:_(t,`${n} evolution`),y:_(e,`${n} visibility`)}),`toCoordinates`),y=u(e=>{if(e){if(e===`+<>`)return`bidirectional`;if(e===`+<`)return`backward`;if(e===`+>`)return`forward`}},`getFlowFromPort`),b=u(e=>{if(!e?.startsWith(`+`))return{};let t=/^\+'([^']*)'/.exec(e)?.[1];return e.includes(`<>`)?{flow:`bidirectional`,label:t}:e.includes(`<`)?{flow:`backward`,label:t}:e.includes(`>`)?{flow:`forward`,label:t}:{label:t}},`extractFlowFromArrow`),x=u((e,n)=>{if(t(e,n),e.size&&n.setSize(e.size.width,e.size.height),e.evolution){let t=e.evolution.stages.map(e=>e.secondName?`${e.name.trim()} / ${e.secondName.trim()}`:e.name.trim()),r=e.evolution.stages.filter(e=>e.boundary!==void 0).map(e=>e.boundary);n.updateAxes({stages:t,stageBoundaries:r})}if(e.anchors.forEach(e=>{let t=v(e.visibility,e.evolution,`Anchor "${e.name}"`);n.addNode(e.name,e.name,t.x,t.y,`anchor`)}),e.components.forEach(e=>{let t=v(e.visibility,e.evolution,`Component "${e.name}"`),r=e.label?(e.label.negX?-1:1)*e.label.offsetX:void 0,i=e.label?(e.label.negY?-1:1)*e.label.offsetY:void 0,a=e.decorator?.strategy;n.addNode(e.name,e.name,t.x,t.y,`component`,r,i,e.inertia,a)}),e.notes.forEach(e=>{let t=v(e.visibility,e.evolution,`Note "${e.text}"`);n.addNote(e.text,t.x,t.y)}),e.pipelines.forEach(e=>{let t=n.getNode(e.parent);if(!t||typeof t.y!=`number`)throw Error(`Pipeline "${e.parent}" must reference an existing component with coordinates.`);let r=t.y;n.startPipeline(e.parent),e.components.forEach(t=>{let i=`${e.parent}_${t.name}`,a=t.label?(t.label.negX?-1:1)*t.label.offsetX:void 0,o=t.label?(t.label.negY?-1:1)*t.label.offsetY:void 0,s=_(t.evolution,`Pipeline component "${t.name}" evolution`);n.addNode(i,t.name,s,r,`pipeline-component`,a,o),n.addPipelineComponent(e.parent,i)})}),e.links.forEach(e=>{let t=!!e.arrow&&(e.arrow.includes(`-.->`)||e.arrow.includes(`.-.`)),r=y(e.fromPort)??y(e.toPort),{flow:i,label:a}=b(e.arrow);!r&&i&&(r=i);let o=e.linkLabel,s=a??o;n.addLink(n.resolveNodeId(e.from),n.resolveNodeId(e.to),t,s,r)}),e.evolves.forEach(e=>{let t=n.getNode(e.component);if(t?.y!==void 0){let r=_(e.target,`Evolve target for "${e.component}"`);n.addTrend(e.component,r,t.y)}}),e.annotations.length>0){let t=e.annotations[0],r=v(t.x,t.y,`Annotations box`);n.setAnnotationsBox(r.x,r.y)}e.annotation.forEach(e=>{let t=v(e.x,e.y,`Annotation ${e.number}`);n.addAnnotation(e.number,[{x:t.x,y:t.y}],e.text)}),e.accelerators.forEach(e=>{let t=v(e.x,e.y,`Accelerator "${e.name}"`);n.addAccelerator(e.name,t.x,t.y)}),e.deaccelerators.forEach(e=>{let t=v(e.x,e.y,`Deaccelerator "${e.name}"`);n.addDeaccelerator(e.name,t.x,t.y)})},`populateDb`),S={parser:{yy:void 0},parse:u(async t=>{let r=await e(`wardley`,t);n.debug(r);let i=S.parser?.yy;if(!i||typeof i.addNode!=`function`)throw Error(`parser.parser?.yy was not a WardleyDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues.`);x(r,i)},`parse`)},C=new class{constructor(){this.nodes=new Map,this.links=[],this.trends=new Map,this.pipelines=new Map,this.annotations=[],this.notes=[],this.accelerators=[],this.deaccelerators=[],this.axes={}}static{u(this,`WardleyBuilder`)}addNode(e){let t=this.nodes.get(e.id)??{id:e.id,label:e.label},n={...t,...e,className:e.className??t.className,labelOffsetX:e.labelOffsetX??t.labelOffsetX,labelOffsetY:e.labelOffsetY??t.labelOffsetY};this.nodes.set(e.id,n)}addLink(e){this.links.push(e)}addTrend(e){this.trends.set(e.nodeId,e)}startPipeline(e){this.pipelines.set(e,{nodeId:e,componentIds:[]});let t=this.nodes.get(e);t&&(t.isPipelineParent=!0)}addPipelineComponent(e,t){let n=this.pipelines.get(e);n&&n.componentIds.push(t);let r=this.nodes.get(t);r&&(r.inPipeline=!0)}addAnnotation(e){this.annotations.push(e)}addNote(e){this.notes.push(e)}addAccelerator(e){this.accelerators.push(e)}addDeaccelerator(e){this.deaccelerators.push(e)}setAnnotationsBox(e,t){this.annotationsBox={x:e,y:t}}setAxes(e){this.axes={...this.axes,...e}}setSize(e,t){this.size={width:e,height:t}}getNode(e){return this.nodes.get(e)}resolveNodeId(e){if(this.nodes.has(e))return e;for(let[t,n]of this.nodes)if(n.label===e)return t;return e}build(){let e=[];for(let t of this.nodes.values()){if(typeof t.x!=`number`||typeof t.y!=`number`)throw Error(`Node "${t.label}" is missing coordinates`);e.push(t)}return{nodes:e,links:[...this.links],trends:[...this.trends.values()],pipelines:[...this.pipelines.values()],annotations:[...this.annotations],notes:[...this.notes],accelerators:[...this.accelerators],deaccelerators:[...this.deaccelerators],annotationsBox:this.annotationsBox,axes:{...this.axes},size:this.size}}clear(){this.nodes.clear(),this.links=[],this.trends.clear(),this.pipelines.clear(),this.annotations=[],this.notes=[],this.accelerators=[],this.deaccelerators=[],this.annotationsBox=void 0,this.axes={},this.size=void 0}};function w(){return h()[`wardley-beta`]}u(w,`getConfig`);function T(e,t,n,r,i,a,o,s,c){C.addNode({id:e,label:t,x:n,y:r,className:i,labelOffsetX:a,labelOffsetY:o,inertia:s,sourceStrategy:c})}u(T,`addNode`);function E(e,t,n=!1,r,i){C.addLink({source:e,target:t,dashed:n,label:r,flow:i})}u(E,`addLink`);function D(e,t,n){C.addTrend({nodeId:e,targetX:t,targetY:n})}u(D,`addTrend`);function O(e,t,n){C.addAnnotation({number:e,coordinates:t,text:n})}u(O,`addAnnotation`);function k(e,t,n){C.addNote({text:e,x:t,y:n})}u(k,`addNote`);function A(e,t,n){C.addAccelerator({name:e,x:t,y:n})}u(A,`addAccelerator`);function j(e,t,n){C.addDeaccelerator({name:e,x:t,y:n})}u(j,`addDeaccelerator`);function M(e,t){C.setAnnotationsBox(e,t)}u(M,`setAnnotationsBox`);function N(e,t){C.setSize(e,t)}u(N,`setSize`);function P(e){C.startPipeline(e)}u(P,`startPipeline`);function F(e,t){C.addPipelineComponent(e,t)}u(F,`addPipelineComponent`);function I(e){C.setAxes(e)}u(I,`updateAxes`);function L(e){return C.getNode(e)}u(L,`getNode`);function R(e){return C.resolveNodeId(e)}u(R,`resolveNodeId`);function z(){return C.build()}u(z,`getWardleyData`);function B(){C.clear(),r()}u(B,`clear`);var V={getConfig:w,addNode:T,addLink:E,addTrend:D,addAnnotation:O,addNote:k,addAccelerator:A,addDeaccelerator:j,setAnnotationsBox:M,setSize:N,startPipeline:P,addPipelineComponent:F,updateAxes:I,getNode:L,resolveNodeId:R,getWardleyData:z,clear:B,setAccTitle:c,getAccTitle:g,setDiagramTitle:o,getDiagramTitle:l,getAccDescription:s,setAccDescription:d},H=[`Genesis`,`Custom Built`,`Product`,`Commodity`],U=u(()=>{let{themeVariables:e}=h();return{backgroundColor:e.wardley?.backgroundColor??e.background??`#fff`,axisColor:e.wardley?.axisColor??`#000`,axisTextColor:e.wardley?.axisTextColor??e.primaryTextColor??`#222`,gridColor:e.wardley?.gridColor??`rgba(100, 100, 100, 0.2)`,componentFill:e.wardley?.componentFill??`#fff`,componentStroke:e.wardley?.componentStroke??`#000`,componentLabelColor:e.wardley?.componentLabelColor??e.primaryTextColor??`#222`,linkStroke:e.wardley?.linkStroke??`#000`,evolutionStroke:e.wardley?.evolutionStroke??`#dc3545`,annotationStroke:e.wardley?.annotationStroke??`#000`,annotationTextColor:e.wardley?.annotationTextColor??e.primaryTextColor??`#222`,annotationFill:e.wardley?.annotationFill??e.background??`#fff`}},`getTheme`),W=u(()=>{let e=h()[`wardley-beta`];return{width:e?.width??900,height:e?.height??600,padding:e?.padding??48,nodeRadius:e?.nodeRadius??6,nodeLabelOffset:e?.nodeLabelOffset??8,axisFontSize:e?.axisFontSize??12,labelFontSize:e?.labelFontSize??10,showGrid:e?.showGrid??!1,useMaxWidth:e?.useMaxWidth??!0}},`getConfigValues`),G={parser:S,db:V,renderer:{draw:u((e,t,r,i)=>{n.debug(`Rendering Wardley map
|
|
2
2
|
`+e);let o=W(),s=U(),c=o.nodeRadius*1.6,l=i.db,d=l.getWardleyData(),p=l.getDiagramTitle(),m=d.size?.width??o.width,h=d.size?.height??o.height,g=f(t);g.selectAll(`*`).remove(),a(g,h,m,o.useMaxWidth),g.attr(`viewBox`,`0 0 ${m} ${h}`);let _=g.append(`g`).attr(`class`,`wardley-map`),v=g.append(`defs`);v.append(`marker`).attr(`id`,`arrow-${t}`).attr(`viewBox`,`0 0 10 10`).attr(`refX`,9).attr(`refY`,5).attr(`markerWidth`,6).attr(`markerHeight`,6).attr(`orient`,`auto-start-reverse`).append(`path`).attr(`d`,`M 0 0 L 10 5 L 0 10 z`).attr(`fill`,s.evolutionStroke).attr(`stroke`,`none`),v.append(`marker`).attr(`id`,`link-arrow-end-${t}`).attr(`viewBox`,`0 0 10 10`).attr(`refX`,9).attr(`refY`,5).attr(`markerWidth`,5).attr(`markerHeight`,5).attr(`orient`,`auto`).append(`path`).attr(`d`,`M 0 0 L 10 5 L 0 10 z`).attr(`fill`,s.linkStroke).attr(`stroke`,`none`),v.append(`marker`).attr(`id`,`link-arrow-start-${t}`).attr(`viewBox`,`0 0 10 10`).attr(`refX`,1).attr(`refY`,5).attr(`markerWidth`,5).attr(`markerHeight`,5).attr(`orient`,`auto`).append(`path`).attr(`d`,`M 10 0 L 0 5 L 10 10 z`).attr(`fill`,s.linkStroke).attr(`stroke`,`none`),_.append(`rect`).attr(`class`,`wardley-background`).attr(`width`,m).attr(`height`,h).attr(`fill`,s.backgroundColor);let y=m-o.padding*2,b=h-o.padding*2;p&&_.append(`text`).attr(`class`,`wardley-title`).attr(`x`,m/2).attr(`y`,o.padding/2).attr(`fill`,s.axisTextColor).attr(`font-size`,o.axisFontSize*1.05).attr(`font-weight`,`bold`).attr(`text-anchor`,`middle`).attr(`dominant-baseline`,`middle`).text(p);let x=u(e=>o.padding+e/100*y,`projectX`),S=u(e=>h-o.padding-e/100*b,`projectY`),C=_.append(`g`).attr(`class`,`wardley-axes`);C.append(`line`).attr(`x1`,o.padding).attr(`x2`,m-o.padding).attr(`y1`,h-o.padding).attr(`y2`,h-o.padding).attr(`stroke`,s.axisColor).attr(`stroke-width`,1),C.append(`line`).attr(`x1`,o.padding).attr(`x2`,o.padding).attr(`y1`,o.padding).attr(`y2`,h-o.padding).attr(`stroke`,s.axisColor).attr(`stroke-width`,1);let w=d.axes.xLabel??`Evolution`,T=d.axes.yLabel??`Visibility`;C.append(`text`).attr(`class`,`wardley-axis-label wardley-axis-label-x`).attr(`x`,o.padding+y/2).attr(`y`,h-o.padding/4).attr(`fill`,s.axisTextColor).attr(`font-size`,o.axisFontSize).attr(`font-weight`,`bold`).attr(`text-anchor`,`middle`).text(w),C.append(`text`).attr(`class`,`wardley-axis-label wardley-axis-label-y`).attr(`x`,o.padding/3).attr(`y`,o.padding+b/2).attr(`fill`,s.axisTextColor).attr(`font-size`,o.axisFontSize).attr(`font-weight`,`bold`).attr(`text-anchor`,`middle`).attr(`transform`,`rotate(-90 ${o.padding/3} ${o.padding+b/2})`).text(T);let E=d.axes.stages&&d.axes.stages.length>0?d.axes.stages:H;if(E.length>0){let e=_.append(`g`).attr(`class`,`wardley-stages`),t=d.axes.stageBoundaries,n=[];if(t&&t.length===E.length){let e=0;t.forEach(t=>{n.push({start:e,end:t}),e=t})}else{let e=1/E.length;E.forEach((t,r)=>{n.push({start:r*e,end:(r+1)*e})})}E.forEach((t,r)=>{let i=n[r],a=o.padding+i.start*y,c=(a+(o.padding+i.end*y))/2;r>0&&e.append(`line`).attr(`x1`,a).attr(`x2`,a).attr(`y1`,o.padding).attr(`y2`,h-o.padding).attr(`stroke`,`#000`).attr(`stroke-width`,1).attr(`stroke-dasharray`,`5 5`).attr(`opacity`,.8),e.append(`text`).attr(`class`,`wardley-stage-label`).attr(`x`,c).attr(`y`,h-o.padding/1.5).attr(`fill`,s.axisTextColor).attr(`font-size`,o.axisFontSize-2).attr(`text-anchor`,`middle`).text(t)})}if(o.showGrid){let e=_.append(`g`).attr(`class`,`wardley-grid`);for(let t=1;t<4;t++){let n=t/4,r=o.padding+y*n;e.append(`line`).attr(`x1`,r).attr(`x2`,r).attr(`y1`,o.padding).attr(`y2`,h-o.padding).attr(`stroke`,s.gridColor).attr(`stroke-dasharray`,`2 6`),e.append(`line`).attr(`x1`,o.padding).attr(`x2`,m-o.padding).attr(`y1`,h-o.padding-b*n).attr(`y2`,h-o.padding-b*n).attr(`stroke`,s.gridColor).attr(`stroke-dasharray`,`2 6`)}}let D=new Map;if(d.nodes.forEach(e=>{D.set(e.id,{x:x(e.x),y:S(e.y),node:e})}),d.pipelines.length>0){let e=_.append(`g`).attr(`class`,`wardley-pipelines`),t=_.append(`g`).attr(`class`,`wardley-pipeline-links`);d.pipelines.forEach(n=>{if(n.componentIds.length===0)return;let r=n.componentIds.map(e=>({id:e,pos:D.get(e),node:d.nodes.find(t=>t.id===e)})).filter(e=>e.pos&&e.node).sort((e,t)=>e.node.x-t.node.x);for(let e=0;e<r.length-1;e++){let n=r[e],i=r[e+1];t.append(`line`).attr(`class`,`wardley-pipeline-evolution-link`).attr(`x1`,n.pos.x).attr(`y1`,n.pos.y).attr(`x2`,i.pos.x).attr(`y2`,i.pos.y).attr(`stroke`,s.linkStroke).attr(`stroke-width`,1).attr(`stroke-dasharray`,`4 4`)}let i=1/0,a=-1/0,l=0;if(n.componentIds.forEach(e=>{let t=D.get(e);t&&(i=Math.min(i,t.x),a=Math.max(a,t.x),l=t.y)}),i!==1/0&&a!==-1/0){let t=o.nodeRadius*4,r=l-t/2,u=D.get(n.nodeId);u&&(u.x=(i+a)/2,u.y=r-c/6),e.append(`rect`).attr(`class`,`wardley-pipeline-box`).attr(`x`,i-15).attr(`y`,r).attr(`width`,a-i+30).attr(`height`,t).attr(`fill`,`none`).attr(`stroke`,s.axisColor).attr(`stroke-width`,1.5).attr(`rx`,4).attr(`ry`,4)}})}let O=_.append(`g`).attr(`class`,`wardley-links`),k=new Map;d.pipelines.forEach(e=>{k.set(e.nodeId,new Set(e.componentIds))});let A=d.links.filter(e=>!(!D.has(e.source)||!D.has(e.target)||k.get(e.target)?.has(e.source)));O.selectAll(`line`).data(A).enter().append(`line`).attr(`class`,e=>`wardley-link${e.dashed?` wardley-link--dashed`:``}`).attr(`x1`,e=>{let t=D.get(e.source),n=D.get(e.target),r=d.nodes.find(t=>t.id===e.source).isPipelineParent?c/Math.sqrt(2):o.nodeRadius,i=n.x-t.x,a=n.y-t.y,s=Math.sqrt(i*i+a*a);return t.x+i/s*r}).attr(`y1`,e=>{let t=D.get(e.source),n=D.get(e.target),r=d.nodes.find(t=>t.id===e.source).isPipelineParent?c/Math.sqrt(2):o.nodeRadius,i=n.x-t.x,a=n.y-t.y,s=Math.sqrt(i*i+a*a);return t.y+a/s*r}).attr(`x2`,e=>{let t=D.get(e.source),n=D.get(e.target),r=d.nodes.find(t=>t.id===e.target).isPipelineParent?c/Math.sqrt(2):o.nodeRadius,i=t.x-n.x,a=t.y-n.y,s=Math.sqrt(i*i+a*a);return n.x+i/s*r}).attr(`y2`,e=>{let t=D.get(e.source),n=D.get(e.target),r=d.nodes.find(t=>t.id===e.target).isPipelineParent?c/Math.sqrt(2):o.nodeRadius,i=t.x-n.x,a=t.y-n.y,s=Math.sqrt(i*i+a*a);return n.y+a/s*r}).attr(`stroke`,s.linkStroke).attr(`stroke-width`,1).attr(`stroke-dasharray`,e=>e.dashed?`6 6`:null).attr(`marker-end`,e=>e.flow===`forward`||e.flow===`bidirectional`?`url(#link-arrow-end-${t})`:null).attr(`marker-start`,e=>e.flow===`backward`||e.flow===`bidirectional`?`url(#link-arrow-start-${t})`:null),O.selectAll(`text`).data(A.filter(e=>e.label)).enter().append(`text`).attr(`class`,`wardley-link-label`).attr(`x`,e=>{let t=D.get(e.source),n=D.get(e.target),r=(t.x+n.x)/2,i=n.y-t.y,a=n.x-t.x;return r+i/Math.sqrt(a*a+i*i)*8}).attr(`y`,e=>{let t=D.get(e.source),n=D.get(e.target),r=(t.y+n.y)/2,i=n.x-t.x,a=n.y-t.y,o=Math.sqrt(i*i+a*a);return r+-i/o*8}).attr(`fill`,s.axisTextColor).attr(`font-size`,o.labelFontSize).attr(`text-anchor`,`middle`).attr(`dominant-baseline`,`middle`).attr(`transform`,e=>{let t=D.get(e.source),n=D.get(e.target),r=(t.x+n.x)/2,i=(t.y+n.y)/2,a=n.x-t.x,o=n.y-t.y,s=Math.sqrt(a*a+o*o),c=o/s,l=-a/s,u=r+c*8,d=i+l*8,f=Math.atan2(o,a)*180/Math.PI;return(f>90||f<-90)&&(f+=180),`rotate(${f} ${u} ${d})`}).text(e=>e.label);let j=_.append(`g`).attr(`class`,`wardley-trends`),M=d.trends.map(e=>{let t=D.get(e.nodeId);if(!t)return null;let n=x(e.targetX),r=S(e.targetY),i=n-t.x,a=r-t.y,s=Math.sqrt(i*i+a*a),c=o.nodeRadius+2;return{origin:t,targetX:n,targetY:r,adjustedX2:s>c?n-i/s*c:n,adjustedY2:s>c?r-a/s*c:r}}).filter(e=>e!==null);j.selectAll(`line`).data(M).enter().append(`line`).attr(`class`,`wardley-trend`).attr(`x1`,e=>e.origin.x).attr(`y1`,e=>e.origin.y).attr(`x2`,e=>e.adjustedX2).attr(`y2`,e=>e.adjustedY2).attr(`stroke`,s.evolutionStroke).attr(`stroke-width`,1).attr(`stroke-dasharray`,`4 4`).attr(`marker-end`,`url(#arrow-${t})`);let N=_.append(`g`).attr(`class`,`wardley-nodes`).selectAll(`g`).data(d.nodes).enter().append(`g`).attr(`class`,e=>[`wardley-node`,e.className?`wardley-node--${e.className}`:``].filter(Boolean).join(` `));N.filter(e=>e.sourceStrategy===`outsource`).append(`circle`).attr(`class`,`wardley-outsource-overlay`).attr(`cx`,e=>D.get(e.id).x).attr(`cy`,e=>D.get(e.id).y).attr(`r`,o.nodeRadius*2).attr(`fill`,`#666`).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),N.filter(e=>e.sourceStrategy===`buy`).append(`circle`).attr(`class`,`wardley-buy-overlay`).attr(`cx`,e=>D.get(e.id).x).attr(`cy`,e=>D.get(e.id).y).attr(`r`,o.nodeRadius*2).attr(`fill`,`#ccc`).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),N.filter(e=>e.sourceStrategy===`build`).append(`circle`).attr(`class`,`wardley-build-overlay`).attr(`cx`,e=>D.get(e.id).x).attr(`cy`,e=>D.get(e.id).y).attr(`r`,o.nodeRadius*2).attr(`fill`,`#eee`).attr(`stroke`,`#000`).attr(`stroke-width`,1);let P=N.filter(e=>e.sourceStrategy===`market`);P.append(`circle`).attr(`class`,`wardley-market-overlay`).attr(`cx`,e=>D.get(e.id).x).attr(`cy`,e=>D.get(e.id).y).attr(`r`,o.nodeRadius*2).attr(`fill`,`white`).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),N.filter(e=>!e.isPipelineParent&&e.sourceStrategy!==`market`&&e.className!==`anchor`).append(`circle`).attr(`cx`,e=>D.get(e.id).x).attr(`cy`,e=>D.get(e.id).y).attr(`r`,o.nodeRadius).attr(`fill`,s.componentFill).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1);let F=o.nodeRadius*.7,I=o.nodeRadius*1.2;if(P.append(`line`).attr(`class`,`wardley-market-line`).attr(`x1`,e=>D.get(e.id).x).attr(`y1`,e=>D.get(e.id).y-I).attr(`x2`,e=>D.get(e.id).x-I*Math.cos(Math.PI/6)).attr(`y2`,e=>D.get(e.id).y+I*Math.sin(Math.PI/6)).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),P.append(`line`).attr(`class`,`wardley-market-line`).attr(`x1`,e=>D.get(e.id).x-I*Math.cos(Math.PI/6)).attr(`y1`,e=>D.get(e.id).y+I*Math.sin(Math.PI/6)).attr(`x2`,e=>D.get(e.id).x+I*Math.cos(Math.PI/6)).attr(`y2`,e=>D.get(e.id).y+I*Math.sin(Math.PI/6)).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),P.append(`line`).attr(`class`,`wardley-market-line`).attr(`x1`,e=>D.get(e.id).x+I*Math.cos(Math.PI/6)).attr(`y1`,e=>D.get(e.id).y+I*Math.sin(Math.PI/6)).attr(`x2`,e=>D.get(e.id).x).attr(`y2`,e=>D.get(e.id).y-I).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),P.append(`circle`).attr(`class`,`wardley-market-dot`).attr(`cx`,e=>D.get(e.id).x).attr(`cy`,e=>D.get(e.id).y-I).attr(`r`,F).attr(`fill`,`white`).attr(`stroke`,s.componentStroke).attr(`stroke-width`,2),P.append(`circle`).attr(`class`,`wardley-market-dot`).attr(`cx`,e=>D.get(e.id).x-I*Math.cos(Math.PI/6)).attr(`cy`,e=>D.get(e.id).y+I*Math.sin(Math.PI/6)).attr(`r`,F).attr(`fill`,`white`).attr(`stroke`,s.componentStroke).attr(`stroke-width`,2),P.append(`circle`).attr(`class`,`wardley-market-dot`).attr(`cx`,e=>D.get(e.id).x+I*Math.cos(Math.PI/6)).attr(`cy`,e=>D.get(e.id).y+I*Math.sin(Math.PI/6)).attr(`r`,F).attr(`fill`,`white`).attr(`stroke`,s.componentStroke).attr(`stroke-width`,2),N.filter(e=>e.isPipelineParent===!0).append(`rect`).attr(`x`,e=>D.get(e.id).x-c/2).attr(`y`,e=>D.get(e.id).y-c/2).attr(`width`,c).attr(`height`,c).attr(`fill`,s.componentFill).attr(`stroke`,s.componentStroke).attr(`stroke-width`,1),N.filter(e=>e.inertia===!0).append(`line`).attr(`class`,`wardley-inertia`).attr(`x1`,e=>{let t=D.get(e.id),n=e.isPipelineParent?c/2+15:o.nodeRadius+15;return e.sourceStrategy&&(n+=o.nodeRadius+10),t.x+n}).attr(`y1`,e=>{let t=D.get(e.id),n=e.isPipelineParent?c:o.nodeRadius*2;return t.y-n/2}).attr(`x2`,e=>{let t=D.get(e.id),n=e.isPipelineParent?c/2+15:o.nodeRadius+15;return e.sourceStrategy&&(n+=o.nodeRadius+10),t.x+n}).attr(`y2`,e=>{let t=D.get(e.id),n=e.isPipelineParent?c:o.nodeRadius*2;return t.y+n/2}).attr(`stroke`,s.componentStroke).attr(`stroke-width`,6),N.append(`text`).attr(`x`,e=>{let t=D.get(e.id);if(e.className===`anchor`)return e.labelOffsetX===void 0?t.x:t.x+e.labelOffsetX;let n=o.nodeLabelOffset;e.sourceStrategy&&e.labelOffsetX===void 0&&(n+=10);let r=e.labelOffsetX??n;return t.x+r}).attr(`y`,e=>{let t=D.get(e.id);if(e.className===`anchor`)return e.labelOffsetY===void 0?t.y-3:t.y+e.labelOffsetY;let n=-o.nodeLabelOffset;e.sourceStrategy&&e.labelOffsetY===void 0&&(n-=10);let r=e.labelOffsetY??n;return t.y+r}).attr(`class`,`wardley-node-label`).attr(`fill`,e=>e.className===`evolved`?s.evolutionStroke:e.className===`anchor`?`#000`:s.componentLabelColor).attr(`font-size`,o.labelFontSize).attr(`font-weight`,e=>e.className===`anchor`?`bold`:`normal`).attr(`text-anchor`,e=>e.className===`anchor`?`middle`:`start`).attr(`dominant-baseline`,e=>e.className===`anchor`?`middle`:`auto`).text(e=>e.label),d.annotations.length>0){let e=_.append(`g`).attr(`class`,`wardley-annotations`);if(d.annotations.forEach(t=>{let n=t.coordinates.map(e=>({x:x(e.x),y:S(e.y)}));if(n.length>1)for(let t=0;t<n.length-1;t++)e.append(`line`).attr(`class`,`wardley-annotation-line`).attr(`x1`,n[t].x).attr(`y1`,n[t].y).attr(`x2`,n[t+1].x).attr(`y2`,n[t+1].y).attr(`stroke`,s.axisColor).attr(`stroke-width`,1.5).attr(`stroke-dasharray`,`4 4`);n.forEach(n=>{let r=e.append(`g`).attr(`class`,`wardley-annotation`);r.append(`circle`).attr(`cx`,n.x).attr(`cy`,n.y).attr(`r`,10).attr(`fill`,`white`).attr(`stroke`,s.axisColor).attr(`stroke-width`,1.5),r.append(`text`).attr(`x`,n.x).attr(`y`,n.y).attr(`text-anchor`,`middle`).attr(`dominant-baseline`,`central`).attr(`font-size`,10).attr(`fill`,s.axisTextColor).attr(`font-weight`,`bold`).text(t.number)})}),d.annotationsBox){let t=x(d.annotationsBox.x),n=S(d.annotationsBox.y),r=e.append(`g`).attr(`class`,`wardley-annotations-box`),i=[...d.annotations].filter(e=>e.text).sort((e,t)=>e.number-t.number),a=[];if(i.forEach((e,i)=>{let o=r.append(`text`).attr(`x`,t+10).attr(`y`,n+10+(i+1)*16).attr(`font-size`,11).attr(`fill`,s.axisTextColor).attr(`text-anchor`,`start`).attr(`dominant-baseline`,`middle`).text(`${e.number}. ${e.text}`);a.push(o)}),a.length>0){let e=0,c=0;a.forEach(t=>{let n=t.node(),r=n.getComputedTextLength();e=Math.max(e,r);let i=n.getBBox();c=Math.max(c,i.height)});let l=e+20+105,u=i.length*16+20+c/2,d=o.padding,f=m-o.padding-l,p=o.padding,g=h-o.padding-u;t=Math.max(d,Math.min(t,f)),n=Math.max(p,Math.min(n,g)),a.forEach((e,r)=>{e.attr(`x`,t+10).attr(`y`,n+10+(r+1)*16)}),r.insert(`rect`,`text`).attr(`x`,t).attr(`y`,n).attr(`width`,l).attr(`height`,u).attr(`fill`,`white`).attr(`stroke`,s.axisColor).attr(`stroke-width`,1.5).attr(`rx`,4).attr(`ry`,4)}}}if(d.notes.length>0){let e=_.append(`g`).attr(`class`,`wardley-notes`);d.notes.forEach(t=>{let n=x(t.x),r=S(t.y);e.append(`text`).attr(`x`,n).attr(`y`,r).attr(`text-anchor`,`start`).attr(`font-size`,11).attr(`fill`,s.axisTextColor).attr(`font-weight`,`bold`).text(t.text)})}if(d.accelerators.length>0){let e=_.append(`g`).attr(`class`,`wardley-accelerators`);d.accelerators.forEach(t=>{let n=x(t.x),r=S(t.y),i=`
|
|
3
3
|
M ${n} ${r-30/2}
|
|
4
4
|
L ${n+60-20} ${r-30/2}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./linear-
|
|
1
|
+
import{t as e}from"./linear-CvMBw9cA.js";import{t}from"./ordinal-hYBb2elL.js";import{t as n}from"./init-D6jRqBbL.js";import{$t as r,An as i,Jt as a,N as o,T as s,Zt as c,_n as l,en as u,gt as d,hn as f,in as p,kn as m,mn as h,mt as g,nn as _,on as v,pn as y,tn as b}from"./MermaidBlock-DWuxETaJ.js";function x(e,t,n){e=+e,t=+t,n=(i=arguments.length)<2?(t=e,e=0,1):i<3?1:+n;for(var r=-1,i=Math.max(0,Math.ceil((t-e)/n))|0,a=Array(i);++r<i;)a[r]=e+r*n;return a}function S(){var e=t().unknown(void 0),r=e.domain,i=e.range,a=0,o=1,s,c,l=!1,u=0,d=0,f=.5;delete e.unknown;function p(){var e=r().length,t=o<a,n=t?o:a,p=t?a:o;s=(p-n)/Math.max(1,e-u+d*2),l&&(s=Math.floor(s)),n+=(p-n-s*(e-u))*f,c=s*(1-u),l&&(n=Math.round(n),c=Math.round(c));var m=x(e).map(function(e){return n+s*e});return i(t?m.reverse():m)}return e.domain=function(e){return arguments.length?(r(e),p()):r()},e.range=function(e){return arguments.length?([a,o]=e,a=+a,o=+o,p()):[a,o]},e.rangeRound=function(e){return[a,o]=e,a=+a,o=+o,l=!0,p()},e.bandwidth=function(){return c},e.step=function(){return s},e.round=function(e){return arguments.length?(l=!!e,p()):l},e.padding=function(e){return arguments.length?(u=Math.min(1,d=+e),p()):u},e.paddingInner=function(e){return arguments.length?(u=Math.min(1,e),p()):u},e.paddingOuter=function(e){return arguments.length?(d=+e,p()):d},e.align=function(e){return arguments.length?(f=Math.max(0,Math.min(1,e)),p()):f},e.copy=function(){return S(r(),[a,o]).round(l).paddingInner(u).paddingOuter(d).align(f)},n.apply(p(),arguments)}var C=(function(){var e=m(function(e,t,n,r){for(n||={},r=e.length;r--;n[e[r]]=t);return n},`o`),t=[1,10,12,14,16,18,19,21,23],n=[2,6],r=[1,3],i=[1,5],a=[1,6],o=[1,7],s=[1,5,10,12,14,16,18,19,21,23,34,35,36],c=[1,25],l=[1,26],u=[1,28],d=[1,29],f=[1,30],p=[1,31],h=[1,32],g=[1,33],_=[1,34],v=[1,35],y=[1,36],b=[1,37],x=[1,43],S=[1,42],C=[1,47],w=[1,50],T=[1,10,12,14,16,18,19,21,23,34,35,36],E=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],D=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36,41,42,43,44,45,46,47,48,49,50],O=[1,64],k={trace:m(function(){},`trace`),yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,commaSeparatedNumbers:25,SQUARE_BRACES_END:26,NUMBER_WITH_DECIMAL:27,COMMA:28,xAxisData:29,bandData:30,ARROW_DELIMITER:31,commaSeparatedTexts:32,yAxisData:33,NEWLINE:34,SEMI:35,EOF:36,alphaNum:37,STR:38,MD_STR:39,alphaNumToken:40,AMP:41,NUM:42,ALPHA:43,PLUS:44,EQUALS:45,MULT:46,DOT:47,BRKT:48,MINUS:49,UNDERSCORE:50,$accept:0,$end:1},terminals_:{2:`error`,5:`XYCHART`,8:`CHART_ORIENTATION`,10:`title`,12:`X_AXIS`,14:`Y_AXIS`,16:`LINE`,18:`BAR`,19:`acc_title`,20:`acc_title_value`,21:`acc_descr`,22:`acc_descr_value`,23:`acc_descr_multiline_value`,24:`SQUARE_BRACES_START`,26:`SQUARE_BRACES_END`,27:`NUMBER_WITH_DECIMAL`,28:`COMMA`,31:`ARROW_DELIMITER`,34:`NEWLINE`,35:`SEMI`,36:`EOF`,38:`STR`,39:`MD_STR`,41:`AMP`,42:`NUM`,43:`ALPHA`,44:`PLUS`,45:`EQUALS`,46:`MULT`,47:`DOT`,48:`BRKT`,49:`MINUS`,50:`UNDERSCORE`},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[13,1],[13,2],[13,1],[29,1],[29,3],[30,3],[32,3],[32,1],[15,1],[15,2],[15,1],[33,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[37,1],[37,2],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1]],performAction:m(function(e,t,n,r,i,a,o){var s=a.length-1;switch(i){case 5:r.setOrientation(a[s]);break;case 9:r.setDiagramTitle(a[s].text.trim());break;case 12:r.setLineData({text:``,type:`text`},a[s]);break;case 13:r.setLineData(a[s-1],a[s]);break;case 14:r.setBarData({text:``,type:`text`},a[s]);break;case 15:r.setBarData(a[s-1],a[s]);break;case 16:this.$=a[s].trim(),r.setAccTitle(this.$);break;case 17:case 18:this.$=a[s].trim(),r.setAccDescription(this.$);break;case 19:this.$=a[s-1];break;case 20:this.$=[Number(a[s-2]),...a[s]];break;case 21:this.$=[Number(a[s])];break;case 22:r.setXAxisTitle(a[s]);break;case 23:r.setXAxisTitle(a[s-1]);break;case 24:r.setXAxisTitle({type:`text`,text:``});break;case 25:r.setXAxisBand(a[s]);break;case 26:r.setXAxisRangeData(Number(a[s-2]),Number(a[s]));break;case 27:this.$=a[s-1];break;case 28:this.$=[a[s-2],...a[s]];break;case 29:this.$=[a[s]];break;case 30:r.setYAxisTitle(a[s]);break;case 31:r.setYAxisTitle(a[s-1]);break;case 32:r.setYAxisTitle({type:`text`,text:``});break;case 33:r.setYAxisRangeData(Number(a[s-2]),Number(a[s]));break;case 37:this.$={text:a[s],type:`text`};break;case 38:this.$={text:a[s],type:`text`};break;case 39:this.$={text:a[s],type:`markdown`};break;case 40:this.$=a[s];break;case 41:this.$=a[s-1]+``+a[s];break}},`anonymous`),table:[e(t,n,{3:1,4:2,7:4,5:r,34:i,35:a,36:o}),{1:[3]},e(t,n,{4:2,7:4,3:8,5:r,34:i,35:a,36:o}),e(t,n,{4:2,7:4,6:9,3:10,5:r,8:[1,11],34:i,35:a,36:o}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},e(s,[2,34]),e(s,[2,35]),e(s,[2,36]),{1:[2,1]},e(t,n,{4:2,7:4,3:21,5:r,34:i,35:a,36:o}),{1:[2,3]},e(s,[2,5]),e(t,[2,7],{4:22,34:i,35:a,36:o}),{11:23,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},{11:39,13:38,24:x,27:S,29:40,30:41,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},{11:45,15:44,27:C,33:46,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},{11:49,17:48,24:w,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},{11:52,17:51,24:w,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},{20:[1,53]},{22:[1,54]},e(T,[2,18]),{1:[2,2]},e(T,[2,8]),e(T,[2,9]),e(E,[2,37],{40:55,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b}),e(E,[2,38]),e(E,[2,39]),e(D,[2,40]),e(D,[2,42]),e(D,[2,43]),e(D,[2,44]),e(D,[2,45]),e(D,[2,46]),e(D,[2,47]),e(D,[2,48]),e(D,[2,49]),e(D,[2,50]),e(D,[2,51]),e(T,[2,10]),e(T,[2,22],{30:41,29:56,24:x,27:S}),e(T,[2,24]),e(T,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},e(T,[2,11]),e(T,[2,30],{33:60,27:C}),e(T,[2,32]),{31:[1,61]},e(T,[2,12]),{17:62,24:w},{25:63,27:O},e(T,[2,14]),{17:65,24:w},e(T,[2,16]),e(T,[2,17]),e(D,[2,41]),e(T,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},e(T,[2,31]),{27:[1,69]},e(T,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},e(T,[2,15]),e(T,[2,26]),e(T,[2,27]),{11:59,32:72,37:24,38:c,39:l,40:27,41:u,42:d,43:f,44:p,45:h,46:g,47:_,48:v,49:y,50:b},e(T,[2,33]),e(T,[2,19]),{25:73,27:O},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:m(function(e,t){if(t.recoverable)this.trace(e);else{var n=Error(e);throw n.hash=t,n}},`parseError`),parse:m(function(e){var t=this,n=[0],r=[],i=[null],a=[],o=this.table,s=``,c=0,l=0,u=0,d=2,f=1,p=a.slice.call(arguments,1),h=Object.create(this.lexer),g={yy:{}};for(var _ in this.yy)Object.prototype.hasOwnProperty.call(this.yy,_)&&(g.yy[_]=this.yy[_]);h.setInput(e,g.yy),g.yy.lexer=h,g.yy.parser=this,h.yylloc===void 0&&(h.yylloc={});var v=h.yylloc;a.push(v);var y=h.options&&h.options.ranges;typeof g.yy.parseError==`function`?this.parseError=g.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function b(e){n.length-=2*e,i.length-=e,a.length-=e}m(b,`popStack`);function x(){var e=r.pop()||h.lex()||f;return typeof e!=`number`&&(e instanceof Array&&(r=e,e=r.pop()),e=t.symbols_[e]||e),e}m(x,`lex`);for(var S,C,w,T,E,D={},O,k,A,j;;){if(w=n[n.length-1],this.defaultActions[w]?T=this.defaultActions[w]:(S??=x(),T=o[w]&&o[w][S]),T===void 0||!T.length||!T[0]){var M=``;for(O in j=[],o[w])this.terminals_[O]&&O>d&&j.push(`'`+this.terminals_[O]+`'`);M=h.showPosition?`Parse error on line `+(c+1)+`:
|
|
2
2
|
`+h.showPosition()+`
|
|
3
3
|
Expecting `+j.join(`, `)+`, got '`+(this.terminals_[S]||S)+`'`:`Parse error on line `+(c+1)+`: Unexpected `+(S==f?`end of input`:`'`+(this.terminals_[S]||S)+`'`),this.parseError(M,{text:h.match,token:this.terminals_[S]||S,line:h.yylineno,loc:v,expected:j})}if(T[0]instanceof Array&&T.length>1)throw Error(`Parse Error: multiple actions possible at state: `+w+`, token: `+S);switch(T[0]){case 1:n.push(S),i.push(h.yytext),a.push(h.yylloc),n.push(T[1]),S=null,C?(S=C,C=null):(l=h.yyleng,s=h.yytext,c=h.yylineno,v=h.yylloc,u>0&&u--);break;case 2:if(k=this.productions_[T[1]][1],D.$=i[i.length-k],D._$={first_line:a[a.length-(k||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(k||1)].first_column,last_column:a[a.length-1].last_column},y&&(D._$.range=[a[a.length-(k||1)].range[0],a[a.length-1].range[1]]),E=this.performAction.apply(D,[s,l,c,g.yy,T[1],i,a].concat(p)),E!==void 0)return E;k&&(n=n.slice(0,-1*k*2),i=i.slice(0,-1*k),a=a.slice(0,-1*k)),n.push(this.productions_[T[1]][0]),i.push(D.$),a.push(D._$),A=o[n[n.length-2]][n[n.length-1]],n.push(A);break;case 3:return!0}}return!0},`parse`)};k.lexer=(function(){return{EOF:1,parseError:m(function(e,t){if(this.yy.parser)this.yy.parser.parseError(e,t);else throw Error(e)},`parseError`),setInput:m(function(e,t){return this.yy=t||this.yy||{},this._input=e,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match=``,this.conditionStack=[`INITIAL`],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},`setInput`),input:m(function(){var e=this._input[0];return this.yytext+=e,this.yyleng++,this.offset++,this.match+=e,this.matched+=e,e.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),e},`input`),unput:m(function(e){var t=e.length,n=e.split(/(?:\r\n?|\n)/g);this._input=e+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-t),this.offset-=t;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-t},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-t]),this.yyleng=this.yytext.length,this},`unput`),more:m(function(){return this._more=!0,this},`more`),reject:m(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError(`Lexical error on line `+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
|
|
4
4
|
`+this.showPosition(),{text:``,token:null,line:this.yylineno});return this},`reject`),less:m(function(e){this.unput(this.match.slice(e))},`less`),pastInput:m(function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?`...`:``)+e.substr(-20).replace(/\n/g,``)},`pastInput`),upcomingInput:m(function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?`...`:``)).replace(/\n/g,``)},`upcomingInput`),showPosition:m(function(){var e=this.pastInput(),t=Array(e.length+1).join(`-`);return e+this.upcomingInput()+`
|
ksadk/server/static/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
7
7
|
<title>AgentEngine</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-QSwCHuB8.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-jOPmTOZH.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -4,7 +4,9 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import contextlib
|
|
7
|
+
import importlib
|
|
7
8
|
import json
|
|
9
|
+
import logging
|
|
8
10
|
import os
|
|
9
11
|
import shutil
|
|
10
12
|
import signal
|
|
@@ -12,7 +14,7 @@ import time
|
|
|
12
14
|
import uuid
|
|
13
15
|
from dataclasses import dataclass, field
|
|
14
16
|
from pathlib import Path, PurePosixPath
|
|
15
|
-
from typing import Any, Callable
|
|
17
|
+
from typing import Any, Callable, ContextManager
|
|
16
18
|
|
|
17
19
|
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
|
|
18
20
|
from fastapi.responses import JSONResponse
|
|
@@ -28,20 +30,19 @@ from ksadk.terminal_exec_policy import (
|
|
|
28
30
|
validate_terminal_exec_argv as validate_exec_argv_with_policy,
|
|
29
31
|
)
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
import pty
|
|
33
|
-
except ImportError: # pragma: no cover - exercised through subprocess import test
|
|
34
|
-
pty = None # type: ignore[assignment]
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
35
34
|
|
|
36
|
-
try:
|
|
37
|
-
import select
|
|
38
|
-
except ImportError: # pragma: no cover - Windows compatibility
|
|
39
|
-
select = None # type: ignore[assignment]
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
def _optional_platform_module(name: str) -> Any | None:
|
|
37
|
+
try:
|
|
38
|
+
return importlib.import_module(name)
|
|
39
|
+
except ImportError:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
pty = _optional_platform_module("pty")
|
|
44
|
+
select = _optional_platform_module("select")
|
|
45
|
+
termios = _optional_platform_module("termios")
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
TERMINAL_REPLAY_BUFFER_BYTES = 64 * 1024
|
|
@@ -96,12 +97,7 @@ def _env_bool(name: str, default: bool) -> bool:
|
|
|
96
97
|
|
|
97
98
|
|
|
98
99
|
def native_terminal_supported() -> bool:
|
|
99
|
-
return
|
|
100
|
-
os.name != "nt"
|
|
101
|
-
and pty is not None
|
|
102
|
-
and select is not None
|
|
103
|
-
and termios is not None
|
|
104
|
-
)
|
|
100
|
+
return os.name != "nt" and pty is not None and select is not None and termios is not None
|
|
105
101
|
|
|
106
102
|
|
|
107
103
|
class TerminalSessionManager:
|
|
@@ -121,6 +117,24 @@ class TerminalSessionManager:
|
|
|
121
117
|
self._terminate_session(session)
|
|
122
118
|
self.sessions.clear()
|
|
123
119
|
|
|
120
|
+
async def close(self) -> None:
|
|
121
|
+
"""Terminate and await every terminal task owned by this manager."""
|
|
122
|
+
sessions = list(self.sessions.values())
|
|
123
|
+
tasks: list[asyncio.Task[Any]] = []
|
|
124
|
+
attachments: set[WebSocket] = set()
|
|
125
|
+
for session in sessions:
|
|
126
|
+
self._terminate_session(session)
|
|
127
|
+
attachments.update(session.attachments)
|
|
128
|
+
tasks.extend(
|
|
129
|
+
task for task in (session.reader_task, session.wait_task) if task is not None
|
|
130
|
+
)
|
|
131
|
+
for ws in attachments:
|
|
132
|
+
with contextlib.suppress(Exception):
|
|
133
|
+
await ws.close(code=1012, reason="runtime shutting down")
|
|
134
|
+
if tasks:
|
|
135
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
136
|
+
self.sessions.clear()
|
|
137
|
+
|
|
124
138
|
def serialize(self, session: TerminalSession) -> dict[str, Any]:
|
|
125
139
|
return {
|
|
126
140
|
"terminal_session_id": session.id,
|
|
@@ -213,7 +227,10 @@ class TerminalSessionManager:
|
|
|
213
227
|
session = TerminalSession(
|
|
214
228
|
id=f"term-{uuid.uuid4().hex[:12]}",
|
|
215
229
|
session_id=str(
|
|
216
|
-
payload.get("session_id")
|
|
230
|
+
payload.get("session_id")
|
|
231
|
+
or payload.get("sessionId")
|
|
232
|
+
or payload.get("SessionId")
|
|
233
|
+
or ""
|
|
217
234
|
).strip(),
|
|
218
235
|
mode=str(payload.get("mode") or "tui").strip().lower(),
|
|
219
236
|
framework=self._current_framework(),
|
|
@@ -255,7 +272,10 @@ class TerminalSessionManager:
|
|
|
255
272
|
for session in list(self.sessions.values()):
|
|
256
273
|
if session.deleted:
|
|
257
274
|
continue
|
|
258
|
-
if
|
|
275
|
+
if (
|
|
276
|
+
session.status == "detached"
|
|
277
|
+
and now - session.updated_at > TERMINAL_DETACHED_TTL_SECONDS
|
|
278
|
+
):
|
|
259
279
|
session.deleted = True
|
|
260
280
|
session.status = "deleted"
|
|
261
281
|
self._terminate_session(session)
|
|
@@ -272,7 +292,9 @@ class TerminalSessionManager:
|
|
|
272
292
|
):
|
|
273
293
|
raise ValueError("too many terminal sessions in this runtime")
|
|
274
294
|
if session_id:
|
|
275
|
-
per_business_session = [
|
|
295
|
+
per_business_session = [
|
|
296
|
+
session for session in active_sessions if session.session_id == session_id
|
|
297
|
+
]
|
|
276
298
|
if len(per_business_session) >= _env_int(
|
|
277
299
|
"AGENTENGINE_TERMINAL_MAX_SESSIONS_PER_BUSINESS_SESSION",
|
|
278
300
|
MAX_TERMINAL_SESSIONS_PER_BUSINESS_SESSION,
|
|
@@ -285,7 +307,11 @@ class TerminalSessionManager:
|
|
|
285
307
|
if mode == "tui":
|
|
286
308
|
return self._resolve_tui_command(session)
|
|
287
309
|
if mode == "exec":
|
|
288
|
-
policy =
|
|
310
|
+
policy = (
|
|
311
|
+
HERMES_TERMINAL_EXEC_POLICY
|
|
312
|
+
if framework == "hermes"
|
|
313
|
+
else OPENCLAW_TERMINAL_EXEC_POLICY
|
|
314
|
+
)
|
|
289
315
|
if framework not in {"hermes", "openclaw"}:
|
|
290
316
|
policy = GENERIC_TERMINAL_EXEC_POLICY
|
|
291
317
|
return validate_exec_argv_with_policy(session.argv, policy=policy)
|
|
@@ -296,13 +322,17 @@ class TerminalSessionManager:
|
|
|
296
322
|
if framework == "hermes" and shutil.which("hermes"):
|
|
297
323
|
command = ["hermes", "chat"]
|
|
298
324
|
if session.session_id and _env_bool("HERMES_TERMINAL_RESUME_ENABLED", True):
|
|
299
|
-
command.extend(
|
|
325
|
+
command.extend(
|
|
326
|
+
[os.getenv("HERMES_TERMINAL_RESUME_FLAG", "--resume"), session.session_id]
|
|
327
|
+
)
|
|
300
328
|
session.argv = command
|
|
301
329
|
return command
|
|
302
330
|
if framework == "openclaw" and shutil.which("openclaw"):
|
|
303
331
|
command = ["openclaw", "tui"]
|
|
304
332
|
if session.session_id:
|
|
305
|
-
command.extend(
|
|
333
|
+
command.extend(
|
|
334
|
+
[os.getenv("OPENCLAW_TERMINAL_SESSION_FLAG", "--session"), session.session_id]
|
|
335
|
+
)
|
|
306
336
|
session.argv = command
|
|
307
337
|
return command
|
|
308
338
|
shell = os.getenv("SHELL") or "/bin/sh"
|
|
@@ -367,13 +397,15 @@ class TerminalSessionManager:
|
|
|
367
397
|
session.fd = None
|
|
368
398
|
|
|
369
399
|
async def _session_reader(self, session: TerminalSession) -> None:
|
|
370
|
-
|
|
400
|
+
fd = session.fd
|
|
401
|
+
selector = select
|
|
402
|
+
if fd is None or selector is None:
|
|
371
403
|
return
|
|
372
404
|
loop = asyncio.get_running_loop()
|
|
373
405
|
while True:
|
|
374
|
-
await loop.run_in_executor(None, lambda:
|
|
406
|
+
await loop.run_in_executor(None, lambda: selector.select([fd], [], [], None))
|
|
375
407
|
try:
|
|
376
|
-
data = os.read(
|
|
408
|
+
data = os.read(fd, 4096)
|
|
377
409
|
except OSError:
|
|
378
410
|
return
|
|
379
411
|
if not data:
|
|
@@ -396,7 +428,11 @@ class TerminalSessionManager:
|
|
|
396
428
|
|
|
397
429
|
async def _attach_existing(self, ws: WebSocket, session: TerminalSession) -> None:
|
|
398
430
|
session.attachments.add(ws)
|
|
399
|
-
session.status =
|
|
431
|
+
session.status = (
|
|
432
|
+
"running"
|
|
433
|
+
if session.status == "detached" and session.pid is not None
|
|
434
|
+
else session.status
|
|
435
|
+
)
|
|
400
436
|
session.updated_at = time.time()
|
|
401
437
|
try:
|
|
402
438
|
await ws.send_text(
|
|
@@ -466,9 +502,10 @@ class TerminalSessionManager:
|
|
|
466
502
|
|
|
467
503
|
def _persist_metadata(self, session: TerminalSession) -> None:
|
|
468
504
|
try:
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
505
|
+
# Persist only under the current runtime user's state directory. An
|
|
506
|
+
# environment-controlled absolute path would select an arbitrary
|
|
507
|
+
# write location before the terminal server starts.
|
|
508
|
+
state_dir = Path.home() / ".agentengine" / "terminal"
|
|
472
509
|
state_dir.mkdir(parents=True, exist_ok=True)
|
|
473
510
|
(state_dir / f"{session.id}.json").write_text(
|
|
474
511
|
json.dumps(self.serialize(session), ensure_ascii=False, indent=2),
|
|
@@ -482,7 +519,8 @@ def _set_winsize(fd: int, rows: int, cols: int) -> None:
|
|
|
482
519
|
if termios is None:
|
|
483
520
|
return
|
|
484
521
|
with contextlib.suppress(Exception):
|
|
485
|
-
|
|
522
|
+
set_winsize = getattr(termios, "tcsetwinsize")
|
|
523
|
+
set_winsize(fd, (int(rows or 24), int(cols or 80)))
|
|
486
524
|
|
|
487
525
|
|
|
488
526
|
async def _wait_process(pid: int) -> int:
|
|
@@ -495,14 +533,19 @@ async def _wait_process(pid: int) -> int:
|
|
|
495
533
|
return status
|
|
496
534
|
|
|
497
535
|
|
|
498
|
-
def register_terminal_routes(
|
|
536
|
+
def register_terminal_routes(
|
|
537
|
+
app: FastAPI,
|
|
538
|
+
manager: TerminalSessionManager,
|
|
539
|
+
*,
|
|
540
|
+
bind_context: Callable[[], ContextManager[Any]] | None = None,
|
|
541
|
+
) -> None:
|
|
499
542
|
@app.post("/_ksadk/terminal/sessions")
|
|
500
543
|
async def create_terminal_session(request: Request) -> JSONResponse:
|
|
501
544
|
payload = await request.json()
|
|
502
545
|
try:
|
|
503
546
|
session = await manager.create_or_reuse(payload if isinstance(payload, dict) else {})
|
|
504
|
-
except ValueError
|
|
505
|
-
return JSONResponse({"error":
|
|
547
|
+
except ValueError:
|
|
548
|
+
return JSONResponse({"error": "invalid_terminal_request"}, status_code=400)
|
|
506
549
|
return JSONResponse({"session": manager.serialize(session)})
|
|
507
550
|
|
|
508
551
|
@app.get("/_ksadk/terminal/sessions")
|
|
@@ -525,27 +568,37 @@ def register_terminal_routes(app: FastAPI, manager: TerminalSessionManager) -> N
|
|
|
525
568
|
|
|
526
569
|
@app.websocket("/_ksadk/terminal/ws")
|
|
527
570
|
async def terminal_ws(ws: WebSocket) -> None:
|
|
528
|
-
if
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
try:
|
|
533
|
-
query_session_id = str(ws.query_params.get("terminal_session_id") or "").strip()
|
|
534
|
-
if query_session_id:
|
|
535
|
-
await manager.attach(ws, query_session_id)
|
|
571
|
+
context = bind_context() if bind_context is not None else contextlib.nullcontext()
|
|
572
|
+
with context:
|
|
573
|
+
if TERMINAL_SUBPROTOCOL not in (ws.headers.get("sec-websocket-protocol") or ""):
|
|
574
|
+
await ws.close(code=4400, reason="missing ks-terminal.v1 subprotocol")
|
|
536
575
|
return
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
576
|
+
await ws.accept(subprotocol=TERMINAL_SUBPROTOCOL)
|
|
577
|
+
try:
|
|
578
|
+
query_session_id = str(ws.query_params.get("terminal_session_id") or "").strip()
|
|
579
|
+
if query_session_id:
|
|
580
|
+
await manager.attach(ws, query_session_id)
|
|
581
|
+
return
|
|
582
|
+
first = await ws.receive_text()
|
|
583
|
+
payload = json.loads(first)
|
|
584
|
+
if payload.get("type") == "attach":
|
|
585
|
+
terminal_session_id = str(payload.get("terminal_session_id") or "").strip()
|
|
586
|
+
await manager.attach(ws, terminal_session_id)
|
|
587
|
+
return
|
|
588
|
+
if payload.get("type") != "start":
|
|
589
|
+
raise ValueError("first frame must be start")
|
|
590
|
+
await manager.legacy_start(ws, payload)
|
|
591
|
+
except WebSocketDisconnect:
|
|
542
592
|
return
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
593
|
+
except Exception:
|
|
594
|
+
logger.exception("terminal websocket request failed")
|
|
595
|
+
if ws.client_state == WebSocketState.CONNECTED:
|
|
596
|
+
await ws.send_text(
|
|
597
|
+
json.dumps(
|
|
598
|
+
{
|
|
599
|
+
"type": "error",
|
|
600
|
+
"message": "Terminal request failed; see server logs for details.",
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
)
|
|
604
|
+
await ws.close()
|
ksadk/sessions/__init__.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
4
|
+
import contextvars
|
|
3
5
|
import logging
|
|
4
6
|
import os
|
|
7
|
+
from contextlib import contextmanager
|
|
5
8
|
from dataclasses import dataclass
|
|
6
|
-
from typing import Callable
|
|
9
|
+
from typing import Callable, Iterator
|
|
7
10
|
from urllib.parse import urlsplit, urlunsplit
|
|
8
11
|
|
|
9
12
|
from ksadk.sessions.base import BaseSessionService, Session, SessionEvent, SessionState
|
|
@@ -21,6 +24,10 @@ from ksadk.sessions.in_memory import InMemorySessionService
|
|
|
21
24
|
from ksadk.sessions.local_service import create_local_session_service
|
|
22
25
|
|
|
23
26
|
_cached_session_service: BaseSessionService | None = None
|
|
27
|
+
_cached_session_service_loop: asyncio.AbstractEventLoop | None = None
|
|
28
|
+
_session_service_override: contextvars.ContextVar[BaseSessionService | None] = (
|
|
29
|
+
contextvars.ContextVar("ksadk_session_service", default=None)
|
|
30
|
+
)
|
|
24
31
|
logger = logging.getLogger(__name__)
|
|
25
32
|
|
|
26
33
|
|
|
@@ -48,12 +55,16 @@ def register_session_backend(name: str, factory: SessionBackendFactory) -> None:
|
|
|
48
55
|
def resolve_session_backend_config(*, backend: str | None = None) -> SessionBackendConfig:
|
|
49
56
|
_register_builtin_backends()
|
|
50
57
|
resolved_backend = (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
(
|
|
59
|
+
backend
|
|
60
|
+
or os.getenv("KSADK_SESSION_BACKEND")
|
|
61
|
+
or os.getenv("AGENTENGINE_SESSION_BACKEND")
|
|
62
|
+
or os.getenv("KSADK_STM_BACKEND")
|
|
63
|
+
or ""
|
|
64
|
+
)
|
|
65
|
+
.strip()
|
|
66
|
+
.lower()
|
|
67
|
+
)
|
|
57
68
|
if not resolved_backend:
|
|
58
69
|
resolved_backend = "local"
|
|
59
70
|
if resolved_backend == "sqlite":
|
|
@@ -86,14 +97,10 @@ def resolve_session_backend_config(*, backend: str | None = None) -> SessionBack
|
|
|
86
97
|
or "default"
|
|
87
98
|
).strip()
|
|
88
99
|
tenant_id = (
|
|
89
|
-
os.getenv("KSADK_TENANT_ID")
|
|
90
|
-
or os.getenv("AGENTENGINE_TENANT_ID")
|
|
91
|
-
or "default"
|
|
100
|
+
os.getenv("KSADK_TENANT_ID") or os.getenv("AGENTENGINE_TENANT_ID") or "default"
|
|
92
101
|
).strip()
|
|
93
102
|
workspace_id = (
|
|
94
|
-
os.getenv("KSADK_WORKSPACE_ID")
|
|
95
|
-
or os.getenv("AGENTENGINE_WORKSPACE_ID")
|
|
96
|
-
or "default"
|
|
103
|
+
os.getenv("KSADK_WORKSPACE_ID") or os.getenv("AGENTENGINE_WORKSPACE_ID") or "default"
|
|
97
104
|
).strip()
|
|
98
105
|
return SessionBackendConfig(
|
|
99
106
|
backend=resolved_backend,
|
|
@@ -188,7 +195,8 @@ def log_session_backend_diagnostics(*, backend: str | None = None) -> None:
|
|
|
188
195
|
logger.info("KSADK session backend: %s", payload)
|
|
189
196
|
if not bool(payload.get("ProductionSafe")):
|
|
190
197
|
logger.warning(
|
|
191
|
-
"KSADK session backend %s is not cross-pod recoverable;
|
|
198
|
+
"KSADK session backend %s is not cross-pod recoverable; "
|
|
199
|
+
"use postgres for K8s multi-replica deployments.",
|
|
192
200
|
payload.get("Backend"),
|
|
193
201
|
)
|
|
194
202
|
|
|
@@ -225,23 +233,64 @@ def create_session_service(
|
|
|
225
233
|
return service
|
|
226
234
|
|
|
227
235
|
|
|
236
|
+
@contextmanager
|
|
237
|
+
def bind_session_service(service: BaseSessionService) -> Iterator[None]:
|
|
238
|
+
"""Bind a service to the current request/task context."""
|
|
239
|
+
token = _session_service_override.set(service)
|
|
240
|
+
try:
|
|
241
|
+
yield
|
|
242
|
+
finally:
|
|
243
|
+
_session_service_override.reset(token)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _running_loop() -> asyncio.AbstractEventLoop | None:
|
|
247
|
+
try:
|
|
248
|
+
return asyncio.get_running_loop()
|
|
249
|
+
except RuntimeError:
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
|
|
228
253
|
def resolve_session_service() -> BaseSessionService:
|
|
229
|
-
|
|
254
|
+
"""Resolve a request-bound service or a loop-safe legacy fallback.
|
|
255
|
+
|
|
256
|
+
``LocalSessionService`` owns asyncio synchronization primitives. A process
|
|
257
|
+
cache shared by pytest-asyncio loops can therefore reuse a lock bound to a
|
|
258
|
+
closed peer loop. Legacy non-request callers retain caching, while async
|
|
259
|
+
callers never reuse a cache created by another running loop.
|
|
260
|
+
"""
|
|
261
|
+
global _cached_session_service, _cached_session_service_loop
|
|
262
|
+
|
|
263
|
+
override = _session_service_override.get()
|
|
264
|
+
if override is not None:
|
|
265
|
+
return override
|
|
266
|
+
|
|
267
|
+
loop = _running_loop()
|
|
230
268
|
if _cached_session_service is not None:
|
|
231
|
-
|
|
269
|
+
if loop is None or _cached_session_service_loop is loop:
|
|
270
|
+
return _cached_session_service
|
|
271
|
+
if _cached_session_service_loop is None:
|
|
272
|
+
# A synchronous startup path created the service. Associate it
|
|
273
|
+
# with the first async caller rather than replacing it eagerly.
|
|
274
|
+
_cached_session_service_loop = loop
|
|
275
|
+
return _cached_session_service
|
|
276
|
+
|
|
232
277
|
_cached_session_service = create_session_service()
|
|
278
|
+
_cached_session_service_loop = loop
|
|
233
279
|
return _cached_session_service
|
|
234
280
|
|
|
235
281
|
|
|
236
282
|
async def reset_session_service() -> None:
|
|
237
|
-
global _cached_session_service
|
|
283
|
+
global _cached_session_service, _cached_session_service_loop
|
|
238
284
|
if _cached_session_service is None:
|
|
285
|
+
_cached_session_service_loop = None
|
|
239
286
|
return
|
|
240
287
|
|
|
241
|
-
|
|
288
|
+
service = _cached_session_service
|
|
289
|
+
_cached_session_service = None
|
|
290
|
+
_cached_session_service_loop = None
|
|
291
|
+
close = getattr(service, "aclose", None)
|
|
242
292
|
if close is not None:
|
|
243
293
|
await close()
|
|
244
|
-
_cached_session_service = None
|
|
245
294
|
|
|
246
295
|
|
|
247
296
|
def get_session_service() -> BaseSessionService:
|
|
@@ -255,6 +304,7 @@ async def close_session_service() -> None:
|
|
|
255
304
|
__all__ = [
|
|
256
305
|
"ADKSessionAdapter",
|
|
257
306
|
"BaseSessionService",
|
|
307
|
+
"bind_session_service",
|
|
258
308
|
"ConversationSessionCore",
|
|
259
309
|
"InMemorySessionService",
|
|
260
310
|
"LangChainSessionAdapter",
|
ksadk/sessions/base.py
CHANGED
|
@@ -78,16 +78,11 @@ class SessionEvent:
|
|
|
78
78
|
return cls(
|
|
79
79
|
id=str(payload.get("id") or generate_id()),
|
|
80
80
|
session_id=str(
|
|
81
|
-
payload.get("session_id")
|
|
82
|
-
or payload.get("sessionId")
|
|
83
|
-
or session_id
|
|
84
|
-
or ""
|
|
81
|
+
payload.get("session_id") or payload.get("sessionId") or session_id or ""
|
|
85
82
|
),
|
|
86
83
|
author=str(payload.get("author") or ""),
|
|
87
84
|
event_type=str(
|
|
88
|
-
payload.get("event_type")
|
|
89
|
-
or payload.get("eventType")
|
|
90
|
-
or _infer_event_type(payload)
|
|
85
|
+
payload.get("event_type") or payload.get("eventType") or _infer_event_type(payload)
|
|
91
86
|
),
|
|
92
87
|
content=dict(payload.get("content") or {}),
|
|
93
88
|
timestamp=normalize_timestamp(payload.get("timestamp")),
|
|
@@ -190,10 +185,7 @@ class Session:
|
|
|
190
185
|
return cls(
|
|
191
186
|
id=str(payload.get("id") or generate_id()),
|
|
192
187
|
agent_id=str(
|
|
193
|
-
payload.get("agent_id")
|
|
194
|
-
or payload.get("app_name")
|
|
195
|
-
or payload.get("appName")
|
|
196
|
-
or ""
|
|
188
|
+
payload.get("agent_id") or payload.get("app_name") or payload.get("appName") or ""
|
|
197
189
|
),
|
|
198
190
|
user_id=str(payload.get("user_id") or payload.get("userId") or ""),
|
|
199
191
|
title=str(payload.get("title") or payload.get("Title") or ""),
|
|
@@ -272,6 +264,14 @@ class BaseSessionService(abc.ABC):
|
|
|
272
264
|
async def get_session(self, session_id: str) -> Optional[Session]:
|
|
273
265
|
raise NotImplementedError
|
|
274
266
|
|
|
267
|
+
async def get_session_metadata(self, session_id: str) -> Optional[Session]:
|
|
268
|
+
"""Return session ownership/state without requiring the event transcript."""
|
|
269
|
+
|
|
270
|
+
session = await self.get_session(session_id)
|
|
271
|
+
if session is not None:
|
|
272
|
+
session.events = []
|
|
273
|
+
return session
|
|
274
|
+
|
|
275
275
|
@abc.abstractmethod
|
|
276
276
|
async def list_sessions(
|
|
277
277
|
self,
|
|
@@ -331,6 +331,26 @@ class BaseSessionService(abc.ABC):
|
|
|
331
331
|
) -> int:
|
|
332
332
|
raise NotImplementedError
|
|
333
333
|
|
|
334
|
+
@abc.abstractmethod
|
|
335
|
+
async def get_events_for_agent(
|
|
336
|
+
self,
|
|
337
|
+
agent_id: str,
|
|
338
|
+
user_id: Optional[str] = None,
|
|
339
|
+
offset: Optional[int] = None,
|
|
340
|
+
limit: Optional[int] = None,
|
|
341
|
+
) -> list[SessionEvent]:
|
|
342
|
+
"""跨会话事件查询,必须由存储后端提供无截断实现。"""
|
|
343
|
+
raise NotImplementedError
|
|
344
|
+
|
|
345
|
+
@abc.abstractmethod
|
|
346
|
+
async def count_events_for_agent(
|
|
347
|
+
self,
|
|
348
|
+
agent_id: str,
|
|
349
|
+
user_id: Optional[str] = None,
|
|
350
|
+
) -> int:
|
|
351
|
+
"""跨会话事件计数,必须由存储后端提供无截断实现。"""
|
|
352
|
+
raise NotImplementedError
|
|
353
|
+
|
|
334
354
|
@abc.abstractmethod
|
|
335
355
|
async def get_state(
|
|
336
356
|
self,
|