revit-api-docs 0.1.0__tar.gz → 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 (80) hide show
  1. revit_api_docs-0.3.0/CHANGELOG.md +263 -0
  2. revit_api_docs-0.3.0/PKG-INFO +239 -0
  3. revit_api_docs-0.3.0/README.md +205 -0
  4. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/api_parser/parse_chm.py +23 -12
  5. revit_api_docs-0.3.0/pipeline/build_data_v1_1.py +992 -0
  6. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/embedder/embed.py +64 -27
  7. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pyproject.toml +2 -2
  8. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/__init__.py +1 -1
  9. revit_api_docs-0.3.0/revit_api_docs/bm25.py +239 -0
  10. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/config.py +27 -0
  11. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/data.py +50 -11
  12. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/default_config.yaml +16 -2
  13. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/google.py +2 -1
  14. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/openai.py +4 -1
  15. revit_api_docs-0.3.0/revit_api_docs/environment.py +277 -0
  16. revit_api_docs-0.3.0/revit_api_docs/environment.yaml +306 -0
  17. revit_api_docs-0.3.0/revit_api_docs/reranker.py +595 -0
  18. revit_api_docs-0.3.0/revit_api_docs/retriever.py +1455 -0
  19. revit_api_docs-0.3.0/revit_api_docs/server.py +424 -0
  20. revit_api_docs-0.3.0/tests/conftest.py +210 -0
  21. revit_api_docs-0.3.0/tests/fixtures/retrieval_queries.yaml +614 -0
  22. revit_api_docs-0.3.0/tests/fixtures/retrieval_queries_v2.yaml +633 -0
  23. revit_api_docs-0.3.0/tests/test_bm25_index.py +285 -0
  24. revit_api_docs-0.3.0/tests/test_bm25_recall.py +136 -0
  25. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/tests/test_data.py +52 -2
  26. revit_api_docs-0.3.0/tests/test_environment.py +177 -0
  27. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/tests/test_package.py +1 -0
  28. revit_api_docs-0.3.0/tests/test_rerank.py +653 -0
  29. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/tests/test_retriever.py +89 -31
  30. revit_api_docs-0.3.0/tests/test_server.py +375 -0
  31. revit_api_docs-0.3.0/tests/test_shipped_db.py +160 -0
  32. revit_api_docs-0.3.0/tests/test_vector_search.py +364 -0
  33. revit_api_docs-0.1.0/CHANGELOG.md +0 -32
  34. revit_api_docs-0.1.0/PKG-INFO +0 -139
  35. revit_api_docs-0.1.0/README.md +0 -105
  36. revit_api_docs-0.1.0/revit_api_docs/reranker.py +0 -177
  37. revit_api_docs-0.1.0/revit_api_docs/retriever.py +0 -901
  38. revit_api_docs-0.1.0/revit_api_docs/server.py +0 -244
  39. revit_api_docs-0.1.0/tests/conftest.py +0 -75
  40. revit_api_docs-0.1.0/tests/test_server.py +0 -151
  41. revit_api_docs-0.1.0/tests/test_shipped_db.py +0 -75
  42. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/.gitignore +0 -0
  43. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/LICENSE +0 -0
  44. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/__init__.py +0 -0
  45. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/api_parser/__init__.py +0 -0
  46. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/api_parser/quality_agent.py +0 -0
  47. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/demo_dual_store.py +0 -0
  48. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/demo_production_real.py +0 -0
  49. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/demo_real_golden.py +0 -0
  50. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/demo_real_scoring.py +0 -0
  51. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/demo_scoring.py +0 -0
  52. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/demo_sdk_cleaning.py +0 -0
  53. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/embedder/__init__.py +0 -0
  54. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/knowledge_builder/__init__.py +0 -0
  55. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/run_all.ipynb +0 -0
  56. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/sdk_parser/__init__.py +0 -0
  57. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/sdk_parser/extract.py +0 -0
  58. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/pipeline/sdk_parser/quality_agent.py +0 -0
  59. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/__main__.py +0 -0
  60. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/__init__.py +0 -0
  61. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/__init__.py +0 -0
  62. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/base.py +0 -0
  63. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/llm_client.py +0 -0
  64. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/__init__.py +0 -0
  65. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/loader.py +0 -0
  66. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage1_no_html.md +0 -0
  67. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage1_system.md +0 -0
  68. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage1_with_html.md +0 -0
  69. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage2.md +0 -0
  70. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage2_system.md +0 -0
  71. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.rewrite_query.md +0 -0
  72. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.rewrite_query_system.md +0 -0
  73. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_extract_readme_system.md +0 -0
  74. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_extract_readme_user.md +0 -0
  75. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_golden_code.md +0 -0
  76. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_golden_code_system.md +0 -0
  77. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_file_batch.md +0 -0
  78. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_file_system.md +0 -0
  79. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_project.md +0 -0
  80. {revit_api_docs-0.1.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_project_system.md +0 -0
@@ -0,0 +1,263 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.0] - 2026-10-26
10
+
11
+ Vector hits now come back as the entries they describe and count also
12
+ without a reranker; reranking picks its provider from the keys that are set.
13
+ The data set `v1.1-data` adds constructor and interface member pages, and its
14
+ vector store lines up with the SQLite rows.
15
+
16
+ **Upgrading from 0.2.0** (`uvx --refresh revit-api-docs`): on the first start the server replaces an installed
17
+ `v1.0-data` (its `manifest.json` names the old release) with `v1.1-data`, a
18
+ download of 267 MB (all four files); a data directory without a
19
+ manifest (a hand-copied tree) is used as it is. With an embedding key and a
20
+ tree that still holds `v1.0-data`, the first vector query logs the warning
21
+ `vector_store_misaligned`: its record ids do not line up with the SQLite rows,
22
+ and hits are matched by entry name. Without any key nothing changes beyond the
23
+ new entries. Reranker choice: with only `COHERE_API_KEY` set Cohere still
24
+ reranks; with `TYPESAFE_API_KEY` set Jev now reranks without
25
+ `REVIT_API_DOCS_RERANK_PROVIDER=jev` (set the provider to `cohere` to keep
26
+ Cohere).
27
+
28
+ ### Added
29
+
30
+ - Data set `v1.1-data` (`RELEASE_TAG`; the download URL and SHA-256 list in
31
+ `data.py` follow it): the 27,596 entries of `v1.0-data` are kept unchanged
32
+ under the same ids, and 1,266 pages of the same reference are appended
33
+ (ids 27,597-28,862): 1,040 constructor pages (`XYZ(Double, Double, Double)
34
+ Constructor`, `Transaction(Document, String) Constructor`, overload lists)
35
+ and 226 members whose C# signature has no `public`, mostly interface
36
+ members (`IExternalEventHandler.Execute`, `IConnector.Origin`,
37
+ `IFailuresPreprocessor.PreprocessFailures`) and explicit interface
38
+ implementations. 28,862 entries in all. Source: `RevitAPI.chm` of the
39
+ Revit 2026.3 SDK, whose pages are the same set as the Revit 2026 reference
40
+ the first release was built from. The API vector store is rebuilt from the
41
+ new SQLite with the same model (`text-embedding-3-large`, 3072 dimensions):
42
+ one record per row and every record id is its row id, so the first vector
43
+ query no longer logs `vector_store_misaligned` (`download` reports
44
+ `aligned`). The SDK files (`revit_sdk.db`, `chromadb_code.tar.gz`) are the
45
+ `v1.0-data` ones.
46
+ - The vector documents are now `name : summary` (`v1.0-data` embedded mostly
47
+ the entry name alone: 21,952 of its 28,863 records); on the 223 test
48
+ queries this raised fused nDCG@5 without a reranker from 0.610 to 0.647
49
+ (task requests 0.438 to 0.459) and left it with Jev at 0.842 against 0.846
50
+ (task requests 0.778 against 0.794).
51
+ - `pipeline/build_data_v1_1.py` (sdist only): builds `v1.1-data` from the
52
+ `v1.0-data` SQLite and the CHM pages: appends the pages the base lacks
53
+ (pages whose name is in the base under another `full_id`, or whose content
54
+ is a base row's under a name the v1.0 rewrite changed, are listed and not
55
+ appended), runs the quality agent on the new rows only, re-embeds every
56
+ row, packages the four release files with `SHA256SUMS.txt` and checks the
57
+ vector store against the rows without an API call.
58
+
59
+ ### Fixed
60
+
61
+ - Vector search returned unrelated entries. The vector store of the
62
+ `v1.0-data` release numbers its 28,863 API records independently of the
63
+ 27,596 rows of `revit_api.db` (2 ids name the same entry in both), and hits
64
+ were looked up by record id. A hit is now matched to the row whose entry
65
+ name equals the record's `name` metadata (the row with the record's own id
66
+ when it carries that name; among rows sharing a name the one with the
67
+ record's `full_id` or `info`, else the lowest id). 27,591 records (95.6%)
68
+ reach 27,512 rows (99.7%); records without a row are dropped. The SDK sample
69
+ store's ids match its rows, and matching by project name keeps them. The
70
+ name map is built on the first vector query and kept in memory.
71
+ - Consistency probe: on the first vector query 50 records of each vector
72
+ collection are compared with SQLite. When fewer than 90% of the sampled ids
73
+ name the same entry as the row with that id, the warning
74
+ `vector_store_misaligned` is logged and hits are matched by name (`v1.0-data`:
75
+ 0/50 ids, 49/50 names). When fewer than 50% of the sampled names are found
76
+ either, vector search is off for the process and keyword search answers
77
+ alone. `revit-api-docs download` prints the check for the installed data set.
78
+ - A second retriever in the same process could not open the vector store
79
+ ("An instance of Chroma already exists ... with different settings"): each
80
+ ChromaDB client now gets its own `Settings` object.
81
+
82
+ ### Changed
83
+
84
+ - Hybrid ranking by reciprocal rank fusion: the vector hits and the BM25 hits,
85
+ `retrieval.api.top_k` (30) of each, are fused with score = sum of
86
+ 1 / (60 + rank), and the best 30 go to the reranker; without a reranker they
87
+ are cut to `top_k`. On equal scores a keyword hit comes first. Before, the
88
+ two lists were merged by distances on different scales, so without a
89
+ reranker vector-only hits never reached the top 5, and up to 60 candidates
90
+ went to the reranker. Without an embedding key the BM25 order and results
91
+ are unchanged. On 223 English test queries without reranking (measured on
92
+ `v1.1-data`): nDCG@5 0.557 with BM25 alone, 0.647 fused, and 0.355 -> 0.459
93
+ on the 113 multi-step task requests, whose answer is among the top 30 for
94
+ 82% instead of 72% of them.
95
+ - The default rerank provider is `auto`: Jev when `TYPESAFE_API_KEY` is set,
96
+ otherwise Cohere when `COHERE_API_KEY` is set, otherwise none.
97
+ `REVIT_API_DOCS_RERANK_PROVIDER` (now `auto`, `jev`, `cohere` or `none`)
98
+ still wins, and the `Rerank:` line names the provider that ran. README:
99
+ Jev is the recommended reranker, Cohere optional and the fallback for Jev.
100
+ - Cohere requests time out after 20 s instead of 10 s (the same as Jev); 10 s
101
+ cut off about 1% of calls.
102
+ - `search_revit_api` and `get_code_examples` are unchanged: names,
103
+ parameters and the first output line. The tool description now counts
104
+ 28,862 entries.
105
+ - CHM parser (`pipeline/api_parser/parse_chm.py`): `parse_single_html` and
106
+ `parse_all_api_html` take `keep_constructors` (default `False`, the old
107
+ behaviour); the C# signature no longer has to contain `public` (interface
108
+ members such as `void Execute(UIApplication app)` were skipped as a whole
109
+ page); a page with neither a signature nor a members table is still
110
+ skipped.
111
+ - `pipeline.embedder.embed.embed_api_data(..., resume=False,
112
+ document_template="NS")`: with `resume=True` the collection is kept and
113
+ only missing row ids are embedded; `document_template` picks the embedded
114
+ text per API row (`NS` `name : summary`, the default and the `v1.1-data`
115
+ store; `FS` `full_id : summary`, the earlier behaviour; `N` the entry name)
116
+ and is recorded in `meta.json`. `pipeline/build_data_v1_1.py
117
+ --document-template` passes it on (default `NS`).
118
+
119
+ ## [0.2.0] - 2026-10-26
120
+
121
+ Better candidates without any key, and an opt-in relevance check: BM25 keyword
122
+ search over an SQLite FTS5 index, optional Jev reranking with a calibrated
123
+ relevance per entry and abstention, a streamable HTTP transport, and curated
124
+ development-environment notes.
125
+
126
+ **Upgrading from 0.1.0** (`uvx --refresh revit-api-docs`): the first search
127
+ builds `sqlite/revit_api_fts.db` (an FTS5 index, 11.8 MB) next to the data set
128
+ in under a second. `search_revit_api` output starts with `Rerank: <reranker>;
129
+ data set: Revit 2026`. Abstention is new and opt-in:
130
+ `REVIT_API_DOCS_MIN_RELEVANCE` (Jev only) only decides whether to abstain and
131
+ drops no entry; the abstention line does not claim that the member is missing.
132
+
133
+ ### Added
134
+
135
+ - Jev rerank provider (TypeSafe System One, `POST https://api.typesafe.ai/v1/systemone`,
136
+ one `noul` question per candidate): `REVIT_API_DOCS_RERANK_PROVIDER=jev` with
137
+ `TYPESAFE_API_KEY`. Up to 30 candidates per request, 2 requests in flight,
138
+ 2 retries with backoff on 429/529/5xx/timeouts, 20 s timeout. A failed or
139
+ unconfigured Jev call falls back to Cohere (when `COHERE_API_KEY` is set) or
140
+ to no reranking.
141
+ - `search_revit_api` output starts with the reranker that ran
142
+ (`Rerank: jev | cohere | none`, plus `(unavailable: jev)` after a fallback);
143
+ Jev-ranked entries carry `Relevance: 0.00-1.00`.
144
+ - Abstention: with Jev and `REVIT_API_DOCS_MIN_RELEVANCE`, when no entry
145
+ reaches the threshold the output starts with "No entry in the Revit 2026
146
+ data set scored high enough for this query (best relevance x < y)" followed
147
+ by the low-scoring candidates. Other providers never abstain.
148
+ - Streamable HTTP transport: `revit-api-docs serve --transport http --host
149
+ 127.0.0.1 --port 8765` (endpoint `/mcp`); stdio remains the default. A
150
+ non-loopback `--host` logs a warning: there is no built-in authentication.
151
+ - Development-environment notes: a curated English corpus shipped with the
152
+ package (`environment.yaml`: target framework, SDK, manifest, reference
153
+ packages for Revit 2024-2027, each with a release range and a source URL),
154
+ matched by keywords. `search_revit_api` appends up to five matching notes,
155
+ also while the data set is still downloading and without any key;
156
+ `revit-api-docs environment [query] [--revit 2027]` prints them. The
157
+ `jev-data-handling` note points at TypeSafe's data processing terms.
158
+ - Retrieval regression fixture `tests/fixtures/retrieval_queries.yaml`: 60
159
+ English queries with verified gold rows in the v1.0-data reference (50
160
+ answerable, 10 not). `tests/test_bm25_recall.py` runs them against the
161
+ shipped data set when it is installed: gold in the BM25 top 30 for at least
162
+ 44 of 50 (measured 45), hit@5 at least 36 of 50 (measured 38), and a
163
+ non-empty candidate list for every unanswerable query. No network.
164
+ - A second regression fixture, `tests/fixtures/retrieval_queries_v2.yaml`: 60
165
+ more English queries (40 answerable, 20 not, 9 of those next to a real API,
166
+ such as a class name used as a member or a misspelling), none shared with
167
+ the first set. `tests/test_bm25_recall.py` runs both sets;
168
+ for this one: gold in the BM25 top 30 for at least 33 of 40 (measured 34),
169
+ hit@5 at least 25 of 40 (measured 27), and candidates for at least 19 of the
170
+ 20 unanswerable queries (measured 19).
171
+ - `close()` on the rerank providers releases their HTTP client.
172
+ - README: when to turn on Jev (`REVIT_API_DOCS_RERANK_PROVIDER=jev` with a
173
+ TypeSafe key; nDCG@5 0.675 -> 0.871 on the test queries, about $0.23 per
174
+ 1,000 queries), what a `REVIT_API_DOCS_MIN_RELEVANCE` of 0.15 filters and
175
+ what it does not, and why not 0.5. Defaults are unchanged.
176
+
177
+ ### Changed
178
+
179
+ - The `Rerank:` line also names the data set the entries come from: `Rerank:
180
+ <provider>[ (unavailable: ...)]; data set: Revit <version>`, the version
181
+ taken from the configuration (`revit_version`, 2026 for the v1.0-data
182
+ release). It stays the first line, or the second after an abstention line,
183
+ so an answer can cite the data set version next to a result; the tool
184
+ description and the server instructions say so. The `Rerank:` prefix is
185
+ unchanged.
186
+ - `REVIT_API_DOCS_MIN_RELEVANCE` only decides whether to abstain. When at
187
+ least one entry reaches it, the entries below it are no longer dropped:
188
+ every reranked entry comes back (up to `top_k`) with its `Relevance`, so a
189
+ correct entry scored just under the threshold stays in the list. Abstention
190
+ itself, and the output format, are unchanged.
191
+ - README and the `jev-rerank-provider` environment note describe the
192
+ threshold as a relevance filter: at 0.15 it filters out clearly unrelated
193
+ queries (not about Revit, types the data set does not have) and abstains
194
+ on about 2.5% of the queries that have an answer, but it cannot spot a
195
+ misspelt or misplaced member name, for which the closest real API usually
196
+ comes first and a compile check decides. "No entry scored high enough" is
197
+ described as "nothing relevant, or worded differently", not as "the member
198
+ does not exist"; the README no longer says the value is being validated.
199
+ - The rerank HTTP clients (Jev and Cohere) keep idle connections open for 5
200
+ minutes (`keepalive_expiry=300`; httpx closes them after 5 s), so a query
201
+ after a pause can reuse the connection instead of setting up TLS again.
202
+ The other connection limits stay at httpx's defaults.
203
+ - Keyword search over the API reference ranks with BM25 on an SQLite FTS5
204
+ index instead of LIKE substring scoring. The index is a separate file,
205
+ `sqlite/revit_api_fts.db` next to `revit_api.db` (which is never written),
206
+ built on first use in under a second and rebuilt when the source database's
207
+ SHA-256 or the index format changes; the installer neither downloads nor
208
+ flags it. Identifiers also match by their camel-case parts, so misspelt or
209
+ unknown names (`FiltredElementColector`) get candidates instead of "No API
210
+ entries found". Without vector search the keyword search now hands the
211
+ reranker `retrieval.api.top_k` (30) candidates instead of the requested
212
+ count; with vector search it adds the requested count, as before. A Python
213
+ whose sqlite3 lacks FTS5 keeps the LIKE scorer and logs one warning.
214
+ - The Jev and Cohere rerank providers keep one HTTP client per instance, and
215
+ with it the open connection, instead of building one per call. Against the
216
+ hosted Jev API a Jev-reranked `search_revit_api` call took about 2.1 s
217
+ before (10 candidates); now the first call of a process takes about 2.3 s
218
+ and later ones about 0.4 s (30 candidates).
219
+ - The abstention line no longer claims the class or member may not exist: it
220
+ says that no entry scored high enough and that either the member is absent
221
+ from this version or the data set has it under a different name or wording.
222
+ The tool description and server instructions say the same. A low best score
223
+ cannot tell a missing member from one the candidate search did not bring up.
224
+ - The embedding providers look up their API key before importing the SDK, so
225
+ keyword-only runs (no key) no longer import `openai`; `search` starts about
226
+ 2 s faster.
227
+ - `search` and `download` log plain `logger: message` lines to stderr at
228
+ WARNING (`-v` for INFO), with `httpx` request lines hidden; the MCP server's
229
+ logging is unchanged. The index/content mismatch of the shipped data set is
230
+ logged at INFO instead of WARNING.
231
+ - Download progress: on a terminal the line is redrawn in place; in host logs
232
+ and pipes one line per 10% instead of one per second.
233
+ - Tool descriptions and the server instructions state that queries are English
234
+ only.
235
+ - The Cohere reranker shares a provider interface with Jev; its requests and
236
+ its fall-back-to-input-order behaviour are unchanged.
237
+
238
+ ## [0.1.0] - 2026-09-20
239
+
240
+ First release, split out of the `revit-api-rag` repository (working-tree copy,
241
+ no git history).
242
+
243
+ ### Added
244
+
245
+ - MCP server `revit-api-docs` (stdio) with two read-only tools:
246
+ `search_revit_api(query, top_k)` and `get_code_examples(query, top_k)`.
247
+ - Data set as GitHub Release `v1.0-data` (Revit 2026 API reference SQLite,
248
+ SDK samples SQLite, two ChromaDB indexes); downloaded on first run into the
249
+ per-user data directory, SHA-256 verified, resumable. `REVIT_API_DOCS_DATA_DIR`
250
+ overrides the location; `revit-api-docs download` prefetches.
251
+ - Keyword search over SQLite works with no API key; an OpenAI-compatible
252
+ embedding key adds vector search, `COHERE_API_KEY` adds reranking. Embedding
253
+ or rerank failures fall back to keyword search instead of erroring.
254
+ - CLI: `serve` (default), `download`, `search <query> [--examples] [--top-k]`.
255
+ - Offline data pipeline (`pipeline/`, `uv sync --extra pipeline`) from the old
256
+ repository, importing the package's shared retriever, LLM client and prompts.
257
+ - CI (tests + build on Linux/Windows, Python 3.11/3.13) and PyPI Trusted
258
+ Publishing on version tags.
259
+
260
+ [Unreleased]: https://github.com/revitbridge/revit-api-docs/compare/v0.3.0...HEAD
261
+ [0.3.0]: https://github.com/revitbridge/revit-api-docs/compare/v0.2.0...v0.3.0
262
+ [0.2.0]: https://github.com/revitbridge/revit-api-docs/compare/v0.1.0...v0.2.0
263
+ [0.1.0]: https://github.com/revitbridge/revit-api-docs/releases/tag/v0.1.0
@@ -0,0 +1,239 @@
1
+ Metadata-Version: 2.5
2
+ Name: revit-api-docs
3
+ Version: 0.3.0
4
+ Summary: Revit API reference search for MCP hosts: local semantic + keyword lookup over the Revit 2026 API docs and SDK samples
5
+ Project-URL: Homepage, https://github.com/revitbridge/revit-api-docs
6
+ Project-URL: Issues, https://github.com/revitbridge/revit-api-docs/issues
7
+ Project-URL: Changelog, https://github.com/revitbridge/revit-api-docs/blob/main/CHANGELOG.md
8
+ Project-URL: Data, https://github.com/revitbridge/revit-api-docs/releases/tag/v1.1-data
9
+ Author: revitbridge
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: api-docs,bim,mcp,rag,revit
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: chromadb<2,>=1
23
+ Requires-Dist: httpx>=0.27
24
+ Requires-Dist: mcp<3,>=2
25
+ Requires-Dist: openai<3,>=1
26
+ Requires-Dist: pyyaml>=6
27
+ Provides-Extra: pipeline
28
+ Requires-Dist: beautifulsoup4>=4.12; extra == 'pipeline'
29
+ Requires-Dist: google-genai>=1; extra == 'pipeline'
30
+ Requires-Dist: tqdm>=4.66; extra == 'pipeline'
31
+ Requires-Dist: tree-sitter-c-sharp>=0.20; extra == 'pipeline'
32
+ Requires-Dist: tree-sitter>=0.20; extra == 'pipeline'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # revit-api-docs
36
+
37
+ Revit API reference search as an MCP server: two read-only tools over a local
38
+ copy of the Revit 2026 API documentation (28,862 classes, constructors,
39
+ methods, properties and enums) and the official SDK samples (153 projects).
40
+
41
+ **Optional.** It exists for models that do not know the Revit API well. If
42
+ your model already writes correct Revit code, you do not need it;
43
+ [revit-bridge](https://github.com/revitbridge/revit-bridge) works without it.
44
+ It never talks to Revit and it never calls a model itself.
45
+
46
+ Queries are **English only**: the corpus is the English API reference. A host
47
+ model that talks to its user in another language rewrites the request into
48
+ English API names or English task keywords before calling a tool.
49
+
50
+ ## Install
51
+
52
+ Prerequisites: Python 3.11+ with [`uv`](https://docs.astral.sh/uv/) (for
53
+ `uvx`), about 700 MB of disk for the data set, network for the first run.
54
+
55
+ **Claude Desktop** — `claude_desktop_config.json`:
56
+
57
+ ```json
58
+ {
59
+ "mcpServers": {
60
+ "revit-api-docs": {
61
+ "command": "uvx",
62
+ "args": ["revit-api-docs"]
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ **Claude Code**:
69
+
70
+ ```bash
71
+ claude mcp add revit-api-docs -- uvx revit-api-docs
72
+ ```
73
+
74
+ **Any MCP client** — run `uvx revit-api-docs` as a stdio server.
75
+
76
+ **Any MCP client over HTTP** — run the server with the MCP streamable HTTP
77
+ transport and point the client at `/mcp`:
78
+
79
+ ```bash
80
+ uvx revit-api-docs serve --transport http --host 127.0.0.1 --port 8765
81
+ ```
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "revit-api-docs": {
87
+ "type": "http",
88
+ "url": "http://127.0.0.1:8765/mcp"
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ (Claude Code: `claude mcp add --transport http revit-api-docs http://127.0.0.1:8765/mcp`.)
95
+ stdio stays the default. The HTTP transport has no built-in authentication:
96
+ keep it on a loopback address, or put it behind a reverse proxy that
97
+ authenticates; the server logs a warning when `--host` is not a loopback
98
+ address.
99
+
100
+ On the first start the server downloads the data set (267 MB, four files) from
101
+ this repository's [`v1.1-data` release](https://github.com/revitbridge/revit-api-docs/releases/tag/v1.1-data)
102
+ into `%LOCALAPPDATA%\revit-api-docs` (Windows) or `~/.local/share/revit-api-docs`
103
+ (Linux; `~/Library/Application Support/revit-api-docs` on macOS), verifies each
104
+ file's SHA-256 and unpacks the vector stores. Tool calls made while that runs
105
+ return a short progress message instead of results. To do it ahead of time:
106
+
107
+ ```bash
108
+ uvx revit-api-docs download
109
+ ```
110
+
111
+ From a checkout: `uv sync` then `uv run revit-api-docs`.
112
+
113
+ ## Use
114
+
115
+ Two tools, both read-only:
116
+
117
+ - `search_revit_api(query, top_k=10)` — API entries with signature, parameters
118
+ and remarks. Query with an API name (`Wall.Create`,
119
+ `FilteredElementCollector OfCategory`) or a short task (`create floor from
120
+ boundary`). The first line names the reranker that ordered the entries
121
+ (`jev`, `cohere` or `none`) and the data set they come from, for example
122
+ `Rerank: none; data set: Revit 2026`; after an abstention line it is the
123
+ second line. Development-environment questions (`target framework for
124
+ Revit 2027 add-in`) also get up to five curated environment notes
125
+ (framework, SDK, manifest, reference packages per Revit release, each with
126
+ its source); these ship with the package and work before the data set is
127
+ installed and without any key.
128
+ - `get_code_examples(query, top_k=3)` — C# from the SDK samples that use the
129
+ matching APIs, with the project name and the APIs each sample touches.
130
+
131
+ Without any API key the server answers from keyword search over the SQLite
132
+ reference: BM25 over a full-text index of entry names, IDs, summaries and
133
+ signatures, where identifiers also match by their camel-case parts, so a
134
+ misspelt or unknown name still gets candidates. The index (11.8 MB) is built
135
+ next to the data set on first use (under a second). With an embedding key it
136
+ adds semantic search over the vector store and fuses the two rankings by rank,
137
+ which helps most with task descriptions that do not name the API. With a
138
+ TypeSafe key it reranks the candidates with Jev, which returns a calibrated
139
+ relevance per entry; with only a Cohere key it reranks with Cohere. With a Jev
140
+ threshold set and no entry reaching it, the output starts with an abstention
141
+ line and then lists the candidates with their relevance, for reference. See
142
+ Configure.
143
+
144
+ Try it from a terminal (installs the data set if needed):
145
+
146
+ ```bash
147
+ uvx revit-api-docs search "Wall.Create"
148
+ uvx revit-api-docs search "rotate element around axis" --examples
149
+ uvx revit-api-docs environment --revit 2027 # environment notes, no data set needed
150
+ uvx revit-api-docs environment "target framework" # notes a query matches
151
+ ```
152
+
153
+ ## Configure
154
+
155
+ All settings are environment variables; there is no config file to edit.
156
+
157
+ | Variable | Default | Meaning |
158
+ |---|---|---|
159
+ | `REVIT_API_DOCS_DATA_DIR` | `%LOCALAPPDATA%\revit-api-docs` (Windows), `~/.local/share/revit-api-docs` (Linux), `~/Library/Application Support/revit-api-docs` (macOS) | Where the data set lives. An existing tree with `sqlite/` and `chromadb/` from the old `revit-api-rag` checkout works as is |
160
+ | `REVIT_API_DOCS_EMBEDDING_API_KEY` | *(unset)* | Key for the embedding endpoint; turns on semantic (vector) search. `OPENROUTER_API_KEY` is used when this is unset |
161
+ | `REVIT_API_DOCS_EMBEDDING_BASE_URL` | `https://openrouter.ai/api/v1` | Any OpenAI-compatible `/embeddings` endpoint |
162
+ | `REVIT_API_DOCS_EMBEDDING_MODEL` | `openai/text-embedding-3-large` | Must produce the same 3072-dimensional space the shipped vectors were built with (`text-embedding-3-large`); another model makes vector search return noise |
163
+ | `TYPESAFE_API_KEY` | *(unset)* | Key for TypeSafe System One (Jev), the recommended reranker: with the default provider `auto` setting this key is enough. At most 30 candidates per request, 2 requests in flight, 2 retries, 20 s timeout |
164
+ | `COHERE_API_KEY` | *(unset)* | Optional. Cohere `rerank-v3.5` (native REST API, 20 s timeout): reranks when it is the only rerank key set, and is the fallback for a failed Jev call when both are set |
165
+ | `REVIT_API_DOCS_RERANK_PROVIDER` | `auto` | `auto`, `jev`, `cohere` or `none`. `auto` reranks with Jev when `TYPESAFE_API_KEY` is set, otherwise with Cohere when `COHERE_API_KEY` is set, otherwise not at all; an explicit value wins. With Jev, a failed or unconfigured call falls back to Cohere when `COHERE_API_KEY` is set, otherwise to no reranking; the first output line says which one ran |
166
+ | `REVIT_API_DOCS_JEV_MODEL` | `jev-latest` | Jev model or alias; pin a version such as `jev-1.14.0` for reproducible results |
167
+ | `REVIT_API_DOCS_MIN_RELEVANCE` | *(unset)* | Probability 0-1 (`retrieval.api.min_relevance`). Only honoured while Jev ranks the results, and it only decides whether to abstain: no entry is dropped, every result keeps its `Relevance` line. When no entry reaches it, `search_revit_api` starts with "No entry in the Revit 2026 data set scored high enough for this query", notes that the member may be absent from this version or listed under a different name or wording, and lists the low-scoring candidates for reference. No effect with Cohere or without reranking. See "Reranking with Jev" below |
168
+ | `REVIT_API_DOCS_RELEASE_URL` | this repository's `v1.1-data` release | Mirror for the data files; the SHA-256 checks still apply |
169
+ | `HTTPS_PROXY` / `HTTP_PROXY` | *(unset)* | Proxy for the embedding and rerank calls |
170
+
171
+ Pass them through the `env` block of your MCP host's server entry.
172
+
173
+ Recommended setup: a `TYPESAFE_API_KEY` (Jev reranking), plus an embedding key
174
+ when requests describe multi-step tasks rather than name APIs. Without any key
175
+ the server runs on BM25 keyword search alone.
176
+
177
+ **Reranking with Jev.** Jev is the recommended reranker, and the default
178
+ provider (`auto`) uses it whenever `TYPESAFE_API_KEY` is set. Cohere is
179
+ optional: `auto` uses it when only `COHERE_API_KEY` is set, and with both keys
180
+ it is the fallback for a failed Jev call. Measured on `v1.0-data`: on 60
181
+ English test queries (50 with a known answer) over the keyword (BM25)
182
+ candidates, with no embedding key, Jev raised nDCG@5 from 0.675 to 0.871 and
183
+ never turned a correct top-5 answer into a miss. On 223 further queries over
184
+ the same candidates Jev reached an nDCG@5 of 0.788 against Cohere's 0.674. Input tokens cost about $0.23 per 1,000
185
+ queries; Cohere bills $2 per 1,000 searches.
186
+ `REVIT_API_DOCS_MIN_RELEVANCE` stays unset by default. Set to 0.15 it filters
187
+ out clearly unrelated queries (questions that are not about Revit, types this
188
+ data set does not have), abstaining on about 2.5% of the queries that do have
189
+ an answer (measured on `v1.0-data`). It cannot spot a misspelt or misplaced
190
+ member name: such a query usually gets the closest real API as the first
191
+ result, to be confirmed with a compile check. **Do not use 0.5**: it
192
+ abstained on 14% of the queries that have an answer. What TypeSafe keeps: see the `jev-data-handling` note
193
+ (`uvx revit-api-docs environment typesafe`).
194
+
195
+ **Vector search.** An embedding key (`REVIT_API_DOCS_EMBEDDING_API_KEY`, or
196
+ `OPENROUTER_API_KEY`) turns it on; each query then costs one embedding request
197
+ (about 0.9 s). The vector hits and the BM25 hits, 30 of each, are fused by
198
+ reciprocal rank (score = sum of 1 / (60 + rank)) and the best 30 go to the
199
+ reranker; without a reranker they are cut to `top_k`. On 223 English test
200
+ queries without reranking (measured on `v1.1-data`), fusion raises nDCG@5
201
+ from 0.557 (BM25 alone) to 0.647, and on the 113 of them that describe a
202
+ multi-step task from 0.355 to 0.459, with an answer among the top 30 for 82%
203
+ of those instead of 72%. Each
204
+ vector hit is matched to its entry by name. On the first vector query the
205
+ server samples 50 records of each vector collection: when the record ids do
206
+ not line up with the rows it logs the warning `vector_store_misaligned` and
207
+ keeps matching by name (the older `v1.0-data` vector store numbers its records
208
+ differently from the rows of `revit_api.db`; `v1.1-data` is aligned and logs
209
+ nothing); when the names are not found either, it turns vector search off
210
+ until the server restarts and answers from keyword search. `revit-api-docs download`
211
+ prints the same check for the installed data set.
212
+
213
+ Privacy: with an embedding, Cohere or TypeSafe key the query text and the
214
+ candidate API entries (public documentation) are sent to that provider. Keep
215
+ queries to API names and generic task descriptions, in English.
216
+
217
+ Data set (`v1.1-data`): the API reference comes from `RevitAPI.chm` of the
218
+ Revit 2026.3 SDK (the same pages as the Revit 2026 reference) and includes
219
+ constructor pages and interface members such as
220
+ `IExternalEventHandler.Execute`: 28,862 entries, of which the 27,596 of
221
+ `v1.0-data` are unchanged under the same ids. The SDK samples (153 projects)
222
+ come from the Revit 2026 SDK. The SQLite databases and ChromaDB indexes were
223
+ built with the pipeline in `pipeline/` (`uv sync --extra pipeline`; needs the
224
+ CHM, the SDK and OpenRouter/Cohere keys in the environment). `v1.1-data` was
225
+ built from `v1.0-data` with `uv run python -m pipeline.build_data_v1_1
226
+ --html-dir <CHM html dir> --base-db <v1.0-data dir>/sqlite/revit_api.db`, which
227
+ appends the pages `v1.0-data` lacked and rebuilds the API vector store so that
228
+ every record id is its row id. The server does not need any of that.
229
+
230
+ Development:
231
+
232
+ ```bash
233
+ uv sync
234
+ uv run pytest
235
+ uv build
236
+ uvx --from . revit-api-docs search "Wall.Create"
237
+ ```
238
+
239
+ License: MIT. Issues and discussion: <https://github.com/revitbridge/revit-api-docs/issues>.