vera-doc 0.2.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.
- vera_doc-0.2.0/.gitignore +12 -0
- vera_doc-0.2.0/PKG-INFO +510 -0
- vera_doc-0.2.0/README.md +490 -0
- vera_doc-0.2.0/pyproject.toml +33 -0
- vera_doc-0.2.0/src/vera/__init__.py +39 -0
- vera_doc-0.2.0/src/vera/collection.py +922 -0
- vera_doc-0.2.0/src/vera/core/__init__.py +1 -0
- vera_doc-0.2.0/src/vera/core/access.py +124 -0
- vera_doc-0.2.0/src/vera/core/embeddings.py +87 -0
- vera_doc-0.2.0/src/vera/core/figures.py +144 -0
- vera_doc-0.2.0/src/vera/core/inspection.py +20 -0
- vera_doc-0.2.0/src/vera/core/schema.py +169 -0
- vera_doc-0.2.0/src/vera/core/search.py +257 -0
- vera_doc-0.2.0/src/vera/core/validation.py +225 -0
- vera_doc-0.2.0/src/vera/corpus.py +517 -0
- vera_doc-0.2.0/src/vera/database.py +731 -0
- vera_doc-0.2.0/src/vera/document.py +383 -0
- vera_doc-0.2.0/src/vera/models.py +162 -0
vera_doc-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vera-doc
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Vector-Embedded Retrieval Archive document and retrieval engine
|
|
5
|
+
Project-URL: Homepage, https://github.com/dkylewillis/vera
|
|
6
|
+
Project-URL: Repository, https://github.com/dkylewillis/vera
|
|
7
|
+
Project-URL: Specification, https://github.com/dkylewillis/vera/blob/main/docs/vera-spec-v0.2.md
|
|
8
|
+
Author: Kyle Willis
|
|
9
|
+
License: Apache-2.0
|
|
10
|
+
Keywords: embeddings,rag,semantic-search,sqlite,vector-database
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Requires-Dist: numpy>=1.24
|
|
17
|
+
Provides-Extra: ml
|
|
18
|
+
Requires-Dist: sentence-transformers>=2.7; extra == 'ml'
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# vera-doc
|
|
22
|
+
|
|
23
|
+
`vera-doc` is VERA's embedded storage and search engine. It stores ready-made
|
|
24
|
+
text chunks in a portable SQLite `.vera` file and provides transactional CRUD,
|
|
25
|
+
embeddings, metadata filters, keyword search, vector search, hybrid search,
|
|
26
|
+
corpus search, and rebuildable library indexes.
|
|
27
|
+
|
|
28
|
+
It intentionally contains no PDF parsing, OCR, source extraction, chunking,
|
|
29
|
+
MCP, CLI, or desktop dependencies. Applications extract and chunk content
|
|
30
|
+
before calling `vera-doc`. The separate `vera-extract` package provides the
|
|
31
|
+
standard PDF pipeline.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python -m pip install vera-doc
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Python 3.10 or newer is required. The default hashing embedder needs no model
|
|
40
|
+
download or API key.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from vera import ChunkRecord, VeraDatabase
|
|
46
|
+
|
|
47
|
+
records = [
|
|
48
|
+
ChunkRecord(
|
|
49
|
+
id="pipe-requirement",
|
|
50
|
+
text="The minimum pipe diameter is 12 inches.",
|
|
51
|
+
metadata={
|
|
52
|
+
"source_filename": "manual.pdf",
|
|
53
|
+
"page_start": 42,
|
|
54
|
+
"heading_path": "Chapter 4 > Pipe Design",
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
with VeraDatabase.create("manual.vera") as database:
|
|
60
|
+
database.add(records)
|
|
61
|
+
|
|
62
|
+
with VeraDatabase.open("manual.vera") as database:
|
|
63
|
+
results = database.search(
|
|
64
|
+
text="minimum pipe size",
|
|
65
|
+
mode="hybrid",
|
|
66
|
+
top_k=5,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
for result in results:
|
|
70
|
+
print(result.score, result.record.text)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`VeraDatabase.open()` is read-only by default. Use `mode="write"` when adding,
|
|
74
|
+
updating, or deleting records.
|
|
75
|
+
|
|
76
|
+
## What is stored in a `.vera` file?
|
|
77
|
+
|
|
78
|
+
A VERA 0.2 file is one SQLite database containing:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
manual.vera
|
|
82
|
+
├── vera_metadata Format, embedding configuration, archive metadata
|
|
83
|
+
├── chunks Final searchable text and JSON metadata
|
|
84
|
+
├── embeddings One float32 vector per chunk
|
|
85
|
+
├── chunks_fts SQLite FTS5 keyword index
|
|
86
|
+
├── attachments Optional opaque binary payloads
|
|
87
|
+
└── chunk_attachments Typed links from chunks to attachments
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The core schema is conceptually:
|
|
91
|
+
|
|
92
|
+
```sql
|
|
93
|
+
CREATE TABLE chunks (
|
|
94
|
+
chunk_id TEXT PRIMARY KEY,
|
|
95
|
+
text TEXT NOT NULL,
|
|
96
|
+
metadata_json TEXT NOT NULL,
|
|
97
|
+
created_at TEXT NOT NULL,
|
|
98
|
+
updated_at TEXT NOT NULL
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE TABLE embeddings (
|
|
102
|
+
chunk_id TEXT PRIMARY KEY REFERENCES chunks(chunk_id),
|
|
103
|
+
model_name TEXT NOT NULL,
|
|
104
|
+
model_dimension INTEGER NOT NULL,
|
|
105
|
+
vector BLOB NOT NULL,
|
|
106
|
+
vector_format TEXT NOT NULL,
|
|
107
|
+
created_at TEXT NOT NULL
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
CREATE TABLE attachments (
|
|
111
|
+
attachment_id TEXT PRIMARY KEY,
|
|
112
|
+
mime_type TEXT NOT NULL,
|
|
113
|
+
filename TEXT,
|
|
114
|
+
data BLOB NOT NULL,
|
|
115
|
+
hash TEXT NOT NULL,
|
|
116
|
+
metadata_json TEXT NOT NULL,
|
|
117
|
+
created_at TEXT NOT NULL
|
|
118
|
+
);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Pages, headings, citations, bounding boxes, and source identity are optional
|
|
122
|
+
chunk metadata. Original files and extracted images may be stored as opaque
|
|
123
|
+
attachments. `vera-doc` stores these values but does not interpret or extract
|
|
124
|
+
them.
|
|
125
|
+
|
|
126
|
+
## Public objects
|
|
127
|
+
|
|
128
|
+
### `ChunkRecord`
|
|
129
|
+
|
|
130
|
+
The only indexed record type:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
ChunkRecord(
|
|
134
|
+
id: str,
|
|
135
|
+
text: str,
|
|
136
|
+
metadata: Mapping[str, JSONValue] = {},
|
|
137
|
+
vector: Sequence[float] | None = None,
|
|
138
|
+
attachments: tuple[AttachmentRef, ...] = (),
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- `id` is a non-empty caller-controlled identifier.
|
|
143
|
+
- `text` is final chunk text. `vera-doc` never splits or cleans it.
|
|
144
|
+
- `metadata` may contain any JSON-compatible object.
|
|
145
|
+
- `vector` may contain a precomputed embedding. When omitted, the configured
|
|
146
|
+
embedding function embeds `text`.
|
|
147
|
+
- `attachments` links the chunk to stored attachments.
|
|
148
|
+
|
|
149
|
+
Records are immutable. IDs, text, metadata, vectors, and attachment references
|
|
150
|
+
are validated when the object is created or written.
|
|
151
|
+
|
|
152
|
+
### `AttachmentRecord`
|
|
153
|
+
|
|
154
|
+
An optional opaque binary payload:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
AttachmentRecord(
|
|
158
|
+
id: str,
|
|
159
|
+
data: bytes,
|
|
160
|
+
media_type: str,
|
|
161
|
+
filename: str | None = None,
|
|
162
|
+
checksum: str | None = None,
|
|
163
|
+
metadata: Mapping[str, JSONValue] = {},
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The SHA-256 checksum is computed automatically. If a checksum is supplied, it
|
|
168
|
+
must match the bytes. Attachments are not embedded or searchable.
|
|
169
|
+
|
|
170
|
+
### `AttachmentRef`
|
|
171
|
+
|
|
172
|
+
Links a chunk to an attachment:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
AttachmentRef(
|
|
176
|
+
attachment_id="source-pdf",
|
|
177
|
+
role="source",
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The role is caller-defined. Common roles include `source`, `figure`, and
|
|
182
|
+
`viewer_data`.
|
|
183
|
+
|
|
184
|
+
### `QueryResult`
|
|
185
|
+
|
|
186
|
+
Returned by `VeraDatabase.search()`:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
QueryResult(
|
|
190
|
+
record: ChunkRecord,
|
|
191
|
+
score: float,
|
|
192
|
+
semantic_score: float | None,
|
|
193
|
+
keyword_score: float | None,
|
|
194
|
+
)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Call `result.as_dict()` for a JSON-compatible result without the raw vector.
|
|
198
|
+
|
|
199
|
+
### `EmbeddingFunction`
|
|
200
|
+
|
|
201
|
+
A structural protocol for custom embedders:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
class EmbeddingFunction:
|
|
205
|
+
model_name: str
|
|
206
|
+
dimension: int
|
|
207
|
+
|
|
208
|
+
def embed(self, texts: list[str]) -> numpy.ndarray:
|
|
209
|
+
...
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The same model and dimension must be used for stored records and text queries.
|
|
213
|
+
|
|
214
|
+
## `VeraDatabase` methods
|
|
215
|
+
|
|
216
|
+
### Create and open
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
VeraDatabase.create(
|
|
220
|
+
path,
|
|
221
|
+
*,
|
|
222
|
+
embedding_function=None,
|
|
223
|
+
model="hashing",
|
|
224
|
+
metadata=None,
|
|
225
|
+
overwrite=False,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
VeraDatabase.open(
|
|
229
|
+
path,
|
|
230
|
+
*,
|
|
231
|
+
mode="read",
|
|
232
|
+
embedding_function=None,
|
|
233
|
+
)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`create()` publishes a valid database atomically. It raises `FileExistsError`
|
|
237
|
+
unless `overwrite=True`. Both methods return context managers.
|
|
238
|
+
|
|
239
|
+
### Add records
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
database.add(records)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Inserts an iterable of `ChunkRecord` objects. Existing IDs raise
|
|
246
|
+
`DuplicateRecordError`. The chunk row, embedding, FTS row, and attachment links
|
|
247
|
+
are written in one transaction.
|
|
248
|
+
|
|
249
|
+
### Insert or replace records
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
database.upsert(records)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Inserts new IDs and replaces existing records. Replacement updates text,
|
|
256
|
+
metadata, embedding, keyword index, and attachment links together.
|
|
257
|
+
|
|
258
|
+
### Retrieve records
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
database.get(
|
|
262
|
+
ids=None,
|
|
263
|
+
*,
|
|
264
|
+
where=None,
|
|
265
|
+
limit=None,
|
|
266
|
+
)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Returns `ChunkRecord` objects, including their vectors and attachment links.
|
|
270
|
+
`where` performs exact equality matching on top-level metadata keys:
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
records = database.get(where={"discipline": "civil"})
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Delete records
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
deleted_count = database.delete(
|
|
280
|
+
ids=None,
|
|
281
|
+
*,
|
|
282
|
+
where=None,
|
|
283
|
+
)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Deleting a chunk also deletes its embedding, keyword-index row, and attachment
|
|
287
|
+
links. It does not delete the attachments themselves.
|
|
288
|
+
|
|
289
|
+
### Search
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
database.search(
|
|
293
|
+
*,
|
|
294
|
+
text=None,
|
|
295
|
+
vector=None,
|
|
296
|
+
mode="hybrid",
|
|
297
|
+
where=None,
|
|
298
|
+
top_k=10,
|
|
299
|
+
)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Supported modes:
|
|
303
|
+
|
|
304
|
+
- `keyword` uses SQLite FTS5 and BM25 ranking.
|
|
305
|
+
- `semantic` uses cosine similarity against stored vectors.
|
|
306
|
+
- `hybrid` independently normalizes semantic and keyword scores, then combines
|
|
307
|
+
them with equal weight.
|
|
308
|
+
|
|
309
|
+
Semantic search accepts query `text` or a compatible precomputed `vector`.
|
|
310
|
+
Keyword and hybrid search require text.
|
|
311
|
+
|
|
312
|
+
### Attachments
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
database.put_attachments(attachments, upsert=False)
|
|
316
|
+
attachment = database.get_attachment("source-pdf")
|
|
317
|
+
database.delete_attachment("source-pdf")
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Referenced attachments cannot be deleted until their chunk links are removed.
|
|
321
|
+
Missing attachments raise `RecordNotFoundError`.
|
|
322
|
+
|
|
323
|
+
### Archive metadata
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
metadata = database.metadata
|
|
327
|
+
database.set_metadata({"project": "stormwater"})
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Archive metadata is a JSON-compatible object separate from per-chunk metadata.
|
|
331
|
+
|
|
332
|
+
### Transactions
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
with database.transaction():
|
|
336
|
+
database.put_attachments(attachments)
|
|
337
|
+
database.add(records)
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
The entire block commits together. An exception rolls it back. Nested
|
|
341
|
+
transactions are intentionally rejected.
|
|
342
|
+
|
|
343
|
+
### Inspection and validation
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
info = database.inspect()
|
|
347
|
+
report = database.validate()
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Inspection reports the format, model, dimension, counts, and archive metadata.
|
|
351
|
+
Validation checks SQLite integrity, required tables and metadata, embedding and
|
|
352
|
+
FTS parity, vector lengths, JSON payloads, foreign keys, and attachment hashes.
|
|
353
|
+
|
|
354
|
+
### Close
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
database.close()
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Context managers call `close()` automatically.
|
|
361
|
+
|
|
362
|
+
## Exceptions
|
|
363
|
+
|
|
364
|
+
- `DuplicateRecordError` — `add()` received an existing ID.
|
|
365
|
+
- `RecordNotFoundError` — a chunk references an unknown attachment or a
|
|
366
|
+
requested attachment does not exist.
|
|
367
|
+
- `ReadOnlyError` — a mutation was attempted after a read-only open.
|
|
368
|
+
- Standard `FileNotFoundError`, `FileExistsError`, `TypeError`, and
|
|
369
|
+
`ValueError` are used for ordinary path and validation failures.
|
|
370
|
+
|
|
371
|
+
## Optional attachments example
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
from vera import (
|
|
375
|
+
AttachmentRecord,
|
|
376
|
+
AttachmentRef,
|
|
377
|
+
ChunkRecord,
|
|
378
|
+
VeraDatabase,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
source = AttachmentRecord(
|
|
382
|
+
id="source-pdf",
|
|
383
|
+
data=pdf_bytes,
|
|
384
|
+
media_type="application/pdf",
|
|
385
|
+
filename="manual.pdf",
|
|
386
|
+
metadata={"role": "source"},
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
chunk = ChunkRecord(
|
|
390
|
+
id="chunk-1",
|
|
391
|
+
text="The final, already-extracted chunk.",
|
|
392
|
+
metadata={"page_start": 42},
|
|
393
|
+
attachments=(AttachmentRef("source-pdf", role="source"),),
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
with VeraDatabase.create("manual.vera") as database:
|
|
397
|
+
with database.transaction():
|
|
398
|
+
database.put_attachments([source])
|
|
399
|
+
database.add([chunk])
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## Custom embeddings
|
|
403
|
+
|
|
404
|
+
```python
|
|
405
|
+
import numpy as np
|
|
406
|
+
|
|
407
|
+
from vera import ChunkRecord, VeraDatabase
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
class MyEmbedder:
|
|
411
|
+
model_name = "example/my-embedder"
|
|
412
|
+
dimension = 2
|
|
413
|
+
|
|
414
|
+
def embed(self, texts: list[str]) -> np.ndarray:
|
|
415
|
+
return np.asarray([[1.0, 0.0] for _ in texts], dtype=np.float32)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
embedder = MyEmbedder()
|
|
419
|
+
|
|
420
|
+
with VeraDatabase.create(
|
|
421
|
+
"custom.vera",
|
|
422
|
+
embedding_function=embedder,
|
|
423
|
+
) as database:
|
|
424
|
+
database.add([ChunkRecord(id="one", text="Example text")])
|
|
425
|
+
|
|
426
|
+
with VeraDatabase.open(
|
|
427
|
+
"custom.vera",
|
|
428
|
+
embedding_function=embedder,
|
|
429
|
+
) as database:
|
|
430
|
+
results = database.search(text="example", mode="semantic")
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Callers may instead provide `ChunkRecord.vector` and search with a query
|
|
434
|
+
vector.
|
|
435
|
+
|
|
436
|
+
## Libraries of `.vera` files
|
|
437
|
+
|
|
438
|
+
`VeraCorpus` searches a directory of `.vera` files as one corpus:
|
|
439
|
+
|
|
440
|
+
```python
|
|
441
|
+
from vera import VeraCorpus
|
|
442
|
+
|
|
443
|
+
with VeraCorpus.open("./library", recursive=True) as corpus:
|
|
444
|
+
results = corpus.search("detention requirements", top_k=5)
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
For larger libraries, create a persistent derived index:
|
|
448
|
+
|
|
449
|
+
```python
|
|
450
|
+
from vera import (
|
|
451
|
+
build_library_index,
|
|
452
|
+
library_index_status,
|
|
453
|
+
update_library_index,
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
build_library_index("./library", recursive=True)
|
|
457
|
+
print(library_index_status("./library"))
|
|
458
|
+
update_library_index("./library")
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
The `.vera-index/` directory is rebuildable. Individual `.vera` files remain
|
|
462
|
+
the source of truth.
|
|
463
|
+
|
|
464
|
+
## Legacy document API
|
|
465
|
+
|
|
466
|
+
`VeraDocument` remains a read-oriented compatibility facade for VERA 0.1,
|
|
467
|
+
the CLI, the desktop app, and citation-oriented workflows:
|
|
468
|
+
|
|
469
|
+
```python
|
|
470
|
+
from vera import VeraDocument
|
|
471
|
+
|
|
472
|
+
with VeraDocument.open("manual.vera") as document:
|
|
473
|
+
results = document.search(
|
|
474
|
+
"detention requirements",
|
|
475
|
+
mode="hybrid",
|
|
476
|
+
top_k=5,
|
|
477
|
+
context_chunks=1,
|
|
478
|
+
)
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
New applications that create or mutate databases should use `VeraDatabase`.
|
|
482
|
+
|
|
483
|
+
## Package source structure
|
|
484
|
+
|
|
485
|
+
```text
|
|
486
|
+
src/vera/
|
|
487
|
+
├── __init__.py Public exports
|
|
488
|
+
├── models.py Chunk, attachment, and query value objects
|
|
489
|
+
├── database.py Transactional vector-database facade
|
|
490
|
+
├── document.py Legacy/read-oriented compatibility facade
|
|
491
|
+
├── corpus.py Multi-file corpus search
|
|
492
|
+
├── collection.py Persistent library index
|
|
493
|
+
└── core/
|
|
494
|
+
├── schema.py SQLite schema and format versions
|
|
495
|
+
├── validation.py Integrity and contract validation
|
|
496
|
+
├── embeddings.py Embedders and vector serialization
|
|
497
|
+
├── search.py Legacy search implementation
|
|
498
|
+
├── inspection.py Legacy inspection helpers
|
|
499
|
+
├── access.py Legacy page/asset/region access
|
|
500
|
+
└── figures.py Legacy figure access
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
Source extraction lives under `packages/vera-extract`, and MCP integration
|
|
504
|
+
lives under `packages/vera-mcp`.
|
|
505
|
+
|
|
506
|
+
## Format and API references
|
|
507
|
+
|
|
508
|
+
- [VERA 0.2 specification](https://github.com/dkylewillis/vera/blob/main/docs/vera-spec-v0.2.md)
|
|
509
|
+
- [Full Python API guide](https://github.com/dkylewillis/vera/blob/main/docs/python-api.md)
|
|
510
|
+
- [Architecture](https://github.com/dkylewillis/vera/blob/main/docs/architecture.md)
|