synapse-cli-agent 0.1.41__tar.gz → 0.1.42__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.41 → synapse_cli_agent-0.1.42}/CHANGELOG.md +13 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/PKG-INFO +1 -1
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/pyproject.toml +1 -1
- synapse_cli_agent-0.1.42/release_body.md +12 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/rust_openai.py +48 -29
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/middleware.py +18 -2
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/rendering.py +67 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/status_controller.py +15 -3
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript/controller.py +9 -2
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript_blocks.py +152 -2
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/tui.py +3 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/tui_launch.py +3 -0
- synapse_cli_agent-0.1.42/src/synapse/ui/workspace.py +64 -0
- synapse_cli_agent-0.1.42/tests/test_markdown_image.py +147 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_model_request_compression_middleware.py +26 -1
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_model_retry.py +12 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_rust_openai_model.py +100 -0
- synapse_cli_agent-0.1.42/tests/test_status_controller.py +31 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_transcript_controller.py +14 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/uv.lock +1 -1
- synapse_cli_agent-0.1.41/release_body.md +0 -7
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.dockerignore +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.github/workflows/ci.yml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.github/workflows/docs.yml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.github/workflows/native-compression-wheels.yml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.github/workflows/native-core-tool-wheels.yml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.github/workflows/release.yml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.gitignore +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.python-version +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.readthedocs.yaml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/.zed/settings.json +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/AGENTS.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/Dockerfile.web +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/LICENSE +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/README.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/README.zh-CN.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/agent_upstream.txt +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/approval-behavior.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/assets/demo.gif +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/assets/synapse-logo.svg +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/assets/tui-preview.png +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/cli_upstream.txt +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/debug_compact.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/decode_screenshot.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/capability-matrix.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/decisions.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/index.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-0-protocol-baseline.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-1-core-transport.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-2-prompt-semantics.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-3-permissions.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-4-session-lifecycle.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-5-session-mcp.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-6-client-services.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-7-advanced-capabilities.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/phase-8-compliance.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/acp-adapter/progress.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-development-guide.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/baseline-report.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/decisions.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/index.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/migration.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-0-baseline.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-1-streaming-core.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-2-turn-runtime.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-3-tui-cutover.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-4-session-runtime.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-5-multi-session.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-6-project-runtime.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-7-global-control-plane.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/phase-8-hardening.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/post-review-fix-plan.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/agent-runtime-decoupling/progress.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/architecture-flow.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/architecture.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/cli.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/codex-session-discovery-phase-1.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/codex-session-import-phase-2.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/config.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/design.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/docker-web.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/index.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/install.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/math-formulas-test.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/mcp.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/models.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/native-compression-core.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/native-core-tool.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/permissions.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/quickstart.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/sessions.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/skills.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/smith_output.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/subagents.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/tool-output-transform.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/tui-cursor-refactor.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/tutorial.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/docs/x-agent-development-guide.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/examples/mcp.example.json +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/examples/models.example.json +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/examples/settings.example.json +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/middleware_upstream.txt +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/mkdocs.yml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/Cargo.lock +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/Cargo.toml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/LICENSE +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/NOTICE +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/README.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/pyproject.toml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/python/synapse_core_tool/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/src/file_access.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/src/file_tools.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/src/lib.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/src/llm.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/src/math_render.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/src/search.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-core-tool/uv.lock +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/Cargo.lock +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/Cargo.toml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/LICENSE +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/NOTICE +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/README.md +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/pyproject.toml +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/python/synapse_tool_compress_core/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/ccr.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/ccr_in_memory.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/mod.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/relevance/base.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/relevance/bm25.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/signals/keyword_detector.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/signals/line_importance.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/adaptive_sizer.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/anchor_selector.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/code_compressor.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/diff_compressor.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/log_compressor.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/search_compressor.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/analyzer.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/anchors.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/builder.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/classifier.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/classifier.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/compactor.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/formatter.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/ir.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/mod.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/walker.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/config.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/constraints.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/crusher.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/crushers.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/error_keywords.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/field_detect.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/hashing.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/mod.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/observer.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/orchestration.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/outliers.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/planning.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/statistics.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/stats_math.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/traits.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/types.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/rust/synapse-tool-compress-core/src/lib.rs +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/scripts/build_check_rust_openai.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/scripts/install.ps1 +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/scripts/release.ps1 +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/scripts/serve_web.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/slash_cmds_upstream.txt +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/__main__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/agent.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/client_services.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/content.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/events.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/lifecycle.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/mcp.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/permissions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/server.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/sessions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/acp/updates.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/app/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/app/agent.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/app/agent_assembly.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/app/agent_md.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/cli.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/compression.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/goal.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/helpers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/mcp.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/model.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/result.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/sessions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/slash_cmds.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/slash_complete.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/commands/theme.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/content/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/content/input_history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/content/multimodal.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/content/prompts.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/content/skills_catalog.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/entry.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/model.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/steering.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/store.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/goals/tools.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/checkpoint_seed.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/codex_config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/codex_history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/codex_import.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/codex_sessions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/describe_image.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/herdr.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/http_clients.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/llm_openai_compat.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/llm_openai_websocket.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/mcp_client.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/openai_oauth.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/openai_oauth_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/openai_usage.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/turbo.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/integrations/vision_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/memory/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/memory/auto_recorder.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/memory/embedder.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/memory/long_term.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/helpers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/persist.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/profile.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/providers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models/registry.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/models_registry.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/debug_inspector.html +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/debug_server.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/exit_trace.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/heap_dump.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/llm_debug.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/observability/startup_trace.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/planner/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/planner/task_planner.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/projects/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/projects/catalog.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/rag/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/rag/knowledge_base.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/agent_loop/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/agent_loop/model.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/agent_loop/request.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/agent_loop/turn.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/async_runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/backends.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/cancellation.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/context_compact.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/debug_capture_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/execute_capture.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/filesystem_tool_prompt_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/fs_permissions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/harness.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/hitl.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/interaction_ledger.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/model_request_compression_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/pathing.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/projects/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/projects/identity.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/projects/runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/safety.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/session_header_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/session_headers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/session_prewarm.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/sessions/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/sessions/events.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/sessions/manager.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/sessions/persistence.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/sessions/ref.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/sessions/runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/steer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/accumulator.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/adapters.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/events.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/parser.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/protocol.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/stream_events.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/streaming/tool_model.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/subagent_config_persist.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/subagent_specs.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/subagents.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/timeline.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/token_rate.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/tool_ignore.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/tool_output_eval.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/tool_output_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/runtime/tool_output_usage_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/cancel_repair.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/search_index.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/store.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/summary.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/transcript.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/transcript_migration.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/sessions/transcript_projection.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/settings/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/settings/config_paths.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/settings/schema.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/subagents.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/detection.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/metrics.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/models.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/pipeline.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/repository.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tool_output/transformers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tools/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tools/describe_image.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tools/filesystem_patch.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tools/filesystem_search.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/tools/session_tools.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/agent_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/answer_divider.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/approval.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/codex_usage.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/fast.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/goal.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/key_hints.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/mcp.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/mode.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/model.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/thread.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/turbo.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/components/turn_stats.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/context.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/bottombar/core.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/chrome/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/chrome/controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/clipboard.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/active_session_switcher.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/base.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/codex_config_import.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/codex_reset.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/codex_session_list.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/compression_diagnostics.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/git_explore.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/mcp_panel.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/model_form.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/model_manager.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/model_picker.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/provider_catalog.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/safety_panel.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/session_list.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/subagent_config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/theme_designer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/dialogs/theme_picker.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/drawer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/formatters.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/git_explore/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/git_explore/engine.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/git_explore/provider.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/git_explore/unified.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/image_preview.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/image_render.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/image_viewer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/math_image.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/mermaid_image.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/prompt_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/selectable_static.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/selectable_text.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/sink.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/steer_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/steer_widget.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/stream.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/stream_events.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/stream_runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/textual_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/textual_stream_sink.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/theme.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/theme_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/timeline.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/tool_blocks.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/components/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/components/branch.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/components/title.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/components/tool_output.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/components/usage.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/components/workspace.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/context.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/core.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/git_changes_popover.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/git_chrome.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/tool_output_popover.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/topbar/widget.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript/factory.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript/history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript/state.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/tui_styles.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn/controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn/event_bridge.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn/event_renderer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn/persistence.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn/request.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn_rail.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/turn_rail_widgets.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/user_turn.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/user_turn_block.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/welcome.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/web.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/synapse.cmd +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/__init__.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/acp/initialize.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/agent_stream/core_scenarios.json +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/duplicate_response_item.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/incomplete_and_aborted.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/legacy_compaction.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/normal_completed.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/replacement_history.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/rollback.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/codex_rollouts/unsupported_replacement.jsonl +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/sample_repo/calculator.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/sample_repo/test_calculator.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/fixtures/tool_output_eval.json +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p0_baseline.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p1_core.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p1_transport.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p2_content.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p2_events.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p2_updates.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p3_agent.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p3_permissions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p4_history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p4_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p5_mcp.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p6_client_services.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_acp_p8_compliance.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_agent_factory.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_agent_lifecycle.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_agent_turn_runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_approval.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_async_checkpointer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_backends.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_bottombar_registry.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_cancel_repair.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_capabilities.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_checkpoint_seed.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_chrome_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_cli.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_cli_codex_import.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_clipboard.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_codex_config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_codex_history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_codex_import.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_codex_sessions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_codex_sessions_windows.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_compact_tool_descriptions.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_context_compact.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_context_window.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_debug_capture_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_debug_inspector.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_describe_image.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_dialogs.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_entry.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_filesystem_patch_tool.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_filesystem_search_tools.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_git_changes_popover.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_git_chrome.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_git_explore.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_goal_live_tui.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_goals.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_heap_dump.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_herdr_integration.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_http_clients.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_image_render.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_image_viewer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_input_history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_iteration_abc.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_layered_config.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_math_image_render.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_mcp_schema.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_mermaid_image.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_mermaid_render.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_middleware_async.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_model_dialogs.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_model_providers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_models_persist.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_multimodal.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_native_math_render.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_openai_compat_reasoning.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_openai_oauth.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_openai_oauth_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_openai_usage.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_openai_websocket.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_pathing.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_project_catalog.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_project_drawer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_project_runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_project_switch.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_prompt_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_prompts.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_runtime_hardening.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_runtime_manager.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_runtime_streaming.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_safety.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_search_index.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_session_headers.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_session_persistence.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_session_prewarm.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_session_runtime.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_session_store.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_session_summary.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_slash_and_mcp.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_slash_complete.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_slash_effects.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_startup_defer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_startup_trace.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_steer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_steer_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_stream_cancel.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_stream_semantic_fixtures.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_stream_tool_items.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_stream_ui.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_subagent_config_dialog.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_subagent_config_persist.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_subagent_status.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_subagents.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_textual_stream_sink.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_theme.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_theme_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_timeline.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_token_rate.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_blocks.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_ignore.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_intent.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_output.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_output_eval.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_output_slash.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tool_output_usage_middleware.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_topbar_context_ratio.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_topbar_registry.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_transcript.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_transcript_history.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_transcript_history_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_transcript_migration.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_transcript_projection.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tui_active_session_switcher.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tui_codex_import.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tui_paste.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_tui_selection.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_turn_controller.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_turn_event_renderer.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_turn_rail_minimap.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_turn_request.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_usage_restore.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_user_turn_style.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/test_welcome.py +0 -0
- {synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/tests/tool_output_plugin_fixture.py +0 -0
|
@@ -8,6 +8,19 @@ All entries are written in English.
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## v0.1.42
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
- Retried a stale native Responses WebSocket connection once on a fresh socket when the request failed before any output, while avoiding replay after partial streaming output.
|
|
16
|
+
- Classified native WebSocket send/receive connection failures as transient without broadly retrying unrelated operating-system errors.
|
|
17
|
+
|
|
18
|
+
### Engineering
|
|
19
|
+
|
|
20
|
+
- Added focused coverage for WebSocket reconnect/replay behavior and transient transport-error classification.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
11
24
|
## v0.1.41
|
|
12
25
|
|
|
13
26
|
### New Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: synapse-cli-agent
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.42
|
|
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
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## v0.1.42
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- Retried a stale native Responses WebSocket connection once on a fresh socket when the request failed before any output, while avoiding replay after partial streaming output.
|
|
6
|
+
- Classified native WebSocket send/receive connection failures as transient without broadly retrying unrelated operating-system errors.
|
|
7
|
+
|
|
8
|
+
### Engineering
|
|
9
|
+
|
|
10
|
+
- Added focused coverage for WebSocket reconnect/replay behavior and transient transport-error classification.
|
|
11
|
+
|
|
12
|
+
---
|
|
@@ -1052,37 +1052,56 @@ class RustOpenAIChatModel(BaseChatModel):
|
|
|
1052
1052
|
req = self._build_request(messages, tools=tools, stop=stop, streaming=True, **kwargs)
|
|
1053
1053
|
response_state: dict[str, Any] = {}
|
|
1054
1054
|
if self.use_responses_api and self.use_websocket:
|
|
1055
|
-
from synapse.integrations.llm_openai_websocket import
|
|
1056
|
-
|
|
1057
|
-
)
|
|
1055
|
+
from synapse.integrations.llm_openai_websocket import prepare_responses_websocket_event
|
|
1056
|
+
from synapse.runtime.middleware import should_retry_transient_model_error
|
|
1058
1057
|
|
|
1059
1058
|
event = prepare_responses_websocket_event(req)
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1059
|
+
# A long-lived WebSocket connection sits idle in the cache while the
|
|
1060
|
+
# peer or an intermediate idle-timeout recycles the socket, so the
|
|
1061
|
+
# next ``send_raw`` can fail with a connection-aborted IO error
|
|
1062
|
+
# (Windows 10053) without any warning. Retry once on a fresh
|
|
1063
|
+
# connection, but only before any chunk has been emitted — replaying
|
|
1064
|
+
# after output would duplicate tokens.
|
|
1065
|
+
websocket_replay_attempts = 1
|
|
1066
|
+
for attempt in range(websocket_replay_attempts + 1):
|
|
1067
|
+
response_state = {}
|
|
1068
|
+
yielded_chunk = False
|
|
1069
|
+
try:
|
|
1070
|
+
ws = self._ensure_websocket()
|
|
1071
|
+
stream = ws.request(json.dumps(event, default=str))
|
|
1072
|
+
for raw in stream:
|
|
1073
|
+
payload = json.loads(raw)
|
|
1074
|
+
chunk_msg = aimessage_chunk_from_responses_event(payload, response_state)
|
|
1075
|
+
if chunk_msg is None:
|
|
1076
|
+
continue
|
|
1077
|
+
gen = ChatGenerationChunk(message=chunk_msg)
|
|
1078
|
+
yielded_chunk = True
|
|
1079
|
+
if run_manager:
|
|
1080
|
+
text = chunk_msg.content if isinstance(chunk_msg.content, str) else ""
|
|
1081
|
+
if text:
|
|
1082
|
+
run_manager.on_llm_new_token(text, chunk=gen)
|
|
1083
|
+
yield gen
|
|
1084
|
+
return
|
|
1085
|
+
except Exception as exc:
|
|
1086
|
+
# A socket error (or consumer cancellation) leaves the
|
|
1087
|
+
# connection unusable; drop it so the next attempt opens a
|
|
1088
|
+
# fresh one.
|
|
1089
|
+
self._reset_websocket()
|
|
1090
|
+
if (
|
|
1091
|
+
yielded_chunk
|
|
1092
|
+
or attempt >= websocket_replay_attempts
|
|
1093
|
+
or not should_retry_transient_model_error(exc)
|
|
1094
|
+
):
|
|
1095
|
+
raise
|
|
1096
|
+
# Connection failed before any output; reconnect and retry.
|
|
1097
|
+
continue
|
|
1098
|
+
except BaseException:
|
|
1099
|
+
# GeneratorExit is raised when a synchronous consumer closes
|
|
1100
|
+
# the iterator early. The native producer then closes its
|
|
1101
|
+
# socket, so do not leave the now-invalid handle cached on
|
|
1102
|
+
# this model.
|
|
1103
|
+
self._reset_websocket()
|
|
1104
|
+
raise
|
|
1086
1105
|
return
|
|
1087
1106
|
client = self._ensure_client()
|
|
1088
1107
|
if self.use_responses_api:
|
|
@@ -39,6 +39,18 @@ _TRANSIENT_MODEL_ERROR_MARKERS = (
|
|
|
39
39
|
"upstream request timeout",
|
|
40
40
|
"rate limit",
|
|
41
41
|
"rate_limit",
|
|
42
|
+
# Connection-level failures (TCP reset / aborted / timed-out sockets and
|
|
43
|
+
# the native WebSocket transport) are transient: the underlying peer or an
|
|
44
|
+
# intermediate idle-timeout recycles the socket, but a fresh connection
|
|
45
|
+
# usually succeeds. Match these so the model retry middleware recovers the
|
|
46
|
+
# call instead of surfacing a one-shot "websocket send failed" to the user.
|
|
47
|
+
"connection reset",
|
|
48
|
+
"connection aborted",
|
|
49
|
+
"connection closed",
|
|
50
|
+
"software caused connection abort",
|
|
51
|
+
"websocket send failed",
|
|
52
|
+
"websocket recv failed",
|
|
53
|
+
"websocket connection is closed",
|
|
42
54
|
)
|
|
43
55
|
|
|
44
56
|
# ---------------------------------------------------------------------------
|
|
@@ -668,11 +680,15 @@ def current_prompt_cleanup_saved_tokens() -> int:
|
|
|
668
680
|
# Text block prefixes injected by deepagents middleware. Each block
|
|
669
681
|
# duplicates content already present in the corresponding tool definition
|
|
670
682
|
# (e.g. ``write_todos`` description, filesystem tool docs). Stripping them
|
|
671
|
-
# saves
|
|
683
|
+
# saves tokens per model call without losing any capability.
|
|
684
|
+
#
|
|
685
|
+
# ``## Skills System`` is intentionally NOT stripped: it is the skill index
|
|
686
|
+
# (name + description + path) that lets the model auto-discover and trigger
|
|
687
|
+
# local skills. Without it, skills are not auto-discoverable from the prompt
|
|
688
|
+
# and must be surfaced via the /skills command or a human pointer.
|
|
672
689
|
|
|
673
690
|
_REDUNDANT_BLOCK_PREFIXES: tuple[str, ...] = (
|
|
674
691
|
"\n\n## `write_todos`",
|
|
675
|
-
"\n\n## Skills System",
|
|
676
692
|
"\n\n## Following Conventions",
|
|
677
693
|
)
|
|
678
694
|
|
|
@@ -11,6 +11,7 @@ from rich import box
|
|
|
11
11
|
from rich.console import Console, ConsoleOptions, RenderResult
|
|
12
12
|
from rich.markdown import BlockQuote as _BlockQuote
|
|
13
13
|
from rich.markdown import CodeBlock as _CodeBlock
|
|
14
|
+
from rich.markdown import ImageItem as _RichImageItem
|
|
14
15
|
from rich.markdown import Markdown as _Markdown
|
|
15
16
|
from rich.markdown import MarkdownElement
|
|
16
17
|
from rich.markdown import TableElement as _TableElement
|
|
@@ -633,11 +634,77 @@ class _QuoteLineBlockQuote(_BlockQuote):
|
|
|
633
634
|
yield new_line
|
|
634
635
|
|
|
635
636
|
|
|
637
|
+
_IMAGE_MAX_COLS = 100
|
|
638
|
+
_IMAGE_MAX_ROWS = 30
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def _render_image_path(destination: str) -> Any | None:
|
|
642
|
+
"""Best-effort terminal pixel renderable for a local image path.
|
|
643
|
+
|
|
644
|
+
Mirrors ``_render_mermaid_image``: decode the image with Pillow and wrap it
|
|
645
|
+
in the active ``textual_image`` protocol renderer (sixel / TGP / half-cell /
|
|
646
|
+
unicode). Returns ``None`` when the path is not a readable local image or no
|
|
647
|
+
renderer is available so callers can fall back to the Rich ``[image]``
|
|
648
|
+
placeholder. HTTP(S) URLs are not resolved here and fall through.
|
|
649
|
+
"""
|
|
650
|
+
if not destination or destination.startswith(("http://", "https://")):
|
|
651
|
+
return None
|
|
652
|
+
try:
|
|
653
|
+
from PIL import Image as PILImage
|
|
654
|
+
|
|
655
|
+
from synapse.ui.image_render import (
|
|
656
|
+
_resolve_renderer,
|
|
657
|
+
fit_cell_size,
|
|
658
|
+
renderer_needs_extra_row,
|
|
659
|
+
)
|
|
660
|
+
from synapse.ui.workspace import resolve_workspace_path
|
|
661
|
+
|
|
662
|
+
renderer_cls = _resolve_renderer()
|
|
663
|
+
if renderer_cls is None:
|
|
664
|
+
return None
|
|
665
|
+
path = resolve_workspace_path(destination)
|
|
666
|
+
if path is None:
|
|
667
|
+
return None
|
|
668
|
+
image = PILImage.open(path)
|
|
669
|
+
image.load()
|
|
670
|
+
width, height = image.size
|
|
671
|
+
cols, rows = fit_cell_size(
|
|
672
|
+
width,
|
|
673
|
+
height,
|
|
674
|
+
max_cols=_IMAGE_MAX_COLS,
|
|
675
|
+
max_rows=_IMAGE_MAX_ROWS,
|
|
676
|
+
extra_rows=1 if renderer_needs_extra_row() else 0,
|
|
677
|
+
)
|
|
678
|
+
return renderer_cls(image, width=cols, height=rows)
|
|
679
|
+
except Exception: # noqa: BLE001 - any image-path failure falls back to placeholder
|
|
680
|
+
return None
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
class _ImageItem(_RichImageItem):
|
|
684
|
+
"""Markdown image element that renders local images via the pixel pipeline.
|
|
685
|
+
|
|
686
|
+
Overrides Rich's ``ImageItem`` placeholder so ```` resolves a
|
|
687
|
+
readable local image through ``_render_image_path`` (the same Pillow +
|
|
688
|
+
``textual_image`` pipeline used for mermaid / math). Any failure falls back
|
|
689
|
+
to the original Rich ``[image]`` placeholder.
|
|
690
|
+
"""
|
|
691
|
+
|
|
692
|
+
def __rich_console__(
|
|
693
|
+
self, console: Console, options: ConsoleOptions
|
|
694
|
+
) -> RenderResult:
|
|
695
|
+
image = _render_image_path(self.destination)
|
|
696
|
+
if image is not None:
|
|
697
|
+
yield image
|
|
698
|
+
return
|
|
699
|
+
yield from super().__rich_console__(console, options)
|
|
700
|
+
|
|
701
|
+
|
|
636
702
|
class _FullBorderMarkdown(_Markdown):
|
|
637
703
|
"""Rich Markdown with full table borders and mermaid diagram fences."""
|
|
638
704
|
|
|
639
705
|
elements: ClassVar[dict[str, type[MarkdownElement]]] = {
|
|
640
706
|
**_Markdown.elements,
|
|
707
|
+
"image": _ImageItem,
|
|
641
708
|
"table_open": _FullTableElement,
|
|
642
709
|
"fence": _MermaidCodeBlock,
|
|
643
710
|
"code_block": _MermaidCodeBlock,
|
|
@@ -10,6 +10,7 @@ import time
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
from rich.text import Text
|
|
13
|
+
from textual.css.query import NoMatches
|
|
13
14
|
from textual.widgets import Input, Static
|
|
14
15
|
|
|
15
16
|
import synapse.ui.tui_styles as _styles
|
|
@@ -45,7 +46,13 @@ class StatusController:
|
|
|
45
46
|
self._phase = phase or "idle"
|
|
46
47
|
self._detail = detail
|
|
47
48
|
busy = self._phase not in {"idle", "ready", ""}
|
|
48
|
-
|
|
49
|
+
try:
|
|
50
|
+
app.query_one("#status", Static).set_class(busy, "busy")
|
|
51
|
+
except NoMatches:
|
|
52
|
+
# A timer/worker callback can race with screen teardown. Keep the
|
|
53
|
+
# controller state, but do not turn an already-unmounted UI into
|
|
54
|
+
# an application error.
|
|
55
|
+
return
|
|
49
56
|
if busy:
|
|
50
57
|
app.sub_title = f"{model_status_label(app.settings)} · {self._phase}"
|
|
51
58
|
else:
|
|
@@ -158,7 +165,12 @@ class StatusController:
|
|
|
158
165
|
app = self._app
|
|
159
166
|
elapsed = max(0.0, time.monotonic() - self._activity_started)
|
|
160
167
|
busy = self._phase not in {"idle", "ready", ""}
|
|
161
|
-
|
|
168
|
+
try:
|
|
169
|
+
status = app.query_one("#status", Static)
|
|
170
|
+
except NoMatches:
|
|
171
|
+
# Textual removes the screen tree before all interval callbacks
|
|
172
|
+
# have necessarily drained during shutdown.
|
|
173
|
+
return
|
|
162
174
|
width = max(int(getattr(app.size, "width", 0) or 0), 48)
|
|
163
175
|
# Account for CSS padding (0 2).
|
|
164
176
|
usable = max(16, width - 4)
|
|
@@ -228,4 +240,4 @@ class StatusController:
|
|
|
228
240
|
except Exception: # noqa: BLE001
|
|
229
241
|
pass
|
|
230
242
|
self.render_status()
|
|
231
|
-
self.sync_prompt_placeholder()
|
|
243
|
+
self.sync_prompt_placeholder()
|
{synapse_cli_agent-0.1.41 → synapse_cli_agent-0.1.42}/src/synapse/ui/transcript/controller.py
RENAMED
|
@@ -13,6 +13,7 @@ from typing import Any
|
|
|
13
13
|
|
|
14
14
|
from rich.text import Text
|
|
15
15
|
from textual.containers import Vertical, VerticalScroll
|
|
16
|
+
from textual.css.query import NoMatches
|
|
16
17
|
from textual.events import MouseUp
|
|
17
18
|
from textual.widgets import Static
|
|
18
19
|
|
|
@@ -188,7 +189,13 @@ class TranscriptController:
|
|
|
188
189
|
def _mount_block(self, block: Any, *, dismiss_welcome: bool = True) -> None:
|
|
189
190
|
if dismiss_welcome:
|
|
190
191
|
self._dismiss_welcome()
|
|
191
|
-
|
|
192
|
+
try:
|
|
193
|
+
timeline = self._app.query_one("#log", VerticalScroll)
|
|
194
|
+
except NoMatches:
|
|
195
|
+
# Background callbacks may arrive after Textual has torn down the
|
|
196
|
+
# screen tree. The event is no longer renderable, so discard only
|
|
197
|
+
# the UI write instead of surfacing a shutdown error.
|
|
198
|
+
return
|
|
192
199
|
follow = timeline.max_scroll_y <= 0 or timeline.scroll_y >= timeline.max_scroll_y - 1
|
|
193
200
|
timeline.mount(block)
|
|
194
201
|
self.state.current_turn_blocks.append(block)
|
|
@@ -716,4 +723,4 @@ class TranscriptController:
|
|
|
716
723
|
st.last_answer_text = ""
|
|
717
724
|
st.last_thought_body = ""
|
|
718
725
|
st.last_thought_elapsed = 0.0
|
|
719
|
-
st.thought_expanded = False
|
|
726
|
+
st.thought_expanded = False
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import io
|
|
6
|
+
import re
|
|
5
7
|
import threading
|
|
6
8
|
import time
|
|
7
9
|
from collections.abc import Callable
|
|
@@ -47,6 +49,59 @@ _markdown_render_executor = ThreadPoolExecutor(
|
|
|
47
49
|
)
|
|
48
50
|
|
|
49
51
|
|
|
52
|
+
_IMAGE_RENDER_WORKERS = 2
|
|
53
|
+
_image_render_executor = ThreadPoolExecutor(
|
|
54
|
+
max_workers=_IMAGE_RENDER_WORKERS,
|
|
55
|
+
thread_name_prefix="synapse-image",
|
|
56
|
+
)
|
|
57
|
+
_IMAGE_MAX_COLS = 100
|
|
58
|
+
_IMAGE_MAX_ROWS = 30
|
|
59
|
+
|
|
60
|
+
_MD_IMAGE_RE = re.compile(r"!\[[^\]]*\]\(([^)]*)\)")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _image_src(destination: str) -> str:
|
|
64
|
+
"""Extract the image path from an ```` render target."""
|
|
65
|
+
stripped = destination.strip()
|
|
66
|
+
return stripped.split()[0] if stripped else ""
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def split_markdown_images(text: str) -> list[tuple[str, str]]:
|
|
70
|
+
"""Split Markdown into ``(kind, content)`` runs.
|
|
71
|
+
|
|
72
|
+
``image`` runs carry the raw image source from ````; ``markdown``
|
|
73
|
+
runs are plain text kept verbatim for the Rich renderer. Used by answer
|
|
74
|
+
blocks so attached images render through the terminal pixel pipeline.
|
|
75
|
+
"""
|
|
76
|
+
if not text:
|
|
77
|
+
return [("markdown", "")]
|
|
78
|
+
parts: list[tuple[str, str]] = []
|
|
79
|
+
cursor = 0
|
|
80
|
+
for match in _MD_IMAGE_RE.finditer(text):
|
|
81
|
+
if match.start() > cursor:
|
|
82
|
+
parts.append(("markdown", text[cursor : match.start()]))
|
|
83
|
+
src = _image_src(match.group(1))
|
|
84
|
+
if src:
|
|
85
|
+
parts.append(("image", src))
|
|
86
|
+
cursor = match.end()
|
|
87
|
+
if cursor < len(text):
|
|
88
|
+
parts.append(("markdown", text[cursor:]))
|
|
89
|
+
return parts or [("markdown", text)]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _read_image_bytes(source: str) -> bytes | None:
|
|
93
|
+
"""Read a local image file in a background worker; ``None`` on failure."""
|
|
94
|
+
from synapse.ui.workspace import resolve_workspace_path
|
|
95
|
+
|
|
96
|
+
path = resolve_workspace_path(source)
|
|
97
|
+
if path is None:
|
|
98
|
+
return None
|
|
99
|
+
try:
|
|
100
|
+
return path.read_bytes()
|
|
101
|
+
except Exception: # noqa: BLE001 - unreadable image falls back to placeholder
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
|
|
50
105
|
def _render_mermaid_png(source: str) -> bytes | None:
|
|
51
106
|
"""Run only native Mermaid PNG rendering in a background worker."""
|
|
52
107
|
from synapse.ui.rendering import render_mermaid_png
|
|
@@ -291,6 +346,7 @@ class AnswerBlock(SelectableStatic):
|
|
|
291
346
|
self._markdown_max_chars = max(1, int(markdown_max_chars))
|
|
292
347
|
self._mermaid_render_generation = 0
|
|
293
348
|
self._markdown_render_generation = 0
|
|
349
|
+
self._image_render_generation = 0
|
|
294
350
|
# Historical restore defers long-body markdown parsing to a worker so
|
|
295
351
|
# first paint stays cheap: show plain text, then swap in the renderable.
|
|
296
352
|
self._defer_markdown = bool(defer_markdown)
|
|
@@ -351,6 +407,9 @@ class AnswerBlock(SelectableStatic):
|
|
|
351
407
|
if any(sub.kind == "math" for sub in split_block_math(segment.source)):
|
|
352
408
|
has_enriched = True
|
|
353
409
|
break
|
|
410
|
+
if _MD_IMAGE_RE.search(segment.source):
|
|
411
|
+
has_enriched = True
|
|
412
|
+
break
|
|
354
413
|
if not has_enriched:
|
|
355
414
|
return []
|
|
356
415
|
|
|
@@ -370,8 +429,12 @@ class AnswerBlock(SelectableStatic):
|
|
|
370
429
|
if sub.kind == "math":
|
|
371
430
|
widget = make_math_widget(sub.source, color=fg)
|
|
372
431
|
widgets.append(widget or MathFallbackBlock(sub.source))
|
|
373
|
-
|
|
374
|
-
|
|
432
|
+
continue
|
|
433
|
+
for kind, content in split_markdown_images(sub.source):
|
|
434
|
+
if kind == "image" and content:
|
|
435
|
+
widgets.append(_ImageRenderPlaceholder(content))
|
|
436
|
+
elif content.strip():
|
|
437
|
+
widgets.append(Static(render_markdown(content)))
|
|
375
438
|
return widgets
|
|
376
439
|
except Exception: # noqa: BLE001 - composite rendering is optional
|
|
377
440
|
return []
|
|
@@ -384,11 +447,13 @@ class AnswerBlock(SelectableStatic):
|
|
|
384
447
|
if widgets:
|
|
385
448
|
self.mount(*widgets)
|
|
386
449
|
self.call_after_refresh(self._start_mermaid_renders)
|
|
450
|
+
self.call_after_refresh(self._start_image_renders)
|
|
387
451
|
except Exception: # noqa: BLE001 - widget may be detaching during session switch
|
|
388
452
|
pass
|
|
389
453
|
|
|
390
454
|
def on_mount(self) -> None:
|
|
391
455
|
self.call_after_refresh(self._start_mermaid_renders)
|
|
456
|
+
self.call_after_refresh(self._start_image_renders)
|
|
392
457
|
if self._pending_markdown:
|
|
393
458
|
self._pending_markdown = False
|
|
394
459
|
self._schedule_markdown_render(self.body)
|
|
@@ -461,8 +526,84 @@ class AnswerBlock(SelectableStatic):
|
|
|
461
526
|
except Exception: # noqa: BLE001 - transcript may detach during session switch
|
|
462
527
|
pass
|
|
463
528
|
|
|
529
|
+
def _start_image_renders(self) -> None:
|
|
530
|
+
"""Submit unrendered image placeholders without blocking Textual's loop."""
|
|
531
|
+
if not self.is_attached:
|
|
532
|
+
return
|
|
533
|
+
generation = self._image_render_generation
|
|
534
|
+
for placeholder in self.query(_ImageRenderPlaceholder):
|
|
535
|
+
if placeholder.render_started:
|
|
536
|
+
continue
|
|
537
|
+
placeholder.render_started = True
|
|
538
|
+
future = _image_render_executor.submit(
|
|
539
|
+
_read_image_bytes, placeholder.source
|
|
540
|
+
)
|
|
541
|
+
future.add_done_callback(
|
|
542
|
+
lambda completed, target=placeholder, expected=generation: (
|
|
543
|
+
self._deliver_image(completed, target, expected)
|
|
544
|
+
)
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
def _deliver_image(
|
|
548
|
+
self,
|
|
549
|
+
future: Future[bytes | None],
|
|
550
|
+
placeholder: _ImageRenderPlaceholder,
|
|
551
|
+
generation: int,
|
|
552
|
+
) -> None:
|
|
553
|
+
"""Schedule a completed background image load back onto the UI thread."""
|
|
554
|
+
try:
|
|
555
|
+
data = future.result()
|
|
556
|
+
except Exception: # noqa: BLE001 - app/widget may be shutting down
|
|
557
|
+
return
|
|
558
|
+
try:
|
|
559
|
+
_schedule_on_app_thread(
|
|
560
|
+
self.app,
|
|
561
|
+
self._replace_image_placeholder,
|
|
562
|
+
placeholder,
|
|
563
|
+
data,
|
|
564
|
+
generation,
|
|
565
|
+
)
|
|
566
|
+
except Exception: # noqa: BLE001 - app/widget may be shutting down
|
|
567
|
+
pass
|
|
568
|
+
|
|
569
|
+
def _replace_image_placeholder(
|
|
570
|
+
self,
|
|
571
|
+
placeholder: _ImageRenderPlaceholder,
|
|
572
|
+
data: bytes | None,
|
|
573
|
+
generation: int,
|
|
574
|
+
) -> None:
|
|
575
|
+
"""Replace a still-current image placeholder once its file is loaded."""
|
|
576
|
+
if (
|
|
577
|
+
generation != self._image_render_generation
|
|
578
|
+
or not self.is_attached
|
|
579
|
+
or not placeholder.is_attached
|
|
580
|
+
):
|
|
581
|
+
return
|
|
582
|
+
widget = None
|
|
583
|
+
if data:
|
|
584
|
+
try:
|
|
585
|
+
from PIL import Image as PILImage
|
|
586
|
+
|
|
587
|
+
from synapse.ui.image_render import make_pil_image_widget
|
|
588
|
+
|
|
589
|
+
img = PILImage.open(io.BytesIO(data))
|
|
590
|
+
img.load()
|
|
591
|
+
widget = make_pil_image_widget(
|
|
592
|
+
img, max_cols=_IMAGE_MAX_COLS, max_rows=_IMAGE_MAX_ROWS
|
|
593
|
+
)
|
|
594
|
+
except Exception: # noqa: BLE001 - corrupt image falls back to placeholder
|
|
595
|
+
widget = None
|
|
596
|
+
if widget is None:
|
|
597
|
+
widget = Static(Text(f"[image: {placeholder.source}]", style="dim italic"))
|
|
598
|
+
try:
|
|
599
|
+
self.mount(widget, before=placeholder)
|
|
600
|
+
placeholder.remove()
|
|
601
|
+
except Exception: # noqa: BLE001 - transcript may detach during session switch
|
|
602
|
+
pass
|
|
603
|
+
|
|
464
604
|
def _render_block(self) -> None:
|
|
465
605
|
self._mermaid_render_generation += 1
|
|
606
|
+
self._image_render_generation += 1
|
|
466
607
|
body = self.body or ""
|
|
467
608
|
fg = _resolve_color(self._fg_color, _DEFAULT_FG, "fg")
|
|
468
609
|
if self.live:
|
|
@@ -560,6 +701,15 @@ class _MermaidRenderPlaceholder(Static):
|
|
|
560
701
|
super().__init__(Text("Rendering Mermaid diagram...", style="dim italic"))
|
|
561
702
|
|
|
562
703
|
|
|
704
|
+
class _ImageRenderPlaceholder(Static):
|
|
705
|
+
"""Lightweight UI-thread placeholder while a local image loads on a worker."""
|
|
706
|
+
|
|
707
|
+
def __init__(self, source: str) -> None:
|
|
708
|
+
self.source = source
|
|
709
|
+
self.render_started = False
|
|
710
|
+
super().__init__(Text("Loading image...", style="dim italic"))
|
|
711
|
+
|
|
712
|
+
|
|
563
713
|
class _MarkdownBlock(Static):
|
|
564
714
|
"""A Markdown transcript block that can rebuild after a theme switch."""
|
|
565
715
|
|
|
@@ -1490,6 +1490,9 @@ class CodingAgentApp(App[None]):
|
|
|
1490
1490
|
# Swap the app's project context.
|
|
1491
1491
|
self.settings = project_settings
|
|
1492
1492
|
self.project_root = workspace
|
|
1493
|
+
from synapse.ui.workspace import set_current_workspace
|
|
1494
|
+
|
|
1495
|
+
set_current_workspace(workspace)
|
|
1493
1496
|
self.thread_id = target_thread
|
|
1494
1497
|
if turn is not None:
|
|
1495
1498
|
try:
|
|
@@ -24,6 +24,9 @@ def run_tui(
|
|
|
24
24
|
# ``run_tui`` re-export, so CodingAgentApp must resolve lazily.
|
|
25
25
|
from synapse.observability.startup_trace import global_mark, span
|
|
26
26
|
from synapse.ui.tui import CodingAgentApp
|
|
27
|
+
from synapse.ui.workspace import set_current_workspace
|
|
28
|
+
|
|
29
|
+
set_current_workspace(settings.workspace)
|
|
27
30
|
|
|
28
31
|
try:
|
|
29
32
|
from synapse.ui.theme import bootstrap_theme
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Lightweight workspace-path resolution for UI image rendering.
|
|
2
|
+
|
|
3
|
+
The file-tool and model-facing tools resolve paths against the session
|
|
4
|
+
workspace; the Rich / Textual render path needs the same anchor so a Markdown
|
|
5
|
+
image reference like ```` is found regardless of the process
|
|
6
|
+
working directory (started from anywhere, or after a project switch).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
_ACTIVE_WORKSPACE: Path | None = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def set_current_workspace(workspace: Path | str | None) -> None:
|
|
17
|
+
"""Pin the workspace used for UI image-path resolution.
|
|
18
|
+
|
|
19
|
+
Call this where the active workspace is (re)established — TUI startup and
|
|
20
|
+
in-process project switches. Passing ``None`` clears the override so
|
|
21
|
+
``current_workspace`` falls back to the process working directory.
|
|
22
|
+
"""
|
|
23
|
+
global _ACTIVE_WORKSPACE
|
|
24
|
+
_ACTIVE_WORKSPACE = Path(workspace).resolve() if workspace is not None else None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def clear_workspace_cache() -> None:
|
|
28
|
+
"""Drop the pinned workspace so resolution falls back to the cwd."""
|
|
29
|
+
set_current_workspace(None)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def current_workspace() -> Path:
|
|
33
|
+
"""Return the active workspace, or the cwd when none is pinned."""
|
|
34
|
+
return _ACTIVE_WORKSPACE if _ACTIVE_WORKSPACE is not None else Path.cwd().resolve()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def resolve_workspace_path(
|
|
38
|
+
raw: str | None,
|
|
39
|
+
*,
|
|
40
|
+
workspace: Path | str | None = None,
|
|
41
|
+
) -> Path | None:
|
|
42
|
+
"""Resolve ``raw`` against the workspace, or ``None`` for URLs/missing files.
|
|
43
|
+
|
|
44
|
+
``raw`` may be workspace-relative or absolute. HTTP(S) URLs and files that
|
|
45
|
+
do not exist return ``None`` so callers can fall back to an image
|
|
46
|
+
placeholder. ``workspace`` overrides the process workspace for tests and
|
|
47
|
+
explicit contexts.
|
|
48
|
+
"""
|
|
49
|
+
if not raw:
|
|
50
|
+
return None
|
|
51
|
+
text = str(raw).strip()
|
|
52
|
+
if not text or text.startswith(("http://", "https://")):
|
|
53
|
+
return None
|
|
54
|
+
root = Path(workspace).resolve() if workspace is not None else current_workspace()
|
|
55
|
+
path = Path(text)
|
|
56
|
+
if not path.is_absolute():
|
|
57
|
+
path = root / path
|
|
58
|
+
try:
|
|
59
|
+
path = path.resolve()
|
|
60
|
+
except OSError:
|
|
61
|
+
return None
|
|
62
|
+
if not path.is_file():
|
|
63
|
+
return None
|
|
64
|
+
return path
|