bathys 0.8.0__tar.gz → 0.9.0__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 (106) hide show
  1. {bathys-0.8.0 → bathys-0.9.0}/.remember/logs/memory-2026-09-09.log +41 -0
  2. {bathys-0.8.0 → bathys-0.9.0}/CHANGELOG.md +14 -0
  3. {bathys-0.8.0 → bathys-0.9.0}/PKG-INFO +4 -4
  4. {bathys-0.8.0 → bathys-0.9.0}/README.md +3 -3
  5. bathys-0.9.0/docs/product/ideas-borrowed.md +69 -0
  6. {bathys-0.8.0 → bathys-0.9.0}/docs/product/roadmap.md +1 -0
  7. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/.remember/logs/memory-2026-09-09.log +17 -0
  8. {bathys-0.8.0 → bathys-0.9.0}/pyproject.toml +1 -1
  9. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/__init__.py +1 -1
  10. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/core.py +54 -4
  11. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/crawler.py +44 -3
  12. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/server.py +6 -1
  13. {bathys-0.8.0 → bathys-0.9.0}/.github/workflows/ci.yml +0 -0
  14. {bathys-0.8.0 → bathys-0.9.0}/.gitignore +0 -0
  15. {bathys-0.8.0 → bathys-0.9.0}/.remember/.gitignore +0 -0
  16. {bathys-0.8.0 → bathys-0.9.0}/.remember/logs/hook-errors.log +0 -0
  17. {bathys-0.8.0 → bathys-0.9.0}/.remember/logs/memory-2026-09-06.log +0 -0
  18. {bathys-0.8.0 → bathys-0.9.0}/.remember/logs/memory-2026-09-07.log +0 -0
  19. {bathys-0.8.0 → bathys-0.9.0}/.remember/logs/memory-2026-09-08.log +0 -0
  20. {bathys-0.8.0 → bathys-0.9.0}/.remember/tmp/case-divergence +0 -0
  21. {bathys-0.8.0 → bathys-0.9.0}/.remember/tmp/no-transcript-notice +0 -0
  22. {bathys-0.8.0 → bathys-0.9.0}/.remember/tmp/post-tool-ran +0 -0
  23. {bathys-0.8.0 → bathys-0.9.0}/.remember/tmp/session-slug +0 -0
  24. {bathys-0.8.0 → bathys-0.9.0}/Dockerfile +0 -0
  25. {bathys-0.8.0 → bathys-0.9.0}/LICENSE +0 -0
  26. {bathys-0.8.0 → bathys-0.9.0}/THIRD_PARTY_NOTICES.md +0 -0
  27. {bathys-0.8.0 → bathys-0.9.0}/agents/HARNESS-DROPIN.md +0 -0
  28. {bathys-0.8.0 → bathys-0.9.0}/agents/bathys-researcher.md +0 -0
  29. {bathys-0.8.0 → bathys-0.9.0}/agents/skills/bathys-deep-dive/SKILL.md +0 -0
  30. {bathys-0.8.0 → bathys-0.9.0}/agents/skills/bathys-source-audit/SKILL.md +0 -0
  31. {bathys-0.8.0 → bathys-0.9.0}/docs/adr/0001-python-crawl4ai.md +0 -0
  32. {bathys-0.8.0 → bathys-0.9.0}/docs/adr/0002-pin-mcp-sdk-v1.md +0 -0
  33. {bathys-0.8.0 → bathys-0.9.0}/docs/adr/0003-self-managed-searxng.md +0 -0
  34. {bathys-0.8.0 → bathys-0.9.0}/docs/adr/0004-bm25-distillation.md +0 -0
  35. {bathys-0.8.0 → bathys-0.9.0}/docs/adr/0005-cache-raw-before-distill.md +0 -0
  36. {bathys-0.8.0 → bathys-0.9.0}/docs/adr/0006-three-tool-string-surface.md +0 -0
  37. {bathys-0.8.0 → bathys-0.9.0}/docs/architecture/data-flow.md +0 -0
  38. {bathys-0.8.0 → bathys-0.9.0}/docs/architecture/overview.md +0 -0
  39. {bathys-0.8.0 → bathys-0.9.0}/docs/architecture/pipeline.md +0 -0
  40. {bathys-0.8.0 → bathys-0.9.0}/docs/assets/banner.svg +0 -0
  41. {bathys-0.8.0 → bathys-0.9.0}/docs/contracts/config.md +0 -0
  42. {bathys-0.8.0 → bathys-0.9.0}/docs/contracts/mcp-tools.md +0 -0
  43. {bathys-0.8.0 → bathys-0.9.0}/docs/contracts/module-contracts.md +0 -0
  44. {bathys-0.8.0 → bathys-0.9.0}/docs/contracts/output-format.md +0 -0
  45. {bathys-0.8.0 → bathys-0.9.0}/docs/getting-started/cases.md +0 -0
  46. {bathys-0.8.0 → bathys-0.9.0}/docs/getting-started/configure.md +0 -0
  47. {bathys-0.8.0 → bathys-0.9.0}/docs/getting-started/install.md +0 -0
  48. {bathys-0.8.0 → bathys-0.9.0}/docs/getting-started/integrate.md +0 -0
  49. {bathys-0.8.0 → bathys-0.9.0}/docs/index.md +0 -0
  50. {bathys-0.8.0 → bathys-0.9.0}/docs/integrations/claude-code.md +0 -0
  51. {bathys-0.8.0 → bathys-0.9.0}/docs/integrations/cursor.md +0 -0
  52. {bathys-0.8.0 → bathys-0.9.0}/docs/integrations/generic-mcp.md +0 -0
  53. {bathys-0.8.0 → bathys-0.9.0}/docs/integrations/overview.md +0 -0
  54. {bathys-0.8.0 → bathys-0.9.0}/docs/integrations/zcode.md +0 -0
  55. {bathys-0.8.0 → bathys-0.9.0}/docs/meta/glossary.md +0 -0
  56. {bathys-0.8.0 → bathys-0.9.0}/docs/meta/style-guide.md +0 -0
  57. {bathys-0.8.0 → bathys-0.9.0}/docs/operations/metrics.md +0 -0
  58. {bathys-0.8.0 → bathys-0.9.0}/docs/operations/runbook.md +0 -0
  59. {bathys-0.8.0 → bathys-0.9.0}/docs/product/api-engine-initiative.md +0 -0
  60. {bathys-0.8.0 → bathys-0.9.0}/docs/product/charter.md +0 -0
  61. {bathys-0.8.0 → bathys-0.9.0}/docs/product/competitive.md +0 -0
  62. {bathys-0.8.0 → bathys-0.9.0}/docs/product/features.md +0 -0
  63. {bathys-0.8.0 → bathys-0.9.0}/docs/product/mind-initiative.md +0 -0
  64. {bathys-0.8.0 → bathys-0.9.0}/docs/product/ocr-initiative.md +0 -0
  65. {bathys-0.8.0 → bathys-0.9.0}/gpu-llm-analysis-2026.html +0 -0
  66. {bathys-0.8.0 → bathys-0.9.0}/gpu-llm-multiagent-2026.html +0 -0
  67. {bathys-0.8.0 → bathys-0.9.0}/install.sh +0 -0
  68. {bathys-0.8.0 → bathys-0.9.0}/integrations/README.md +0 -0
  69. {bathys-0.8.0 → bathys-0.9.0}/integrations/hermes/README.md +0 -0
  70. {bathys-0.8.0 → bathys-0.9.0}/integrations/hermes/install.py +0 -0
  71. {bathys-0.8.0 → bathys-0.9.0}/integrations/pi/README.md +0 -0
  72. {bathys-0.8.0 → bathys-0.9.0}/integrations/pi/assets/bathys-rules.md +0 -0
  73. {bathys-0.8.0 → bathys-0.9.0}/integrations/zcode/README.md +0 -0
  74. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/.remember/.gitignore +0 -0
  75. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/.remember/logs/hook-errors.log +0 -0
  76. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/.remember/logs/memory-2026-09-08.log +0 -0
  77. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/.remember/tmp/no-transcript-notice +0 -0
  78. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/.remember/tmp/post-tool-ran +0 -0
  79. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/README.md +0 -0
  80. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/bin/cli.js +0 -0
  81. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/bin/postinstall.js +0 -0
  82. {bathys-0.8.0 → bathys-0.9.0}/npm/bathys-mcp/package.json +0 -0
  83. {bathys-0.8.0 → bathys-0.9.0}/scripts/acceptance_v02.py +0 -0
  84. {bathys-0.8.0 → bathys-0.9.0}/scripts/batch_check.py +0 -0
  85. {bathys-0.8.0 → bathys-0.9.0}/scripts/metrics_report.py +0 -0
  86. {bathys-0.8.0 → bathys-0.9.0}/scripts/smoke.py +0 -0
  87. {bathys-0.8.0 → bathys-0.9.0}/scripts/stdio_check.py +0 -0
  88. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/batch.py +0 -0
  89. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/cache.py +0 -0
  90. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/compose.yaml +0 -0
  91. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/config.py +0 -0
  92. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/distill.py +0 -0
  93. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/doctor.py +0 -0
  94. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/installer.py +0 -0
  95. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/searx.py +0 -0
  96. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/searxng-settings.yml +0 -0
  97. {bathys-0.8.0 → bathys-0.9.0}/src/bathys/services.py +0 -0
  98. {bathys-0.8.0 → bathys-0.9.0}/tests/test_batch.py +0 -0
  99. {bathys-0.8.0 → bathys-0.9.0}/tests/test_cache.py +0 -0
  100. {bathys-0.8.0 → bathys-0.9.0}/tests/test_config.py +0 -0
  101. {bathys-0.8.0 → bathys-0.9.0}/tests/test_core.py +0 -0
  102. {bathys-0.8.0 → bathys-0.9.0}/tests/test_distill.py +0 -0
  103. {bathys-0.8.0 → bathys-0.9.0}/tests/test_installer.py +0 -0
  104. {bathys-0.8.0 → bathys-0.9.0}/tests/test_searx.py +0 -0
  105. {bathys-0.8.0 → bathys-0.9.0}/tests/test_v04.py +0 -0
  106. {bathys-0.8.0 → bathys-0.9.0}/uv.lock +0 -0
