docforge-sdk 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,342 @@
1
+ # ====== Code Summary ======
2
+ # The explorer resource — the READ surface over one collection's documents (catalogue, detail, pages,
3
+ # IR, chunks), plus deletion and the chunk searchability toggles (single + bulk). The full document IR
4
+ # view (get_ir) is grouped here since it is a per-document read. All URL/body logic lives once in the
5
+ # pure _ExplorerSpecs mixin so the async/sync shells differ ONLY by ``await``.
6
+
7
+ # ====== Local Project Imports ======
8
+ from .._requestspec import RequestSpec
9
+ from ..models.explorer import (
10
+ BulkChunkEnabledPatch,
11
+ BulkChunkEnabledResponse,
12
+ ChunkEnabledPatch,
13
+ ChunkEnabledResult,
14
+ ChunkInfo,
15
+ DocumentDetail,
16
+ DocumentListItem,
17
+ PageInfo,
18
+ )
19
+ from ..models.ir import DocumentIRModel
20
+ from ._base import AsyncResource, SyncResource, _ResourceMixin
21
+
22
+
23
+ class _ExplorerSpecs(_ResourceMixin):
24
+ """Pure ``RequestSpec`` builders for the explorer endpoints — the single source of URL/body logic."""
25
+
26
+ _COLLECTIONS_PATH = "/collections"
27
+ _DOCUMENTS_PATH = "/documents"
28
+ _CHUNKS_PATH = "/chunks"
29
+
30
+ def _list_documents_spec(self, collection_id: str) -> RequestSpec:
31
+ """
32
+ Build the spec for listing a collection's documents.
33
+
34
+ Args:
35
+ collection_id (str): The owning collection's UUID.
36
+
37
+ Returns:
38
+ RequestSpec: A GET on the collection's documents catalogue.
39
+ """
40
+ return RequestSpec("GET", f"{self._COLLECTIONS_PATH}/{collection_id}/documents")
41
+
42
+ def _get_document_spec(self, document_id: str) -> RequestSpec:
43
+ """
44
+ Build the spec for fetching one document's detail.
45
+
46
+ Args:
47
+ document_id (str): The document's UUID.
48
+
49
+ Returns:
50
+ RequestSpec: A GET on the document resource.
51
+ """
52
+ return RequestSpec("GET", f"{self._DOCUMENTS_PATH}/{document_id}")
53
+
54
+ def _get_pages_spec(self, document_id: str) -> RequestSpec:
55
+ """
56
+ Build the spec for fetching a document's pages.
57
+
58
+ Args:
59
+ document_id (str): The document's UUID.
60
+
61
+ Returns:
62
+ RequestSpec: A GET on the document's pages sub-resource.
63
+ """
64
+ return RequestSpec("GET", f"{self._DOCUMENTS_PATH}/{document_id}/pages")
65
+
66
+ def _get_ir_spec(self, document_id: str) -> RequestSpec:
67
+ """
68
+ Build the spec for fetching a document's full canonical IR.
69
+
70
+ Args:
71
+ document_id (str): The document's UUID.
72
+
73
+ Returns:
74
+ RequestSpec: A GET on the document's IR sub-resource.
75
+ """
76
+ return RequestSpec("GET", f"{self._DOCUMENTS_PATH}/{document_id}/ir")
77
+
78
+ def _get_chunks_spec(self, document_id: str) -> RequestSpec:
79
+ """
80
+ Build the spec for fetching a document's chunks.
81
+
82
+ Args:
83
+ document_id (str): The document's UUID.
84
+
85
+ Returns:
86
+ RequestSpec: A GET on the document's chunks sub-resource.
87
+ """
88
+ return RequestSpec("GET", f"{self._DOCUMENTS_PATH}/{document_id}/chunks")
89
+
90
+ def _delete_document_spec(self, document_id: str) -> RequestSpec:
91
+ """
92
+ Build the spec for deleting a document.
93
+
94
+ Args:
95
+ document_id (str): The document to delete.
96
+
97
+ Returns:
98
+ RequestSpec: A DELETE on the document resource.
99
+ """
100
+ return RequestSpec("DELETE", f"{self._DOCUMENTS_PATH}/{document_id}")
101
+
102
+ def _set_chunk_enabled_spec(self, chunk_id: str, enabled: bool) -> RequestSpec:
103
+ """
104
+ Build the spec for toggling one chunk's searchability.
105
+
106
+ Args:
107
+ chunk_id (str): The chunk to toggle.
108
+ enabled (bool): The desired searchability state.
109
+
110
+ Returns:
111
+ RequestSpec: A PATCH on the chunk's ``/enabled`` sub-resource.
112
+ """
113
+ return RequestSpec(
114
+ "PATCH",
115
+ f"{self._CHUNKS_PATH}/{chunk_id}/enabled",
116
+ json=ChunkEnabledPatch(enabled=enabled).model_dump(mode="json"),
117
+ )
118
+
119
+ def _set_chunks_enabled_spec(self, patch: BulkChunkEnabledPatch) -> RequestSpec:
120
+ """
121
+ Build the spec for toggling several chunks' searchability in one call.
122
+
123
+ Args:
124
+ patch (BulkChunkEnabledPatch): The chunk ids and the state to apply to all of them.
125
+
126
+ Returns:
127
+ RequestSpec: A PATCH on the chunks collection's ``/enabled`` route.
128
+ """
129
+ return RequestSpec(
130
+ "PATCH", f"{self._CHUNKS_PATH}/enabled", json=patch.model_dump(mode="json")
131
+ )
132
+
133
+
134
+ class AsyncExplorer(AsyncResource, _ExplorerSpecs):
135
+ """Asynchronous document explorer (browse, detail, IR, chunks, deletion, chunk toggles)."""
136
+
137
+ async def list_documents(self, collection_id: str) -> list[DocumentListItem]:
138
+ """
139
+ List a collection's documents, newest first.
140
+
141
+ Args:
142
+ collection_id (str): The owning collection's UUID.
143
+
144
+ Returns:
145
+ list[DocumentListItem]: One row per document.
146
+ """
147
+ return await self._transport.request(
148
+ self._list_documents_spec(collection_id), list[DocumentListItem]
149
+ )
150
+
151
+ async def get_document(self, document_id: str) -> DocumentDetail:
152
+ """
153
+ Fetch one document's full facts and resolved metadata.
154
+
155
+ Args:
156
+ document_id (str): The document's UUID.
157
+
158
+ Returns:
159
+ DocumentDetail: The document detail.
160
+ """
161
+ return await self._transport.request(self._get_document_spec(document_id), DocumentDetail)
162
+
163
+ async def get_pages(self, document_id: str) -> list[PageInfo]:
164
+ """
165
+ Fetch a document's pages.
166
+
167
+ Args:
168
+ document_id (str): The document's UUID.
169
+
170
+ Returns:
171
+ list[PageInfo]: One entry per page.
172
+ """
173
+ return await self._transport.request(self._get_pages_spec(document_id), list[PageInfo])
174
+
175
+ async def get_ir(self, document_id: str) -> DocumentIRModel:
176
+ """
177
+ Fetch a document's full canonical IR (blocks, tables, figures, enrichments).
178
+
179
+ Args:
180
+ document_id (str): The document's UUID.
181
+
182
+ Returns:
183
+ DocumentIRModel: The full IR payload.
184
+ """
185
+ return await self._transport.request(self._get_ir_spec(document_id), DocumentIRModel)
186
+
187
+ async def get_chunks(self, document_id: str) -> list[ChunkInfo]:
188
+ """
189
+ Fetch a document's retrieval chunks.
190
+
191
+ Args:
192
+ document_id (str): The document's UUID.
193
+
194
+ Returns:
195
+ list[ChunkInfo]: One entry per chunk.
196
+ """
197
+ return await self._transport.request(self._get_chunks_spec(document_id), list[ChunkInfo])
198
+
199
+ async def delete_document(self, document_id: str) -> None:
200
+ """
201
+ Delete a document and everything derived from it.
202
+
203
+ Args:
204
+ document_id (str): The document to delete.
205
+ """
206
+ return await self._transport.request(self._delete_document_spec(document_id), type(None))
207
+
208
+ async def set_chunk_enabled(self, chunk_id: str, enabled: bool) -> ChunkEnabledResult:
209
+ """
210
+ Toggle one chunk's searchability.
211
+
212
+ Args:
213
+ chunk_id (str): The chunk to toggle.
214
+ enabled (bool): True to make searchable, False to hide.
215
+
216
+ Returns:
217
+ ChunkEnabledResult: The recomputed effective state and whether a re-embed is needed.
218
+ """
219
+ return await self._transport.request(
220
+ self._set_chunk_enabled_spec(chunk_id, enabled), ChunkEnabledResult
221
+ )
222
+
223
+ async def set_chunks_enabled(self, patch: BulkChunkEnabledPatch) -> BulkChunkEnabledResponse:
224
+ """
225
+ Toggle several chunks' searchability to the same state in one call.
226
+
227
+ Args:
228
+ patch (BulkChunkEnabledPatch): The chunk ids and the state to apply.
229
+
230
+ Returns:
231
+ BulkChunkEnabledResponse: Per-chunk outcomes plus any ids that did not resolve.
232
+ """
233
+ return await self._transport.request(
234
+ self._set_chunks_enabled_spec(patch), BulkChunkEnabledResponse
235
+ )
236
+
237
+
238
+ class SyncExplorer(SyncResource, _ExplorerSpecs):
239
+ """Synchronous document explorer (browse, detail, IR, chunks, deletion, chunk toggles)."""
240
+
241
+ def list_documents(self, collection_id: str) -> list[DocumentListItem]:
242
+ """
243
+ List a collection's documents, newest first.
244
+
245
+ Args:
246
+ collection_id (str): The owning collection's UUID.
247
+
248
+ Returns:
249
+ list[DocumentListItem]: One row per document.
250
+ """
251
+ return self._transport.request(
252
+ self._list_documents_spec(collection_id), list[DocumentListItem]
253
+ )
254
+
255
+ def get_document(self, document_id: str) -> DocumentDetail:
256
+ """
257
+ Fetch one document's full facts and resolved metadata.
258
+
259
+ Args:
260
+ document_id (str): The document's UUID.
261
+
262
+ Returns:
263
+ DocumentDetail: The document detail.
264
+ """
265
+ return self._transport.request(self._get_document_spec(document_id), DocumentDetail)
266
+
267
+ def get_pages(self, document_id: str) -> list[PageInfo]:
268
+ """
269
+ Fetch a document's pages.
270
+
271
+ Args:
272
+ document_id (str): The document's UUID.
273
+
274
+ Returns:
275
+ list[PageInfo]: One entry per page.
276
+ """
277
+ return self._transport.request(self._get_pages_spec(document_id), list[PageInfo])
278
+
279
+ def get_ir(self, document_id: str) -> DocumentIRModel:
280
+ """
281
+ Fetch a document's full canonical IR (blocks, tables, figures, enrichments).
282
+
283
+ Args:
284
+ document_id (str): The document's UUID.
285
+
286
+ Returns:
287
+ DocumentIRModel: The full IR payload.
288
+ """
289
+ return self._transport.request(self._get_ir_spec(document_id), DocumentIRModel)
290
+
291
+ def get_chunks(self, document_id: str) -> list[ChunkInfo]:
292
+ """
293
+ Fetch a document's retrieval chunks.
294
+
295
+ Args:
296
+ document_id (str): The document's UUID.
297
+
298
+ Returns:
299
+ list[ChunkInfo]: One entry per chunk.
300
+ """
301
+ return self._transport.request(self._get_chunks_spec(document_id), list[ChunkInfo])
302
+
303
+ def delete_document(self, document_id: str) -> None:
304
+ """
305
+ Delete a document and everything derived from it.
306
+
307
+ Args:
308
+ document_id (str): The document to delete.
309
+ """
310
+ return self._transport.request(self._delete_document_spec(document_id), type(None))
311
+
312
+ def set_chunk_enabled(self, chunk_id: str, enabled: bool) -> ChunkEnabledResult:
313
+ """
314
+ Toggle one chunk's searchability.
315
+
316
+ Args:
317
+ chunk_id (str): The chunk to toggle.
318
+ enabled (bool): True to make searchable, False to hide.
319
+
320
+ Returns:
321
+ ChunkEnabledResult: The recomputed effective state and whether a re-embed is needed.
322
+ """
323
+ return self._transport.request(
324
+ self._set_chunk_enabled_spec(chunk_id, enabled), ChunkEnabledResult
325
+ )
326
+
327
+ def set_chunks_enabled(self, patch: BulkChunkEnabledPatch) -> BulkChunkEnabledResponse:
328
+ """
329
+ Toggle several chunks' searchability to the same state in one call.
330
+
331
+ Args:
332
+ patch (BulkChunkEnabledPatch): The chunk ids and the state to apply.
333
+
334
+ Returns:
335
+ BulkChunkEnabledResponse: Per-chunk outcomes plus any ids that did not resolve.
336
+ """
337
+ return self._transport.request(
338
+ self._set_chunks_enabled_spec(patch), BulkChunkEnabledResponse
339
+ )
340
+
341
+
342
+ __all__ = ["AsyncExplorer", "SyncExplorer"]
@@ -0,0 +1,53 @@
1
+ # ====== Code Summary ======
2
+ # The health (liveness) resource. The probe lives at the BARE origin (/health), outside /api/v1, so
3
+ # both shells route through the transport's request_bare helper rather than the versioned request.
4
+ # All URL logic lives once in the pure _HealthSpecs mixin; the async/sync shells differ only by await.
5
+
6
+ # ====== Local Project Imports ======
7
+ from .._requestspec import RequestSpec
8
+ from ..models.health import HealthStatus
9
+ from ._base import AsyncResource, SyncResource, _ResourceMixin
10
+
11
+
12
+ class _HealthSpecs(_ResourceMixin):
13
+ """Pure ``RequestSpec`` builders for the health endpoint — the single source of URL logic."""
14
+
15
+ _HEALTH_PATH = "/health"
16
+
17
+ def _ping_spec(self) -> RequestSpec:
18
+ """
19
+ Build the spec for the liveness probe.
20
+
21
+ Returns:
22
+ RequestSpec: A GET on the bare-root ``/health`` route (outside ``/api/v1``).
23
+ """
24
+ return RequestSpec("GET", self._HEALTH_PATH)
25
+
26
+
27
+ class AsyncHealth(AsyncResource, _HealthSpecs):
28
+ """Asynchronous liveness probe."""
29
+
30
+ async def ping(self) -> HealthStatus:
31
+ """
32
+ Probe the API's liveness.
33
+
34
+ Returns:
35
+ HealthStatus: The status payload (``status == "ok"`` when serving).
36
+ """
37
+ return await self._transport.request_bare(self._ping_spec(), HealthStatus)
38
+
39
+
40
+ class SyncHealth(SyncResource, _HealthSpecs):
41
+ """Synchronous liveness probe."""
42
+
43
+ def ping(self) -> HealthStatus:
44
+ """
45
+ Probe the API's liveness.
46
+
47
+ Returns:
48
+ HealthStatus: The status payload (``status == "ok"`` when serving).
49
+ """
50
+ return self._transport.request_bare(self._ping_spec(), HealthStatus)
51
+
52
+
53
+ __all__ = ["AsyncHealth", "SyncHealth"]
@@ -0,0 +1,161 @@
1
+ # ====== Code Summary ======
2
+ # The jobs resource — the live ingestion status the UI polls. All URL/param logic lives once in the
3
+ # pure _JobsSpecs mixin so AsyncJobs and SyncJobs differ ONLY by ``await``. The collection filter on
4
+ # the list endpoint is a query parameter (not a path segment), threaded through the spec's params.
5
+
6
+ # ====== Local Project Imports ======
7
+ from .._requestspec import RequestSpec
8
+ from ..models.jobs import JobStatus, JobTrace, WorkersLive
9
+ from ._base import AsyncResource, SyncResource, _ResourceMixin
10
+
11
+
12
+ class _JobsSpecs(_ResourceMixin):
13
+ """Pure ``RequestSpec`` builders for the jobs endpoints — the single source of URL/param logic."""
14
+
15
+ _JOBS_PATH = "/jobs"
16
+
17
+ def _list_spec(self, collection_id: str) -> RequestSpec:
18
+ """
19
+ Build the spec for listing a collection's jobs.
20
+
21
+ Args:
22
+ collection_id (str): The collection whose jobs to list (a QUERY parameter).
23
+
24
+ Returns:
25
+ RequestSpec: A GET on the jobs collection filtered by ``collection_id``.
26
+ """
27
+ return RequestSpec("GET", self._JOBS_PATH, params={"collection_id": collection_id})
28
+
29
+ def _get_spec(self, job_id: str) -> RequestSpec:
30
+ """
31
+ Build the spec for fetching one job's status.
32
+
33
+ Args:
34
+ job_id (str): The job's UUID.
35
+
36
+ Returns:
37
+ RequestSpec: A GET on the job resource.
38
+ """
39
+ return RequestSpec("GET", f"{self._JOBS_PATH}/{job_id}")
40
+
41
+ def _get_events_spec(self, job_id: str) -> RequestSpec:
42
+ """
43
+ Build the spec for fetching a job's per-node execution trace.
44
+
45
+ Args:
46
+ job_id (str): The job's UUID.
47
+
48
+ Returns:
49
+ RequestSpec: A GET on the job's ``/events`` sub-resource.
50
+ """
51
+ return RequestSpec("GET", f"{self._JOBS_PATH}/{job_id}/events")
52
+
53
+ def _live_workers_spec(self) -> RequestSpec:
54
+ """
55
+ Build the spec for the live worker-activity view.
56
+
57
+ Returns:
58
+ RequestSpec: A GET on the jobs ``/workers/live`` route.
59
+ """
60
+ return RequestSpec("GET", f"{self._JOBS_PATH}/workers/live")
61
+
62
+
63
+ class AsyncJobs(AsyncResource, _JobsSpecs):
64
+ """Asynchronous ingestion-job monitoring."""
65
+
66
+ async def list(self, collection_id: str) -> list[JobStatus]:
67
+ """
68
+ List a collection's jobs, newest first.
69
+
70
+ Args:
71
+ collection_id (str): The collection whose jobs to list.
72
+
73
+ Returns:
74
+ list[JobStatus]: Every job of the collection with its live state.
75
+ """
76
+ return await self._transport.request(self._list_spec(collection_id), list[JobStatus])
77
+
78
+ async def get(self, job_id: str) -> JobStatus:
79
+ """
80
+ Fetch one job's live status.
81
+
82
+ Args:
83
+ job_id (str): The job's UUID.
84
+
85
+ Returns:
86
+ JobStatus: The job's current state.
87
+ """
88
+ return await self._transport.request(self._get_spec(job_id), JobStatus)
89
+
90
+ async def get_events(self, job_id: str) -> JobTrace:
91
+ """
92
+ Fetch a job's per-node execution trace, in run order.
93
+
94
+ Args:
95
+ job_id (str): The job's UUID.
96
+
97
+ Returns:
98
+ JobTrace: The ordered per-node trace.
99
+ """
100
+ return await self._transport.request(self._get_events_spec(job_id), JobTrace)
101
+
102
+ async def live_workers(self) -> WorkersLive:
103
+ """
104
+ Fetch everything running right now, grouped by worker.
105
+
106
+ Returns:
107
+ WorkersLive: The live per-worker activity view.
108
+ """
109
+ return await self._transport.request(self._live_workers_spec(), WorkersLive)
110
+
111
+
112
+ class SyncJobs(SyncResource, _JobsSpecs):
113
+ """Synchronous ingestion-job monitoring."""
114
+
115
+ def list(self, collection_id: str) -> list[JobStatus]:
116
+ """
117
+ List a collection's jobs, newest first.
118
+
119
+ Args:
120
+ collection_id (str): The collection whose jobs to list.
121
+
122
+ Returns:
123
+ list[JobStatus]: Every job of the collection with its live state.
124
+ """
125
+ return self._transport.request(self._list_spec(collection_id), list[JobStatus])
126
+
127
+ def get(self, job_id: str) -> JobStatus:
128
+ """
129
+ Fetch one job's live status.
130
+
131
+ Args:
132
+ job_id (str): The job's UUID.
133
+
134
+ Returns:
135
+ JobStatus: The job's current state.
136
+ """
137
+ return self._transport.request(self._get_spec(job_id), JobStatus)
138
+
139
+ def get_events(self, job_id: str) -> JobTrace:
140
+ """
141
+ Fetch a job's per-node execution trace, in run order.
142
+
143
+ Args:
144
+ job_id (str): The job's UUID.
145
+
146
+ Returns:
147
+ JobTrace: The ordered per-node trace.
148
+ """
149
+ return self._transport.request(self._get_events_spec(job_id), JobTrace)
150
+
151
+ def live_workers(self) -> WorkersLive:
152
+ """
153
+ Fetch everything running right now, grouped by worker.
154
+
155
+ Returns:
156
+ WorkersLive: The live per-worker activity view.
157
+ """
158
+ return self._transport.request(self._live_workers_spec(), WorkersLive)
159
+
160
+
161
+ __all__ = ["AsyncJobs", "SyncJobs"]