predev-api 1.0.0__tar.gz → 1.1.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.
- {predev_api-1.0.0/predev_api.egg-info → predev_api-1.1.0}/PKG-INFO +49 -1
- {predev_api-1.0.0 → predev_api-1.1.0}/README.md +48 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/predev_api/__init__.py +16 -2
- {predev_api-1.0.0 → predev_api-1.1.0}/predev_api/client.py +59 -13
- predev_api-1.1.0/predev_api/exceptions.py +86 -0
- {predev_api-1.0.0 → predev_api-1.1.0/predev_api.egg-info}/PKG-INFO +49 -1
- {predev_api-1.0.0 → predev_api-1.1.0}/setup.py +1 -1
- predev_api-1.0.0/predev_api/exceptions.py +0 -18
- {predev_api-1.0.0 → predev_api-1.1.0}/LICENSE +0 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/MANIFEST.in +0 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/predev_api.egg-info/SOURCES.txt +0 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/predev_api.egg-info/dependency_links.txt +0 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/predev_api.egg-info/requires.txt +0 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/predev_api.egg-info/top_level.txt +0 -0
- {predev_api-1.0.0 → predev_api-1.1.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: predev-api
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Python client for the Pre.dev Architect API - Generate comprehensive software specifications
|
|
5
5
|
Home-page: https://github.com/predotdev/predev-api
|
|
6
6
|
Author: Pre.dev
|
|
@@ -653,3 +653,51 @@ print(f"{result['completed']}/{result['total']} done in {result['totalCreditsUse
|
|
|
653
653
|
- Minimum: **0.1 credits per task** ($0.01)
|
|
654
654
|
- 10x margin on underlying LLM + sandbox compute
|
|
655
655
|
- 1 credit = $0.10
|
|
656
|
+
|
|
657
|
+
### Error handling
|
|
658
|
+
|
|
659
|
+
The browser-task endpoints raise typed exceptions for the most common
|
|
660
|
+
gating cases. Every billing-gate exception carries an `action_url` — a
|
|
661
|
+
deep link back to pre.dev that auto-opens the right modal (subscribe /
|
|
662
|
+
buy credits) when the user lands there:
|
|
663
|
+
|
|
664
|
+
```python
|
|
665
|
+
from predev_api import (
|
|
666
|
+
PredevAPI,
|
|
667
|
+
InsufficientCreditsError,
|
|
668
|
+
SubscriptionRequiredError,
|
|
669
|
+
RateLimitError,
|
|
670
|
+
QueueFullError,
|
|
671
|
+
)
|
|
672
|
+
import webbrowser
|
|
673
|
+
|
|
674
|
+
client = PredevAPI(api_key="your_pre.dev_api_key")
|
|
675
|
+
|
|
676
|
+
try:
|
|
677
|
+
client.browser_agent([{"url": "https://example.com", "instruction": "extract h1"}])
|
|
678
|
+
except InsufficientCreditsError as e:
|
|
679
|
+
# Send the user to the credits modal — `action_url` is the canonical link.
|
|
680
|
+
if e.action_url:
|
|
681
|
+
webbrowser.open(e.action_url)
|
|
682
|
+
except SubscriptionRequiredError as e:
|
|
683
|
+
if e.action_url:
|
|
684
|
+
webbrowser.open(e.action_url)
|
|
685
|
+
except RateLimitError:
|
|
686
|
+
pass # back off and retry
|
|
687
|
+
except QueueFullError:
|
|
688
|
+
pass # wait for in-flight tasks to drain
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
Mid-stream errors on the SSE stream raise the same typed exceptions, so a
|
|
692
|
+
`for msg in client.browser_agent(..., stream=True):` loop wrapped in
|
|
693
|
+
`try/except` is enough — no special event handling required.
|
|
694
|
+
|
|
695
|
+
| Exception | HTTP | `code` |
|
|
696
|
+
|---|---|---|
|
|
697
|
+
| `SubscriptionRequiredError` | 402 | `SUBSCRIPTION_REQUIRED` |
|
|
698
|
+
| `InsufficientCreditsError` | 402 | `INSUFFICIENT_CREDITS` |
|
|
699
|
+
| `RateLimitError` | 429 | `RATE_LIMITED` |
|
|
700
|
+
| `QueueFullError` | 429 | `QUEUE_FULL` |
|
|
701
|
+
| `BatchTooLargeError` | 400 | `BATCH_TOO_LARGE` |
|
|
702
|
+
| `AuthenticationError` | 401 | — |
|
|
703
|
+
| `PredevAPIError` | other | — |
|
|
@@ -613,3 +613,51 @@ print(f"{result['completed']}/{result['total']} done in {result['totalCreditsUse
|
|
|
613
613
|
- Minimum: **0.1 credits per task** ($0.01)
|
|
614
614
|
- 10x margin on underlying LLM + sandbox compute
|
|
615
615
|
- 1 credit = $0.10
|
|
616
|
+
|
|
617
|
+
### Error handling
|
|
618
|
+
|
|
619
|
+
The browser-task endpoints raise typed exceptions for the most common
|
|
620
|
+
gating cases. Every billing-gate exception carries an `action_url` — a
|
|
621
|
+
deep link back to pre.dev that auto-opens the right modal (subscribe /
|
|
622
|
+
buy credits) when the user lands there:
|
|
623
|
+
|
|
624
|
+
```python
|
|
625
|
+
from predev_api import (
|
|
626
|
+
PredevAPI,
|
|
627
|
+
InsufficientCreditsError,
|
|
628
|
+
SubscriptionRequiredError,
|
|
629
|
+
RateLimitError,
|
|
630
|
+
QueueFullError,
|
|
631
|
+
)
|
|
632
|
+
import webbrowser
|
|
633
|
+
|
|
634
|
+
client = PredevAPI(api_key="your_pre.dev_api_key")
|
|
635
|
+
|
|
636
|
+
try:
|
|
637
|
+
client.browser_agent([{"url": "https://example.com", "instruction": "extract h1"}])
|
|
638
|
+
except InsufficientCreditsError as e:
|
|
639
|
+
# Send the user to the credits modal — `action_url` is the canonical link.
|
|
640
|
+
if e.action_url:
|
|
641
|
+
webbrowser.open(e.action_url)
|
|
642
|
+
except SubscriptionRequiredError as e:
|
|
643
|
+
if e.action_url:
|
|
644
|
+
webbrowser.open(e.action_url)
|
|
645
|
+
except RateLimitError:
|
|
646
|
+
pass # back off and retry
|
|
647
|
+
except QueueFullError:
|
|
648
|
+
pass # wait for in-flight tasks to drain
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
Mid-stream errors on the SSE stream raise the same typed exceptions, so a
|
|
652
|
+
`for msg in client.browser_agent(..., stream=True):` loop wrapped in
|
|
653
|
+
`try/except` is enough — no special event handling required.
|
|
654
|
+
|
|
655
|
+
| Exception | HTTP | `code` |
|
|
656
|
+
|---|---|---|
|
|
657
|
+
| `SubscriptionRequiredError` | 402 | `SUBSCRIPTION_REQUIRED` |
|
|
658
|
+
| `InsufficientCreditsError` | 402 | `INSUFFICIENT_CREDITS` |
|
|
659
|
+
| `RateLimitError` | 429 | `RATE_LIMITED` |
|
|
660
|
+
| `QueueFullError` | 429 | `QUEUE_FULL` |
|
|
661
|
+
| `BatchTooLargeError` | 400 | `BATCH_TOO_LARGE` |
|
|
662
|
+
| `AuthenticationError` | 401 | — |
|
|
663
|
+
| `PredevAPIError` | other | — |
|
|
@@ -27,14 +27,28 @@ from .client import (
|
|
|
27
27
|
AlternativeTechStackItemApi,
|
|
28
28
|
SpecEnrichedTechStackItem,
|
|
29
29
|
)
|
|
30
|
-
from .exceptions import
|
|
30
|
+
from .exceptions import (
|
|
31
|
+
PredevAPIError,
|
|
32
|
+
AuthenticationError,
|
|
33
|
+
RateLimitError,
|
|
34
|
+
SubscriptionRequiredError,
|
|
35
|
+
InsufficientCreditsError,
|
|
36
|
+
QueueFullError,
|
|
37
|
+
BatchTooLargeError,
|
|
38
|
+
exception_for_code,
|
|
39
|
+
)
|
|
31
40
|
|
|
32
|
-
__version__ = "1.
|
|
41
|
+
__version__ = "1.1.0"
|
|
33
42
|
__all__ = [
|
|
34
43
|
"PredevAPI",
|
|
35
44
|
"PredevAPIError",
|
|
36
45
|
"AuthenticationError",
|
|
37
46
|
"RateLimitError",
|
|
47
|
+
"SubscriptionRequiredError",
|
|
48
|
+
"InsufficientCreditsError",
|
|
49
|
+
"QueueFullError",
|
|
50
|
+
"BatchTooLargeError",
|
|
51
|
+
"exception_for_code",
|
|
38
52
|
"ZippedDocsUrl",
|
|
39
53
|
"SpecCoreFunctionality",
|
|
40
54
|
"SpecTechStackItem",
|
|
@@ -6,7 +6,16 @@ from typing import Optional, Dict, Any, Literal, List, Union, BinaryIO, Iterator
|
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
import json
|
|
8
8
|
import requests
|
|
9
|
-
from .exceptions import
|
|
9
|
+
from .exceptions import (
|
|
10
|
+
PredevAPIError,
|
|
11
|
+
AuthenticationError,
|
|
12
|
+
RateLimitError,
|
|
13
|
+
SubscriptionRequiredError,
|
|
14
|
+
InsufficientCreditsError,
|
|
15
|
+
QueueFullError,
|
|
16
|
+
BatchTooLargeError,
|
|
17
|
+
exception_for_code,
|
|
18
|
+
)
|
|
10
19
|
|
|
11
20
|
|
|
12
21
|
@dataclass
|
|
@@ -132,7 +141,9 @@ class SpecGraphNode:
|
|
|
132
141
|
label: str = ""
|
|
133
142
|
type: Optional[str] = None
|
|
134
143
|
description: Optional[str] = None
|
|
135
|
-
|
|
144
|
+
# userFlowGraph: BFS depth from roles (roles = 0, flows >= 1, None when
|
|
145
|
+
# unreachable). architectureGraph: C4 diagram level ("C1" | "C2").
|
|
146
|
+
level: Optional[Union[int, str]] = None
|
|
136
147
|
hours: Optional[float] = None
|
|
137
148
|
|
|
138
149
|
|
|
@@ -625,7 +636,7 @@ class PredevAPI:
|
|
|
625
636
|
include_events: Include full event timeline (can be large due to screenshots)
|
|
626
637
|
|
|
627
638
|
Returns:
|
|
628
|
-
Dict with id, total, completed, results,
|
|
639
|
+
Dict with id, total, completed, results, totalCreditsUsed, status
|
|
629
640
|
"""
|
|
630
641
|
qs = "?includeEvents=true" if include_events else ""
|
|
631
642
|
url = f"{self.base_url}/browser-agent/{batch_id}{qs}"
|
|
@@ -710,7 +721,7 @@ class PredevAPI:
|
|
|
710
721
|
get_browser_agent(id) for progress.
|
|
711
722
|
|
|
712
723
|
Returns:
|
|
713
|
-
Without stream: Dict with id, total, completed, results,
|
|
724
|
+
Without stream: Dict with id, total, completed, results, totalCreditsUsed
|
|
714
725
|
With stream: Iterator yielding dicts with 'event' and 'data' keys:
|
|
715
726
|
- event='task_event': real-time events (navigation, screenshot, plan, action, etc.)
|
|
716
727
|
- event='task_result': a single task completed
|
|
@@ -782,6 +793,18 @@ class PredevAPI:
|
|
|
782
793
|
current_event = line[7:].strip()
|
|
783
794
|
elif line.startswith("data: ") and current_event:
|
|
784
795
|
data = json.loads(line[6:])
|
|
796
|
+
# Mid-stream `error` events carry the same
|
|
797
|
+
# `{ error, code, actionUrl? }` shape the REST endpoints
|
|
798
|
+
# do — surface them as typed exceptions so callers can
|
|
799
|
+
# `except InsufficientCreditsError` cleanly.
|
|
800
|
+
if current_event == "error" and isinstance(data, dict):
|
|
801
|
+
raise exception_for_code(
|
|
802
|
+
data.get("code"),
|
|
803
|
+
data.get("error")
|
|
804
|
+
or data.get("message")
|
|
805
|
+
or "Browser agent error",
|
|
806
|
+
data.get("actionUrl") or data.get("action_url"),
|
|
807
|
+
)
|
|
785
808
|
yield {"event": current_event, "data": data}
|
|
786
809
|
current_event = ""
|
|
787
810
|
except requests.RequestException as e:
|
|
@@ -946,22 +969,45 @@ class PredevAPI:
|
|
|
946
969
|
return {"file": (filename, file)}
|
|
947
970
|
|
|
948
971
|
def _handle_response(self, response: requests.Response) -> None:
|
|
949
|
-
"""Handle API response and raise appropriate exceptions.
|
|
972
|
+
"""Handle API response and raise appropriate exceptions.
|
|
973
|
+
|
|
974
|
+
Browser-task gating errors come back as a structured body
|
|
975
|
+
``{"error": ..., "code": ..., "actionUrl": ...}`` (HTTP 402 / 429 /
|
|
976
|
+
400). We parse the body before short-circuiting on status code so
|
|
977
|
+
``code: SUBSCRIPTION_REQUIRED`` becomes :class:`SubscriptionRequiredError`
|
|
978
|
+
with its ``action_url`` populated, instead of a generic
|
|
979
|
+
:class:`PredevAPIError`.
|
|
980
|
+
"""
|
|
950
981
|
if response.status_code == 200:
|
|
951
982
|
return
|
|
952
983
|
|
|
984
|
+
# Try to parse the structured error body up front.
|
|
985
|
+
error_body = None
|
|
986
|
+
error_message = "Unknown error"
|
|
987
|
+
try:
|
|
988
|
+
error_body = response.json()
|
|
989
|
+
error_message = (
|
|
990
|
+
error_body.get("error")
|
|
991
|
+
or error_body.get("message")
|
|
992
|
+
or str(error_body)
|
|
993
|
+
)
|
|
994
|
+
except Exception:
|
|
995
|
+
error_message = response.text or f"HTTP {response.status_code}"
|
|
996
|
+
|
|
997
|
+
# Structured `code` wins — covers SUBSCRIPTION_REQUIRED /
|
|
998
|
+
# INSUFFICIENT_CREDITS / QUEUE_FULL / BATCH_TOO_LARGE / RATE_LIMITED.
|
|
999
|
+
if isinstance(error_body, dict) and error_body.get("code"):
|
|
1000
|
+
raise exception_for_code(
|
|
1001
|
+
error_body["code"],
|
|
1002
|
+
error_message,
|
|
1003
|
+
error_body.get("actionUrl") or error_body.get("action_url"),
|
|
1004
|
+
)
|
|
1005
|
+
|
|
953
1006
|
if response.status_code == 401:
|
|
954
1007
|
raise AuthenticationError("Invalid API key")
|
|
955
1008
|
|
|
956
1009
|
if response.status_code == 429:
|
|
957
|
-
raise RateLimitError(
|
|
958
|
-
|
|
959
|
-
try:
|
|
960
|
-
error_data = response.json()
|
|
961
|
-
error_message = error_data.get("error") or error_data.get(
|
|
962
|
-
"message") or str(error_data)
|
|
963
|
-
except Exception:
|
|
964
|
-
error_message = response.text or "Unknown error"
|
|
1010
|
+
raise RateLimitError(error_message)
|
|
965
1011
|
|
|
966
1012
|
raise PredevAPIError(
|
|
967
1013
|
f"API request failed with status {response.status_code}: {error_message}"
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom exceptions for the Pre.dev API client.
|
|
3
|
+
|
|
4
|
+
Browser-task gating errors carry the same shape as the Node SDK:
|
|
5
|
+
``code`` selects a typed exception, and ``action_url`` is a deep link
|
|
6
|
+
back to pre.dev that auto-opens the right billing modal (subscribe /
|
|
7
|
+
buy credits) when the user lands there. Older endpoints just return
|
|
8
|
+
``{"error": "..."}`` and surface as ``PredevAPIError``.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PredevAPIError(Exception):
|
|
15
|
+
"""Base exception for Pre.dev API errors."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AuthenticationError(PredevAPIError):
|
|
20
|
+
"""Raised when authentication fails (HTTP 401)."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class RateLimitError(PredevAPIError):
|
|
25
|
+
"""Raised when a request is rate-limited (HTTP 429, ``code: RATE_LIMITED``)."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SubscriptionRequiredError(PredevAPIError):
|
|
30
|
+
"""HTTP 402, ``code: SUBSCRIPTION_REQUIRED``.
|
|
31
|
+
|
|
32
|
+
Trial limit reached on this API key — the user needs an active
|
|
33
|
+
subscription to keep running browser-agent tasks.
|
|
34
|
+
|
|
35
|
+
``action_url``, when present, is a deep link back to pre.dev that
|
|
36
|
+
auto-opens the subscribe modal.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, message: str, action_url: Optional[str] = None):
|
|
40
|
+
super().__init__(message)
|
|
41
|
+
self.action_url = action_url
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class InsufficientCreditsError(PredevAPIError):
|
|
45
|
+
"""HTTP 402, ``code: INSUFFICIENT_CREDITS``.
|
|
46
|
+
|
|
47
|
+
Subscription is fine but the credit balance is too low to cover this
|
|
48
|
+
request. ``action_url`` deep-links to the credit-purchase modal.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, message: str, action_url: Optional[str] = None):
|
|
52
|
+
super().__init__(message)
|
|
53
|
+
self.action_url = action_url
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class QueueFullError(PredevAPIError):
|
|
57
|
+
"""HTTP 429, ``code: QUEUE_FULL`` — too many in-flight tasks for this user."""
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class BatchTooLargeError(PredevAPIError):
|
|
62
|
+
"""HTTP 400, ``code: BATCH_TOO_LARGE`` — request had more tasks than the per-batch maximum."""
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def exception_for_code(
|
|
67
|
+
code: Optional[str],
|
|
68
|
+
message: str,
|
|
69
|
+
action_url: Optional[str] = None,
|
|
70
|
+
) -> PredevAPIError:
|
|
71
|
+
"""Map a structured error ``code`` to the right typed exception.
|
|
72
|
+
|
|
73
|
+
Falls back to :class:`PredevAPIError` for unknown codes so callers
|
|
74
|
+
that just want ``str(e)`` keep working.
|
|
75
|
+
"""
|
|
76
|
+
if code == "SUBSCRIPTION_REQUIRED":
|
|
77
|
+
return SubscriptionRequiredError(message, action_url)
|
|
78
|
+
if code == "INSUFFICIENT_CREDITS":
|
|
79
|
+
return InsufficientCreditsError(message, action_url)
|
|
80
|
+
if code == "QUEUE_FULL":
|
|
81
|
+
return QueueFullError(message)
|
|
82
|
+
if code == "BATCH_TOO_LARGE":
|
|
83
|
+
return BatchTooLargeError(message)
|
|
84
|
+
if code == "RATE_LIMITED":
|
|
85
|
+
return RateLimitError(message)
|
|
86
|
+
return PredevAPIError(message)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: predev-api
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Python client for the Pre.dev Architect API - Generate comprehensive software specifications
|
|
5
5
|
Home-page: https://github.com/predotdev/predev-api
|
|
6
6
|
Author: Pre.dev
|
|
@@ -653,3 +653,51 @@ print(f"{result['completed']}/{result['total']} done in {result['totalCreditsUse
|
|
|
653
653
|
- Minimum: **0.1 credits per task** ($0.01)
|
|
654
654
|
- 10x margin on underlying LLM + sandbox compute
|
|
655
655
|
- 1 credit = $0.10
|
|
656
|
+
|
|
657
|
+
### Error handling
|
|
658
|
+
|
|
659
|
+
The browser-task endpoints raise typed exceptions for the most common
|
|
660
|
+
gating cases. Every billing-gate exception carries an `action_url` — a
|
|
661
|
+
deep link back to pre.dev that auto-opens the right modal (subscribe /
|
|
662
|
+
buy credits) when the user lands there:
|
|
663
|
+
|
|
664
|
+
```python
|
|
665
|
+
from predev_api import (
|
|
666
|
+
PredevAPI,
|
|
667
|
+
InsufficientCreditsError,
|
|
668
|
+
SubscriptionRequiredError,
|
|
669
|
+
RateLimitError,
|
|
670
|
+
QueueFullError,
|
|
671
|
+
)
|
|
672
|
+
import webbrowser
|
|
673
|
+
|
|
674
|
+
client = PredevAPI(api_key="your_pre.dev_api_key")
|
|
675
|
+
|
|
676
|
+
try:
|
|
677
|
+
client.browser_agent([{"url": "https://example.com", "instruction": "extract h1"}])
|
|
678
|
+
except InsufficientCreditsError as e:
|
|
679
|
+
# Send the user to the credits modal — `action_url` is the canonical link.
|
|
680
|
+
if e.action_url:
|
|
681
|
+
webbrowser.open(e.action_url)
|
|
682
|
+
except SubscriptionRequiredError as e:
|
|
683
|
+
if e.action_url:
|
|
684
|
+
webbrowser.open(e.action_url)
|
|
685
|
+
except RateLimitError:
|
|
686
|
+
pass # back off and retry
|
|
687
|
+
except QueueFullError:
|
|
688
|
+
pass # wait for in-flight tasks to drain
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
Mid-stream errors on the SSE stream raise the same typed exceptions, so a
|
|
692
|
+
`for msg in client.browser_agent(..., stream=True):` loop wrapped in
|
|
693
|
+
`try/except` is enough — no special event handling required.
|
|
694
|
+
|
|
695
|
+
| Exception | HTTP | `code` |
|
|
696
|
+
|---|---|---|
|
|
697
|
+
| `SubscriptionRequiredError` | 402 | `SUBSCRIPTION_REQUIRED` |
|
|
698
|
+
| `InsufficientCreditsError` | 402 | `INSUFFICIENT_CREDITS` |
|
|
699
|
+
| `RateLimitError` | 429 | `RATE_LIMITED` |
|
|
700
|
+
| `QueueFullError` | 429 | `QUEUE_FULL` |
|
|
701
|
+
| `BatchTooLargeError` | 400 | `BATCH_TOO_LARGE` |
|
|
702
|
+
| `AuthenticationError` | 401 | — |
|
|
703
|
+
| `PredevAPIError` | other | — |
|
|
@@ -9,7 +9,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="predev-api",
|
|
12
|
-
version="1.
|
|
12
|
+
version="1.1.0",
|
|
13
13
|
author="Pre.dev",
|
|
14
14
|
author_email="support@pre.dev",
|
|
15
15
|
description="Python client for the Pre.dev Architect API - Generate comprehensive software specifications",
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Custom exceptions for the Pre.dev API client
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class PredevAPIError(Exception):
|
|
7
|
-
"""Base exception for Pre.dev API errors."""
|
|
8
|
-
pass
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class AuthenticationError(PredevAPIError):
|
|
12
|
-
"""Raised when authentication fails."""
|
|
13
|
-
pass
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class RateLimitError(PredevAPIError):
|
|
17
|
-
"""Raised when rate limit is exceeded."""
|
|
18
|
-
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|