@@ -140,3 +140,44 @@
140
140
  13:14:06 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
141
141
  13:14:28 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
142
142
  13:14:43 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
143
+ 13:15:04 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
144
+ 13:15:20 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
145
+ 13:36:02 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
146
+ 13:36:14 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
147
+ 13:44:58 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
148
+ 13:45:07 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
149
+ 13:45:15 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
150
+ 13:45:28 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
151
+ 13:45:46 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
152
+ 13:46:06 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
153
+ 13:46:18 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
154
+ 13:46:27 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
155
+ 13:46:38 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
156
+ 13:46:47 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
157
+ 13:46:56 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
158
+ 13:47:04 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
159
+ 13:47:14 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
160
+ 13:47:14 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
161
+ 13:47:31 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
162
+ 13:47:41 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
163
+ 13:47:51 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
164
+ 13:48:02 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
165
+ 13:48:11 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
166
+ 13:48:20 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
167
+ 13:48:30 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
168
+ 13:48:40 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
169
+ 13:48:52 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
170
+ 13:49:00 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
171
+ 13:49:11 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
172
+ 13:49:11 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
173
+ 13:49:22 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
174
+ 13:49:32 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
175
+ 13:49:43 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
176
+ 13:49:53 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
177
+ 13:50:05 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
178
+ 13:50:13 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
179
+ 13:50:28 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
180
+ 13:50:39 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
181
+ 13:50:50 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
182
+ 13:51:03 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
183
+ 13:51:16 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/.remember
@@ -2,6 +2,20 @@
2
2
 
