passageway 0.3.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 (233) hide show
  1. passageway-0.3.0/.claude-plugin/marketplace.json +14 -0
  2. passageway-0.3.0/.claude-plugin/plugin.json +18 -0
  3. passageway-0.3.0/.dockerignore +17 -0
  4. passageway-0.3.0/.gitattributes +2 -0
  5. passageway-0.3.0/.github/dependabot.yml +62 -0
  6. passageway-0.3.0/.github/workflows/audit.yml +25 -0
  7. passageway-0.3.0/.github/workflows/checks.yml +120 -0
  8. passageway-0.3.0/.github/workflows/cla.yml +30 -0
  9. passageway-0.3.0/.github/workflows/dependabot-automerge.yml +22 -0
  10. passageway-0.3.0/.github/workflows/pages.yml +43 -0
  11. passageway-0.3.0/.github/workflows/release.yml +141 -0
  12. passageway-0.3.0/.gitignore +11 -0
  13. passageway-0.3.0/CLA.md +29 -0
  14. passageway-0.3.0/CLAUDE.md +29 -0
  15. passageway-0.3.0/CONTRIBUTING.md +5 -0
  16. passageway-0.3.0/Dockerfile +61 -0
  17. passageway-0.3.0/LICENSE +75 -0
  18. passageway-0.3.0/LICENSE-FREE-TRIAL +57 -0
  19. passageway-0.3.0/PKG-INFO +73 -0
  20. passageway-0.3.0/README.md +29 -0
  21. passageway-0.3.0/connectors/confluence/README.md +48 -0
  22. passageway-0.3.0/connectors/confluence/passageway_connector_confluence/__init__.py +1 -0
  23. passageway-0.3.0/connectors/confluence/passageway_connector_confluence/__main__.py +3 -0
  24. passageway-0.3.0/connectors/confluence/passageway_connector_confluence/connector.py +307 -0
  25. passageway-0.3.0/connectors/confluence/passageway_connector_confluence/html.py +160 -0
  26. passageway-0.3.0/connectors/confluence/pyproject.toml +22 -0
  27. passageway-0.3.0/connectors/confluence/tests/conftest.py +42 -0
  28. passageway-0.3.0/connectors/confluence/tests/fake_confluence.py +142 -0
  29. passageway-0.3.0/connectors/confluence/tests/test_confluence_connector.py +175 -0
  30. passageway-0.3.0/connectors/confluence/tests/test_confluence_contract.py +38 -0
  31. passageway-0.3.0/connectors/confluence/tests/test_storage.py +57 -0
  32. passageway-0.3.0/connectors/llmstxt/README.md +85 -0
  33. passageway-0.3.0/connectors/llmstxt/passageway_connector_llmstxt/__init__.py +0 -0
  34. passageway-0.3.0/connectors/llmstxt/passageway_connector_llmstxt/__main__.py +3 -0
  35. passageway-0.3.0/connectors/llmstxt/passageway_connector_llmstxt/connector.py +209 -0
  36. passageway-0.3.0/connectors/llmstxt/pyproject.toml +22 -0
  37. passageway-0.3.0/connectors/llmstxt/tests/conftest.py +54 -0
  38. passageway-0.3.0/connectors/llmstxt/tests/test_llmstxt_connector.py +183 -0
  39. passageway-0.3.0/connectors/llmstxt/tests/test_llmstxt_contract.py +87 -0
  40. passageway-0.3.0/connectors/markdown/README.md +122 -0
  41. passageway-0.3.0/connectors/markdown/passageway_connector_markdown/__init__.py +1 -0
  42. passageway-0.3.0/connectors/markdown/passageway_connector_markdown/__main__.py +3 -0
  43. passageway-0.3.0/connectors/markdown/passageway_connector_markdown/connector.py +244 -0
  44. passageway-0.3.0/connectors/markdown/pyproject.toml +22 -0
  45. passageway-0.3.0/connectors/markdown/tests/conftest.py +40 -0
  46. passageway-0.3.0/connectors/markdown/tests/test_markdown_connector.py +341 -0
  47. passageway-0.3.0/connectors/markdown/tests/test_markdown_contract.py +80 -0
  48. passageway-0.3.0/connectors/sitemap/README.md +81 -0
  49. passageway-0.3.0/connectors/sitemap/passageway_connector_sitemap/__init__.py +0 -0
  50. passageway-0.3.0/connectors/sitemap/passageway_connector_sitemap/__main__.py +3 -0
  51. passageway-0.3.0/connectors/sitemap/passageway_connector_sitemap/connector.py +264 -0
  52. passageway-0.3.0/connectors/sitemap/pyproject.toml +25 -0
  53. passageway-0.3.0/connectors/sitemap/tests/conftest.py +57 -0
  54. passageway-0.3.0/connectors/sitemap/tests/test_sitemap_connector.py +148 -0
  55. passageway-0.3.0/connectors/sitemap/tests/test_sitemap_contract.py +94 -0
  56. passageway-0.3.0/connectors/trilium/README.md +45 -0
  57. passageway-0.3.0/connectors/trilium/passageway_connector_trilium/__init__.py +1 -0
  58. passageway-0.3.0/connectors/trilium/passageway_connector_trilium/__main__.py +3 -0
  59. passageway-0.3.0/connectors/trilium/passageway_connector_trilium/connector.py +227 -0
  60. passageway-0.3.0/connectors/trilium/passageway_connector_trilium/html.py +172 -0
  61. passageway-0.3.0/connectors/trilium/pyproject.toml +22 -0
  62. passageway-0.3.0/connectors/trilium/tests/conftest.py +43 -0
  63. passageway-0.3.0/connectors/trilium/tests/fake_etapi.py +211 -0
  64. passageway-0.3.0/connectors/trilium/tests/fixture-cases.toml +64 -0
  65. passageway-0.3.0/connectors/trilium/tests/test_trilium_connector.py +216 -0
  66. passageway-0.3.0/connectors/trilium/tests/test_trilium_contract.py +38 -0
  67. passageway-0.3.0/connectors/trilium/tests/test_trilium_parity.py +32 -0
  68. passageway-0.3.0/connectors/wikipedia/README.md +57 -0
  69. passageway-0.3.0/connectors/wikipedia/passageway_connector_wikipedia/__init__.py +1 -0
  70. passageway-0.3.0/connectors/wikipedia/passageway_connector_wikipedia/__main__.py +3 -0
  71. passageway-0.3.0/connectors/wikipedia/passageway_connector_wikipedia/connector.py +125 -0
  72. passageway-0.3.0/connectors/wikipedia/passageway_connector_wikipedia/mediawiki.py +144 -0
  73. passageway-0.3.0/connectors/wikipedia/passageway_connector_wikipedia/sections.py +54 -0
  74. passageway-0.3.0/connectors/wikipedia/pyproject.toml +22 -0
  75. passageway-0.3.0/connectors/wikipedia/tests/conftest.py +11 -0
  76. passageway-0.3.0/connectors/wikipedia/tests/fake_mediawiki.py +91 -0
  77. passageway-0.3.0/connectors/wikipedia/tests/test_wikipedia_client.py +192 -0
  78. passageway-0.3.0/connectors/wikipedia/tests/test_wikipedia_connector.py +139 -0
  79. passageway-0.3.0/connectors/wikipedia/tests/test_wikipedia_contract.py +57 -0
  80. passageway-0.3.0/connectors/wikipedia/tests/test_wikipedia_live.py +16 -0
  81. passageway-0.3.0/connectors/wikipedia/tests/test_wikipedia_sections.py +56 -0
  82. passageway-0.3.0/docs/CNAME +1 -0
  83. passageway-0.3.0/docs/adr/0001-out-of-process-connectors.md +42 -0
  84. passageway-0.3.0/docs/adr/0002-connectors-as-workspace-packages.md +30 -0
  85. passageway-0.3.0/docs/adr/0003-json-lines-over-a-subprocess-stays.md +48 -0
  86. passageway-0.3.0/docs/adr/0004-no-summary-for-source-substitution.md +29 -0
  87. passageway-0.3.0/docs/adr/0005-confluence-data-center-first.md +27 -0
  88. passageway-0.3.0/docs/adr/0006-https-trusts-the-system-store.md +27 -0
  89. passageway-0.3.0/docs/adr/0007-instances-under-one-user.md +28 -0
  90. passageway-0.3.0/docs/adr/0008-a-failed-fetch-batch-keeps-the-rest.md +28 -0
  91. passageway-0.3.0/docs/configuration.md +118 -0
  92. passageway-0.3.0/docs/connectors/confluence.md +7 -0
  93. passageway-0.3.0/docs/connectors/llmstxt.md +7 -0
  94. passageway-0.3.0/docs/connectors/markdown.md +7 -0
  95. passageway-0.3.0/docs/connectors/sitemap.md +7 -0
  96. passageway-0.3.0/docs/connectors/trilium.md +7 -0
  97. passageway-0.3.0/docs/connectors/wikipedia.md +7 -0
  98. passageway-0.3.0/docs/deploy.md +84 -0
  99. passageway-0.3.0/docs/development.md +51 -0
  100. passageway-0.3.0/docs/embedders/openai.md +5 -0
  101. passageway-0.3.0/docs/guides/agents.md +33 -0
  102. passageway-0.3.0/docs/guides/claude-code.md +42 -0
  103. passageway-0.3.0/docs/guides/evaluate.md +153 -0
  104. passageway-0.3.0/docs/guides/write-a-connector.md +152 -0
  105. passageway-0.3.0/docs/how-it-works.md +81 -0
  106. passageway-0.3.0/docs/index.md +61 -0
  107. passageway-0.3.0/docs/install.md +100 -0
  108. passageway-0.3.0/docs/javascripts/mermaid.js +12 -0
  109. passageway-0.3.0/docs/licence.md +46 -0
  110. passageway-0.3.0/docs/logo.svg +5 -0
  111. passageway-0.3.0/docs/measurements.history.json +12 -0
  112. passageway-0.3.0/docs/measurements.md +95 -0
  113. passageway-0.3.0/docs/models.history.json +38 -0
  114. passageway-0.3.0/docs/models.md +126 -0
  115. passageway-0.3.0/docs/reference/LICENSE +21 -0
  116. passageway-0.3.0/docs/reference/connector-protocol.md +56 -0
  117. passageway-0.3.0/docs/reference/connector-protocol.schema.json +58 -0
  118. passageway-0.3.0/docs/reference/corpus.md +3 -0
  119. passageway-0.3.0/docs/reference/embedder-protocol.md +99 -0
  120. passageway-0.3.0/docs/reference/embedder-protocol.schema.json +44 -0
  121. passageway-0.3.0/docs/reference/sdk.md +89 -0
  122. passageway-0.3.0/docs/roadmap.md +23 -0
  123. passageway-0.3.0/docs/roadmap.yml +263 -0
  124. passageway-0.3.0/docs/stylesheets/extra.css +514 -0
  125. passageway-0.3.0/docs/values.md +169 -0
  126. passageway-0.3.0/docs_hooks/charts.py +166 -0
  127. passageway-0.3.0/docs_hooks/roadmap.py +115 -0
  128. passageway-0.3.0/embedders/openai/README.md +63 -0
  129. passageway-0.3.0/embedders/openai/passageway_embedder_openai/__init__.py +1 -0
  130. passageway-0.3.0/embedders/openai/passageway_embedder_openai/__main__.py +3 -0
  131. passageway-0.3.0/embedders/openai/passageway_embedder_openai/embedder.py +227 -0
  132. passageway-0.3.0/embedders/openai/pyproject.toml +21 -0
  133. passageway-0.3.0/embedders/openai/tests/conftest.py +12 -0
  134. passageway-0.3.0/embedders/openai/tests/fake_openai.py +72 -0
  135. passageway-0.3.0/embedders/openai/tests/test_openai_embedder.py +300 -0
  136. passageway-0.3.0/hooks/hooks.json +15 -0
  137. passageway-0.3.0/mkdocs.yml +134 -0
  138. passageway-0.3.0/overrides/partials/header.html +75 -0
  139. passageway-0.3.0/passageway/__init__.py +0 -0
  140. passageway-0.3.0/passageway/chunk.py +68 -0
  141. passageway-0.3.0/passageway/config.py +315 -0
  142. passageway-0.3.0/passageway/embed.py +213 -0
  143. passageway-0.3.0/passageway/embed_command.py +258 -0
  144. passageway-0.3.0/passageway/eval/__init__.py +1 -0
  145. passageway-0.3.0/passageway/eval/__main__.py +5 -0
  146. passageway-0.3.0/passageway/eval/cases.py +93 -0
  147. passageway-0.3.0/passageway/eval/cli.py +123 -0
  148. passageway-0.3.0/passageway/eval/compare.py +138 -0
  149. passageway-0.3.0/passageway/eval/measure.py +81 -0
  150. passageway-0.3.0/passageway/eval/report.py +282 -0
  151. passageway-0.3.0/passageway/eval/run.py +121 -0
  152. passageway-0.3.0/passageway/index.py +248 -0
  153. passageway-0.3.0/passageway/init.py +60 -0
  154. passageway-0.3.0/passageway/models.py +202 -0
  155. passageway-0.3.0/passageway/protocol.py +229 -0
  156. passageway-0.3.0/passageway/rank.py +153 -0
  157. passageway-0.3.0/passageway/render.py +67 -0
  158. passageway-0.3.0/passageway/server.py +401 -0
  159. passageway-0.3.0/passageway/sessions.py +39 -0
  160. passageway-0.3.0/passageway/skip.py +34 -0
  161. passageway-0.3.0/passageway/sync.py +128 -0
  162. passageway-0.3.0/passageway/testing/__init__.py +0 -0
  163. passageway-0.3.0/passageway/testing/contract.py +17 -0
  164. passageway-0.3.0/passageway/testing/embedder_contract.py +37 -0
  165. passageway-0.3.0/passageway/testing/fake_connector.py +37 -0
  166. passageway-0.3.0/passageway/testing/fake_embedder.py +102 -0
  167. passageway-0.3.0/pyproject.toml +66 -0
  168. passageway-0.3.0/scripts/bump-version.sh +39 -0
  169. passageway-0.3.0/scripts/check-version.sh +36 -0
  170. passageway-0.3.0/scripts/post-to-notefeed.sh +26 -0
  171. passageway-0.3.0/scripts/publish-skills.sh +13 -0
  172. passageway-0.3.0/scripts/recall-hook.sh +87 -0
  173. passageway-0.3.0/scripts/release-notes.sh +38 -0
  174. passageway-0.3.0/scripts/test-recall-hook.sh +95 -0
  175. passageway-0.3.0/sdk/LICENSE +21 -0
  176. passageway-0.3.0/sdk/README.md +15 -0
  177. passageway-0.3.0/sdk/passageway_sdk/__init__.py +191 -0
  178. passageway-0.3.0/sdk/passageway_sdk/markdown.py +78 -0
  179. passageway-0.3.0/sdk/passageway_sdk/settings.py +44 -0
  180. passageway-0.3.0/sdk/passageway_sdk/web.py +142 -0
  181. passageway-0.3.0/sdk/pyproject.toml +24 -0
  182. passageway-0.3.0/sdk/tests/test_markdown.py +77 -0
  183. passageway-0.3.0/sdk/tests/test_sdk.py +296 -0
  184. passageway-0.3.0/sdk/tests/test_settings.py +31 -0
  185. passageway-0.3.0/sdk/tests/test_web.py +204 -0
  186. passageway-0.3.0/skills/create-passageway-connector/SKILL.md +96 -0
  187. passageway-0.3.0/skills/passageway/SKILL.md +62 -0
  188. passageway-0.3.0/skills/passageway-add-source/SKILL.md +51 -0
  189. passageway-0.3.0/skills/passageway-connect/SKILL.md +57 -0
  190. passageway-0.3.0/skills/passageway-evaluate/SKILL.md +98 -0
  191. passageway-0.3.0/skills/passageway-install/SKILL.md +109 -0
  192. passageway-0.3.0/skills/passageway-status/SKILL.md +35 -0
  193. passageway-0.3.0/tests/__init__.py +0 -0
  194. passageway-0.3.0/tests/test_agent_files.py +379 -0
  195. passageway-0.3.0/tests/test_charts.py +29 -0
  196. passageway-0.3.0/tests/test_chunk.py +38 -0
  197. passageway-0.3.0/tests/test_cli.py +99 -0
  198. passageway-0.3.0/tests/test_config.py +249 -0
  199. passageway-0.3.0/tests/test_contract.py +47 -0
  200. passageway-0.3.0/tests/test_dependabot.py +47 -0
  201. passageway-0.3.0/tests/test_docs.py +338 -0
  202. passageway-0.3.0/tests/test_e2e.py +38 -0
  203. passageway-0.3.0/tests/test_embed.py +64 -0
  204. passageway-0.3.0/tests/test_embed_command.py +287 -0
  205. passageway-0.3.0/tests/test_embed_factory.py +55 -0
  206. passageway-0.3.0/tests/test_embed_presets.py +132 -0
  207. passageway-0.3.0/tests/test_embedder_contract.py +62 -0
  208. passageway-0.3.0/tests/test_embedder_schema.py +67 -0
  209. passageway-0.3.0/tests/test_eval_cases.py +111 -0
  210. passageway-0.3.0/tests/test_eval_cli.py +284 -0
  211. passageway-0.3.0/tests/test_eval_compare.py +218 -0
  212. passageway-0.3.0/tests/test_eval_report.py +239 -0
  213. passageway-0.3.0/tests/test_eval_run.py +153 -0
  214. passageway-0.3.0/tests/test_index.py +84 -0
  215. passageway-0.3.0/tests/test_init.py +73 -0
  216. passageway-0.3.0/tests/test_live_models.py +53 -0
  217. passageway-0.3.0/tests/test_models.py +210 -0
  218. passageway-0.3.0/tests/test_models_cli.py +45 -0
  219. passageway-0.3.0/tests/test_oauth.py +194 -0
  220. passageway-0.3.0/tests/test_packages.py +50 -0
  221. passageway-0.3.0/tests/test_protocol.py +217 -0
  222. passageway-0.3.0/tests/test_rank.py +59 -0
  223. passageway-0.3.0/tests/test_release_scripts.py +334 -0
  224. passageway-0.3.0/tests/test_render.py +36 -0
  225. passageway-0.3.0/tests/test_repo_owner.py +14 -0
  226. passageway-0.3.0/tests/test_roadmap.py +82 -0
  227. passageway-0.3.0/tests/test_schema.py +112 -0
  228. passageway-0.3.0/tests/test_server.py +235 -0
  229. passageway-0.3.0/tests/test_sessions.py +47 -0
  230. passageway-0.3.0/tests/test_skip.py +22 -0
  231. passageway-0.3.0/tests/test_sync.py +215 -0
  232. passageway-0.3.0/tests/test_trust.py +52 -0
  233. passageway-0.3.0/uv.lock +2245 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "passageway",
