docforge-sdk 0.16.0__tar.gz → 0.16.2__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 (78) hide show
  1. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/PKG-INFO +2 -2
  2. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/README.md +1 -1
  3. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/__init__.py +6 -0
  4. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/_version.py +1 -1
  5. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/client.py +5 -0
  6. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/__init__.py +6 -0
  7. docforge_sdk-0.16.2/docforge_sdk/models/capabilities.py +103 -0
  8. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/collections.py +6 -6
  9. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/jobs.py +11 -2
  10. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/__init__.py +5 -0
  11. docforge_sdk-0.16.2/docforge_sdk/resources/capabilities.py +54 -0
  12. docforge_sdk-0.16.2/tests/openapi_snapshot.json +1 -0
  13. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/parity_map.py +9 -0
  14. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/route_map.py +2 -0
  15. docforge_sdk-0.16.0/tests/openapi_snapshot.json +0 -1
  16. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/.gitignore +0 -0
  17. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/.python-version +0 -0
  18. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/LICENSE +0 -0
  19. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/_exceptions.py +0 -0
  20. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/_requestspec.py +0 -0
  21. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/_transport_async.py +0 -0
  22. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/_transport_base.py +0 -0
  23. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/_transport_sync.py +0 -0
  24. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/_shared.py +0 -0
  25. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/audit.py +0 -0
  26. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/auth.py +0 -0
  27. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/blobs.py +0 -0
  28. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/corpus.py +0 -0
  29. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/documents.py +0 -0
  30. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/estimate.py +0 -0
  31. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/explorer.py +0 -0
  32. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/health.py +0 -0
  33. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/ir.py +0 -0
  34. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/pipelines.py +0 -0
  35. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/reingest.py +0 -0
  36. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/search.py +0 -0
  37. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/snippets.py +0 -0
  38. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/storage.py +0 -0
  39. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/models/transfers.py +0 -0
  40. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/py.typed +0 -0
  41. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/_base.py +0 -0
  42. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/audit.py +0 -0
  43. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/auth.py +0 -0
  44. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/blobs.py +0 -0
  45. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/collections.py +0 -0
  46. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/corpus.py +0 -0
  47. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/documents.py +0 -0
  48. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/explorer.py +0 -0
  49. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/health.py +0 -0
  50. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/jobs.py +0 -0
  51. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/pipelines.py +0 -0
  52. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/search.py +0 -0
  53. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/snippets.py +0 -0
  54. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/docforge_sdk/resources/transfers.py +0 -0
  55. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/pyproject.toml +0 -0
  56. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/__init__.py +0 -0
  57. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/check_schema_drift.py +0 -0
  58. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/live/__init__.py +0 -0
  59. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/live/test_openapi_parity_live.py +0 -0
  60. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/__init__.py +0 -0
  61. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_audit.py +0 -0
  62. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_auth.py +0 -0
  63. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_blobs.py +0 -0
  64. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_collections.py +0 -0
  65. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_corpus.py +0 -0
  66. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_documents.py +0 -0
  67. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_explorer.py +0 -0
  68. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_health.py +0 -0
  69. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_jobs.py +0 -0
  70. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_models_offline_parity.py +0 -0
  71. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_pipelines.py +0 -0
  72. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_resource_parity.py +0 -0
  73. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_route_coverage.py +0 -0
  74. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_search.py +0 -0
  75. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_snippets.py +0 -0
  76. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_transfers.py +0 -0
  77. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/tests/unit/test_transport.py +0 -0
  78. {docforge_sdk-0.16.0 → docforge_sdk-0.16.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: docforge-sdk
3
- Version: 0.16.0
3
+ Version: 0.16.2
4
4
  Summary: Typed async + sync Python client for the DocForge REST API (standalone, zero server deps).
5
5
  Project-URL: Homepage, https://github.com/Florian-BARRE/docforge
6
6
  Project-URL: Repository, https://github.com/Florian-BARRE/docforge
@@ -304,7 +304,7 @@ with Client("http://localhost:10040", api_token="df_...") as client:
304
304
  ```
305
305
 
306
306
  Key `CreateCollectionRequest` fields beyond the schema: `max_file_size_bytes` (bytes) and
307
- `job_timeout_seconds` (`float | None`, seconds) — the whole-ingest-job wall-clock budget for that
307
+ `job_timeout_seconds` (`float | None`, seconds) — the whole-ingest-job wall-clock job timeout for that
308
308
  collection; `None` (the default) inherits the worker's global job-timeout default. Same field, same
309
309
  semantics on `CollectionModel` (read) and `UpdateCollectionRequest` (write; there, omitting it
310
310
  leaves the current value unchanged, a set value overrides it).
@@ -281,7 +281,7 @@ with Client("http://localhost:10040", api_token="df_...") as client:
281
281
  ```
282
282
 
283
283
  Key `CreateCollectionRequest` fields beyond the schema: `max_file_size_bytes` (bytes) and
284
- `job_timeout_seconds` (`float | None`, seconds) — the whole-ingest-job wall-clock budget for that
284
+ `job_timeout_seconds` (`float | None`, seconds) — the whole-ingest-job wall-clock job timeout for that
285
285
  collection; `None` (the default) inherits the worker's global job-timeout default. Same field, same
286
286
  semantics on `CollectionModel` (read) and `UpdateCollectionRequest` (write; there, omitting it
287
287
  leaves the current value unchanged, a set value overrides it).
@@ -36,6 +36,9 @@ from .models.auth import CreatedKey, CreateKeyRequest, KeyInfo, RotateKeyRequest
36
36
  # ------------------- Blobs models ------------------- #
37
37
  from .models.blobs import BlobContent
38
38
 
39
+ # ------------------- Capabilities models ------------------- #
40
+ from .models.capabilities import CapabilitiesResponse, CapabilityMatrix, ServiceInfo
41
+
39
42
  # ------------------- Collections models ------------------- #
40
43
  from .models.collections import (
41
44
  BulkReingestAccepted,
@@ -201,6 +204,9 @@ __all__ = [
201
204
  "CancelResult",
202
205
  # Blobs
203
206
  "BlobContent",
207
+ "CapabilitiesResponse",
208
+ "CapabilityMatrix",
209
+ "ServiceInfo",
204
210
  # Pipelines
205
211
  "PipelineSurface",
206
212
  "PipelineIndexResponse",
@@ -2,4 +2,4 @@
2
2
  # Single source of truth for the package version. Hatchling reads ``__version__`` from this file to
3
3
  # populate the distribution metadata (see ``[tool.hatch.version]`` in pyproject.toml).
4
4
 
5
- __version__ = "0.16.0"
5
+ __version__ = "0.16.2"
@@ -12,6 +12,7 @@ from ._transport_sync import SyncTransport
12
12
  from .resources.audit import AsyncAudit, SyncAudit
13
13
  from .resources.auth import AsyncAuth, SyncAuth
14
14
  from .resources.blobs import AsyncBlobs, SyncBlobs
15
+ from .resources.capabilities import AsyncCapabilities, SyncCapabilities
15
16
  from .resources.collections import AsyncCollections, SyncCollections
16
17
  from .resources.corpus import AsyncCorpus, SyncCorpus
17
18
  from .resources.documents import AsyncDocuments, SyncDocuments
@@ -31,6 +32,7 @@ class AsyncClient:
31
32
  Attributes:
32
33
  auth (AsyncAuth): API-key management resource.
33
34
  health (AsyncHealth): Liveness probe.
35
+ capabilities (AsyncCapabilities): Public deployment discovery.
34
36
  collections (AsyncCollections): Collection CRUD.
35
37
  documents (AsyncDocuments): Document admission + searchability control.
36
38
  explorer (AsyncExplorer): Document/chunk read surface + IR + toggles.
@@ -57,6 +59,7 @@ class AsyncClient:
57
59
  self.audit = AsyncAudit(self._transport)
58
60
  self.auth = AsyncAuth(self._transport)
59
61
  self.health = AsyncHealth(self._transport)
62
+ self.capabilities = AsyncCapabilities(self._transport)
60
63
  self.collections = AsyncCollections(self._transport)
61
64
  self.documents = AsyncDocuments(self._transport)
62
65
  self.explorer = AsyncExplorer(self._transport)
@@ -93,6 +96,7 @@ class Client:
93
96
  Attributes:
94
97
  auth (SyncAuth): API-key management resource.
95
98
  health (SyncHealth): Liveness probe.
99
+ capabilities (SyncCapabilities): Public deployment discovery.
96
100
  collections (SyncCollections): Collection CRUD.
97
101
  documents (SyncDocuments): Document admission + searchability control.
98
102
  explorer (SyncExplorer): Document/chunk read surface + IR + toggles.
@@ -119,6 +123,7 @@ class Client:
119
123
  self.audit = SyncAudit(self._transport)
120
124
  self.auth = SyncAuth(self._transport)
121
125
  self.health = SyncHealth(self._transport)
126
+ self.capabilities = SyncCapabilities(self._transport)
122
127
  self.collections = SyncCollections(self._transport)
123
128
  self.documents = SyncDocuments(self._transport)
124
129
  self.explorer = SyncExplorer(self._transport)
@@ -20,6 +20,9 @@ from .auth import CreatedKey, CreateKeyRequest, KeyInfo, RotateKeyRequest, WhoAm
20
20
  # ------------------- Blobs models ------------------- #
21
21
  from .blobs import BlobContent
22
22
 
23
+ # ------------------- Capabilities models ------------------- #
24
+ from .capabilities import CapabilitiesResponse, CapabilityMatrix, ServiceInfo
25
+
23
26
  # ------------------- Collections models ------------------- #
24
27
  from .collections import (
25
28
  BulkReingestAccepted,
@@ -253,6 +256,9 @@ __all__ = [
253
256
  "CancelResult",
254
257
  # Blobs
255
258
  "BlobContent",
259
+ "CapabilitiesResponse",
260
+ "CapabilityMatrix",
261
+ "ServiceInfo",
256
262
  # Pipelines
257
263
  "PipelineSurface",
258
264
  "PipelineIndexResponse",
@@ -0,0 +1,103 @@
1
+ # ====== Code Summary ======
2
+ # Response models for the capabilities resource, mirrored field-for-field from the DocForge backend
3
+ # router models (app/backend/libs/capabilities/models.py): the deployment self-description served by
4
+ # the public GET /capabilities — running version, auth state, derived GPU presence, the infra stores +
5
+ # optional sidecars (reachability + what each unlocks) and the available pipeline kinds per family.
6
+
7
+ # ====== Third-Party Library Imports ======
8
+ from pydantic import BaseModel, Field
9
+
10
+
11
+ class ServiceInfo(BaseModel):
12
+ """
13
+ One infra store or optional sidecar of the deployment.
14
+
15
+ Attributes:
16
+ name (str): Stable service name (compose service / network alias).
17
+ role (str): Short role label (e.g. ``"vector"``, ``"embed"``, ``"parse-ocr"``).
18
+ reachable (bool): Sidecar: its short-cached ``/health`` probe currently passes. Store:
19
+ configured (declared, not live-probed — see ``detail``).
20
+ device (str | None): The compute device the sidecar reports at ``/health`` when it exposes one;
21
+ ``None`` when unknown or not applicable (stores).
22
+ provides (list[str]): The capability ids (``"family:kind"``) this service enables — empty for
23
+ infra stores.
24
+ detail (str | None): Optional short status note.
25
+ """
26
+
27
+ name: str = Field(description="Stable service name (compose service / network alias).")
28
+ role: str = Field(description="Short role label (e.g. 'vector', 'embed', 'parse-ocr').")
29
+ reachable: bool = Field(
30
+ description="Sidecar: /health probe currently passes. Store: configured (declared, not probed)."
31
+ )
32
+ device: str | None = Field(
33
+ default=None,
34
+ description="Device the sidecar reports at /health ('cuda'/'cpu'); None when unknown.",
35
+ )
36
+ provides: list[str] = Field(
37
+ default_factory=list,
38
+ description="Capability ids ('family:kind') this service enables (empty for infra stores).",
39
+ )
40
+ detail: str | None = Field(default=None, description="Optional short status note.")
41
+
42
+
43
+ class CapabilityMatrix(BaseModel):
44
+ """
45
+ The available pipeline kinds per family — 'what can this deployment do NOW'.
46
+
47
+ Each list holds the SELECTABLE kinds of that family whose requirement is satisfied: in-worker or
48
+ per-collection-key kinds are always listed; a sidecar-gated kind is listed only while its sidecar
49
+ is reachable. ``metagen`` delegates to the ``llm`` family, so it is legitimately empty.
50
+
51
+ Attributes:
52
+ parsers (list[str]): Available ``parser`` kinds.
53
+ ocr (list[str]): Available ``ocr`` kinds.
54
+ embed (list[str]): Available ``embed`` kinds.
55
+ chunkers (list[str]): Available ``chunker`` kinds.
56
+ vlm (list[str]): Available ``vlm`` kinds.
57
+ llm (list[str]): Available ``llm`` kinds.
58
+ rerank (list[str]): Available ``rerank`` kinds.
59
+ contextualize (list[str]): Available ``contextualize`` kinds.
60
+ metagen (list[str]): Available ``metagen`` kinds (delegates to ``llm``; usually empty).
61
+ """
62
+
63
+ parsers: list[str] = Field(default_factory=list, description="Available parser kinds.")
64
+ ocr: list[str] = Field(default_factory=list, description="Available ocr kinds.")
65
+ embed: list[str] = Field(default_factory=list, description="Available embed kinds.")
66
+ chunkers: list[str] = Field(default_factory=list, description="Available chunker kinds.")
67
+ vlm: list[str] = Field(default_factory=list, description="Available vlm kinds.")
68
+ llm: list[str] = Field(default_factory=list, description="Available llm kinds.")
69
+ rerank: list[str] = Field(default_factory=list, description="Available rerank kinds.")
70
+ contextualize: list[str] = Field(
71
+ default_factory=list, description="Available contextualize kinds."
72
+ )
73
+ metagen: list[str] = Field(default_factory=list, description="Available metagen kinds.")
74
+
75
+
76
+ class CapabilitiesResponse(BaseModel):
77
+ """
78
+ The deployment capabilities snapshot returned by GET /capabilities.
79
+
80
+ Attributes:
81
+ version (str): The running app/image version (``FASTAPI_APP_VERSION`` / ``DOCFORGE_TAG``).
82
+ auth_enabled (bool): Whether API-key bearer auth gates ``/api/v1`` on this deployment.
83
+ gpu_present (bool | None): True when any reachable sidecar reports device ``"cuda"``; False when
84
+ reachable sidecars report only non-cuda devices; None when no device info is available.
85
+ services (list[ServiceInfo]): The infra stores + optional sidecars.
86
+ capabilities (CapabilityMatrix): The available pipeline kinds per family.
87
+ """
88
+
89
+ version: str = Field(
90
+ description="Running app/image version (FASTAPI_APP_VERSION / DOCFORGE_TAG)."
91
+ )
92
+ auth_enabled: bool = Field(description="Whether API-key bearer auth gates /api/v1.")
93
+ gpu_present: bool | None = Field(
94
+ default=None,
95
+ description="True if any reachable sidecar reports device 'cuda'; None when unknown.",
96
+ )
97
+ services: list[ServiceInfo] = Field(
98
+ default_factory=list, description="Infra stores + optional sidecars."
99
+ )
100
+ capabilities: CapabilityMatrix = Field(description="Available pipeline kinds per family.")
101
+
102
+
103
+ __all__ = ["ServiceInfo", "CapabilityMatrix", "CapabilitiesResponse"]
@@ -59,7 +59,7 @@ class CollectionModel(BaseModel):
59
59
  name (str): Unique human name.
60
60
  supported_formats (list[str]): Accepted upload extensions (e.g. pdf).
61
61
  max_file_size_bytes (int): Upload size ceiling, bytes.
62
- job_timeout_seconds (float | None): Per-collection whole-ingest-job wall-clock budget,
62
+ job_timeout_seconds (float | None): Per-collection whole-ingest-job wall-clock job timeout,
63
63
  seconds. None = inherit the worker's global WORKER_JOB_TIMEOUT_SECONDS default.
64
64
  needs_reindex (bool): True when a config change requires reindexing.
65
65
  created_at (datetime | None): Creation timestamp.
@@ -82,7 +82,7 @@ class CollectionModel(BaseModel):
82
82
  default=None,
83
83
  gt=0,
84
84
  description=(
85
- "Per-collection whole-ingest-job wall-clock budget, seconds. None = inherit the "
85
+ "Per-collection whole-ingest-job wall-clock job timeout, seconds. None = inherit the "
86
86
  "worker's global WORKER_JOB_TIMEOUT_SECONDS default."
87
87
  ),
88
88
  )
@@ -132,7 +132,7 @@ class CreateCollectionRequest(BaseModel):
132
132
  name (str): Unique human name.
133
133
  supported_formats (list[str]): Accepted upload extensions (e.g. pdf).
134
134
  max_file_size_bytes (int): Upload size ceiling, bytes.
135
- job_timeout_seconds (float | None): Per-collection whole-ingest-job wall-clock budget,
135
+ job_timeout_seconds (float | None): Per-collection whole-ingest-job wall-clock job timeout,
136
136
  seconds. None = inherit the worker's global WORKER_JOB_TIMEOUT_SECONDS default.
137
137
  fields (list[FieldSpec]): The FULL schema, declared up front (vector space is fixed).
138
138
  pipeline (dict[str, Any] | None): The pipeline blob; omitted → the product default.
@@ -149,7 +149,7 @@ class CreateCollectionRequest(BaseModel):
149
149
  default=None,
150
150
  gt=0,
151
151
  description=(
152
- "Per-collection whole-ingest-job wall-clock budget, seconds. None = inherit the "
152
+ "Per-collection whole-ingest-job wall-clock job timeout, seconds. None = inherit the "
153
153
  "worker's global WORKER_JOB_TIMEOUT_SECONDS default."
154
154
  ),
155
155
  )
@@ -186,7 +186,7 @@ class UpdateCollectionRequest(BaseModel):
186
186
  supported_formats (list[str] | None): New accepted upload extensions.
187
187
  max_file_size_bytes (int | None): New size ceiling, bytes.
188
188
  job_timeout_seconds (float | None): New per-collection whole-ingest-job wall-clock
189
- budget, seconds. Omitted = leave the current value unchanged.
189
+ job timeout, seconds. Omitted = leave the current value unchanged.
190
190
  fields (list[FieldSpec] | None): The TARGET schema (diffed by field name).
191
191
  pipeline (dict[str, Any] | None): New pipeline blob (validated before storage).
192
192
  search (dict[str, Any] | None): New search graph blob ({} = stock default).
@@ -210,7 +210,7 @@ class UpdateCollectionRequest(BaseModel):
210
210
  default=None,
211
211
  gt=0,
212
212
  description=(
213
- "New per-collection whole-ingest-job wall-clock budget, seconds. Omitted = leave the "
213
+ "New per-collection whole-ingest-job wall-clock job timeout, seconds. Omitted = leave the "
214
214
  "current value unchanged; a set value overrides the global WORKER_JOB_TIMEOUT_SECONDS."
215
215
  ),
216
216
  )
@@ -40,7 +40,10 @@ class JobStatus(BaseModel):
40
40
  failed_node_id (str | None): The deepest node that raised — only set on a failed job.
41
41
  failed_node_kind (str | None): That node's kind/family label — only set on a failed job.
42
42
  failed_item_index (int | None): The fan-out item index the failure sits in (None outside one).
43
- error_type (str | None): The exception class name of the failure (e.g. "TimeoutError").
43
+ error_type (str | None): Structured cause of the failure — usually the raising exception's
44
+ class name (e.g. "TimeoutError"), plus the reaper's attributed "worker_killed" (process
45
+ lost — crash/OOM) and "job_timeout_exceeded" (a stage wedged past the job timeout on a
46
+ live worker).
44
47
  """
45
48
 
46
49
  job_id: str = Field(description="The job row's UUID.")
@@ -101,7 +104,13 @@ class JobStatus(BaseModel):
101
104
  default=None, description="Fan-out item index the failure sits in (None outside a fan-out)."
102
105
  )
103
106
  error_type: str | None = Field(
104
- default=None, description="Exception class name of the failure (e.g. 'TimeoutError')."
107
+ default=None,
108
+ description=(
109
+ "Structured cause of the failure. Usually the raising exception's class name (e.g. "
110
+ "'TimeoutError'); the reaper also attributes 'worker_killed' (the worker process was "
111
+ "lost — crash/OOM-kill) and 'job_timeout_exceeded' (a stage wedged past the job's "
112
+ "timeout on a live worker). Set only on a failed job."
113
+ ),
105
114
  )
106
115
 
107
116
 
@@ -10,6 +10,9 @@ from .auth import AsyncAuth, SyncAuth
10
10
  # ------------------- Blobs resource ------------------- #
11
11
  from .blobs import AsyncBlobs, SyncBlobs
12
12
 
13
+ # ------------------- Capabilities resource ------------------- #
14
+ from .capabilities import AsyncCapabilities, SyncCapabilities
15
+
13
16
  # ------------------- Collections resource ------------------- #
14
17
  from .collections import AsyncCollections, SyncCollections
15
18
 
@@ -56,6 +59,8 @@ __all__ = [
56
59
  "SyncJobs",
57
60
  "AsyncBlobs",
58
61
  "SyncBlobs",
62
+ "AsyncCapabilities",
63
+ "SyncCapabilities",
59
64
  "AsyncPipelines",
60
65
  "SyncPipelines",
61
66
  "AsyncTransfers",
@@ -0,0 +1,54 @@
1
+ # ====== Code Summary ======
2
+ # The capabilities (deployment discovery) resource. Like /health, GET /capabilities lives at the BARE
3
+ # origin (outside /api/v1), so both shells route through the transport's request_bare helper rather
4
+ # than the versioned request. All URL logic lives once in the pure _CapabilitiesSpecs mixin; the
5
+ # async/sync shells differ only by await.
6
+
7
+ # ====== Local Project Imports ======
8
+ from .._requestspec import RequestSpec
9
+ from ..models.capabilities import CapabilitiesResponse
10
+ from ._base import AsyncResource, SyncResource, _ResourceMixin
11
+
12
+
13
+ class _CapabilitiesSpecs(_ResourceMixin):
14
+ """Pure ``RequestSpec`` builders for the capabilities endpoint — the single source of URL logic."""
15
+
16
+ _CAPABILITIES_PATH = "/capabilities"
17
+
18
+ def _describe_spec(self) -> RequestSpec:
19
+ """
20
+ Build the spec for the deployment discovery call.
21
+
22
+ Returns:
23
+ RequestSpec: A GET on the bare-root ``/capabilities`` route (outside ``/api/v1``).
24
+ """
25
+ return RequestSpec("GET", self._CAPABILITIES_PATH)
26
+
27
+
28
+ class AsyncCapabilities(AsyncResource, _CapabilitiesSpecs):
29
+ """Asynchronous deployment discovery."""
30
+
31
+ async def capabilities(self) -> CapabilitiesResponse:
32
+ """
33
+ Discover what this deployment can do right now.
34
+
35
+ Returns:
36
+ CapabilitiesResponse: Version, auth state, GPU presence, the service list and the matrix.
37
+ """
38
+ return await self._transport.request_bare(self._describe_spec(), CapabilitiesResponse)
39
+
40
+
41
+ class SyncCapabilities(SyncResource, _CapabilitiesSpecs):
42
+ """Synchronous deployment discovery."""
43
+
44
+ def capabilities(self) -> CapabilitiesResponse:
45
+ """
46
+ Discover what this deployment can do right now.
47
+
48
+ Returns:
49
+ CapabilitiesResponse: Version, auth state, GPU presence, the service list and the matrix.
50
+ """
51
+ return self._transport.request_bare(self._describe_spec(), CapabilitiesResponse)
52
+
53
+
54
+ __all__ = ["AsyncCapabilities", "SyncCapabilities"]