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,291 @@
1
+ # ====== Code Summary ======
2
+ # The pipelines resource — discovery + design of the pipeline graph surfaces. The graph JSON is OPAQUE
3
+ # to the SDK: blob/operations/action pass through as plain dicts, only the typed ENVELOPE comes back.
4
+ # All URL/body logic lives once in the pure _PipelinesSpecs mixin so the async/sync shells differ ONLY
5
+ # by ``await``.
6
+
7
+ # ====== Standard Library Imports ======
8
+ from typing import Any
9
+
10
+ # ====== Local Project Imports ======
11
+ from .._requestspec import RequestSpec
12
+ from ..models.pipelines import (
13
+ EditResponse,
14
+ InspectResponse,
15
+ PipelineDesignResponse,
16
+ PipelineIndexResponse,
17
+ StageApplyResponse,
18
+ StageViewResponse,
19
+ )
20
+ from ._base import AsyncResource, SyncResource, _ResourceMixin
21
+
22
+
23
+ class _PipelinesSpecs(_ResourceMixin):
24
+ """Pure ``RequestSpec`` builders for the pipeline endpoints — the single source of URL/body logic."""
25
+
26
+ _PIPELINES_PATH = "/pipelines"
27
+
28
+ def _list_surfaces_spec(self) -> RequestSpec:
29
+ """
30
+ Build the spec for discovering the available pipeline surfaces.
31
+
32
+ Returns:
33
+ RequestSpec: A GET on the pipelines index.
34
+ """
35
+ return RequestSpec("GET", self._PIPELINES_PATH)
36
+
37
+ def _get_design_spec(self, key: str, full: bool) -> RequestSpec:
38
+ """
39
+ Build the spec for opening a pipeline's design payload.
40
+
41
+ Args:
42
+ key (str): The pipeline key (e.g. ``"ingest"``).
43
+ full (bool): Whether to include the advanced palette blocks.
44
+
45
+ Returns:
46
+ RequestSpec: A GET on the pipeline resource, carrying the ``full`` query flag.
47
+ """
48
+ return RequestSpec("GET", f"{self._PIPELINES_PATH}/{key}", params={"full": full})
49
+
50
+ def _inspect_spec(self, key: str, blob: dict[str, Any]) -> RequestSpec:
51
+ """
52
+ Build the spec for inspecting an edited pipeline blob.
53
+
54
+ Args:
55
+ key (str): The pipeline key.
56
+ blob (dict[str, Any]): The opaque graph blob to inspect.
57
+
58
+ Returns:
59
+ RequestSpec: A POST to the pipeline's ``/inspect`` route.
60
+ """
61
+ return RequestSpec("POST", f"{self._PIPELINES_PATH}/{key}/inspect", json={"blob": blob})
62
+
63
+ def _edit_spec(
64
+ self, key: str, blob: dict[str, Any], operations: list[dict[str, Any]]
65
+ ) -> RequestSpec:
66
+ """
67
+ Build the spec for applying graph operations to a pipeline blob.
68
+
69
+ Args:
70
+ key (str): The pipeline key.
71
+ blob (dict[str, Any]): The opaque graph blob the operations start from.
72
+ operations (list[dict[str, Any]]): The ordered, opaque edit operations.
73
+
74
+ Returns:
75
+ RequestSpec: A POST to the pipeline's ``/edit`` route.
76
+ """
77
+ return RequestSpec(
78
+ "POST",
79
+ f"{self._PIPELINES_PATH}/{key}/edit",
80
+ json={"blob": blob, "operations": operations},
81
+ )
82
+
83
+ def _view_stages_spec(self, key: str, blob: dict[str, Any]) -> RequestSpec:
84
+ """
85
+ Build the spec for deriving the stage view of a pipeline blob.
86
+
87
+ Args:
88
+ key (str): The pipeline key.
89
+ blob (dict[str, Any]): The opaque graph blob to view as stages.
90
+
91
+ Returns:
92
+ RequestSpec: A POST to the pipeline's ``/stages/view`` route.
93
+ """
94
+ return RequestSpec("POST", f"{self._PIPELINES_PATH}/{key}/stages/view", json={"blob": blob})
95
+
96
+ def _apply_stage_spec(
97
+ self, key: str, blob: dict[str, Any], action: dict[str, Any]
98
+ ) -> RequestSpec:
99
+ """
100
+ Build the spec for compiling a stage action into a pipeline blob.
101
+
102
+ Args:
103
+ key (str): The pipeline key.
104
+ blob (dict[str, Any]): The opaque graph blob the action starts from.
105
+ action (dict[str, Any]): The opaque stage action to apply.
106
+
107
+ Returns:
108
+ RequestSpec: A POST to the pipeline's ``/stages/apply`` route.
109
+ """
110
+ return RequestSpec(
111
+ "POST",
112
+ f"{self._PIPELINES_PATH}/{key}/stages/apply",
113
+ json={"blob": blob, "action": action},
114
+ )
115
+
116
+
117
+ class AsyncPipelines(AsyncResource, _PipelinesSpecs):
118
+ """Asynchronous pipeline discovery + design surface."""
119
+
120
+ async def list_surfaces(self) -> PipelineIndexResponse:
121
+ """
122
+ Discover the pipeline design surfaces the backend serves.
123
+
124
+ Returns:
125
+ PipelineIndexResponse: One entry per available surface.
126
+ """
127
+ return await self._transport.request(self._list_surfaces_spec(), PipelineIndexResponse)
128
+
129
+ async def get_design(self, key: str, full: bool = True) -> PipelineDesignResponse:
130
+ """
131
+ Open a pipeline's design payload (palette + blob + issues).
132
+
133
+ Args:
134
+ key (str): The pipeline key (e.g. ``"ingest"``).
135
+ full (bool): Include the advanced palette blocks.
136
+
137
+ Returns:
138
+ PipelineDesignResponse: The design payload.
139
+ """
140
+ return await self._transport.request(
141
+ self._get_design_spec(key, full), PipelineDesignResponse
142
+ )
143
+
144
+ async def inspect(self, key: str, blob: dict[str, Any]) -> InspectResponse:
145
+ """
146
+ Inspect an edited pipeline blob (validity + issues + described tree).
147
+
148
+ Args:
149
+ key (str): The pipeline key.
150
+ blob (dict[str, Any]): The opaque graph blob to inspect.
151
+
152
+ Returns:
153
+ InspectResponse: The described mirror of the blob.
154
+ """
155
+ return await self._transport.request(self._inspect_spec(key, blob), InspectResponse)
156
+
157
+ async def edit(
158
+ self, key: str, blob: dict[str, Any], operations: list[dict[str, Any]]
159
+ ) -> EditResponse:
160
+ """
161
+ Apply ordered graph operations to a pipeline blob, server-side.
162
+
163
+ Args:
164
+ key (str): The pipeline key.
165
+ blob (dict[str, Any]): The opaque graph blob the operations start from.
166
+ operations (list[dict[str, Any]]): The ordered, opaque edit operations.
167
+
168
+ Returns:
169
+ EditResponse: The edited blob plus validity + issues + described tree.
170
+ """
171
+ return await self._transport.request(self._edit_spec(key, blob, operations), EditResponse)
172
+
173
+ async def view_stages(self, key: str, blob: dict[str, Any]) -> StageViewResponse:
174
+ """
175
+ Derive the stage view of a pipeline blob.
176
+
177
+ Args:
178
+ key (str): The pipeline key.
179
+ blob (dict[str, Any]): The opaque graph blob to view as stages.
180
+
181
+ Returns:
182
+ StageViewResponse: The ordered stages plus the validity verdict.
183
+ """
184
+ return await self._transport.request(self._view_stages_spec(key, blob), StageViewResponse)
185
+
186
+ async def apply_stage(
187
+ self, key: str, blob: dict[str, Any], action: dict[str, Any]
188
+ ) -> StageApplyResponse:
189
+ """
190
+ Compile a stage action into a pipeline blob.
191
+
192
+ Args:
193
+ key (str): The pipeline key.
194
+ blob (dict[str, Any]): The opaque graph blob the action starts from.
195
+ action (dict[str, Any]): The opaque stage action to apply.
196
+
197
+ Returns:
198
+ StageApplyResponse: The recompiled blob plus its stage view, validity and notices.
199
+ """
200
+ return await self._transport.request(
201
+ self._apply_stage_spec(key, blob, action), StageApplyResponse
202
+ )
203
+
204
+
205
+ class SyncPipelines(SyncResource, _PipelinesSpecs):
206
+ """Synchronous pipeline discovery + design surface."""
207
+
208
+ def list_surfaces(self) -> PipelineIndexResponse:
209
+ """
210
+ Discover the pipeline design surfaces the backend serves.
211
+
212
+ Returns:
213
+ PipelineIndexResponse: One entry per available surface.
214
+ """
215
+ return self._transport.request(self._list_surfaces_spec(), PipelineIndexResponse)
216
+
217
+ def get_design(self, key: str, full: bool = True) -> PipelineDesignResponse:
218
+ """
219
+ Open a pipeline's design payload (palette + blob + issues).
220
+
221
+ Args:
222
+ key (str): The pipeline key (e.g. ``"ingest"``).
223
+ full (bool): Include the advanced palette blocks.
224
+
225
+ Returns:
226
+ PipelineDesignResponse: The design payload.
227
+ """
228
+ return self._transport.request(self._get_design_spec(key, full), PipelineDesignResponse)
229
+
230
+ def inspect(self, key: str, blob: dict[str, Any]) -> InspectResponse:
231
+ """
232
+ Inspect an edited pipeline blob (validity + issues + described tree).
233
+
234
+ Args:
235
+ key (str): The pipeline key.
236
+ blob (dict[str, Any]): The opaque graph blob to inspect.
237
+
238
+ Returns:
239
+ InspectResponse: The described mirror of the blob.
240
+ """
241
+ return self._transport.request(self._inspect_spec(key, blob), InspectResponse)
242
+
243
+ def edit(
244
+ self, key: str, blob: dict[str, Any], operations: list[dict[str, Any]]
245
+ ) -> EditResponse:
246
+ """
247
+ Apply ordered graph operations to a pipeline blob, server-side.
248
+
249
+ Args:
250
+ key (str): The pipeline key.
251
+ blob (dict[str, Any]): The opaque graph blob the operations start from.
252
+ operations (list[dict[str, Any]]): The ordered, opaque edit operations.
253
+
254
+ Returns:
255
+ EditResponse: The edited blob plus validity + issues + described tree.
256
+ """
257
+ return self._transport.request(self._edit_spec(key, blob, operations), EditResponse)
258
+
259
+ def view_stages(self, key: str, blob: dict[str, Any]) -> StageViewResponse:
260
+ """
261
+ Derive the stage view of a pipeline blob.
262
+
263
+ Args:
264
+ key (str): The pipeline key.
265
+ blob (dict[str, Any]): The opaque graph blob to view as stages.
266
+
267
+ Returns:
268
+ StageViewResponse: The ordered stages plus the validity verdict.
269
+ """
270
+ return self._transport.request(self._view_stages_spec(key, blob), StageViewResponse)
271
+
272
+ def apply_stage(
273
+ self, key: str, blob: dict[str, Any], action: dict[str, Any]
274
+ ) -> StageApplyResponse:
275
+ """
276
+ Compile a stage action into a pipeline blob.
277
+
278
+ Args:
279
+ key (str): The pipeline key.
280
+ blob (dict[str, Any]): The opaque graph blob the action starts from.
281
+ action (dict[str, Any]): The opaque stage action to apply.
282
+
283
+ Returns:
284
+ StageApplyResponse: The recompiled blob plus its stage view, validity and notices.
285
+ """
286
+ return self._transport.request(
287
+ self._apply_stage_spec(key, blob, action), StageApplyResponse
288
+ )
289
+
290
+
291
+ __all__ = ["AsyncPipelines", "SyncPipelines"]
@@ -0,0 +1,70 @@
1
+ # ====== Code Summary ======
2
+ # The search resource — a hybrid search over one collection's chunks. All URL/body logic lives once in
3
+ # the pure _SearchSpecs mixin so AsyncSearch and SyncSearch differ ONLY by ``await``.
4
+
5
+ # ====== Local Project Imports ======
6
+ from .._requestspec import RequestSpec
7
+ from ..models.search import SearchRequest, SearchResponse
8
+ from ._base import AsyncResource, SyncResource, _ResourceMixin
9
+
10
+
11
+ class _SearchSpecs(_ResourceMixin):
12
+ """Pure ``RequestSpec`` builders for the search endpoint — the single source of URL/body logic."""
13
+
14
+ _COLLECTIONS_PATH = "/collections"
15
+
16
+ def _search_spec(self, collection_id: str, request: SearchRequest) -> RequestSpec:
17
+ """
18
+ Build the spec for searching a collection.
19
+
20
+ Args:
21
+ collection_id (str): The collection to search.
22
+ request (SearchRequest): The query, filters and target modalities.
23
+
24
+ Returns:
25
+ RequestSpec: A POST to the collection's ``/search`` route carrying the query body.
26
+ """
27
+ return RequestSpec(
28
+ "POST",
29
+ f"{self._COLLECTIONS_PATH}/{collection_id}/search",
30
+ json=request.model_dump(mode="json"),
31
+ )
32
+
33
+
34
+ class AsyncSearch(AsyncResource, _SearchSpecs):
35
+ """Asynchronous hybrid search."""
36
+
37
+ async def search(self, collection_id: str, request: SearchRequest) -> SearchResponse:
38
+ """
39
+ Run a hybrid search over a collection and return ranked, hydrated chunk hits.
40
+
41
+ Args:
42
+ collection_id (str): The collection to search.
43
+ request (SearchRequest): The query, filters and target modalities.
44
+
45
+ Returns:
46
+ SearchResponse: The echoed query and its hits, best first.
47
+ """
48
+ return await self._transport.request(
49
+ self._search_spec(collection_id, request), SearchResponse
50
+ )
51
+
52
+
53
+ class SyncSearch(SyncResource, _SearchSpecs):
54
+ """Synchronous hybrid search."""
55
+
56
+ def search(self, collection_id: str, request: SearchRequest) -> SearchResponse:
57
+ """
58
+ Run a hybrid search over a collection and return ranked, hydrated chunk hits.
59
+
60
+ Args:
61
+ collection_id (str): The collection to search.
62
+ request (SearchRequest): The query, filters and target modalities.
63
+
64
+ Returns:
65
+ SearchResponse: The echoed query and its hits, best first.
66
+ """
67
+ return self._transport.request(self._search_spec(collection_id, request), SearchResponse)
68
+
69
+
70
+ __all__ = ["AsyncSearch", "SyncSearch"]
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: docforge-sdk
3
+ Version: 0.1.0
4
+ Summary: Typed async + sync Python client for the DocForge REST API (standalone, zero server deps).
5
+ Project-URL: Homepage, https://github.com/Florian-BARRE/docforge
6
+ Project-URL: Repository, https://github.com/Florian-BARRE/docforge
7
+ Project-URL: Issues, https://github.com/Florian-BARRE/docforge/issues
8
+ Author: Florian Barré
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: api-client,async,client,docforge,document-intelligence,rag,retrieval,sdk
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: httpx>=0.28
21
+ Requires-Dist: pydantic>=2.7
22
+ Description-Content-Type: text/markdown
23
+
24
+ # docforge-sdk
25
+
26
+ A typed Python client for the [DocForge](https://github.com/Florian-BARRE/docforge) REST API. It
27
+ ships **both** an asynchronous and a synchronous client with an identical surface, is fully
28
+ type-hinted (`py.typed`), and has **zero dependency on the DocForge server tree** — it is a
29
+ clean-room client that talks to the API over HTTP only (`httpx` + `pydantic` + hand-written models
30
+ that mirror the public REST contract), so it can be vendored or published independently.
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pip install docforge-sdk
36
+ ```
37
+
38
+ ## Async usage
39
+
40
+ ```python
41
+ import asyncio
42
+
43
+ from docforge_sdk import AsyncClient, SearchRequest
44
+
45
+
46
+ async def main() -> None:
47
+ async with AsyncClient("http://localhost:10040", api_token="df_root_...") as client:
48
+ collections = await client.collections.list()
49
+ for collection in collections:
50
+ print(collection.id, collection.name)
51
+
52
+ hits = await client.search.search(
53
+ collections[0].id,
54
+ SearchRequest(query="quarterly revenue", limit=5),
55
+ )
56
+ for hit in hits.hits:
57
+ print(hit.score, hit.text)
58
+
59
+
60
+ asyncio.run(main())
61
+ ```
62
+
63
+ ## Sync usage
64
+
65
+ ```python
66
+ from docforge_sdk import Client, SearchRequest
67
+
68
+ with Client("http://localhost:10040", api_token="df_root_...") as client:
69
+ collections = client.collections.list()
70
+ hits = client.search.search(
71
+ collections[0].id,
72
+ SearchRequest(query="quarterly revenue", limit=5),
73
+ )
74
+ for hit in hits.hits:
75
+ print(hit.score, hit.text)
76
+ ```
77
+
78
+ The two clients expose the same resources and method signatures; the sync methods are the async ones
79
+ without `await`. Available resource groups: `auth`, `health`, `collections`, `documents`, `explorer`,
80
+ `search`, `jobs`, `blobs`, `pipelines`.
81
+
82
+ ## License
83
+
84
+ MIT — see [LICENSE](LICENSE). This SDK is deliberately licensed **MIT even though the parent DocForge
85
+ repository is GPLv3**: it is a standalone, clean-room client (HTTP models only, no server code), so a
86
+ permissive per-directory license is intentional and lets any project depend on it freely.
87
+
88
+ ## Publishing (maintainers)
89
+
90
+ Releases publish to PyPI via **Trusted Publishing (OIDC)** — there is no API token stored in the
91
+ repo. To cut a release, tag a commit with the `sdk-v<version>` prefix (the version must match
92
+ `docforge_sdk/_version.py`) and push the tag:
93
+
94
+ ```bash
95
+ git tag sdk-v0.1.0
96
+ git push origin sdk-v0.1.0
97
+ ```
98
+
99
+ The `.github/workflows/release-sdk.yml` workflow then builds and uploads the sdist + wheel.
100
+
101
+ **One-time PyPI setup** (done once by the maintainer, before the first release):
102
+
103
+ 1. Reserve the project name `docforge-sdk` on PyPI.
104
+ 2. Under the project's *Publishing* settings, add a **GitHub trusted publisher** with:
105
+ - Owner: `Florian-BARRE`
106
+ - Repository: `docforge`
107
+ - Workflow name: `release-sdk.yml`
108
+ - Environment: `pypi`
@@ -0,0 +1,36 @@
1
+ docforge_sdk/__init__.py,sha256=XS61Q-rfIdy3TvxfSjw6zViGfUsUB9Y4ZKkjV_ltUZU,3876
2
+ docforge_sdk/_exceptions.py,sha256=BrfgSn2Yq6dKSFg_i9FHDdWrb9N1HwwwbVKH4nAadmQ,3592
3
+ docforge_sdk/_requestspec.py,sha256=HuRnpPA4O_lwXgByYekgJtpGNFss_fqZ6d_6ucSpfaY,1331
4
+ docforge_sdk/_transport_async.py,sha256=bYfuah01yxKMzRlsMhyABzkTIxr8huyAbSOfp1hwVEo,6129
5
+ docforge_sdk/_transport_base.py,sha256=120RPWiuhSD30TOKCqVC519nOgrOHIAMq5y8vkFhP_0,5317
6
+ docforge_sdk/_transport_sync.py,sha256=OVTjKtvshj13K_AmRrTtLkCyahHXHtfKhT4ufSd4Wx4,6022
7
+ docforge_sdk/_version.py,sha256=0LO1fk-0zhM_r0SLBJ2pX3jrF69BB9BM1EQETn22bDI,239
8
+ docforge_sdk/client.py,sha256=vaKECQr8AgjUI-UmXoZEBeKgyMX2PgQ4wPTc0aF4uQw,5301
9
+ docforge_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ docforge_sdk/models/__init__.py,sha256=s9pkJbyoRWTz_5NHZ092RQg5WAUGi8KqE3N5udBGqf8,3166
11
+ docforge_sdk/models/_shared.py,sha256=CmV2kKzJBVUj1Pkr0iq78fN51cNg7gEW-pMLM9D837c,3292
12
+ docforge_sdk/models/auth.py,sha256=gTqJOz3l4k_aGzVA4Y8dMFIEgWiRTguYE4y4UCzSCTA,5635
13
+ docforge_sdk/models/blobs.py,sha256=9e_xJiM6bc8F5gG97Bw7N0W2I2RjYyCxtvhDnooPZPc,888
14
+ docforge_sdk/models/collections.py,sha256=qKJK8tt2jYWP87ScTUL3vTLzk8xpMzqfw8zsz96PCKE,6525
15
+ docforge_sdk/models/documents.py,sha256=dJk5aC0uUy6Gda25yP3jpsrGs1XS8Lo1dWMz7McscNo,1809
16
+ docforge_sdk/models/explorer.py,sha256=hqWYNY-dJSYJlUNcRxv4njwoKvM8kzBfIZ4ShS9Y5OQ,10761
17
+ docforge_sdk/models/health.py,sha256=SSWeFtEh2R_eRBuIi2QXFEuy6lPDL03I9uaYC3ESNNk,602
18
+ docforge_sdk/models/ir.py,sha256=2LClyD6_XuJQllc5WUeA32UqM1z30kDNC87IQAo-8us,6269
19
+ docforge_sdk/models/jobs.py,sha256=I22srI1YGUdw1wwL5mOFe_43CMpplgpfXfOtmkFyQeM,3984
20
+ docforge_sdk/models/pipelines.py,sha256=tf5aggvfetPsODEMP-UN77zbiGNmgWqpmXeT5uk5W1k,8054
21
+ docforge_sdk/models/search.py,sha256=VKbO8JrgSiPN7yQt2vy9wxVu51JrYLtCWMz589l6QFU,4544
22
+ docforge_sdk/resources/__init__.py,sha256=kGQed_gnpoo7LE6ViDH7GPm56po6oX7AsLiwqbITV4E,1534
23
+ docforge_sdk/resources/_base.py,sha256=NoDy86ccGsyAZJEU2KjW3NYYJlsypvjmEkQtAdhaS04,1499
24
+ docforge_sdk/resources/auth.py,sha256=a_6tIAX13BXasMN3TDeX7STSdbjZ7QiGMNX62q9y2mo,10042
25
+ docforge_sdk/resources/blobs.py,sha256=SGAEF8XGytf72TQDOFaDEd89_Tj_w88JOOhxO0vrIBs,2182
26
+ docforge_sdk/resources/collections.py,sha256=4yfkQwCcbH5Gj4rkStQeEiTxgzRPl1B8u09KMWe-cTA,6949
27
+ docforge_sdk/resources/documents.py,sha256=p5hrYBwJeLn5Ay7TOfWAmc085h2F32KqbUgN8naHzBY,6114
28
+ docforge_sdk/resources/explorer.py,sha256=BoDY-45Mp-7r097VNpzQOV974kfc_tmLH-ebWNsSDxM,11429
29
+ docforge_sdk/resources/health.py,sha256=WL7_iTwu533R8s7yG8qhB_RUJV4eB6ytKXRDXcB3ILg,1723
30
+ docforge_sdk/resources/jobs.py,sha256=gI679qu26o6RbayUcEsYxOGvwc_atYp40LD1JQkfdpM,5062
31
+ docforge_sdk/resources/pipelines.py,sha256=2A4PY5-wt3nrl5e8vKpl59gE9ws4qXELs2SJci-2Z34,10474
32
+ docforge_sdk/resources/search.py,sha256=b9H5gaRHxSWUukxbNvYMRfxA4CKo_Y-6Es6FVKMlJ4s,2522
33
+ docforge_sdk-0.1.0.dist-info/METADATA,sha256=39g7orUkcmCPSB9YgQ2_zc6wmcdustB41Jlhr9K3Yko,3779
34
+ docforge_sdk-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
35
+ docforge_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=tyuGDFWUibVB0DmTCdzAPFQPBobDYEuQr1pDHxNLTHU,1071
36
+ docforge_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Florian Barré
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.