synapse-cli-agent 0.1.16__tar.gz → 0.1.17__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.
Files changed (336) hide show
  1. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/AGENTS.md +0 -22
  2. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/CHANGELOG.md +17 -0
  3. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/PKG-INFO +1 -1
  4. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/pyproject.toml +1 -1
  5. synapse_cli_agent-0.1.17/release_body.md +16 -0
  6. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/Cargo.lock +1 -1
  7. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/Cargo.toml +1 -1
  8. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/pyproject.toml +1 -1
  9. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/src/lib.rs +6 -3
  10. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/app/agent.py +10 -1
  11. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/content/prompts.py +3 -3
  12. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/backends.py +13 -2
  13. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/harness.py +14 -13
  14. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/middleware.py +11 -0
  15. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/tool_ignore.py +13 -6
  16. synapse_cli_agent-0.1.17/src/synapse/tools/__init__.py +10 -0
  17. synapse_cli_agent-0.1.17/src/synapse/tools/filesystem_search.py +162 -0
  18. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_agent_factory.py +36 -2
  19. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_capabilities.py +7 -0
  20. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_compact_tool_descriptions.py +25 -8
  21. synapse_cli_agent-0.1.17/tests/test_filesystem_search_tools.py +122 -0
  22. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tool_ignore.py +7 -2
  23. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/uv.lock +1 -1
  24. synapse_cli_agent-0.1.16/release_body.md +0 -14
  25. synapse_cli_agent-0.1.16/src/synapse/tools/__init__.py +0 -5
  26. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.github/workflows/ci.yml +0 -0
  27. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.github/workflows/docs.yml +0 -0
  28. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.github/workflows/native-compression-wheels.yml +0 -0
  29. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.github/workflows/native-search-wheels.yml +0 -0
  30. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.github/workflows/release.yml +0 -0
  31. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.gitignore +0 -0
  32. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.python-version +0 -0
  33. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/.readthedocs.yaml +0 -0
  34. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/README.md +0 -0
  35. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/agent_upstream.txt +0 -0
  36. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/cli_upstream.txt +0 -0
  37. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/agent-development-guide.md +0 -0
  38. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/architecture-flow.md +0 -0
  39. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/architecture.md +0 -0
  40. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/cli.md +0 -0
  41. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/codex-session-discovery-phase-1.md +0 -0
  42. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/codex-session-import-phase-2.md +0 -0
  43. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/config.md +0 -0
  44. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/design.md +0 -0
  45. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/index.md +0 -0
  46. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/install.md +0 -0
  47. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/mcp.md +0 -0
  48. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/models.md +0 -0
  49. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/native-compression-core.md +0 -0
  50. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/native-search-core.md +0 -0
  51. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/permissions.md +0 -0
  52. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/quickstart.md +0 -0
  53. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/sessions.md +0 -0
  54. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/skills.md +0 -0
  55. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/smith_output.md +0 -0
  56. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/tool-output-transform.md +0 -0
  57. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/tui-cursor-refactor.md +0 -0
  58. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/tutorial.md +0 -0
  59. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/docs/x-agent-development-guide.md +0 -0
  60. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/examples/mcp.example.json +0 -0
  61. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/examples/models.example.json +0 -0
  62. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/examples/settings.example.json +0 -0
  63. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/middleware_upstream.txt +0 -0
  64. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/mkdocs.yml +0 -0
  65. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/LICENSE +0 -0
  66. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/NOTICE +0 -0
  67. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/README.md +0 -0
  68. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-search-core/python/synapse_search_core/__init__.py +0 -0
  69. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/Cargo.lock +0 -0
  70. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/Cargo.toml +0 -0
  71. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/LICENSE +0 -0
  72. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/NOTICE +0 -0
  73. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/README.md +0 -0
  74. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/pyproject.toml +0 -0
  75. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/python/synapse_tool_compress_core/__init__.py +0 -0
  76. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/ccr.rs +0 -0
  77. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/ccr_in_memory.rs +0 -0
  78. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/mod.rs +0 -0
  79. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/relevance/base.rs +0 -0
  80. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/relevance/bm25.rs +0 -0
  81. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/signals/keyword_detector.rs +0 -0
  82. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/signals/line_importance.rs +0 -0
  83. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/adaptive_sizer.rs +0 -0
  84. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/anchor_selector.rs +0 -0
  85. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/code_compressor.rs +0 -0
  86. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/diff_compressor.rs +0 -0
  87. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/log_compressor.rs +0 -0
  88. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/search_compressor.rs +0 -0
  89. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/analyzer.rs +0 -0
  90. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/anchors.rs +0 -0
  91. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/builder.rs +0 -0
  92. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/classifier.rs +0 -0
  93. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/classifier.rs +0 -0
  94. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/compactor.rs +0 -0
  95. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/formatter.rs +0 -0
  96. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/ir.rs +0 -0
  97. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/mod.rs +0 -0
  98. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/compaction/walker.rs +0 -0
  99. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/config.rs +0 -0
  100. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/constraints.rs +0 -0
  101. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/crusher.rs +0 -0
  102. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/crushers.rs +0 -0
  103. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/error_keywords.rs +0 -0
  104. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/field_detect.rs +0 -0
  105. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/hashing.rs +0 -0
  106. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/mod.rs +0 -0
  107. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/observer.rs +0 -0
  108. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/orchestration.rs +0 -0
  109. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/outliers.rs +0 -0
  110. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/planning.rs +0 -0
  111. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/statistics.rs +0 -0
  112. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/stats_math.rs +0 -0
  113. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/traits.rs +0 -0
  114. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/headroom_port/transforms/smart_crusher/types.rs +0 -0
  115. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/rust/synapse-tool-compress-core/src/lib.rs +0 -0
  116. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/scripts/install.ps1 +0 -0
  117. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/scripts/release.ps1 +0 -0
  118. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/slash_cmds_upstream.txt +0 -0
  119. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/__init__.py +0 -0
  120. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/__main__.py +0 -0
  121. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/app/__init__.py +0 -0
  122. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/app/agent_md.py +0 -0
  123. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/cli.py +0 -0
  124. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/__init__.py +0 -0
  125. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/compression.py +0 -0
  126. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/helpers.py +0 -0
  127. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/mcp.py +0 -0
  128. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/model.py +0 -0
  129. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/result.py +0 -0
  130. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/sessions.py +0 -0
  131. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/slash_cmds.py +0 -0
  132. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/slash_complete.py +0 -0
  133. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/commands/theme.py +0 -0
  134. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/config.py +0 -0
  135. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/content/__init__.py +0 -0
  136. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/content/input_history.py +0 -0
  137. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/content/multimodal.py +0 -0
  138. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/content/skills_catalog.py +0 -0
  139. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/__init__.py +0 -0
  140. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/checkpoint_seed.py +0 -0
  141. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/codex_history.py +0 -0
  142. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/codex_import.py +0 -0
  143. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/codex_sessions.py +0 -0
  144. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/describe_image.py +0 -0
  145. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/http_clients.py +0 -0
  146. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/llm_openai_compat.py +0 -0
  147. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/llm_openai_websocket.py +0 -0
  148. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/mcp_client.py +0 -0
  149. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/openai_oauth.py +0 -0
  150. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/openai_oauth_middleware.py +0 -0
  151. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/integrations/vision_middleware.py +0 -0
  152. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/memory/__init__.py +0 -0
  153. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/memory/auto_recorder.py +0 -0
  154. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/memory/embedder.py +0 -0
  155. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/memory/long_term.py +0 -0
  156. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/models/__init__.py +0 -0
  157. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/models/config.py +0 -0
  158. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/models/helpers.py +0 -0
  159. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/models/profile.py +0 -0
  160. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/models/registry.py +0 -0
  161. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/models_registry.py +0 -0
  162. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/observability/__init__.py +0 -0
  163. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/observability/startup_trace.py +0 -0
  164. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/parallel_subagents.py +0 -0
  165. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/planner/__init__.py +0 -0
  166. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/planner/task_planner.py +0 -0
  167. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/rag/__init__.py +0 -0
  168. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/rag/knowledge_base.py +0 -0
  169. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/__init__.py +0 -0
  170. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/async_runtime.py +0 -0
  171. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/context_compact.py +0 -0
  172. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/execute_capture.py +0 -0
  173. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/fs_permissions.py +0 -0
  174. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/hitl.py +0 -0
  175. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/interaction_ledger.py +0 -0
  176. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/model_request_compression_middleware.py +0 -0
  177. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/pathing.py +0 -0
  178. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/safety.py +0 -0
  179. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/steer.py +0 -0
  180. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/subagents.py +0 -0
  181. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/tool_output_eval.py +0 -0
  182. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/tool_output_middleware.py +0 -0
  183. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/runtime/tool_output_usage_middleware.py +0 -0
  184. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/sessions/__init__.py +0 -0
  185. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/sessions/cancel_repair.py +0 -0
  186. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/sessions/session_recap.py +0 -0
  187. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/sessions/store.py +0 -0
  188. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/sessions/transcript.py +0 -0
  189. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/settings/__init__.py +0 -0
  190. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/settings/config_paths.py +0 -0
  191. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/settings/schema.py +0 -0
  192. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/subagent_monitor.py +0 -0
  193. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/__init__.py +0 -0
  194. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/detection.py +0 -0
  195. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/metrics.py +0 -0
  196. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/models.py +0 -0
  197. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/pipeline.py +0 -0
  198. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/repository.py +0 -0
  199. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tool_output/transformers.py +0 -0
  200. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/tools/session_tools.py +0 -0
  201. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/__init__.py +0 -0
  202. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/answer_divider.py +0 -0
  203. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/__init__.py +0 -0
  204. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/components/__init__.py +0 -0
  205. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/components/key_hints.py +0 -0
  206. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/components/mcp.py +0 -0
  207. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/components/mode.py +0 -0
  208. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/components/model.py +0 -0
  209. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/components/thread.py +0 -0
  210. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/context.py +0 -0
  211. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/bottombar/core.py +0 -0
  212. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/clipboard.py +0 -0
  213. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/__init__.py +0 -0
  214. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/base.py +0 -0
  215. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/codex_session_list.py +0 -0
  216. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/compression_diagnostics.py +0 -0
  217. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/git_explore.py +0 -0
  218. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/mcp_panel.py +0 -0
  219. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/model_picker.py +0 -0
  220. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/safety_panel.py +0 -0
  221. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/session_list.py +0 -0
  222. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/subagent_monitor.py +0 -0
  223. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/theme_designer.py +0 -0
  224. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/dialogs/theme_picker.py +0 -0
  225. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/formatters.py +0 -0
  226. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/git_explore/__init__.py +0 -0
  227. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/git_explore/engine.py +0 -0
  228. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/git_explore/provider.py +0 -0
  229. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/git_explore/unified.py +0 -0
  230. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/rendering.py +0 -0
  231. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/selectable_static.py +0 -0
  232. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/selectable_text.py +0 -0
  233. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/sink.py +0 -0
  234. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/steer_widget.py +0 -0
  235. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/stream.py +0 -0
  236. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/stream_events.py +0 -0
  237. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/stream_runtime.py +0 -0
  238. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/textual_stream_sink.py +0 -0
  239. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/theme.py +0 -0
  240. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/timeline.py +0 -0
  241. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/tool_blocks.py +0 -0
  242. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/__init__.py +0 -0
  243. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/components/__init__.py +0 -0
  244. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/components/branch.py +0 -0
  245. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/components/title.py +0 -0
  246. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/components/tool_output.py +0 -0
  247. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/components/usage.py +0 -0
  248. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/components/workspace.py +0 -0
  249. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/context.py +0 -0
  250. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/core.py +0 -0
  251. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/git_changes_popover.py +0 -0
  252. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/git_chrome.py +0 -0
  253. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/tool_output_popover.py +0 -0
  254. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/topbar/widget.py +0 -0
  255. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/transcript_blocks.py +0 -0
  256. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/tui.py +0 -0
  257. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/turn_rail.py +0 -0
  258. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/turn_rail_widgets.py +0 -0
  259. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/user_turn.py +0 -0
  260. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/user_turn_block.py +0 -0
  261. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/src/synapse/ui/welcome.py +0 -0
  262. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/synapse.cmd +0 -0
  263. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/duplicate_response_item.jsonl +0 -0
  264. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/incomplete_and_aborted.jsonl +0 -0
  265. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/legacy_compaction.jsonl +0 -0
  266. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/normal_completed.jsonl +0 -0
  267. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/replacement_history.jsonl +0 -0
  268. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/rollback.jsonl +0 -0
  269. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/codex_rollouts/unsupported_replacement.jsonl +0 -0
  270. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/sample_repo/calculator.py +0 -0
  271. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/sample_repo/test_calculator.py +0 -0
  272. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/fixtures/tool_output_eval.json +0 -0
  273. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_async_checkpointer.py +0 -0
  274. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_backends.py +0 -0
  275. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_bottombar_registry.py +0 -0
  276. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_cancel_repair.py +0 -0
  277. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_checkpoint_seed.py +0 -0
  278. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_cli.py +0 -0
  279. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_cli_codex_import.py +0 -0
  280. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_codex_history.py +0 -0
  281. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_codex_import.py +0 -0
  282. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_codex_sessions.py +0 -0
  283. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_codex_sessions_windows.py +0 -0
  284. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_config.py +0 -0
  285. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_context_compact.py +0 -0
  286. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_context_window.py +0 -0
  287. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_dag_parallel.py +0 -0
  288. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_describe_image.py +0 -0
  289. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_dialogs.py +0 -0
  290. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_git_changes_popover.py +0 -0
  291. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_git_chrome.py +0 -0
  292. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_git_explore.py +0 -0
  293. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_http_clients.py +0 -0
  294. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_input_history.py +0 -0
  295. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_iteration_abc.py +0 -0
  296. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_layered_config.py +0 -0
  297. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_mcp_schema.py +0 -0
  298. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_mermaid_render.py +0 -0
  299. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_middleware_async.py +0 -0
  300. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_model_request_compression_middleware.py +0 -0
  301. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_model_retry.py +0 -0
  302. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_multimodal.py +0 -0
  303. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_openai_compat_reasoning.py +0 -0
  304. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_openai_oauth.py +0 -0
  305. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_openai_oauth_middleware.py +0 -0
  306. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_openai_websocket.py +0 -0
  307. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_pathing.py +0 -0
  308. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_safety.py +0 -0
  309. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_session_recap.py +0 -0
  310. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_slash_and_mcp.py +0 -0
  311. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_slash_complete.py +0 -0
  312. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_startup_defer.py +0 -0
  313. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_steer.py +0 -0
  314. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_stream_cancel.py +0 -0
  315. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_stream_tool_items.py +0 -0
  316. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_stream_ui.py +0 -0
  317. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_subagent_monitor_dialog.py +0 -0
  318. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_subagent_status.py +0 -0
  319. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_theme.py +0 -0
  320. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_timeline.py +0 -0
  321. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tool_intent.py +0 -0
  322. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tool_output.py +0 -0
  323. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tool_output_eval.py +0 -0
  324. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tool_output_slash.py +0 -0
  325. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tool_output_usage_middleware.py +0 -0
  326. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_topbar_context_ratio.py +0 -0
  327. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_topbar_registry.py +0 -0
  328. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_transcript.py +0 -0
  329. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tui_codex_import.py +0 -0
  330. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tui_selection.py +0 -0
  331. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_tui_sink.py +0 -0
  332. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_turn_rail_minimap.py +0 -0
  333. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_usage_restore.py +0 -0
  334. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_user_turn_style.py +0 -0
  335. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/test_welcome.py +0 -0
  336. {synapse_cli_agent-0.1.16 → synapse_cli_agent-0.1.17}/tests/tool_output_plugin_fixture.py +0 -0
