synapse-cli-agent 0.1.28__tar.gz → 0.1.29__tar.gz
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.
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/CHANGELOG.md +20 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/PKG-INFO +2 -1
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/pyproject.toml +2 -1
- synapse_cli_agent-0.1.29/release_body.md +19 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/Cargo.lock +1 -1
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/Cargo.toml +1 -1
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/pyproject.toml +1 -1
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/exit_trace.py +12 -34
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/agent_loop/model.py +6 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/agent_loop/turn.py +5 -1
- synapse_cli_agent-0.1.29/src/synapse/runtime/cancellation.py +24 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/parser.py +4 -1
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/stream_events.py +2 -1
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/cancel_repair.py +34 -7
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/image_viewer.py +6 -1
- synapse_cli_agent-0.1.29/src/synapse/ui/mermaid_image.py +148 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/rendering.py +188 -5
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/status_controller.py +2 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/stream.py +4 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/transcript_blocks.py +111 -11
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/tui_styles.py +28 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn/controller.py +239 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_agent_turn_runtime.py +25 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_cancel_repair.py +36 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_image_render.py +11 -0
- synapse_cli_agent-0.1.29/tests/test_image_viewer.py +40 -0
- synapse_cli_agent-0.1.29/tests/test_mermaid_image.py +485 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_stream_cancel.py +25 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_turn_controller.py +393 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/uv.lock +17 -2
- synapse_cli_agent-0.1.28/release_body.md +0 -24
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.dockerignore +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.github/workflows/ci.yml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.github/workflows/docs.yml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.github/workflows/native-compression-wheels.yml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.github/workflows/native-core-tool-wheels.yml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.github/workflows/release.yml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.gitignore +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.python-version +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/.readthedocs.yaml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/AGENTS.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/Dockerfile.web +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/LICENSE +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/README.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/README.zh-CN.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/agent-studio-prototype/favicon.svg +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/agent-studio-prototype/index.html +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/agent-studio-prototype/script.js +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/agent-studio-prototype/styles.css +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/agent_upstream.txt +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/assets/synapse-logo.svg +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/assets/tui-preview.png +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/cli_upstream.txt +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/debug_compact.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/decode_screenshot.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-development-guide.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/baseline-report.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/decisions.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/index.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/migration.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-0-baseline.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-1-streaming-core.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-2-turn-runtime.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-3-tui-cutover.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-4-session-runtime.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-5-multi-session.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-6-project-runtime.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-7-global-control-plane.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/phase-8-hardening.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/post-review-fix-plan.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/agent-runtime-decoupling/progress.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/architecture-flow.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/architecture.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/cli.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/codex-session-discovery-phase-1.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/codex-session-import-phase-2.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/config.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/design.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/docker-web.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/index.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/install.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/math-formulas-test.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/mcp.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/models.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/native-compression-core.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/native-core-tool.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/permissions.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/quickstart.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/sessions.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/skills.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/smith_output.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/subagent-architecture-survey.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/tool-output-transform.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/tui-cursor-refactor.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/tutorial.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/docs/x-agent-development-guide.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/examples/mcp.example.json +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/examples/models.example.json +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/examples/settings.example.json +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/middleware_upstream.txt +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/mkdocs.yml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/LICENSE +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/NOTICE +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/README.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/python/synapse_core_tool/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/src/file_access.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/src/file_tools.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/src/lib.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/src/math_render.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/src/search.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-core-tool/uv.lock +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/Cargo.lock +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/Cargo.toml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/LICENSE +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/NOTICE +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/README.md +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/pyproject.toml +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/python/synapse_tool_compress_core/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/ccr.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/ccr_in_memory.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/mod.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/relevance/base.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/relevance/bm25.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/signals/keyword_detector.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/signals/line_importance.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/adaptive_sizer.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/anchor_selector.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/code_compressor.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/diff_compressor.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/log_compressor.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/search_compressor.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/analyzer.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/anchors.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/builder.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/classifier.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/classifier.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/compactor.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/formatter.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/ir.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/mod.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/walker.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/config.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/constraints.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/crusher.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/crushers.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/error_keywords.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/field_detect.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/hashing.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/mod.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/observer.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/orchestration.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/outliers.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/planning.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/statistics.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/stats_math.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/traits.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/types.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/rust/synapse-tool-compress-core/src/lib.rs +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/scripts/install.ps1 +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/scripts/release.ps1 +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/scripts/serve_web.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/slash_cmds_upstream.txt +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/__main__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/app/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/app/agent.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/app/agent_assembly.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/app/agent_md.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/cli.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/compression.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/goal.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/helpers.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/mcp.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/model.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/result.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/sessions.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/slash_cmds.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/slash_complete.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/commands/theme.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/config.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/content/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/content/input_history.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/content/multimodal.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/content/prompts.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/content/skills_catalog.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/model.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/steering.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/store.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/goals/tools.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/checkpoint_seed.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/codex_history.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/codex_import.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/codex_sessions.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/describe_image.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/http_clients.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/llm_openai_compat.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/llm_openai_websocket.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/mcp_client.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/openai_oauth.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/openai_oauth_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/openai_usage.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/integrations/vision_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/memory/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/memory/auto_recorder.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/memory/embedder.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/memory/long_term.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/models/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/models/config.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/models/helpers.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/models/profile.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/models/registry.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/models_registry.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/debug_inspector.html +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/debug_server.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/heap_dump.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/llm_debug.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/startup_trace.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/parallel_subagents.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/planner/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/planner/task_planner.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/projects/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/projects/catalog.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/rag/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/rag/knowledge_base.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/agent_loop/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/agent_loop/request.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/async_runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/backends.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/context_compact.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/debug_capture_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/execute_capture.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/filesystem_tool_prompt_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/fs_permissions.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/harness.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/hitl.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/interaction_ledger.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/model_request_compression_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/pathing.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/projects/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/projects/identity.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/projects/runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/safety.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/session_prewarm.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/sessions/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/sessions/events.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/sessions/manager.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/sessions/persistence.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/sessions/ref.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/sessions/runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/steer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/accumulator.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/adapters.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/events.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/protocol.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/tool_model.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/subagent_routing.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/subagents.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/timeline.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/token_rate.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/tool_ignore.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/tool_output_eval.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/tool_output_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/tool_output_usage_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/tool_response_truncate_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/search_index.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/store.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/summary.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/transcript.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/transcript_migration.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/sessions/transcript_projection.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/settings/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/settings/config_paths.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/settings/schema.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/subagent_monitor.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/subagents.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/detection.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/metrics.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/models.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/pipeline.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/repository.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tool_output/transformers.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tools/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tools/describe_image.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tools/filesystem_patch.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tools/filesystem_search.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/tools/session_tools.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/agent_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/answer_divider.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/codex_usage.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/fast.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/goal.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/key_hints.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/mcp.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/mode.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/model.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/components/thread.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/context.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/bottombar/core.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/chrome/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/chrome/controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/clipboard.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/active_session_switcher.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/base.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/codex_reset.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/codex_session_list.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/compression_diagnostics.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/git_explore.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/mcp_panel.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/model_picker.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/safety_panel.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/session_list.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/subagent_monitor.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/theme_designer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/dialogs/theme_picker.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/drawer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/formatters.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/git_explore/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/git_explore/engine.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/git_explore/provider.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/git_explore/unified.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/image_preview.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/image_render.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/math_image.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/prompt_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/selectable_static.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/selectable_text.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/sink.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/steer_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/steer_widget.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/stream_events.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/stream_runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/subagent_status_bar.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/textual_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/textual_stream_sink.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/theme.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/theme_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/timeline.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/tool_blocks.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/components/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/components/branch.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/components/title.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/components/tool_output.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/components/usage.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/components/workspace.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/context.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/core.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/git_changes_popover.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/git_chrome.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/tool_output_popover.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/topbar/widget.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/transcript/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/transcript/controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/transcript/factory.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/transcript/history.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/transcript/state.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/tui.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/tui_launch.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn/event_bridge.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn/event_renderer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn/persistence.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn/request.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn_rail.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/turn_rail_widgets.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/user_turn.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/user_turn_block.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/ui/welcome.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/web.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/synapse.cmd +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/__init__.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/agent_stream/core_scenarios.json +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/duplicate_response_item.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/incomplete_and_aborted.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/legacy_compaction.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/normal_completed.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/replacement_history.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/rollback.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/codex_rollouts/unsupported_replacement.jsonl +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/sample_repo/calculator.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/sample_repo/test_calculator.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/fixtures/tool_output_eval.json +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_agent_factory.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_agent_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_async_checkpointer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_backends.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_bottombar_registry.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_capabilities.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_checkpoint_seed.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_chrome_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_cli.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_cli_codex_import.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_codex_history.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_codex_import.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_codex_sessions.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_codex_sessions_windows.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_compact_tool_descriptions.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_config.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_context_compact.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_context_window.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_dag_parallel.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_debug_capture_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_debug_inspector.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_describe_image.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_dialogs.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_filesystem_patch_tool.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_filesystem_search_tools.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_git_changes_popover.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_git_chrome.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_git_explore.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_goal_live_tui.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_goals.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_heap_dump.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_http_clients.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_input_history.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_iteration_abc.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_layered_config.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_math_image_render.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_mcp_schema.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_mermaid_render.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_middleware_async.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_model_request_compression_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_model_retry.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_multimodal.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_native_math_render.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_openai_compat_reasoning.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_openai_oauth.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_openai_oauth_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_openai_usage.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_openai_websocket.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_pathing.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_project_catalog.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_project_drawer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_project_runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_project_switch.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_prompt_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_prompts.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_runtime_hardening.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_runtime_manager.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_runtime_streaming.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_safety.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_search_index.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_session_prewarm.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_session_runtime.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_session_store.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_session_summary.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_slash_and_mcp.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_slash_complete.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_slash_effects.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_startup_defer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_steer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_steer_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_stream_semantic_fixtures.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_stream_tool_items.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_stream_ui.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_subagent_monitor_dialog.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_subagent_status.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_textual_stream_sink.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_theme.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_theme_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_timeline.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_token_rate.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_ignore.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_intent.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_output.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_output_eval.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_output_slash.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_output_usage_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tool_response_truncate_middleware.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_topbar_context_ratio.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_topbar_registry.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_transcript.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_transcript_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_transcript_history.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_transcript_history_controller.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_transcript_migration.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_transcript_projection.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tui_active_session_switcher.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tui_codex_import.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_tui_selection.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_turn_event_renderer.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_turn_rail_minimap.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_turn_request.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_usage_restore.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_user_turn_style.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/test_welcome.py +0 -0
- {synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/tests/tool_output_plugin_fixture.py +0 -0
|
@@ -7,6 +7,26 @@ The release workflow automatically extracts the matching section as release note
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## v0.1.29
|
|
11
|
+
|
|
12
|
+
### 新增功能
|
|
13
|
+
|
|
14
|
+
- TUI 图片查看器:点击 transcript 中的图片可在模态窗口中放大查看,修复点击事件在模态栈切换时的误关闭问题。
|
|
15
|
+
- TUI Mermaid 渲染优化:Mermaid 图片在后台线程渲染,渲染期间显示占位提示,避免原生渲染阻塞事件循环。
|
|
16
|
+
- 后台会话结束时通知前台会话;跨事件边界携带取消原因。
|
|
17
|
+
|
|
18
|
+
### 修复
|
|
19
|
+
|
|
20
|
+
- 修复图片查看器点击关闭时可能移除默认 screen 并抛出 ScreenStackError 的问题。
|
|
21
|
+
- 修复会话切换时 Mermaid 占位渲染的竞态,渲染结果仅在仍处于当前世代且已挂载时替换。
|
|
22
|
+
|
|
23
|
+
### 工程改进
|
|
24
|
+
|
|
25
|
+
- synapse-core-tool 原生扩展发布 0.1.2(修复 pyproject.toml 版本未同步导致的 PyPI 上传失败)。
|
|
26
|
+
- 新增 `make_mermaid_widget_from_png`,将 PNG 渲染与 widget 构建解耦,明确 UI 线程边界。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
10
30
|
## v0.1.28
|
|
11
31
|
|
|
12
32
|
### 新增功能
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: synapse-cli-agent
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.29
|
|
4
4
|
Summary: Local coding agent built on LangChain Deep Agents (LocalShell, no sandbox)
|
|
5
5
|
Project-URL: Homepage, https://github.com/alex8224/synapse-agent
|
|
6
6
|
Project-URL: Repository, https://github.com/alex8224/synapse-agent
|
|
@@ -208,6 +208,7 @@ Requires-Dist: langchain==1.3.14
|
|
|
208
208
|
Requires-Dist: langgraph-checkpoint-sqlite==3.1.0
|
|
209
209
|
Requires-Dist: langgraph==1.2.9
|
|
210
210
|
Requires-Dist: mcp==1.28.1
|
|
211
|
+
Requires-Dist: mmdr==0.3.0
|
|
211
212
|
Requires-Dist: pydantic-settings==2.14.2
|
|
212
213
|
Requires-Dist: python-dotenv==1.2.2
|
|
213
214
|
Requires-Dist: rich==15.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "synapse-cli-agent"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.29"
|
|
4
4
|
description = "Local coding agent built on LangChain Deep Agents (LocalShell, no sandbox)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -20,6 +20,7 @@ dependencies = [
|
|
|
20
20
|
"langgraph==1.2.9",
|
|
21
21
|
"langgraph-checkpoint-sqlite==3.1.0",
|
|
22
22
|
"mcp==1.28.1",
|
|
23
|
+
"mmdr==0.3.0",
|
|
23
24
|
"pydantic-settings==2.14.2",
|
|
24
25
|
"python-dotenv==1.2.2",
|
|
25
26
|
"rich==15.0.0",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## v0.1.29
|
|
2
|
+
|
|
3
|
+
### 新增功能
|
|
4
|
+
|
|
5
|
+
- TUI 图片查看器:点击 transcript 中的图片可在模态窗口中放大查看,修复点击事件在模态栈切换时的误关闭问题。
|
|
6
|
+
- TUI Mermaid 渲染优化:Mermaid 图片在后台线程渲染,渲染期间显示占位提示,避免原生渲染阻塞事件循环。
|
|
7
|
+
- 后台会话结束时通知前台会话;跨事件边界携带取消原因。
|
|
8
|
+
|
|
9
|
+
### 修复
|
|
10
|
+
|
|
11
|
+
- 修复图片查看器点击关闭时可能移除默认 screen 并抛出 ScreenStackError 的问题。
|
|
12
|
+
- 修复会话切换时 Mermaid 占位渲染的竞态,渲染结果仅在仍处于当前世代且已挂载时替换。
|
|
13
|
+
|
|
14
|
+
### 工程改进
|
|
15
|
+
|
|
16
|
+
- synapse-core-tool 原生扩展发布 0.1.2(修复 pyproject.toml 版本未同步导致的 PyPI 上传失败)。
|
|
17
|
+
- 新增 `make_mermaid_widget_from_png`,将 PNG 渲染与 widget 构建解耦,明确 UI 线程边界。
|
|
18
|
+
|
|
19
|
+
---
|
{synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/observability/exit_trace.py
RENAMED
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Collects stage timings across the exit chain (Ctrl+C / ``/exit`` → Textual
|
|
4
4
|
``on_unmount`` → session/project teardown → ``asyncio.run`` executor join →
|
|
5
|
-
atexit MCP/async-runtime close)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Timing only starts when :func:`begin` is called (i.e. a real exit was
|
|
9
|
-
requested); modules imported during tests never emit lines on their own.
|
|
5
|
+
atexit MCP/async-runtime close). The instrumentation (``begin``/``mark``/
|
|
6
|
+
``span``) is kept, but the collected report is **no longer printed to stderr**:
|
|
7
|
+
``duration`` and ``dump`` are no-ops kept only for call-site compatibility.
|
|
10
8
|
"""
|
|
11
9
|
|
|
12
10
|
from __future__ import annotations
|
|
13
11
|
|
|
14
|
-
import sys
|
|
15
12
|
import threading
|
|
16
13
|
import time
|
|
17
14
|
from collections.abc import Iterator
|
|
@@ -75,38 +72,19 @@ class ExitTrace:
|
|
|
75
72
|
self.marks.append((name, since, step))
|
|
76
73
|
|
|
77
74
|
def duration(self, name: str, started: float, **fields: Any) -> None:
|
|
78
|
-
"""
|
|
75
|
+
"""No-op: exit stages are no longer reported to stderr.
|
|
79
76
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
stage began.
|
|
77
|
+
Kept so existing call sites (atexit MCP / async-runtime close) stay
|
|
78
|
+
untouched while the shutdown trace stays silent.
|
|
83
79
|
"""
|
|
84
|
-
|
|
85
|
-
if not self._started:
|
|
86
|
-
return
|
|
87
|
-
elapsed = (time.perf_counter() - started) * 1000
|
|
88
|
-
suffix = " ".join(f"{key}={value}" for key, value in fields.items())
|
|
89
|
-
detail = f" {suffix}" if suffix else ""
|
|
90
|
-
print(
|
|
91
|
-
f"[exit-trace] thread={threading.current_thread().name} "
|
|
92
|
-
f"stage={name} elapsed_ms={elapsed:.1f}{detail}",
|
|
93
|
-
file=sys.stderr,
|
|
94
|
-
)
|
|
80
|
+
del name, started, fields
|
|
95
81
|
|
|
96
82
|
def dump(self, *, header: str = "exit-trace") -> None:
|
|
97
|
-
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
total = (time.perf_counter() - self.t0) * 1000
|
|
103
|
-
print(f"[{header}] total={total:.1f}ms stages={len(marks)}", file=sys.stderr)
|
|
104
|
-
for name, since, step in sorted(marks, key=lambda x: x[1]):
|
|
105
|
-
print(f" +{step:8.1f}ms @{since:8.1f}ms {name}", file=sys.stderr)
|
|
106
|
-
top = sorted(marks, key=lambda x: x[2], reverse=True)[:10]
|
|
107
|
-
print(f"[{header}] top stages:", file=sys.stderr)
|
|
108
|
-
for name, _since, step in top:
|
|
109
|
-
print(f" {step:8.1f}ms {name}", file=sys.stderr)
|
|
83
|
+
"""No-op: the accumulated stage report is no longer printed.
|
|
84
|
+
|
|
85
|
+
Kept for call-site compatibility (``tui_launch`` teardown).
|
|
86
|
+
"""
|
|
87
|
+
del header
|
|
110
88
|
|
|
111
89
|
|
|
112
90
|
EXIT_TRACE = ExitTrace()
|
{synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/agent_loop/model.py
RENAMED
|
@@ -9,6 +9,8 @@ from dataclasses import dataclass, field
|
|
|
9
9
|
from enum import StrEnum
|
|
10
10
|
from typing import TYPE_CHECKING, Any
|
|
11
11
|
|
|
12
|
+
from synapse.runtime.cancellation import mark_cancel_event
|
|
13
|
+
|
|
12
14
|
if TYPE_CHECKING:
|
|
13
15
|
from synapse.runtime.agent_loop.request import TurnRequest
|
|
14
16
|
|
|
@@ -50,6 +52,10 @@ class CancelToken:
|
|
|
50
52
|
if self._event.is_set():
|
|
51
53
|
return False
|
|
52
54
|
self._reason = str(reason or "user")
|
|
55
|
+
# ``stream_agent`` accepts a plain threading.Event for compatibility.
|
|
56
|
+
# Attach the origin before setting it so the parser can distinguish
|
|
57
|
+
# user ESC from lifecycle/goal cancellation without changing that API.
|
|
58
|
+
mark_cancel_event(self._event, self._reason)
|
|
53
59
|
self._event.set()
|
|
54
60
|
return True
|
|
55
61
|
|
{synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/agent_loop/turn.py
RENAMED
|
@@ -244,7 +244,11 @@ class AgentTurnRuntime:
|
|
|
244
244
|
last_ttft_s=result.last_ttft_s,
|
|
245
245
|
last_rate_basis=result.last_rate_basis,
|
|
246
246
|
compact_events=result.compact_events,
|
|
247
|
-
cancel_reason=
|
|
247
|
+
cancel_reason=(
|
|
248
|
+
token.reason or result.cancel_reason
|
|
249
|
+
if status is TurnStatus.CANCELLED
|
|
250
|
+
else None
|
|
251
|
+
),
|
|
248
252
|
)
|
|
249
253
|
|
|
250
254
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Cancellation metadata shared across runtime compatibility boundaries."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import threading
|
|
6
|
+
|
|
7
|
+
_CANCEL_REASON_ATTR = "_synapse_cancel_reason"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def mark_cancel_event(event: threading.Event, reason: str) -> None:
|
|
11
|
+
"""Attach a cancellation origin before setting a compatibility event."""
|
|
12
|
+
try:
|
|
13
|
+
setattr(event, _CANCEL_REASON_ATTR, reason)
|
|
14
|
+
except (AttributeError, TypeError):
|
|
15
|
+
# Some Event-compatible implementations may reject custom attributes.
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def cancel_reason_from_event(event: threading.Event | None) -> str | None:
|
|
20
|
+
"""Return Synapse cancellation metadata attached to a thread event."""
|
|
21
|
+
if event is None:
|
|
22
|
+
return None
|
|
23
|
+
reason = getattr(event, _CANCEL_REASON_ATTR, None)
|
|
24
|
+
return str(reason) if reason else None
|
{synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/parser.py
RENAMED
|
@@ -17,6 +17,7 @@ import time
|
|
|
17
17
|
from collections.abc import Callable
|
|
18
18
|
from typing import Any
|
|
19
19
|
|
|
20
|
+
from synapse.runtime.cancellation import cancel_reason_from_event
|
|
20
21
|
from synapse.runtime.context_compact import (
|
|
21
22
|
is_context_compact_text,
|
|
22
23
|
is_lc_summarization_message,
|
|
@@ -808,6 +809,7 @@ def stream_agent(
|
|
|
808
809
|
except Exception: # noqa: BLE001
|
|
809
810
|
interrupted = False
|
|
810
811
|
|
|
812
|
+
cancel_reason = cancel_reason_from_event(cancel_event) if cancelled else None
|
|
811
813
|
result = StreamResult(
|
|
812
814
|
state=final,
|
|
813
815
|
final_text=final_text if not interrupted else (final_text or ""),
|
|
@@ -826,6 +828,7 @@ def stream_agent(
|
|
|
826
828
|
last_ttft_s=last_ttft_s,
|
|
827
829
|
last_rate_basis=last_rate_basis,
|
|
828
830
|
cancelled=cancelled,
|
|
831
|
+
cancel_reason=cancel_reason,
|
|
829
832
|
interrupted=interrupted,
|
|
830
833
|
compact_events=compact_events,
|
|
831
834
|
)
|
|
@@ -834,7 +837,7 @@ def stream_agent(
|
|
|
834
837
|
try:
|
|
835
838
|
from synapse.sessions.cancel_repair import repair_thread_after_cancel
|
|
836
839
|
|
|
837
|
-
repair_thread_after_cancel(agent, run_config)
|
|
840
|
+
repair_thread_after_cancel(agent, run_config, reason=cancel_reason)
|
|
838
841
|
except Exception: # noqa: BLE001
|
|
839
842
|
pass
|
|
840
843
|
elif interrupted:
|
{synapse_cli_agent-0.1.28 → synapse_cli_agent-0.1.29}/src/synapse/runtime/streaming/stream_events.py
RENAMED
|
@@ -215,7 +215,8 @@ class StreamResult:
|
|
|
215
215
|
last_output_tokens_per_second: float | None = None
|
|
216
216
|
last_ttft_s: float | None = None
|
|
217
217
|
last_rate_basis: str = "end_to_end"
|
|
218
|
-
cancelled: bool = False #
|
|
218
|
+
cancelled: bool = False # turn aborted through cancel_event
|
|
219
|
+
cancel_reason: str | None = None # user / goal_pause / shutdown / unknown
|
|
219
220
|
interrupted: bool = False # graph paused for HITL approval
|
|
220
221
|
compact_events: int = 0 # context-compaction summaries hidden from UI
|
|
221
222
|
def _chunk_text(msg_chunk: Any) -> str:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Keep multi-turn context continuous after
|
|
1
|
+
"""Keep multi-turn context continuous after a turn is cancelled.
|
|
2
2
|
|
|
3
3
|
Hard-stopping astream can leave the LangGraph checkpoint with:
|
|
4
4
|
- AIMessage.tool_calls without matching ToolMessage
|
|
@@ -93,7 +93,16 @@ def _answered_tool_ids(messages: list[Any]) -> set[str]:
|
|
|
93
93
|
return done
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
def
|
|
96
|
+
def _is_user_cancel(reason: str | None) -> bool:
|
|
97
|
+
"""Treat unannotated legacy cancel events as user cancellation."""
|
|
98
|
+
return reason in {None, "user"}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _cancelled_tool_content(reason: str | None) -> str:
|
|
102
|
+
return "[cancelled by user]" if _is_user_cancel(reason) else "[cancelled]"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _pending_tool_seals(messages: list[Any], *, reason: str | None) -> list[Any]:
|
|
97
106
|
from langchain_core.messages import ToolMessage
|
|
98
107
|
|
|
99
108
|
answered = _answered_tool_ids(messages)
|
|
@@ -105,7 +114,7 @@ def _pending_tool_seals(messages: list[Any]) -> list[Any]:
|
|
|
105
114
|
continue
|
|
106
115
|
seals.append(
|
|
107
116
|
ToolMessage(
|
|
108
|
-
content=
|
|
117
|
+
content=_cancelled_tool_content(reason),
|
|
109
118
|
tool_call_id=cid,
|
|
110
119
|
name=_tool_call_name(call),
|
|
111
120
|
status="error",
|
|
@@ -120,6 +129,9 @@ def _needs_cancel_note(messages: list[Any]) -> bool:
|
|
|
120
129
|
return False
|
|
121
130
|
last = messages[-1]
|
|
122
131
|
content = str(getattr(last, "content", "") or "")
|
|
132
|
+
additional_kwargs = getattr(last, "additional_kwargs", None) or {}
|
|
133
|
+
if additional_kwargs.get("synapse_cancel_boundary"):
|
|
134
|
+
return False
|
|
123
135
|
low = content.casefold()
|
|
124
136
|
if _is_ai_msg(last) and not (getattr(last, "tool_calls", None) or []):
|
|
125
137
|
if "cancelled" in low or "终止" in content:
|
|
@@ -133,7 +145,12 @@ def _needs_cancel_note(messages: list[Any]) -> bool:
|
|
|
133
145
|
return True
|
|
134
146
|
|
|
135
147
|
|
|
136
|
-
def repair_thread_after_cancel(
|
|
148
|
+
def repair_thread_after_cancel(
|
|
149
|
+
agent: Any,
|
|
150
|
+
config: dict[str, Any],
|
|
151
|
+
*,
|
|
152
|
+
reason: str | None = None,
|
|
153
|
+
) -> list[str]:
|
|
137
154
|
"""Seal a cancelled turn so the same thread_id remains continuous.
|
|
138
155
|
|
|
139
156
|
Returns short status notes for logs/UI (never raises).
|
|
@@ -158,7 +175,7 @@ def repair_thread_after_cancel(agent: Any, config: dict[str, Any]) -> list[str]:
|
|
|
158
175
|
next_nodes = tuple(str(x) for x in (getattr(snap, "next", None) or ()))
|
|
159
176
|
|
|
160
177
|
try:
|
|
161
|
-
seals = _pending_tool_seals(messages)
|
|
178
|
+
seals = _pending_tool_seals(messages, reason=reason)
|
|
162
179
|
if seals:
|
|
163
180
|
tools_node = _pick_tools_node(nodes, next_nodes)
|
|
164
181
|
if tools_node:
|
|
@@ -175,7 +192,17 @@ def repair_thread_after_cancel(agent: Any, config: dict[str, Any]) -> list[str]:
|
|
|
175
192
|
if _needs_cancel_note(messages):
|
|
176
193
|
from langchain_core.messages import AIMessage
|
|
177
194
|
|
|
178
|
-
|
|
195
|
+
# Lifecycle cancellation still needs a graph boundary, but must not
|
|
196
|
+
# surface as a fabricated user action in the transcript.
|
|
197
|
+
note = AIMessage(
|
|
198
|
+
content=(
|
|
199
|
+
"[本轮已由用户终止,上下文已保留]" if _is_user_cancel(reason) else ""
|
|
200
|
+
),
|
|
201
|
+
additional_kwargs={
|
|
202
|
+
"synapse_cancel_boundary": True,
|
|
203
|
+
"synapse_cancel_reason": reason or "legacy_user",
|
|
204
|
+
},
|
|
205
|
+
)
|
|
179
206
|
model_node = _pick_model_node(nodes, next_nodes)
|
|
180
207
|
if model_node and next_nodes:
|
|
181
208
|
try:
|
|
@@ -205,4 +232,4 @@ def repair_thread_after_cancel(agent: Any, config: dict[str, Any]) -> list[str]:
|
|
|
205
232
|
notes.append("checkpoint ready for next turn")
|
|
206
233
|
except Exception as exc: # noqa: BLE001
|
|
207
234
|
notes.append(f"cancel seal error: {exc}")
|
|
208
|
-
return notes
|
|
235
|
+
return notes
|
|
@@ -90,7 +90,12 @@ class ImageViewerScreen(ModalScreen[None]):
|
|
|
90
90
|
|
|
91
91
|
def on_click(self, event: Click) -> None:
|
|
92
92
|
del event
|
|
93
|
-
|
|
93
|
+
# The click that opened this modal can continue propagating after the
|
|
94
|
+
# app pushes us onto the stack. Only dismiss a viewer that is still
|
|
95
|
+
# the active screen; otherwise pop_screen() could remove the default
|
|
96
|
+
# screen and raise ScreenStackError.
|
|
97
|
+
if self.is_active:
|
|
98
|
+
self.dismiss()
|
|
94
99
|
|
|
95
100
|
|
|
96
101
|
__all__ = [
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Mermaid fences -> mmdr PNG -> textual-image widgets for sealed answers.
|
|
2
|
+
|
|
3
|
+
Mirrors ``synapse.ui.math_image``: the optional native ``mmdr`` extension
|
|
4
|
+
renders mermaid source to PNG, and a protocol-aware widget displays it when the
|
|
5
|
+
terminal supports a true pixel protocol (sixel / kitty TGP).
|
|
6
|
+
|
|
7
|
+
Half-cell and unicode renderers are deliberately excluded: a mermaid graph
|
|
8
|
+
drawn as half-block characters is illegible, so those terminals fall back to
|
|
9
|
+
the termaid ASCII renderer (``_MermaidCodeBlock``) instead.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import io
|
|
15
|
+
import re
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from typing import Any, Literal
|
|
18
|
+
|
|
19
|
+
from synapse.ui.image_render import active_renderer_name, make_pil_image_widget
|
|
20
|
+
from synapse.ui.rendering import render_mermaid_png
|
|
21
|
+
|
|
22
|
+
_MERMAID_MAX_COLS = 100
|
|
23
|
+
_MERMAID_MAX_ROWS = 40
|
|
24
|
+
_MAX_MERMAID_FENCES_PER_ANSWER = 24
|
|
25
|
+
|
|
26
|
+
# True pixel protocols only; halfcell/unicode intentionally excluded.
|
|
27
|
+
_PIXEL_RENDERERS = frozenset({"tgp", "tgpimage", "sixel", "sixelimage"})
|
|
28
|
+
|
|
29
|
+
# Fenced block whose info string names mermaid / mmd (case-insensitive).
|
|
30
|
+
_FENCE_RE = re.compile(
|
|
31
|
+
r"(?ms)^ {0,3}(`{3,}|~{3,})(?i:\s*(mermaid|mmd)\b)[^\n]*\n(.*?)^ {0,3}\1[ \t]*(?:\n|$)"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class MermaidSegment:
|
|
37
|
+
kind: Literal["markdown", "mermaid"]
|
|
38
|
+
source: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True, slots=True)
|
|
42
|
+
class MermaidImageAttachment:
|
|
43
|
+
"""Synthetic image attachment consumed by the shared image viewer."""
|
|
44
|
+
|
|
45
|
+
data: bytes
|
|
46
|
+
mime: str = "image/png"
|
|
47
|
+
name: str = "mermaid-diagram.png"
|
|
48
|
+
source: str = "mermaid"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def split_mermaid_fences(
|
|
52
|
+
text: str, *, max_fences: int = _MAX_MERMAID_FENCES_PER_ANSWER
|
|
53
|
+
) -> list[MermaidSegment]:
|
|
54
|
+
"""Split mermaid fenced blocks from Markdown, preserving everything else."""
|
|
55
|
+
source = text or ""
|
|
56
|
+
segments: list[MermaidSegment] = []
|
|
57
|
+
cursor = 0
|
|
58
|
+
fences = 0
|
|
59
|
+
for match in _FENCE_RE.finditer(source):
|
|
60
|
+
if fences >= max(0, int(max_fences)):
|
|
61
|
+
break
|
|
62
|
+
if match.start() > cursor:
|
|
63
|
+
segments.append(MermaidSegment("markdown", source[cursor : match.start()]))
|
|
64
|
+
segments.append(MermaidSegment("mermaid", match.group(3).strip("\n")))
|
|
65
|
+
fences += 1
|
|
66
|
+
cursor = match.end()
|
|
67
|
+
if cursor < len(source):
|
|
68
|
+
segments.append(MermaidSegment("markdown", source[cursor:]))
|
|
69
|
+
return segments or [MermaidSegment("markdown", source)]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def mermaid_pixel_renderer_active() -> bool:
|
|
73
|
+
"""True when the terminal can display true pixel graphics for diagrams."""
|
|
74
|
+
return active_renderer_name().casefold() in _PIXEL_RENDERERS
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def make_mermaid_widget(source: str) -> Any | None:
|
|
78
|
+
"""Build a protocol-aware image widget for one mermaid fence.
|
|
79
|
+
|
|
80
|
+
Returns ``None`` when mmdr is absent, the terminal has no pixel protocol
|
|
81
|
+
(half-cell / unicode -> callers fall back to termaid ASCII), or the render
|
|
82
|
+
fails. Mirrors ``math_image.make_math_widget``.
|
|
83
|
+
"""
|
|
84
|
+
if not mermaid_pixel_renderer_active():
|
|
85
|
+
return None
|
|
86
|
+
png = render_mermaid_png(source)
|
|
87
|
+
if not png:
|
|
88
|
+
return None
|
|
89
|
+
return make_mermaid_widget_from_png(png)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def make_mermaid_widget_from_png(png: bytes) -> Any | None:
|
|
93
|
+
"""Build an image widget from already-rendered Mermaid PNG bytes.
|
|
94
|
+
|
|
95
|
+
Rendering may happen in a background worker, but Textual widgets must be
|
|
96
|
+
created on the UI thread. Keeping that boundary explicit prevents native
|
|
97
|
+
mmdr work from blocking the event loop.
|
|
98
|
+
"""
|
|
99
|
+
try:
|
|
100
|
+
from PIL import Image as PILImage
|
|
101
|
+
|
|
102
|
+
image = PILImage.open(io.BytesIO(png))
|
|
103
|
+
image.load()
|
|
104
|
+
widget = make_pil_image_widget(
|
|
105
|
+
image,
|
|
106
|
+
max_cols=_MERMAID_MAX_COLS,
|
|
107
|
+
max_rows=_MERMAID_MAX_ROWS,
|
|
108
|
+
)
|
|
109
|
+
if widget is not None:
|
|
110
|
+
widget.add_class("mermaid-image")
|
|
111
|
+
# Reuse the transcript image click contract: CodingAgentApp walks
|
|
112
|
+
# ancestors for this class/metadata and opens ImageViewerScreen.
|
|
113
|
+
widget.add_class("transcript-image")
|
|
114
|
+
widget.image_attachment = MermaidImageAttachment(data=png)
|
|
115
|
+
# Keep consecutive diagrams visually distinct without doubling the
|
|
116
|
+
# gap above and below every image.
|
|
117
|
+
widget.styles.margin = (0, 0, 1, 0)
|
|
118
|
+
return widget
|
|
119
|
+
except Exception: # noqa: BLE001 - malformed image/backend failure falls back
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def mermaid_diagnostic() -> str:
|
|
124
|
+
"""Single-line diagnostic: which backend renders mermaid right now."""
|
|
125
|
+
native = False
|
|
126
|
+
render_ok = False
|
|
127
|
+
try:
|
|
128
|
+
from synapse.ui.rendering import mmdr_available
|
|
129
|
+
|
|
130
|
+
native = mmdr_available()
|
|
131
|
+
render_ok = bool(render_mermaid_png("flowchart LR\n A --> B"))
|
|
132
|
+
except Exception: # noqa: BLE001 - optional native dependency
|
|
133
|
+
native = False
|
|
134
|
+
renderer = active_renderer_name()
|
|
135
|
+
uses_image = render_ok and mermaid_pixel_renderer_active()
|
|
136
|
+
mode = "mmdr-image" if uses_image else "termaid-ascii"
|
|
137
|
+
return f"mermaid={mode} | native={native} | render_ok={render_ok} | widget_renderer={renderer}"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
__all__ = [
|
|
141
|
+
"MermaidImageAttachment",
|
|
142
|
+
"MermaidSegment",
|
|
143
|
+
"make_mermaid_widget",
|
|
144
|
+
"make_mermaid_widget_from_png",
|
|
145
|
+
"mermaid_diagnostic",
|
|
146
|
+
"mermaid_pixel_renderer_active",
|
|
147
|
+
"split_mermaid_fences",
|
|
148
|
+
]
|