3
+ "description": "Claude Code plugin: write connectors for passageway.",
4
+ "owner": {
5
+ "name": "Marcel Bruckner (Marceltov)"
6
+ },
7
+ "plugins": [
8
+ {
9
+ "name": "passageway",
10
+ "source": "./",
11
+ "description": "Skills for passageway: create a connector that feeds a source into passageway's index."
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "passageway",
3
+ "version": "0.3.0",
4
+ "description": "Retrieval for Claude over MCP: connectors feed passages, a relevance gate keeps it quiet when nothing fits. Ships the prompt hook and the skills /passageway (a general guide), /passageway-install (install and run it as a service), /passageway-connect (link Claude Code to a server), /passageway-add-source (index a source), /passageway-status (is it fine, and what to do), /passageway-evaluate (measure retrieval quality on the user's questions) and /create-passageway-connector (write a connector).",
5
+ "author": {
6
+ "name": "Marcel Bruckner"
7
+ },
8
+ "homepage": "https://passageway.marceltov.de/",
9
+ "repository": "https://github.com/getpassageway/passageway",
10
+ "license": "PolyForm-Noncommercial-1.0.0",
11
+ "keywords": [
12
+ "mcp",
13
+ "retrieval",
14
+ "rag",
15
+ "connectors",
16
+ "skills"
17
+ ]
18
+ }
@@ -0,0 +1,17 @@
1
+ .git
2
+ .github
3
+ .venv
4
+ **/.venv
5
+ **/__pycache__
6
+ **/.pytest_cache
7
+ site
8
+ docs
9
+ corpus
10
+ tests
11
+ **/tests
12
+ skills
13
+ hooks
14
+ scripts
15
+ .claude-plugin
16
+ CLAUDE.md
17
+ CHANGELOG.md
@@ -0,0 +1,2 @@
1
+ corpus/en/** linguist-generated=true
2
+ corpus/de/** linguist-generated=true
@@ -0,0 +1,62 @@
1
+ # Dependency bumps as pull requests with CI run. Security updates (switched on in the repository's settings) come at once and skip
2
+ # the cooldown; everything else waits two weeks after a release and comes grouped on Monday mornings. Patch and minor bumps merge by
3
+ # themselves once the required checks are green (.github/workflows/dependabot-automerge.yml); majors wait for review.
4
+ version: 2
5
+
6
+ updates:
7
+ - package-ecosystem: uv
8
+ directory: /
9
+ schedule:
10
+ interval: weekly
11
+ day: monday
12
+ time: "05:00"
13
+ timezone: Europe/Berlin
14
+ cooldown:
15
+ default-days: 14
16
+ open-pull-requests-limit: 5
17
+ commit-message:
18
+ prefix: Dependencies
19
+ labels: [dependencies]
20
+ groups:
21
+ minor-and-patch:
22
+ update-types: [minor, patch]
23
+
24
+ - package-ecosystem: github-actions
25
+ directory: /
26
+ schedule:
27
+ interval: weekly
28
+ day: monday
29
+ time: "05:00"
30
+ timezone: Europe/Berlin
31
+ cooldown:
32
+ default-days: 14
33
+ open-pull-requests-limit: 5
34
+ commit-message:
35
+ prefix: Dependencies
36
+ labels: [dependencies]
37
+ groups:
38
+ actions:
39
+ patterns: ["*"]
40
+
41
+ - package-ecosystem: docker
42
+ directory: /
43
+ schedule:
44
+ interval: weekly
45
+ day: monday
46
+ time: "05:00"
47
+ timezone: Europe/Berlin
48
+ cooldown:
49
+ default-days: 14
50
+ open-pull-requests-limit: 5
51
+ commit-message:
52
+ prefix: Dependencies
53
+ labels: [dependencies]
54
+ # the builder, model and runtime stages must share one Python minor: a new minor is a change to review
55
+ ignore:
56
+ - dependency-name: "python"
57
+ update-types: ["version-update:semver-major", "version-update:semver-minor"]
58
+ - dependency-name: "ghcr.io/astral-sh/uv"
59
+ update-types: ["version-update:semver-major", "version-update:semver-minor"]
60
+ groups:
61
+ minor-and-patch:
62
+ update-types: [minor, patch]
@@ -0,0 +1,25 @@
1
+ name: Audit
2
+
3
+ # Known vulnerabilities in what is shipped: the locked runtime dependencies of the core and of every connector package.
4
+ # A scheduled run, because an advisory appears without a commit. A red run means: upgrade the dependency. Dependabot security
5
+ # updates (.github/dependabot.yml) open the pull request for a fixed version as soon as an advisory is known; this run is the net
6
+ # for what it misses.
7
+ on:
8
+ schedule:
9
+ - cron: "17 5 * * *"
10
+ workflow_dispatch:
11
+ pull_request:
12
+ paths: [.github/workflows/audit.yml]
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ python:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v7
22
+ - uses: astral-sh/setup-uv@v10.3.3
23
+ # The locked versions of what runs in production: no dev group, none of the workspace's own packages.
24
+ - run: uv export -q --frozen --all-packages --no-dev --no-emit-workspace --no-hashes -o requirements-audit.txt
25
+ - run: uvx pip-audit -r requirements-audit.txt --no-deps --disable-pip
@@ -0,0 +1,120 @@
1
+ name: Checks
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ jobs:
7
+ # Which jobs a change needs. A job skipped here counts as passed for the ruleset; a change to this file runs everything.
8
+ # The test suite reads the docs, the skills and the workflows (tests/test_docs.py, tests/test_agent_files.py), so it runs
9
+ # for nearly everything: only files no test and no build reads leave it out.
10
+ changes:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ pull-requests: read
14
+ outputs:
15
+ test: ${{ steps.filter.outputs.test }}
16
+ docs: ${{ steps.filter.outputs.docs }}
17
+ image: ${{ steps.filter.outputs.image }}
18
+ plugin: ${{ steps.filter.outputs.plugin }}
19
+ steps:
20
+ - uses: actions/checkout@v7
21
+ - id: filter
22
+ uses: dorny/paths-filter@v4
23
+ with:
24
+ filters: |
25
+ test:
26
+ - '**'
27
+ - '!LICENSE'
28
+ - '!.gitignore'
29
+ - '!.github/workflows/pages.yml'
30
+ - '!.github/workflows/audit.yml'
31
+ - '!.github/workflows/dependabot-automerge.yml'
32
+ docs:
33
+ - '.github/workflows/checks.yml'
34
+ - 'docs/**'
35
+ - 'docs_hooks/**'
36
+ - 'mkdocs.yml'
37
+ - 'README.md'
38
+ - 'connectors/*/README.md'
39
+ - 'embedders/*/README.md'
40
+ - 'sdk/README.md'
41
+ - 'skills/**'
42
+ - 'scripts/publish-skills.sh'
43
+ - 'corpus/**'
44
+ image:
45
+ - '.github/workflows/checks.yml'
46
+ - 'Dockerfile'
47
+ - '.dockerignore'
48
+ - 'pyproject.toml'
49
+ - 'uv.lock'
50
+ - 'README.md'
51
+ - 'passageway/**'
52
+ - 'sdk/**'
53
+ - 'connectors/**'
54
+ - 'embedders/**'
55
+ plugin:
56
+ - '.github/workflows/checks.yml'
57
+ - '.claude-plugin/**'
58
+ - 'skills/**'
59
+ - 'hooks/**'
60
+ - 'scripts/recall-hook.sh'
61
+ - 'scripts/test-recall-hook.sh'
62
+ test:
63
+ needs: changes
64
+ if: needs.changes.outputs.test == 'true'
65
+ runs-on: ubuntu-latest
66
+ steps:
67
+ - uses: actions/checkout@v7
68
+ - uses: astral-sh/setup-uv@v10.3.3
69
+ - run: uv sync --frozen --all-packages
70
+ - run: uv run pytest -q
71
+ docs:
72
+ needs: changes
73
+ if: needs.changes.outputs.docs == 'true'
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - uses: actions/checkout@v7
77
+ - uses: astral-sh/setup-uv@v10.3.3
78
+ # mkdocs<2: Material 9 isn't compatible with MkDocs 2.0. --strict fails on broken links.
79
+ - run: uvx --with mkdocs-material==9.7.7 --with mkdocs-llmstxt==0.5.1 --with 'mkdocs<2' mkdocs build --strict
80
+ - name: The agent files are in the site
81
+ run: |
82
+ scripts/publish-skills.sh site
83
+ test -s site/llms.txt && test -s site/llms-full.txt
84
+ test -s site/SKILL.md && test -s site/skills/create-passageway-connector/SKILL.md && test -s site/skills/passageway-add-source/SKILL.md && test -s site/skills/passageway-install/SKILL.md
85
+ grep -q "Write a connector" site/llms-full.txt && grep -q "CATEGORY_DEPTH" site/llms-full.txt # the Wikipedia include made it in
86
+ grep -q "pw-timeline" site/roadmap/index.html && grep -q "Markdown connector" site/llms-full.txt # the roadmap timeline
87
+ grep -q "pw-header-links" site/index.html && grep -q "passageway.marceltov.de/llms-full.txt" site/index.html # the header links
88
+ # The plugin manifest, the skills and the hook, checked the way Claude Code loads them.
89
+ plugin:
90
+ needs: changes
91
+ if: needs.changes.outputs.plugin == 'true'
92
+ runs-on: ubuntu-latest
93
+ steps:
94
+ - uses: actions/checkout@v7
95
+ - uses: actions/setup-node@v7
96
+ with:
97
+ node-version: 22
98
+ - run: npm install -g @anthropic-ai/claude-code
99
+ - run: claude plugin validate .
100
+ - run: bash scripts/test-recall-hook.sh
101
+ image:
102
+ needs: changes
103
+ if: needs.changes.outputs.image == 'true'
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - uses: actions/checkout@v7
107
+ - name: Build the sidecar image
108
+ run: docker build -t passageway:ci .
109
+ - name: Start it with one fake source and ask it something
110
+ run: |
111
+ mkdir -p ci-config
112
+ echo '[{"id": "a", "title": "Lighthouses", "url": "http://x/a", "version": "1", "sections": [{"heading": null, "text": "Lighthouses guide ships safely into the harbour at night."}]}]' > ci-config/items.json
113
+ printf '[[connector]]\nname = "fake"\ncommand = ["python", "-m", "passageway.testing.fake_connector"]\nenv = { FAKE_ITEMS = "/config/items.json" }\n' > ci-config/passageway.toml
114
+ docker run -d --name pw -e PASSAGEWAY_LOGIN_PASSWORD=ci-only -p 8082:8082 -v "$PWD/ci-config:/config:ro" passageway:ci
115
+ for i in $(seq 1 60); do curl -s http://localhost:8082/health | grep -qE '"status": ?"ok"' && break; sleep 2; done
116
+ curl -s http://localhost:8082/health | grep -qE '"status": ?"ok"' || { docker logs pw; exit 1; }
117
+ curl -sf -H "Authorization: Bearer ci-only" -H "Content-Type: application/json" \
118
+ -d '{"prompt": "which lighthouses guide ships into the harbour at night"}' http://localhost:8082/recall | grep -q Lighthouses \
119
+ || { docker logs pw; exit 1; }
120
+ docker rm -f pw
@@ -0,0 +1,30 @@
1
+ name: CLA
2
+
3
+ # A pull request from outside waits until its author has accepted CLA.md by comment; signatures live on the cla-signatures branch, because
4
+ # the main ruleset keeps the action from writing to main. The maintainer, Claude (the co-author on commits made with it) and Dependabot need no agreement.
5
+ on:
6
+ issue_comment:
7
+ types: [created]
8
+ pull_request_target:
9
+ types: [opened, closed, synchronize]
10
+
11
+ permissions:
12
+ actions: write
13
+ contents: write
14
+ pull-requests: write
15
+ statuses: write
16
+
17
+ jobs:
18
+ cla:
19
+ if: github.event_name == 'pull_request_target' || github.event.issue.pull_request
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: contributor-assistant/github-action@v2.6.1
23
+ env:
24
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25
+ with:
26
+ path-to-document: https://github.com/getpassageway/passageway/blob/main/CLA.md
27
+ path-to-signatures: signatures.json
28
+ branch: cla-signatures
29
+ allowlist: Marceltov,claude,dependabot[bot]
30
+ custom-pr-sign-comment: I have read the CLA and I agree to it.
@@ -0,0 +1,22 @@
1
+ name: Dependabot auto-merge
2
+
3
+ # Dependabot's patch and minor bumps (security updates included) merge by themselves once the checks the main ruleset requires are
4
+ # green; majors wait for a person. `--auto` only waits because main requires those checks: without the ruleset it would merge at once.
5
+ on: pull_request
6
+
7
+ permissions:
8
+ contents: write
9
+ pull-requests: write
10
+
11
+ jobs:
12
+ automerge:
13
+ if: github.event.pull_request.user.login == 'dependabot[bot]'
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - id: meta
17
+ uses: dependabot/fetch-metadata@v3
18
+ - if: steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor'
19
+ run: gh pr merge --auto --merge "$PR"
20
+ env:
21
+ PR: ${{ github.event.pull_request.html_url }}
22
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,43 @@
1
+ name: Publish docs
2
+
3
+ # Build the documentation site from docs/ with Material for MkDocs and publish it
4
+ # to GitHub Pages. --strict fails the build on broken internal links.
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ paths: ["docs/**", "mkdocs.yml", "skills/**", "connectors/**/README.md", ".github/workflows/pages.yml", "scripts/publish-skills.sh"]
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+ pages: write
15
+ id-token: write
16
+
17
+ concurrency:
18
+ group: pages
19
+ cancel-in-progress: true
20
+
21
+ jobs:
22
+ build:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v7
26
+ - uses: astral-sh/setup-uv@v10.3.3
27
+ # mkdocs<2: Material 9 isn't compatible with MkDocs 2.0.
28
+ - run: uvx --with mkdocs-material==9.7.7 --with mkdocs-llmstxt==0.5.1 --with 'mkdocs<2' mkdocs build --strict
29
+ # MkDocs only builds docs/; the skills live in skills/, and an agent wants them as raw files.
30
+ - run: scripts/publish-skills.sh site
31
+ - uses: actions/upload-pages-artifact@v5
32
+ with:
33
+ path: site
34
+
35
+ deploy:
36
+ needs: build
37
+ runs-on: ubuntu-latest
38
+ environment:
39
+ name: github-pages
40
+ url: ${{ steps.deployment.outputs.page_url }}
41
+ steps:
42
+ - id: deployment
43
+ uses: actions/deploy-pages@v5
@@ -0,0 +1,141 @@
1
+ name: Release
2
+
3
+ # A v* tag creates a GitHub release, posts its notes to notefeed (once per tag), publishes every package to PyPI and builds the image.
4
+ #
5
+ # git tag -a v0.2.0 -m "A one-line headline for the release"
6
+ # git push origin v0.2.0
7
+ #
8
+ # The tag must equal the version in pyproject.toml (scripts/check-version.sh) and the tests must pass.
9
+ # The notes are the annotated tag's message, the pull requests merged since the previous release and
10
+ # install instructions (scripts/release-notes.sh). Without the NOTEFEED_FEED secret (forks) nothing is posted.
11
+
12
+ on:
13
+ push:
14
+ tags: ["v*"]
15
+ workflow_dispatch:
16
+ inputs:
17
+ tag:
18
+ description: "An existing tag to publish again, for example v0.2.0"
19
+ required: true
20
+
21
+ concurrency:
22
+ group: release-${{ inputs.tag || github.ref_name }}
23
+ cancel-in-progress: false
24
+
25
+ permissions:
26
+ contents: write
27
+
28
+ jobs:
29
+ release:
30
+ runs-on: ubuntu-latest
31
+ env:
32
+ TAG: ${{ inputs.tag || github.ref_name }}
33
+ GH_TOKEN: ${{ github.token }}
34
+ steps:
35
+ - uses: actions/checkout@v7
36
+ with:
37
+ ref: refs/tags/${{ inputs.tag || github.ref_name }}
38
+ fetch-depth: 0
39
+ fetch-tags: true
40
+
41
+ - name: Tag matches the project version
42
+ run: scripts/check-version.sh "$TAG"
43
+
44
+ - uses: astral-sh/setup-uv@v10.3.3
45
+ - name: Tests
46
+ run: |
47
+ uv sync --frozen --all-packages
48
+ uv run pytest -q
49
+
50
+ - name: Assemble the release notes
51
+ run: scripts/release-notes.sh "$TAG" > notes.md
52
+
53
+ - name: Create or update the release
54
+ run: |
55
+ if gh release view "$TAG" >/dev/null 2>&1; then
56
+ gh release edit "$TAG" --title "$TAG" --notes-file notes.md
57
+ else
58
+ gh release create "$TAG" --title "$TAG" --notes-file notes.md --verify-tag
59
+ fi
60
+
61
+ # Posts the notes of the release as published, plus a link to it. A re-run does not post twice. A failure here is
62
+ # shown but does not hold back the image.
63
+ - name: Post the notes to notefeed
64
+ continue-on-error: true
65
+ env:
66
+ NOTEFEED_FEED: ${{ secrets.NOTEFEED_FEED }}
67
+ NOTEFEED_FEED_PASSWORD: ${{ secrets.NOTEFEED_FEED_PASSWORD }}
68
+ run: |
69
+ gh release view "$TAG" --json body,url --jq '.body + "\n\n[The release on GitHub](" + .url + ")\n"' > notefeed.md
70
+ scripts/post-to-notefeed.sh "$TAG" notefeed.md
71
+
72
+ publish:
73
+ # Every package to PyPI at the tag's version (by token for the first release, then trusted publishing): the SDK first because the others depend on
74
+ # it, the core last because its extras pin the others. --check-url skips what is already on PyPI, so a re-run after a half-failed
75
+ # release carries on instead of failing. A published version can never be replaced, only yanked.
76
+ runs-on: ubuntu-latest
77
+ needs: release
78
+ environment: pypi
79
+ permissions:
80
+ contents: read
81
+ id-token: write
82
+ env:
83
+ TAG: ${{ inputs.tag || github.ref_name }}
84
+ steps:
85
+ - uses: actions/checkout@v7
86
+ with:
87
+ ref: refs/tags/${{ inputs.tag || github.ref_name }}
88
+ - uses: astral-sh/setup-uv@v10.3.3
89
+ - name: Build every package
90
+ run: uv build --all-packages
91
+ - name: Check the metadata
92
+ run: uvx twine check dist/*
93
+ - name: Publish
94
+ # The first release creates the nine projects with an account token, because a project must exist before PyPI accepts a
95
+ # trusted publisher for it. The follow-up removes this env block and the secret and goes back to trusted publishing.
96
+ env:
97
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
98
+ run: |
99
+ packages="passageway-sdk passageway-connector-confluence passageway-connector-llmstxt passageway-connector-markdown passageway-connector-sitemap passageway-connector-trilium passageway-connector-wikipedia passageway-embedder-openai passageway"
100
+ # An old tag run again by hand builds an old tree whose versions differ: refuse before the first upload, because
101
+ # a half-published release (the SDK up, the rest missing) cannot be repaired.
102
+ for package in $packages; do
103
+ [ "$(compgen -G "dist/${package//-/_}-${TAG#v}*" | wc -l)" -eq 2 ] || { echo "dist/ has no wheel and sdist of $package at ${TAG#v}" >&2; exit 1; }
104
+ done
105
+ for package in $packages; do
106
+ uv publish --check-url https://pypi.org/simple/ "dist/${package//-/_}-${TAG#v}"*
107
+ done
108
+
109
+ image:
110
+ # The sidecar image for amd64 and arm64, tagged with the version; latest moves only on a pushed version tag.
111
+ runs-on: ubuntu-latest
112
+ needs: release
113
+ permissions:
114
+ contents: read
115
+ packages: write
116
+ env:
117
+ TAG: ${{ inputs.tag || github.ref_name }}
118
+ steps:
119
+ - uses: actions/checkout@v7
120
+ with:
121
+ ref: refs/tags/${{ inputs.tag || github.ref_name }}
122
+ - uses: docker/setup-qemu-action@v4
123
+ - uses: docker/setup-buildx-action@v4
124
+ - uses: docker/login-action@v3
125
+ with:
126
+ registry: ghcr.io
127
+ username: ${{ github.actor }}
128
+ password: ${{ secrets.GITHUB_TOKEN }}
129
+ - name: Build and push
130
+ run: |
131
+ image=$(echo "ghcr.io/${{ github.repository_owner }}/passageway" | tr '[:upper:]' '[:lower:]')
132
+ tags="-t $image:${TAG#v}"
133
+ if [ "${{ github.event_name }}" = "push" ]; then tags="$tags -t $image:latest"; fi
134
+ docker buildx build --platform linux/amd64,linux/arm64 --build-arg APP_VERSION="${TAG#v}" $tags --push .
135
+ - name: Build and push the variant with a browser
136
+ # For the sitemap connector's RENDER: the same image plus Chromium, tagged <version>-browser and, on a pushed tag, browser.
137
+ run: |
138
+ image=$(echo "ghcr.io/${{ github.repository_owner }}/passageway" | tr '[:upper:]' '[:lower:]')
139
+ tags="-t $image:${TAG#v}-browser"
140
+ if [ "${{ github.event_name }}" = "push" ]; then tags="$tags -t $image:browser"; fi
141
+ docker buildx build --platform linux/amd64,linux/arm64 --build-arg APP_VERSION="${TAG#v}" --build-arg WITH_BROWSER=1 $tags --push .
@@ -0,0 +1,11 @@
1
+ docs/superpowers/
2
+ .superpowers/
3
+ .env
4
+ .DS_Store
5
+ .venv/
6
+ __pycache__/
7
+ .pytest_cache/
8
+ .models/
9
+ dist/
10
+ site/
11
+ .playwright-mcp/
@@ -0,0 +1,29 @@
1
+ # Contributor License Agreement
2
+
3
+ Adapted from the Apache Software Foundation's Individual Contributor License Agreement V2.2, with "the Foundation" replaced by "the Maintainer" (Marcel Bruckner, who owns and manages passageway). The Apache text is the standard one; the changes are the party, the removed nonprofit clause, and how you accept it.
4
+
5
+ passageway is licensed under the PolyForm Noncommercial License 1.0.0 and sold to companies under a separate licence, so the Maintainer must be able to license every line. This agreement is for your protection as a Contributor as well as the Maintainer's. It does not change your rights to use your own Contributions for any other purpose.
6
+
7
+ **How to accept:** comment `I have read the CLA and I agree to it.` on your first pull request. That comment, under your GitHub account, is your signature; nothing else is collected. Accepting once covers your present and future Contributions. A contributor who works for a company needs that company's permission first (section 4).
8
+
9
+ You accept and agree to the following terms and conditions for Your Contributions (present and future) that you submit to the Maintainer. Except for the license granted herein to the Maintainer and to recipients of software distributed by the Maintainer, You reserve all right, title, and interest in and to Your Contributions.
10
+
11
+ 1. Definitions.
12
+
13
+ "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with the Maintainer. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
14
+
15
+ "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to the Maintainer for inclusion in, or documentation of, any of the products owned or managed by the Maintainer (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Maintainer or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Maintainer for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
16
+
17
+ 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to the Maintainer and to recipients of software distributed by the Maintainer a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
18
+
19
+ 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to the Maintainer and to recipients of software distributed by the Maintainer a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
20
+
21
+ 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, or that your employer has waived such rights for your Contributions to the Maintainer.
22
+
23
+ 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
24
+
25
+ 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
26
+
27
+ 7. Should You wish to submit work that is not Your original creation, You may submit it to the Maintainer separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
28
+
29
+ 8. You agree to notify the Maintainer of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
@@ -0,0 +1,29 @@
1
+ # passageway
2
+
3
+ Retrieval for Claude over MCP: connectors (out-of-process programs speaking JSON Lines) feed passages to a core that indexes and ranks them. Documentation: https://passageway.marceltov.de/ (the pages are in `docs/`).
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ uv sync # the core and every connector package
9
+ uv run pytest -q # the whole suite, offline
10
+ uvx --with mkdocs-material==9.7.7 --with mkdocs-llmstxt==0.5.1 --with 'mkdocs<2' mkdocs build --strict # the docs, as CI builds them
11
+ PASSAGEWAY_LIVE=1 uv run pytest connectors/wikipedia/tests/test_wikipedia_live.py # opt-in, hits Wikipedia
12
+ ```
13
+
14
+ ## Working in this repository
15
+
16
+ - Every change is judged against `docs/values.md`, what passageway stands for; a review names the point it touches ("this breaks V2"). A change to that page needs my approval and says why.
17
+ - Every change starts from an issue. Branches, commits and pull request titles carry `PASSAGEWAY #<issue>:` (the `/ccp:ship-pr` flow). Dependabot's carry `Dependencies:` instead.
18
+ - Tests first: write the failing test, watch it fail, then the code. `tests/test_docs.py` keeps the docs in step with the code.
19
+ - CI is the gate, and I decide when a branch is finished and when it is merged. A `/ccp:ship-pr` request is the go-ahead for push and PR only, not for the merge. Merge only when I say "merge". The one exception: Dependabot's patch and minor bumps merge by themselves once CI is green (`.github/workflows/dependabot-automerge.yml`); its majors wait for me like any other PR.
20
+ - Every HTTPS client verifies against the operating system's trust store: `verify=` (httpx) or `context=` (urllib) is `truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)`, and `tests/test_trust.py` lists the client.
21
+ - Never print or write a secret into a file, a log or a commit. Credentials live in 1Password; GitHub secrets are set by piping from there.
22
+
23
+ ## Roadmap
24
+
25
+ The plan for where passageway is going, and for how trilium-recall folds into it, is `docs/roadmap.yml`, rendered as the timeline on the Roadmap page (`docs/roadmap.md`, `docs_hooks/roadmap.py`). Keep it true: mark a step done in the pull request that finishes it, and change the file in the pull request that changes the plan.
26
+
27
+ ## Releases
28
+
29
+ A `vX.Y.Z` tag is a release and must equal the version in `pyproject.toml`. The Release workflow creates the GitHub release and posts its notes to the notefeed feed; see `docs/development.md`.
@@ -0,0 +1,5 @@
1
+ # Contributing
2
+
3
+ Every change starts from an issue; see `docs/development.md` for the gates and `docs/values.md` for what a change is judged against.
4
+
5
+ passageway is licensed under the PolyForm Noncommercial License 1.0.0 and sold to companies under a separate licence, so the maintainer must be able to license every line. **A pull request from outside is merged only after its author accepts the [contributor licence agreement](CLA.md)** (a comment on the pull request; it is the standard Apache one, with the Maintainer as the party). Open an issue to discuss the change first, or write a connector or embedder of your own: the protocols and the SDK are MIT, and a connector in your own repository needs no agreement.
@@ -0,0 +1,61 @@
1
+ # passageway as a sidecar container: the server, the bundled connectors and embedders, and the default model baked in.
2
+ #
3
+ # Multi-stage: resolve the workspace into a venv with uv, fetch the pinned model and verify its checksums, then ship
4
+ # only the venv, the model and the code on python-slim.
5
+ #
6
+ # docker build -t passageway . (add --build-arg WITH_BROWSER=1 for the sitemap connector's RENDER)
7
+ # docker run -p 8082:8082 -v passageway-data:/data -v ./passageway.toml:/config/passageway.toml \
8
+ # -e PASSAGEWAY_LOGIN_PASSWORD=... passageway
9
+
10
+ # ---- builder: the venv with every workspace package ----
11
+ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
12
+ ENV UV_PYTHON_PREFERENCE=only-system \
13
+ UV_PYTHON_DOWNLOADS=never
14
+ WORKDIR /app
15
+ COPY pyproject.toml uv.lock README.md ./
16
+ COPY passageway/ passageway/
17
+ COPY sdk/ sdk/
18
+ COPY connectors/ connectors/
19
+ COPY embedders/ embedders/
20
+ ARG WITH_BROWSER=0
21
+ RUN uv sync --frozen --no-dev --all-packages $([ "$WITH_BROWSER" = 1 ] && echo --all-extras)
22
+
23
+ # ---- model: the default preset, pinned to a revision, every file verified by checksum ----
24
+ FROM python:3.12-slim-bookworm AS model
25
+ COPY --from=builder /app /app
26
+ RUN /app/.venv/bin/passageway model download --model-dir /models/e5-small
27
+
28
+ # ---- runtime ----
29
+ FROM python:3.12-slim-bookworm
30
+ # curl is used by the container healthcheck.
31
+ RUN apt-get update \
32
+ && apt-get install -y --no-install-recommends curl \
33
+ && rm -rf /var/lib/apt/lists/*
34
+ WORKDIR /app
35
+ COPY --from=builder /app /app
36
+ COPY --from=model /models /models
37
+ # --build-arg WITH_BROWSER=1: Chromium for the sitemap connector's RENDER (about 400 MB more).
38
+ ARG WITH_BROWSER=0
39
+ ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
40
+ RUN if [ "$WITH_BROWSER" = 1 ]; then /app/.venv/bin/playwright install --with-deps chromium && chmod -R a+rX /ms-playwright; fi
41
+ RUN useradd --system --create-home --uid 1000 passageway && mkdir -p /data /config && chown passageway /data
42
+ LABEL org.opencontainers.image.source="https://github.com/getpassageway/passageway" \
43
+ org.opencontainers.image.licenses="PolyForm-Noncommercial-1.0.0"
44
+ USER passageway
45
+
46
+ ARG APP_VERSION=dev
47
+ # glibc keeps freed embedding buffers otherwise: these hold a full build at about 300 MB instead of 400.
48
+ ENV PATH="/app/.venv/bin:$PATH" \
49
+ APP_VERSION=$APP_VERSION \
50
+ MALLOC_ARENA_MAX=2 \
51
+ MALLOC_TRIM_THRESHOLD_=65536 \
52
+ PASSAGEWAY_MODEL_DIR=/models/e5-small \
53
+ PASSAGEWAY_DATA_DIR=/data \
54
+ PASSAGEWAY_CONFIG=/config/passageway.toml \
55
+ PASSAGEWAY_HOST=0.0.0.0
56
+
57
+ VOLUME /data
58
+ EXPOSE 8082
59
+ HEALTHCHECK --interval=60s --timeout=5s --start-period=120s --retries=3 \
60
+ CMD curl -sf -o /dev/null http://localhost:8082/health || exit 1
61
+ CMD ["passageway"]