@@ -1,27 +1,5 @@
1
1
  # Synapse 项目协作指南
2
2
 
3
- ## 用户信息
4
- - 姓名:肖前程
5
- - 年龄:35 岁
6
- - 职业:Java 程序员
7
- - 当前学习方向:Agent 应用开发
8
- - 主语言背景:Java → 正在学习 Python/LangChain Agent 生态
9
-
10
- ## 用户信息
11
- - 姓名:肖前程
12
- - 年龄:35 岁
13
- - 职业:Java 程序员
14
- - 当前学习方向:Agent 应用开发
15
- - 主语言背景:Java → 正在学习 Python/LangChain Agent 生态
16
-
17
- ## 约定
18
- - Python 依赖使用 `uv` 管理。
19
- - 优先小步、可测试的改动。
20
- - CLI 输出简洁,不使用 emoji。
21
- - 默认关闭人工审批(自动放行);除非用户要求,不要自行加审批门槛。
22
- - Backend 仅使用 `LocalShellBackend`,无远程 sandbox。
23
- - 对用户回复与模型思考过程使用中文;代码标识符/路径/命令可保留原文。
24
-
25
3
  ## 当前仓库结构
26
4
 
27
5
  | 路径 | 主要职责 |
@@ -7,6 +7,23 @@ The release workflow automatically extracts the matching section as release note
7
7
 