3
3
  Формат: Keep a Changelog; версии — semver. Дата — дата выпуска версии.
4
4
 
5
+ ## [0.9.0] — 2026-09-09
6
+
7
+ Тема: «Borrowed Ideas» — три фичи, заимствованные из pi-web-access (реализация наша; разведка самого источника проведена живьём через Bathys).
8
+
9
+ ### Добавлено
10
+
11
+ - **`find` в `read_url`** — точный поиск по кэшу сырца без сети (заимствовано из `get_search_content`/`findText`): счётчики совпадений, позиции и контекст; live: 25 совпадений «self-attention» по кэшу PDF за 0.0 с. Работает и по PDF-кэшу.
12
+ - **PDF text-layer в HTTP-ярусе** (`pymupdf`, локально, без ML/облака; заимствовано из их PDF-обработки): PDF-URL читается первым ярусом, `content-type: application/pdf` → текст → обычная дистилляция. Live: «Attention Is All You Need» (2.2 МБ) → 1489 симв. под запрос за 1.1 с. Сканы без текстового слоя — честный отказ (OCR-инициатива остаётся paused); отдельные PDF-ошибки не эскалируют в браузер (`_FinalTierError`) — браузер на PDF всё равно падает с «Download is starting».
13
+ - **Типизация fallback-причин F-102** (заимствовано из их `fallbackOn`): captcha/suspended весят ×3 (липкое состояние), timeout ×1, прочее ×2 — капчевые движки исключаются из fallback-наборов быстрее.
14
+
15
+ ### Исправлено
16
+
17
+ - JS-shell-детектор больше не срабатывает на PDF/извлечённых страницах (пустой raw-html по дизайну ≠ оболочка) — ранее это маскировало PDF-результат ошибкой браузера.
18
+
5
19
  ## [0.8.0] — 2026-09-09
6
20
 
7
21
  Тема: «Engine Orchestration» — вердикт архкома №4 + безключевая оркестрация движков.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: bathys
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Unified local deep-research search service for AI agents — one pipeline (search → extraction → query distillation → cache), zero cloud quotas. MCP stdio server with native harness integration (bathys install).
5
5
  Project-URL: Homepage, https://github.com/Korrnals/bathys
6
6
  Project-URL: Repository, https://github.com/Korrnals/bathys
@@ -33,7 +33,7 @@ Description-Content-Type: text/markdown
33
33
  Сонар находит координаты, батискаф ныряет за полными текстами, дистиллятор поднимает на палубу только то, что отвечает на вопрос.
34
34
 