8
8
  ---
9
9
 
10
+ ## v0.1.17
11
+
12
+ ### 新功能
13
+
14
+ - `find_files` / `search_files` 工具新增 `context_lines`、`case_insensitive`、`head_limit`、`offset` 参数。
15
+ - `search_files` 支持忽略大小写(`case_insensitive`,由 `synapse-search-core` 原生引擎实现)。
16
+ - 支持分页查询(`head_limit` + `offset`),Agent 可按需翻页而非一次性获取全部结果。
17
+
18
+ ### 工程改进
19
+
20
+ - 工具的 Pydantic schema 不再定义 `intent` 字段,改由 `build_intent_schema_middleware` 中间件统一管理。
21
+ - 新增 Synapse 自有文件搜索工具 `find_files` / `search_files`,排除 deepagents 内置 `ls`/`glob`/`grep` 工具。
22
+ - 系统提示词中的 `glob`/`grep` 工具名修正为 `find_files` / `search_files`。
23
+ - `synapse-search-core` 升级至 0.1.1(新增 `case_insensitive` 参数)。
24
+
25
+ ---
26
+
10
27
  ## v0.1.16
11
28
 
12
29
  ### 新功能
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synapse-cli-agent
3
- Version: 0.1.16
3
+ Version: 0.1.17
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "synapse-cli-agent"
3
- version = "0.1.16"
3
+ version = "0.1.17"
4
4
  description = "Local coding agent built on LangChain Deep Agents (LocalShell, no sandbox)"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -0,0 +1,16 @@
1
+ ## v0.1.17
2
+
3
+ ### 新功能
4
+
5
+ - `find_files` / `search_files` 工具新增 `context_lines`、`case_insensitive`、`head_limit`、`offset` 参数。
6
+ - `search_files` 支持忽略大小写(`case_insensitive`,由 `synapse-search-core` 原生引擎实现)。
7
+ - 支持分页查询(`head_limit` + `offset`),Agent 可按需翻页而非一次性获取全部结果。
8
+
9
+ ### 工程改进
10
+
11
+ - 工具的 Pydantic schema 不再定义 `intent` 字段,改由 `build_intent_schema_middleware` 中间件统一管理。
12
+ - 新增 Synapse 自有文件搜索工具 `find_files` / `search_files`,排除 deepagents 内置 `ls`/`glob`/`grep` 工具。
13
+ - 系统提示词中的 `glob`/`grep` 工具名修正为 `find_files` / `search_files`。
14
+ - `synapse-search-core` 升级至 0.1.1(新增 `case_insensitive` 参数)。
15
+
16
+ ---
@@ -391,7 +391,7 @@ dependencies = [
391
391
 
392
392
  [[package]]
393
393
  name = "synapse-search-core"
394
- version = "0.1.0"
394
+ version = "0.1.1"
395
395
  dependencies = [
396
396
  "globset",
397
397
  "grep-regex",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "synapse-search-core"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  edition = "2021"
5
5
  rust-version = "1.80"
6
6
  license = "Apache-2.0"
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "synapse-search-core"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "Native workspace search algorithms for Synapse"
9
9
  requires-python = ">=3.12"
10
10
  license = { text = "Apache-2.0" }
@@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
3
3
  use std::time::UNIX_EPOCH;
4
4
 
5
5
  use globset::{Glob, GlobSet, GlobSetBuilder};
6
- use grep_regex::RegexMatcher;
6
+ use grep_regex::{RegexMatcher, RegexMatcherBuilder};
7
7
  use grep_searcher::{BinaryDetection, Searcher, SearcherBuilder, Sink, SinkContext, SinkMatch};
8
8
  use ignore::WalkBuilder;
9
9
  use pyo3::exceptions::PyValueError;
@@ -121,7 +121,7 @@ fn search_file(
121
121
  Ok(sink.result)
122
122
  }
123
123
 
124
- #[pyfunction(signature = (base_path, pattern, include_glob=None, max_results=1000, context_lines=0))]
124
+ #[pyfunction(signature = (base_path, pattern, include_glob=None, max_results=1000, context_lines=0, case_insensitive=false))]
125
125
  fn grep(
126
126
  py: Python<'_>,
127
127
  base_path: &str,
@@ -129,6 +129,7 @@ fn grep(
129
129
  include_glob: Option<&str>,
130
130
  max_results: usize,
131
131
  context_lines: usize,
132
+ case_insensitive: bool,
132
133
  ) -> PyResult<Py<PyDict>> {
133
134
  if pattern.is_empty() {
134
135
  return Err(PyValueError::new_err("pattern must not be empty"));
@@ -143,7 +144,9 @@ fn grep(
143
144
  base_path.display()
144
145
  )));
145
146
  }
146
- let matcher = RegexMatcher::new(pattern)
147
+ let matcher = RegexMatcherBuilder::new()
148
+ .case_insensitive(case_insensitive)
149
+ .build(pattern)
147
150
  .map_err(|error| PyValueError::new_err(format!("invalid regex pattern: {error}")))?;
148
151
  let include = include_glob
149
152
  .map(compile_glob)
@@ -35,6 +35,7 @@ from synapse.runtime.middleware import (
35
35
  build_strip_redundant_prompt_blocks,
36
36
  build_task_namespace_middleware,
37
37
  build_tool_error_recovery_middleware,
38
+ build_tool_exclusion_middleware,
38
39
  )
39
40
  from synapse.runtime.model_request_compression_middleware import (
40
41
  build_model_request_compression_middleware,
@@ -48,7 +49,7 @@ from synapse.settings import Settings
48
49
  from synapse.tool_output.pipeline import ToolOutputTransformPipeline
49
50
  from synapse.tool_output.repository import ToolOutputRepository
50
51
  from synapse.tool_output.transformers import load_transformer_plugins
51
- from synapse.tools import build_session_tools
52
+ from synapse.tools import build_filesystem_search_tools, build_session_tools
52
53
 
53
54
 
54
55
  def _build_checkpointer(settings: Settings):
@@ -228,6 +229,12 @@ def build_coding_agent(
228
229
  readonly=settings.readonly,
229
230
  excluded_tools=settings.excluded_tools,
230
231
  )
232
+ # Keep deepagents' built-in ``ls``, ``glob``, and ``grep`` out of model
233
+ # requests. Synapse registers the non-conflicting ``find_files`` and
234
+ # ``search_files`` tools explicitly below.
235
+ model_request_excluded_tools = set(settings.excluded_tools) | {"ls", "glob", "grep"}
236
+ if settings.readonly:
237
+ model_request_excluded_tools.update({"execute", "write_file", "edit_file"})
231
238
 
232
239
  interrupt_on = build_interrupt_on(require_approval=settings.require_approval)
233
240
  with span("checkpointer"):
@@ -279,6 +286,7 @@ def build_coding_agent(
279
286
  tools: list[Any] = []
280
287
  if extra_tools:
281
288
  tools.extend(extra_tools)
289
+ tools.extend(build_filesystem_search_tools(backend))
282
290
  # 跨会话查阅工具
283
291
  try:
284
292
  session_tools = build_session_tools(
@@ -392,6 +400,7 @@ def build_coding_agent(
392
400
  ),
393
401
  build_model_retry_middleware(),
394
402
  build_task_namespace_middleware(),
403
+ build_tool_exclusion_middleware(model_request_excluded_tools),
395
404
  ]
396
405
  transform_enabled = bool(getattr(settings, "enable_tool_output_transform", True))
397
406
  try:
@@ -46,7 +46,7 @@ Never scan the entire repository without a specific reason.
46
46
 
47
47
  ## Virtual filesystem
48
48
 
49
- File tools such as `ls`, `glob`, `grep`, `read_file`, `edit_file`, and `write_file`
49
+ File tools such as `find_files`, `search_files`, `read_file`, `edit_file`, and `write_file`
50
50
  operate on a virtual filesystem rooted at `/`.
51
51
 
52
52
  Valid paths:
@@ -109,7 +109,7 @@ Do not use generic intent values such as `run tool` or `read_file`.
109
109
  Search only when required by a clear task.
110
110
  Keep searches targeted and avoid unnecessary full-file output.
111
111
 
112
- For `glob` and `grep` tools, automatically exclude common build artifacts and caches:
112
+ For the `search_files` tool, automatically exclude common build artifacts and caches via the `glob` parameter:
113
113
  * `target/`
114
114
  * `.venv/`
115
115
  * `.node_modules/`
@@ -133,7 +133,7 @@ Run independent tool calls in parallel within the same turn.
133
133
  Parallelize when arguments are already known and results do not depend on each other, including:
134
134
 
135
135
  * Multiple file reads
136
- * `glob` and related file reads
136
+ * `find_files` and related file reads
137
137
  * `execute` and related reads
138
138
  * Edits to different files
139
139
  * Independent test or lint commands
@@ -205,6 +205,9 @@ class CodingLocalShellBackend(LocalShellBackend):
205
205
  pattern: str,
206
206
  path: str | None = None,
207
207
  glob: str | None = None,
208
+ max_results: int = 1000,
209
+ context_lines: int = 0,
210
+ case_insensitive: bool = False,
208
211
  ) -> Any:
209
212
  """Search with the required native Rust engine using regular expressions."""
210
213
  import synapse_search_core
@@ -215,7 +218,8 @@ class CodingLocalShellBackend(LocalShellBackend):
215
218
  return GrepResult(matches=[])
216
219
  try:
217
220
  payload = synapse_search_core.grep(
218
- str(base_path), pattern, include_glob=glob, max_results=1000
221
+ str(base_path), pattern, include_glob=glob, max_results=max_results,
222
+ context_lines=context_lines, case_insensitive=case_insensitive,
219
223
  )
220
224
  except (OSError, RuntimeError, ValueError) as exc:
221
225
  return GrepResult(error=f"Error searching path '{path or '.'}': {exc}", matches=[])
@@ -226,7 +230,12 @@ class CodingLocalShellBackend(LocalShellBackend):
226
230
  matches.append({"path": result_path, "line": item["line"], "text": item["text"]})
227
231
  return GrepResult(matches=matches)
228
232
 
229
- def glob(self, pattern: str, path: str | None = None) -> Any:
233
+ def glob(
234
+ self,
235
+ pattern: str,
236
+ path: str | None = None,
237
+ max_results: int = 1000,
238
+ ) -> Any:
230
239
  """Find files with the required native Rust engine."""
231
240
  from datetime import datetime
232
241
 
@@ -244,6 +253,8 @@ class CodingLocalShellBackend(LocalShellBackend):
244
253
  )
245
254
  matches = []
246
255
  for item in payload["matches"]:
256
+ if len(matches) >= max_results:
257
+ break
247
258
  result_path = self._native_result_path(base_path, item["path"])
248
259
  if result_path is None:
249
260
  continue
@@ -1,10 +1,10 @@
1
- """HarnessProfile registration helpers (excluded_tools etc.)."""
1
+ """Resolve model-facing tool exclusions for the coding harness."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
5
  from collections.abc import Iterable
6
6
 
7
- _DEFAULT_EXCLUDES = frozenset({"ls", "grep"})
7
+ _DEFAULT_EXCLUDES = frozenset({"ls", "glob", "grep"})
8
8
  _DEFAULT_READONLY_EXCLUDES = frozenset(
9
9
  {
10
10
  "execute",
@@ -20,22 +20,23 @@ def apply_harness_exclusions(
20
20
  readonly: bool = False,
21
21
  excluded_tools: Iterable[str] | None = None,
22
22
  ) -> frozenset[str]:
23
- """Register harness excluded_tools for the active model/provider.
23
+ """Return the tools that should be hidden from model requests.
24
24
 
25
- ``ls`` and ``grep`` are excluded by default because ``execute`` can run the
26
- project's native directory and search commands. Read-only mode additionally
27
- excludes ``execute``, ``write_file``, and ``edit_file``.
25
+ ``ls`` is excluded by default because ``execute`` can run the project's
26
+ native directory commands. Read-only mode additionally excludes ``execute``,
27
+ ``write_file``, and ``edit_file``.
28
28
 
29
- deepagents only removes built-in tools via HarnessProfile.excluded_tools
30
- (tools= is additive). Registration is additive/merge under the same key.
29
+ ``model_spec`` is used only to disable deepagents' built-in general-purpose
30
+ subagent. Tool exclusions are applied by Synapse request middleware instead
31
+ of deepagents' process-global harness registry because that registry unions
32
+ exclusions and cannot re-enable a tool such as ``grep`` later in the same
33
+ process.
31
34
  """
32
35
  names = set(_DEFAULT_EXCLUDES)
33
36
  names.update(excluded_tools or [])
34
37
  if readonly:
35
38
  names |= set(_DEFAULT_READONLY_EXCLUDES)
36
39
  excluded = frozenset(n.strip() for n in names if n and n.strip())
37
- if not excluded:
38
- return frozenset()
39
40
 
40
41
  from deepagents import (
41
42
  GeneralPurposeSubagentProfile,
@@ -43,12 +44,12 @@ def apply_harness_exclusions(
43
44
  register_harness_profile,
44
45
  )
45
46
 
47
+ # Tool exclusions are request-local middleware in ``build_coding_agent``.
48
+ # Do not register them here: deepagents merges profile exclusions globally,
49
+ # so a readonly agent would otherwise make later writable agents readonly too.
46
50
  profile = HarnessProfile(
47
- excluded_tools=excluded,
48
51
  general_purpose_subagent=GeneralPurposeSubagentProfile(enabled=False),
49
52
  )
50
- # Model-level and provider-level keys so both string specs and prebuilt
51
- # BaseChatModel resolution paths can match.
52
53
  register_harness_profile(model_spec, profile)
53
54
  if ":" in model_spec:
54
55
  provider = model_spec.split(":", 1)[0]
@@ -696,6 +696,17 @@ _COMPACT_TOOL_DESCRIPTIONS: dict[str, str] = {
696
696
  "Always read a file before editing it. "
697
697
  "Supports images, audio, video, and PDF via multimodal reads."
698
698
  ),
699
+ "grep": (
700
+ "Search workspace files with a regular expression and return matching paths, line "
701
+ "numbers, and text. Examples: pattern='TODO|FIXME', pattern='(?i)error', or "
702
+ "pattern='def\\s+name' with glob='**/*.py'. Escape regex metacharacters when "
703
+ "searching for literal text."
704
+ ),
705
+ "glob": (
706
+ "Find workspace files and directories matching a glob pattern. Supports *, **, and ?. "
707
+ "Examples: '**/*.py' for Python files, 'src/**/*.ts' for TypeScript under src, and "
708
+ "'README?.md' for one-character filename variants."
709
+ ),
699
710
  }
700
711
 
701
712
 
@@ -104,10 +104,21 @@ class _Rule:
104
104
 
105
105
 
106
106
  _BUILTIN_DENY_PATTERNS = (".git/",)
107
+ _DEFAULT_IGNORE_PATTERNS = (
108
+ "target/",
109
+ ".venv/",
110
+ ".node_modules/",
111
+ "node_modules/",
112
+ "__pycache__/",
113
+ )
107
114
  _BUILTIN_DENY_RULES = tuple(
108
115
  _Rule(regex=_gitignore_pattern_to_regex(pattern), negate=False, raw=pattern)
109
116
  for pattern in _BUILTIN_DENY_PATTERNS
110
117
  )
118
+ _DEFAULT_IGNORE_RULES = tuple(
119
+ _Rule(regex=_gitignore_pattern_to_regex(pattern), negate=False, raw=pattern)
120
+ for pattern in _DEFAULT_IGNORE_PATTERNS
121
+ )
111
122
 
112
123
 
113
124
  class ToolIgnoreMatcher:
@@ -196,15 +207,11 @@ class ToolIgnoreMatcher:
196
207
  return False
197
208
  if any(rule.regex.match(rel) for rule in _BUILTIN_DENY_RULES):
198
209
  return True
199
- if not self._rules:
200
- return False
201
- ignored = False
202
- matched = False
210
+ ignored = any(rule.regex.match(rel) for rule in _DEFAULT_IGNORE_RULES)
203
211
  for rule in self._rules:
204
212
  if rule.regex.match(rel):
205
- matched = True
206
213
  ignored = not rule.negate
207
- return ignored if matched else False
214
+ return ignored
208
215
 
209
216
 
210
217
  def relative_to_root(path: str | Path, root: Path) -> str:
@@ -0,0 +1,10 @@
1
+ """Custom tools for the coding agent."""
2
+
3
+ from synapse.tools.filesystem_search import build_filesystem_search_tools
4
+ from synapse.tools.session_tools import build_session_tools, build_tool_result_reader_tool
5
+
6
+ __all__ = [
7
+ "build_filesystem_search_tools",
8
+ "build_session_tools",
9
+ "build_tool_result_reader_tool",
10
+ ]
@@ -0,0 +1,162 @@
1
+ """Model-facing filesystem search tools with stable, Synapse-owned schemas."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Literal
6
+
7
+ from langchain_core.tools import tool
8
+ from pydantic import BaseModel, Field
9
+
10
+
11
+ class FindFilesInput(BaseModel):
12
+ """Arguments for the workspace path-pattern search tool."""
13
+
14
+ pattern: str = Field(description="Glob pattern, such as '**/*.py' or 'README?.md'.")
15
+ path: str | None = Field(
16
+ default=None,
17
+ description="Workspace directory to search. Omit to search the workspace root.",
18
+ )
19
+ max_results: int = Field(
20
+ default=200,
21
+ ge=1,
22
+ le=1000,
23
+ description="Maximum number of matching paths to return from the search backend.",
24
+ )
25
+ head_limit: int = Field(
26
+ default=0,
27
+ ge=0,
28
+ le=1000,
29
+ description="Maximum entries to return to the model (0 = use max_results).",
30
+ )
31
+ offset: int = Field(
32
+ default=0,
33
+ ge=0,
34
+ description="Skip first N entries before applying head_limit (pagination).",
35
+ )
36
+
37
+
38
+ class SearchFilesInput(BaseModel):
39
+ """Arguments for the workspace regular-expression content search tool."""
40
+
41
+ pattern: str = Field(
42
+ description="Regular expression to search for. Use escaped metacharacters for literal text."
43
+ )
44
+ path: str | None = Field(
45
+ default=None,
46
+ description="Workspace file or directory to search. Omit to search the workspace root.",
47
+ )
48
+ glob: str | None = Field(
49
+ default=None,
50
+ description="Optional glob filter, such as '**/*.py' or 'src/**/*.ts'.",
51
+ )
52
+ output_mode: Literal["files_with_matches", "content", "count"] = Field(
53
+ default="files_with_matches",
54
+ description="Return matching file paths, matching lines, or a count for each file.",
55
+ )
56
+ max_results: int = Field(
57
+ default=200,
58
+ ge=1,
59
+ le=1000,
60
+ description="Maximum number of matching lines to return from the search backend.",
61
+ )
62
+ head_limit: int = Field(
63
+ default=0,
64
+ ge=0,
65
+ le=1000,
66
+ description="Maximum entries to return to the model (0 = use max_results).",
67
+ )
68
+ offset: int = Field(
69
+ default=0,
70
+ ge=0,
71
+ description="Skip first N entries before applying head_limit (pagination).",
72
+ )
73
+ context_lines: int = Field(
74
+ default=0,
75
+ ge=0,
76
+ le=10,
77
+ description="Number of context lines to include before and after each match.",
78
+ )
79
+ case_insensitive: bool = Field(
80
+ default=False,
81
+ description="Enable case-insensitive search.",
82
+ )
83
+
84
+
85
+ def build_filesystem_search_tools(backend: Any) -> list[Any]:
86
+ """Create schema-controlled search tools backed by ``CodingLocalShellBackend``."""
87
+
88
+ @tool("find_files", args_schema=FindFilesInput)
89
+ def find_files(
90
+ *,
91
+ pattern: str,
92
+ path: str | None = None,
93
+ max_results: int = 200,
94
+ head_limit: int = 0,
95
+ offset: int = 0,
96
+ ) -> str:
97
+ """Find workspace files and directories by glob pattern."""
98
+ result = backend.glob(pattern=pattern, path=path, max_results=max_results + 1)
99
+ error = getattr(result, "error", None)
100
+ if error:
101
+ return str(error)
102
+ all_matches = list(getattr(result, "matches", []) or [])
103
+ display_limit = head_limit if head_limit > 0 else max_results
104
+ paginated = all_matches[offset : offset + display_limit]
105
+ if not paginated:
106
+ return "No paths matched."
107
+ lines = []
108
+ for item in paginated:
109
+ item_path = item.get("path", "") if isinstance(item, dict) else str(item)
110
+ is_dir = item.get("is_dir", False) if isinstance(item, dict) else False
111
+ lines.append(f"{item_path}{'/' if is_dir else ''}")
112
+ suffix = "\n[Results truncated]" if len(all_matches) > offset + len(paginated) else ""
113
+ return "\n".join(lines) + suffix
114
+
115
+ @tool("search_files", args_schema=SearchFilesInput)
116
+ def search_files(
117
+ *,
118
+ pattern: str,
119
+ path: str | None = None,
120
+ glob: str | None = None,
121
+ output_mode: Literal["files_with_matches", "content", "count"] = "files_with_matches",
122
+ max_results: int = 200,
123
+ head_limit: int = 0,
124
+ offset: int = 0,
125
+ context_lines: int = 0,
126
+ case_insensitive: bool = False,
127
+ ) -> str:
128
+ """Search workspace files with a regular expression."""
129
+ result = backend.grep(
130
+ pattern=pattern,
131
+ path=path,
132
+ glob=glob,
133
+ max_results=max_results + 1 + offset,
134
+ context_lines=context_lines,
135
+ case_insensitive=case_insensitive,
136
+ )
137
+ error = getattr(result, "error", None)
138
+ if error:
139
+ return str(error)
140
+ all_matches = list(getattr(result, "matches", []) or [])
141
+ display_limit = head_limit if head_limit > 0 else max_results
142
+ paginated = all_matches[offset : offset + display_limit]
143
+ if not paginated:
144
+ return "No matches found."
145
+ suffix = "\n[Results truncated]" if len(all_matches) > offset + len(paginated) else ""
146
+ if output_mode == "content":
147
+ content = "\n".join(
148
+ f"{item['path']}:{item['line']}: {item['text']}" for item in paginated
149
+ )
150
+ return content + suffix
151
+ grouped: dict[str, int] = {}
152
+ for item in paginated:
153
+ grouped[item["path"]] = grouped.get(item["path"], 0) + 1
154
+ if output_mode == "count":
155
+ content = "\n".join(
156
+ f"{item_path}: {count}" for item_path, count in grouped.items()
157
+ )
158
+ else:
159
+ content = "\n".join(grouped)
160
+ return content + suffix
161
+
162
+ return [find_files, search_files]
@@ -24,7 +24,7 @@ def test_build_system_prompt_includes_workspace(tmp_path: Path):
24
24
  or "Virtual filesystem" in text
25
25
  or "\u8d44\u6df1\u8f6f\u4ef6\u5de5\u7a0b Agent" in text
26
26
  )
27
- assert "Chinese" in text
27
+ assert "用中文思考和推理" in text
28
28
  assert "Current workspace" in text
29
29
 
30
30
 
@@ -118,7 +118,41 @@ def test_build_coding_agent_wires_create_deep_agent(tmp_path: Path):
118
118
  assert kwargs["model"] is fake_model
119
119
  assert kwargs["backend"] is not None
120
120
  assert kwargs["checkpointer"] is not None
121
- assert kwargs["subagents"] is not None
121
+ search_tools = {
122
+ tool.name: tool
123
+ for tool in kwargs["tools"]
124
+ if tool.name in {"find_files", "search_files"}
125
+ }
126
+ assert set(search_tools) == {"find_files", "search_files"}
127
+ assert search_tools["search_files"].tool_call_schema.model_json_schema()["properties"][
128
+ "pattern"
129
+ ]["description"].startswith("Regular expression")
130
+ exclusion = next(
131
+ middleware
132
+ for middleware in (kwargs.get("middleware") or [])
133
+ if type(middleware).__name__ == "exclude_tools"
134
+ )
135
+
136
+ class _Request:
137
+ def __init__(self, tools): # noqa: ANN001
138
+ self.tools = tools
139
+
140
+ def override(self, **changes): # noqa: ANN003
141
+ return _Request(changes.get("tools", self.tools))
142
+
143
+ ls_tool = MagicMock(name="ls_tool")
144
+ ls_tool.name = "ls"
145
+ glob_tool = MagicMock(name="glob_tool")
146
+ glob_tool.name = "glob"
147
+ grep_tool = MagicMock(name="grep_tool")
148
+ grep_tool.name = "grep"
149
+ find_files_tool = MagicMock(name="find_files_tool")
150
+ find_files_tool.name = "find_files"
151
+ search_files_tool = MagicMock(name="search_files_tool")
152
+ search_files_tool.name = "search_files"
153
+ request = _Request([ls_tool, glob_tool, grep_tool, find_files_tool, search_files_tool])
154
+ filtered = exclusion.wrap_model_call(request, lambda current: current)
155
+ assert [tool.name for tool in filtered.tools] == ["find_files", "search_files"]
122
156
  model_retries = [
123
157
  middleware
124
158
  for middleware in (kwargs.get("middleware") or [])
@@ -570,11 +570,18 @@ def test_fs_permissions_and_harness(tmp_path: Path):
570
570
  assert perms is not None
571
571
  excluded = apply_harness_exclusions("openai:demo")
572
572
  assert "ls" in excluded
573
+ assert "glob" in excluded
573
574
  assert "grep" in excluded
574
575
  excluded = apply_harness_exclusions("openai:demo", readonly=True)
575
576
  assert "write_file" in excluded
576
577
  assert "execute" in excluded
577
578
 
579
+ from deepagents.profiles.harness.harness_profiles import _get_harness_profile
580
+
581
+ profile = _get_harness_profile("openai:demo")
582
+ assert profile is not None
583
+ assert profile.excluded_tools == frozenset()
584
+
578
585
 
579
586
  def test_default_subagents_optional_models(tmp_path: Path):
580
587
  del tmp_path