35
35
  ![python](https://img.shields.io/badge/python-3.10%2B-blue)
36
- ![version](https://img.shields.io/badge/version-0.8.0-9cf)
36
+ ![version](https://img.shields.io/badge/version-0.9.0-9cf)
37
37
  ![mcp](https://img.shields.io/badge/MCP-stdio%20server-6f42c1)
38
38
  ![license](https://img.shields.io/badge/license-MIT-green)
39
39
 
@@ -171,7 +171,7 @@ Bathys — stdio MCP-сервер: блок `mcpServers` один и тот же
171
171
  |---|---|
172
172
  | `deep_research(query, max_sources=3, …)` | ищет, параллельно читает топ-источники, возвращает слитый дистиллят под запрос. Первый вызов для любого ресёрч-вопроса. |
173
173
  | `web_search(query, max_results=8, …)` | ранжированный список ссылок со сниппетами без содержимого страниц; `as_json=true` — чистый JSON для программ. |
174
- | `read_url(url, query=None, max_chars=8000)` | читает одну страницу; с `query` — только релевантные пассажи. |
174
+ | `read_url(url, query=None, find=None)` | читает страницу (включая текстовые PDF); с `query` — релевантные пассажи; с `find` — точный поиск по кэшу сырца без сети. |
175
175
  | `read_urls(urls, query=None, total_chars=12000)` | пакетно читает до 10 известных страниц; бюджет делится между успешными, сбой страницы — одна строка, не сорванный вызов. |
176
176
 
177
177
  Поиск сужается общими фильтрами `time_range`, `category`, `engines`, `language`. Живой футер ответа показывает сжатие и кэш: `[bathys: 41 raw hits, top 3 considered · dove 3 pages · 35669 ch fetched → 7508 ch returned · 3.2s]`.
@@ -210,7 +210,7 @@ Bathys — stdio MCP-сервер: блок `mcpServers` один и тот же
210
210
 
211
211
  ## 📍 Статус
212
212
 
213
- **0.8.0.** Выпускная история: v0.2 «Качество выдачи» (ретраи, здоровье движков), v0.3 «Паритет с Tavily» (`read_urls`, JSON-режим), v0.4 «Эксплуатация» (robots-этика, метрики, `bathys-doctor`), v0.5 «Identity & Harness» (репозиционирование, промпты, субагент), v0.6 «Native Install» (`bathys install`), v0.7 «Ship & Setup» (двухъярусное извлечение, `bathys setup`, однострочник, uninstall) — итоги в [CHANGELOG.md](CHANGELOG.md).
213
+ **0.9.0.** Выпускная история: v0.2 «Качество выдачи» (ретраи, здоровье движков), v0.3 «Паритет с Tavily» (`read_urls`, JSON-режим), v0.4 «Эксплуатация» (robots-этика, метрики, `bathys-doctor`), v0.5 «Identity & Harness» (репозиционирование, промпты, субагент), v0.6 «Native Install» (`bathys install`), v0.7 «Ship & Setup» (двухъярусное извлечение, `bathys setup`, однострочник, uninstall) — итоги в [CHANGELOG.md](CHANGELOG.md).
214
214
 
215
215
  Репозиторий: `github.com/Korrnals/bathys`. Пакет опубликован: [PyPI `bathys`](https://pypi.org/project/bathys/) (pip install), однострочник установки — выше. До 1.0: публикация npm-обёртки `bathys-mcp` и первый прогон Docker-образа; CI (matrix 3.10–3.12 + shellcheck) уже в репозитории.
216
216
 
@@ -7,7 +7,7 @@
7
7
  Сонар находит координаты, батискаф ныряет за полными текстами, дистиллятор поднимает на палубу только то, что отвечает на вопрос.
8
8
 
9
9
  ![python](https://img.shields.io/badge/python-3.10%2B-blue)
10
- ![version](https://img.shields.io/badge/version-0.8.0-9cf)
10
+ ![version](https://img.shields.io/badge/version-0.9.0-9cf)
11
11
  ![mcp](https://img.shields.io/badge/MCP-stdio%20server-6f42c1)
12
12
  ![license](https://img.shields.io/badge/license-MIT-green)
13
13
 
@@ -145,7 +145,7 @@ Bathys — stdio MCP-сервер: блок `mcpServers` один и тот же
145
145
  |---|---|
146
146
  | `deep_research(query, max_sources=3, …)` | ищет, параллельно читает топ-источники, возвращает слитый дистиллят под запрос. Первый вызов для любого ресёрч-вопроса. |
147
147
  | `web_search(query, max_results=8, …)` | ранжированный список ссылок со сниппетами без содержимого страниц; `as_json=true` — чистый JSON для программ. |
148
- | `read_url(url, query=None, max_chars=8000)` | читает одну страницу; с `query` — только релевантные пассажи. |
148
+ | `read_url(url, query=None, find=None)` | читает страницу (включая текстовые PDF); с `query` — релевантные пассажи; с `find` — точный поиск по кэшу сырца без сети. |
149
149
  | `read_urls(urls, query=None, total_chars=12000)` | пакетно читает до 10 известных страниц; бюджет делится между успешными, сбой страницы — одна строка, не сорванный вызов. |
150
150
 
151
151
  Поиск сужается общими фильтрами `time_range`, `category`, `engines`, `language`. Живой футер ответа показывает сжатие и кэш: `[bathys: 41 raw hits, top 3 considered · dove 3 pages · 35669 ch fetched → 7508 ch returned · 3.2s]`.
@@ -184,7 +184,7 @@ Bathys — stdio MCP-сервер: блок `mcpServers` один и тот же
184
184
 
185
185
  ## 📍 Статус
186
186
 
187
- **0.8.0.** Выпускная история: v0.2 «Качество выдачи» (ретраи, здоровье движков), v0.3 «Паритет с Tavily» (`read_urls`, JSON-режим), v0.4 «Эксплуатация» (robots-этика, метрики, `bathys-doctor`), v0.5 «Identity & Harness» (репозиционирование, промпты, субагент), v0.6 «Native Install» (`bathys install`), v0.7 «Ship & Setup» (двухъярусное извлечение, `bathys setup`, однострочник, uninstall) — итоги в [CHANGELOG.md](CHANGELOG.md).
187
+ **0.9.0.** Выпускная история: v0.2 «Качество выдачи» (ретраи, здоровье движков), v0.3 «Паритет с Tavily» (`read_urls`, JSON-режим), v0.4 «Эксплуатация» (robots-этика, метрики, `bathys-doctor`), v0.5 «Identity & Harness» (репозиционирование, промпты, субагент), v0.6 «Native Install» (`bathys install`), v0.7 «Ship & Setup» (двухъярусное извлечение, `bathys setup`, однострочник, uninstall) — итоги в [CHANGELOG.md](CHANGELOG.md).
188
188
 
189
189
  Репозиторий: `github.com/Korrnals/bathys`. Пакет опубликован: [PyPI `bathys`](https://pypi.org/project/bathys/) (pip install), однострочник установки — выше. До 1.0: публикация npm-обёртки `bathys-mcp` и первый прогон Docker-образа; CI (matrix 3.10–3.12 + shellcheck) уже в репозитории.
190
190
 
@@ -0,0 +1,69 @@
1
+ # Заимствованные идеи: pi-web-access → Bathys
2
+
3
+ | Поле | Значение |
4
+ |---|---|
5
+ | Источник | [pi-web-access](https://github.com/nicobailon/pi-web-access) (Pi coding agent extension, 1399★, активен 2026-09) — разведано живьём через Bathys 2026-09-09 |
6
+ | Принцип | Реализация всегда наша; заимствуются **проверенные продуктовой практикой** решения. Pi — Extension для агента (TypeScript, полный системный доступ), Bathys — единый локальный поисковый сервис (MCP, слой данных). Контексты разные — переносим только то, что усиливает наш конвейер, не ломая хартию (без LLM внутри, без облака по умолчанию). |
7
+ | Статус | Кандидаты в роадмап; приоритизация ниже |
8
+
9
+ ## Что переносим (сильные идеи, ранжировано)
10
+
11
+ ### 1. `source_check` — верификация утверждения как machine-readable артефакт ★★★
12
+
13
+ У них: `source_check({claim, queries?, fetchContent?, domainFilter?})` → артефакт: статус `supported | contradicted | unclear | missing-evidence`, цитаты пассажей с оффсетами, SHA-256 хэши контента, качество источников; **ошибки поиска/фетча остаются в артефекте, не выбрасываются молча**.
14
+
15
+ Почему нам: у Bathys уже есть промпт `bathys_source_audit` (текстовая стратегия) и скилл — но статус-вердикты у вызывающего агента остаются текстом, который модель может исказить. Детерминированная часть (сбор источников, пассажи с оффсетами, хэши, «1 источник vs 2 независимых») может считать **движок Bathys** — вердикты `supported/contradicted` по правилу «2 независимых домена» — а синтез остаётся агенту. Это углубление нашего же принципа «слой данных без LLM»: верификация фактуры детерминирована, интерпретация — у харнесса.
16
+
17
+ Реализация: новый инструмент `source_check` (5-й) ИЛИ расширение `read_urls` параметром `claim`; артефакт — наш строковый формат с блоками `[bathys: …]`-статистикой.
18
+
19
+ ### 2. `get_search_content` — пагинация по кэшу с `findText` ★★★
20
+
21
+ У них: сохранённый контент извлекается позже по `responseId` с `offset/limit` или `findText` (exact/case-insensitive/fuzzy, кап 20k, счётчики совпадений и контекст).
22
+
23
+ Почему нам: у Bathys кэш сырца **уже есть** (до дистилляции — это наше преимущество), но агент может получить только повторный дистиллят. Дать `find_text(url, pattern)` — поиск по сырому кэшу без сети: «найди в той статье точную цитату про X». Дёшево (кэш уже лежит), идеально для аудита и точных цитат.
24
+
25
+ Реализация: параметр `find` в `read_url` при cache-HIT или отдельный инструмент; поиск по сырому тексту с контекстом ±N символов.
26
+
27
+ ### 3. GitHub-специализация: клон вместо скрейпа ★★
28
+
29
+ У них: GitHub-URL → локальный `git clone` (кэш на сессию, >350MB → API-вид); PR/issue → приоритизированный markdown-документ (статус, чеки, ревью, комменты, `gh`-CLI) вместо HTML-скрейпа.
30
+
31
+ Почему нам: наш HTTP-ярус на GitHub получает HTML-мусор, браузерный — тяжёлый. Спец-обработчик GitHub-URL (детект по хосту) → `gh api` для PR/issues (структура, а не парсинг) и README+дерево для репо — это **та же двухъярусная философия, но ярус-1 специализируется по типу URL**. `gh` уже есть в системе; без `gh` — фолбэк на HTTP-ярус.
32
+
33
+ Реализация: в `crawler._fetch_http` — редирект на GitHub-ветку (детект: github.com/{owner}/{repo}[/pull|/issues/|N]).
34
+
35
+ ### 4. PDF → Markdown-конверсия ★★
36
+
37
+ У них: PDF-URL → конверсия и сохранение в temp-каталог (агент читает секции `read`-ом, не грузя весь документ в контекст); три движка: datalab (layout-aware), gemini (LLM), unpdf (локально, без ключа).
38
+
39
+ Почему нам: OCR-инициатива у нас **приостановлена** (VLM = GPU-боль), но unpdf-путь — это **локальная конверсия текстовых PDF без ML** (`pip install pymupdf` уже был в плане OCR-инициативы как text-layer). Наш двухъярусный HTTP-ярус сейчас на PDF просто падает («unsupported content-type» — сам видел в коде). Текстовый PDF без ML — честное закрытие 80% PDF-кейса без разморозки OCR.
40
+
41
+ Реализация: детект `content-type: application/pdf` в HTTP-ярусе → pymupdf → текст в тот же конвейер дистилляции. Сканы — честный отказ с указанием на OCR-инициативу.
42
+
43
+ ### 5. Routing/fallback-конфигурация ★ (у нас уже частично есть)
44
+
45
+ У них: `searchRouting: {providers: [...], fallbackOn: [transient, quota, network, invalid-response]}` — типизированные причины фолбэка; `provider: "all"` — параллельный мульти-поиск; `proxy` per-call.
46
+
47
+ Что берём: (а) **типизация причин фолбэка** — наш F-101 ретраится по «пустой выдаче», но не различает `captcha` vs `timeout` vs `quota` на уровне retry-решения (unresponsive_engines это содержит! — парсить причину); (б) `provider: "all"`-режим для `web_search` — параллельный опрос всех активных движков с дедупликацией (у SearXNG это уже есть в `!format=json` — нам нужно просто НЕ передавать engines и объединить) — **дешёво, у нас почти есть**.
48
+
49
+ Не берём: их 25+ облачных провайдеров (против нашей хартии), browser-cookies Gemini Web (приватность-риск, у нас robots-этика), curator-UI (UI = Not-doing).
50
+
51
+ ## Чего НЕ заимствуем (и почему — зафиксировано)
52
+
53
+ | Их фича | Почему нет |
54
+ |---|---|
55
+ | Video understanding (YouTube/Gemini/frames) | Требует облачной VLM (Gemini) — против «ноль облака по умолчанию»; локального аналога без GPU нет |
56
+ | 25+ облачных поисковых провайдеров | Наша ценность — оркестрация локального SearXNG; облако — только опциональные ключи (archcom #4) |
57
+ | Browser-cookie авторизация (Gemini Web) | Приватность-антипаттерн для нашего позиционирования |
58
+ | Curator-UI (браузерный) | UI = Not-doing хартии |
59
+ | LLM-суммаризация результатов | «LLM внутри нет» — синтез у вызывающего агента |
60
+
61
+ ## Приоритизация для роадмапа
62
+
63
+ | # | Фича | Сложность | Версия-кандидат |
64
+ |---|---|---|---|
65
+ | 1 | `find`/`get_search_content` по кэшу сырца | S (кэш уже есть) | v0.9 |
66
+ | 2 | PDF text-layer в HTTP-ярусе (pymupdf) | S–M | v0.9 |
67
+ | 3 | Типизация причин фолбэка + «all»-режим | S | v0.9 |
68
+ | 4 | GitHub-специализация (`gh api`) | M | v0.9/v1.0 |
69
+ | 5 | `source_check`-инструмент с детерминированными вердиктами | M–L | v1.0 (входит в паритет с Tavily-классом) |
@@ -119,6 +119,7 @@ Chromium и SearXNG тяжёлый (порядка гигабайта) — до
119
119
  ## Кандидаты (рассматриваются)
120
120
 
121
121
  - **Лёгкий семантический слой (re-ranker)** (v0.3+) — статус: предложение; спайк одобрен председателем 2026-09-06; интеграция — отдельное решение архкома по критериям гейта в [mind-initiative.md](mind-initiative.md).
122
+ - **Заимствованные фичи из pi-web-access** (v0.9+) — разведано 2026-09-09 через живой Bathys; переносим 5 идей (кэш-find, PDF text-layer, типизация fallback-причин, GitHub-специализация, source_check), отклонены видео-VLM/облачные/cookies-UI — приоритеты в [ideas-borrowed.md](ideas-borrowed.md).
122
123
  - **API-движки метапоиска** (v0.8) — статус: **утверждена владельцем 2026-09-09**, материалы собраны е2е; план и чеклист — [api-engine-initiative.md](api-engine-initiative.md). Оркестрация готовых API-движков SearXNG (braveapi/exaapi), свой движок — только по триггеру.
123
124
  - **OCR-чтение PDF, сканов и скриншотов** (v0.3+) — статус: **приостановлена** (решение мейнтейнера 2026-09-06: приоритет — доступность на любом CPU-железе); возврат — по триггерам §8 в [ocr-initiative.md](ocr-initiative.md).
124
125
 
@@ -42,3 +42,20 @@
42
42
  13:11:12 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
43
43
  13:11:12 [hook] WARNING: no session dir for this project: /var/home/abyss/.distrobox/ubuntu/home/.claude/projects/-var-home-abyss-LABs-MCP-deepreserch-npm-bathys-mcp (slug of /var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp). Memory cannot save until it matches a directory under /var/home/abyss/.distrobox/ubuntu/home/.claude/projects/
44
44
  13:11:21 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
45
+ 13:32:15 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
46
+ 13:32:25 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
47
+ 13:32:25 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
48
+ 13:32:35 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
49
+ 13:32:46 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
50
+ 13:32:58 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
51
+ 13:33:07 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
52
+ 13:33:19 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
53
+ 13:33:30 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
54
+ 13:33:39 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
55
+ 13:33:48 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
56
+ 13:34:57 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
57
+ 13:35:07 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
58
+ 13:35:17 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
59
+ 13:35:39 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
60
+ 13:35:51 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
61
+ 13:44:45 [hook] post-tool: PROJECT_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp PIPELINE_DIR=/var/home/abyss/.distrobox/ubuntu/home/.zcode/cli/plugins/cache/claude-plugins-official/remember/0.20.0 PYTHON=python3 REMEMBER_DIR=/var/home/abyss/LABs/MCP/deepreserch/npm/bathys-mcp/.remember
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bathys"
7
- version = "0.8.0"
7
+ version = "0.9.0"
8
8
  description = "Unified local deep-research search service for AI agents — one pipeline (search → extraction → query distillation → cache), zero cloud quotas. MCP stdio server with native harness integration (bathys install)."
9
9
  keywords = ["mcp", "deep-research", "search", "web-search", "ai-agents", "llm", "local-first", "distillation", "searxng", "crawl4ai"]
10
10
  classifiers = [
@@ -5,4 +5,4 @@ a query-focused distiller keeps only what answers the question. Built to spend
5
5
  the model's tokens on answers, not on boilerplate.
6
6
  """
7
7
 
8
- __version__ = "0.8.0"
8
+ __version__ = "0.9.0"
@@ -4,6 +4,7 @@ so scripts and tests can drive it without MCP framing."""
4
4
  from __future__ import annotations
5
5
 
6
6
  import asyncio
7
+ import re
7
8
  import time
8
9
  from dataclasses import dataclass
9
10
 
@@ -152,10 +153,21 @@ class Engine:
152
153
  self._search_ts = time.monotonic()
153
154
 
154
155
  def _record_health(self, outcome: searx.SearchOutcome) -> None:
155
- """F-102: consecutive-failure streak per engine; any hit resets it."""
156
+ """F-102: consecutive-failure streak per engine; any hit resets it.
157
+ v0.9: failure reasons are now TYPED (borrowed from pi-web-access's
158
+ fallbackOn design) — captcha engines get a longer memory than timeout
159
+ engines, because captchas don't heal in seconds."""
156
160
  for e in outcome.unresponsive:
157
- name = e.split(":")[0]
158
- self._engine_fails[name] = self._engine_fails.get(name, 0) + 1
161
+ parts = e.split(":", 1)
162
+ name = parts[0]
163
+ reason = (parts[1] if len(parts) > 1 else "").lower()
164
+ if "captcha" in reason or "suspended" in reason:
165
+ weight = 3 # captcha: sticky condition, counts triple
166
+ elif "timeout" in reason:
167
+ weight = 1 # timeout: transient, counts as-is
168
+ else:
169
+ weight = 2 # quota/network/unknown
170
+ self._engine_fails[name] = self._engine_fails.get(name, 0) + weight
159
171
  for h in outcome.hits:
160
172
  for name in h.engines:
161
173
  self._engine_fails.pop(name, None)
@@ -331,8 +343,46 @@ class Engine:
331
343
  distilled = distill.passages(slim, query, max_chars)
332
344
  return ReadResult(page=page, distilled=distilled, cache_hit=hit)
333
345
 
346
+ def _find_in_cache(self, url: str, pattern: str, *, limit: int = 3,
347
+ context: int = 160) -> str:
348
+ """find-text over the cached RAW page (borrowed from pi-web-access's
349
+ get_search_content/findText): exact substring search, no network,
350
+ match counters and local context. Cache miss -> honest error."""
351
+ pk = Cache.key("page", url)
352
+ got, stored = self.cache.get(pk)
353
+ if not got:
354
+ return f"[bathys: find — нет кэша для {url}; сначала read_url]"
355
+ if "error" in stored:
356
+ return f"[bathys: find — в кэше ошибка: {stored['error']}]"
357
+ text = stored.get("text", "")
358
+ low, pl = text.lower(), pattern.lower()
359
+ positions: list[int] = []
360
+ i = low.find(pl)
361
+ while i != -1 and len(positions) < 50:
362
+ positions.append(i)
363
+ i = low.find(pl, i + 1)
364
+ if not positions:
365
+ return (f"[bathys: find '{pattern}' — 0 совпадений в кэше "
366
+ f"({len(text)} ch); попробуй read_url с query]")
367
+ total = len(positions)
368
+ shown = positions[:limit]
369
+ blocks = []
370
+ for n, pos in enumerate(shown, 1):
371
+ lo = max(0, pos - context)
372
+ hi = min(len(text), pos + len(pattern) + context)
373
+ frag = ("…" if lo else "") + text[lo:hi] + ("…" if hi < len(text) else "")
374
+ frag = re.sub(r"\s+", " ", frag)
375
+ blocks.append(f"{n}. @{pos}: …{frag}…")
376
+ return (f"[bathys: find '{pattern}' — {total} совпадений(я), показано {len(shown)} "
377
+ f"(кэш сырца, без сети)\n" + "\n".join(blocks))
378
+
334
379
  async def read(self, url: str, *, query: str | None = None, max_chars: int = 8000,
335
- refresh: bool = False) -> str:
380
+ refresh: bool = False, find: str | None = None) -> str:
381
+ if find is not None:
382
+ out = self._find_in_cache(url, find)
383
+ self._log_metrics("read_url", cache="HIT", chars_in=0,
384
+ chars_out=len(out), secs=0.0, url=url)
385
+ return out
336
386
  started = time.monotonic()
337
387
  try:
338
388
  res = await self._read(url, query=query, max_chars=max_chars, refresh=refresh)
@@ -54,6 +54,10 @@ _COMMENT_RE = re.compile(r"<!--.*?-->", re.S)
54
54
  _TAG_RE = re.compile(r"<[^>]+>")
55
55
  _TITLE_RE = re.compile(r"<title\b[^>]*>(.*?)</title>", re.S | re.I)
56
56
  _WS_RE = re.compile(r"\s+")
57
+ class _FinalTierError(RuntimeError):
58
+ """Tier-1 error that must NOT escalate to the browser tier."""
59
+
60
+
57
61
  _APP_ROOT_RE = re.compile(
58
62
  r"<body[^>]*>\s*(<div[^>]*id=[\"']?(app|root|__next|__nuxt)[\"']?[^>]*>\s*"
59
63
  r"(</div>)?\s*</body>)", re.I)
@@ -81,6 +85,23 @@ def _looks_like_js_shell(html: str, text: str) -> bool:
81
85
  return len(text) < 200
82
86
 
83
87
 
88
+ def _pdf_text(content: bytes) -> str | None:
89
+ """Extract the text layer from PDF bytes; None when there is no text."""
90
+ try:
91
+ import pymupdf # optional dependency, lazy import
92
+ except ImportError:
93
+ raise _FinalTierError(
94
+ "crawl failed: PDF support needs `pip install pymupdf` (local, no ML)")
95
+ try:
96
+ doc = pymupdf.open(stream=content, filetype="pdf")
97
+ parts = [page.get_text() for page in doc]
98
+ doc.close()
99
+ except Exception as e:
100
+ raise RuntimeError(f"crawl failed: pdf parse error ({e.__class__.__name__})")
101
+ text = "\n\n".join(parts).strip()
102
+ return text if len(text) >= 40 else None # <40 chars => likely a scan
103
+
104
+
84
105
  class Crawler:
85
106
  """Extraction facade. One shared browser at most, started lazily."""
86
107
 
@@ -161,8 +182,22 @@ class Crawler:
161
182
  ctype = resp.headers.get("content-type", "")
162
183
  if resp.status_code >= 400:
163
184
  raise RuntimeError(f"crawl failed: http {resp.status_code}")
185
+ if "pdf" in ctype or url.lower().endswith(".pdf"):
186
+ # PDF text layer (v0.9, borrowed from pi-web-access's PDF handling):
187
+ # local extraction via pymupdf — no ML, no cloud, no OCR. Scanned
188
+ # PDFs (no text layer) fail honestly and stay out of scope until
189
+ # the paused OCR initiative is revived.
190
+ text = _pdf_text(resp.content)
191
+ if text is None:
192
+ raise _FinalTierError(
193
+ "crawl failed: PDF has no text layer (scanned?) — OCR initiative is paused")
194
+ return (
195
+ Page(url=str(resp.url), status=resp.status_code, title="",
196
+ text=text, raw_chars=len(resp.content), tier="http-pdf"),
197
+ "",
198
+ )
164
199
  if "html" not in ctype and "xml" not in ctype and ctype:
165
- # non-HTML (pdf/json/etc) — not tier-1 material
200
+ # non-HTML (json/etc) — not tier-1 material
166
201
  raise RuntimeError(f"crawl failed: unsupported content-type {ctype.split(';')[0]}")
167
202
  html = resp.text
168
203
  title_m = _TITLE_RE.search(html)
@@ -183,14 +218,20 @@ class Crawler:
183
218
  if mode == "off":
184
219
  page, _ = await self._fetch_http(url, http)
185
220
  return page
186
- # auto: try tier 1, escalate to tier 2 on JS-shell or failure
221
+ # auto: try tier 1, escalate to tier 2 on JS-shell or failure.
222
+ # PDF errors are FINAL (final): a headless browser on a PDF just hits
223
+ # "Download is starting" — escalating would mask the honest message.
187
224
  try:
188
225
  page, html = await self._fetch_http(url, http)
226
+ except _FinalTierError:
227
+ raise
189
228
  except RuntimeError:
190
229
  if mode == "auto":
191
230
  return await self._fetch_browser(url)
192
231
  raise
193
- if not _looks_like_js_shell(html, page.text):
232
+ # PDF/extracted-content pages return empty raw html by design —
233
+ # that is NOT a JS shell; skip the heuristic and return as-is.
234
+ if page.tier != "http" or not _looks_like_js_shell(html, page.text):
194
235
  return page
195
236
  return await self._fetch_browser(url)
196
237
 
@@ -174,6 +174,7 @@ async def read_url(
174
174
  query: str | None = None,
175
175
  max_chars: int = 8000,
176
176
  refresh: bool = False,
177
+ find: str | None = None,
177
178
  ctx: Context = None,
178
179
  ) -> str:
179
180
  """Read one web page; return its main content as clean, budgeted markdown.
@@ -187,8 +188,12 @@ async def read_url(
187
188
  query: optional focus; return only passages relevant to it
188
189
  max_chars: output character budget (300-50000)
189
190
  refresh: ignore cache and re-fetch the page
191
+ find: search the cached RAW text for this exact substring (case-insensitive):
192
+ returns matches with counters and context, no network needed. Requires
193
+ the page to have been read before; combine with query for first reads.
190
194
  """
191
- return await _engine(ctx).read(url, query=query, max_chars=max_chars, refresh=refresh)
195
+ return await _engine(ctx).read(url, query=query, max_chars=max_chars,
196
+ refresh=refresh, find=find)
192
197
 
193
198
 
194
199
  @mcp.tool(annotations=ToolAnnotations(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes