paive-agents 0.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.
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: paive-agents
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for the Paive patent intelligence report API
5
+ License: Proprietary
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: requests>=2.28
9
+ Requires-Dist: httpx>=0.24
10
+
11
+ # paive-agents
12
+
13
+ Official Python SDK for the Paive patent intelligence report API.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install paive-agents
19
+ ```
20
+
21
+ ## Before publishing publicly
22
+
23
+ `src/paive_agents/client.py` currently defaults to a staging server:
24
+
25
+ ```python
26
+ DEFAULT_BASE_URL = "http://34.29.194.252:8000"
27
+ ```
28
+
29
+ This is a working staging link (plain HTTP, IP-based). Before publishing this package
30
+ anywhere public (PyPI, external customers), swap this for your real production domain
31
+ over HTTPS. Until then, this default is fine for internal testing.
32
+
33
+ ## Sync usage
34
+
35
+ ```python
36
+ from paive_agents import Client
37
+
38
+ client = Client(api_key="YOUR_API_KEY")
39
+
40
+ report = client.generate_report(
41
+ patent_id="US12093418B2",
42
+ tech_sector="Biotech / Therapeutics",
43
+ clp_factors=["Application Effect", "Benchmarking Data"],
44
+ market_factors=["Application Effect"],
45
+ licensing_factors=["Application Effect"],
46
+ )
47
+
48
+ print(report.pdf_file)
49
+ ```
50
+
51
+ ## Async usage
52
+
53
+ ```python
54
+ from paive_agents import AsyncClient
55
+
56
+ client = AsyncClient(api_key="YOUR_API_KEY")
57
+ report = await client.generate_report(patent_id="US12093418B2")
58
+ ```
59
+
60
+ ## PDF upload instead of patent_id
61
+
62
+ ```python
63
+ report = client.generate_report(pdf_path="/path/to/patent.pdf")
64
+ ```
65
+
66
+ ## Errors
67
+
68
+ All errors subclass `paive_agents.PaiveError` and carry `.status_code` and `.response_body`:
69
+
70
+ - `AuthenticationError` — invalid/missing API key (401)
71
+ - `PermissionDeniedError` — user lacks permission (403)
72
+ - `InvalidRequestError` — bad request (400/404)
73
+ - `RateLimitError` — usage limit exceeded (429)
74
+ - `ServerError` — server-side failure (500+)
75
+ - `APIConnectionError` — network/connection failure
76
+
77
+ ## What this SDK does NOT change
78
+
79
+ This package only talks to the existing `/api/keys/generate_report` endpoint over HTTP,
80
+ using the same field names and the same `X-API-Key` auth your Django backend already expects.
81
+ No backend files were modified to build this SDK.
@@ -0,0 +1,71 @@
1
+ # paive-agents
2
+
3
+ Official Python SDK for the Paive patent intelligence report API.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install paive-agents
9
+ ```
10
+
11
+ ## Before publishing publicly
12
+
13
+ `src/paive_agents/client.py` currently defaults to a staging server:
14
+
15
+ ```python
16
+ DEFAULT_BASE_URL = "http://34.29.194.252:8000"
17
+ ```
18
+
19
+ This is a working staging link (plain HTTP, IP-based). Before publishing this package
20
+ anywhere public (PyPI, external customers), swap this for your real production domain
21
+ over HTTPS. Until then, this default is fine for internal testing.
22
+
23
+ ## Sync usage
24
+
25
+ ```python
26
+ from paive_agents import Client
27
+
28
+ client = Client(api_key="YOUR_API_KEY")
29
+
30
+ report = client.generate_report(
31
+ patent_id="US12093418B2",
32
+ tech_sector="Biotech / Therapeutics",
33
+ clp_factors=["Application Effect", "Benchmarking Data"],
34
+ market_factors=["Application Effect"],
35
+ licensing_factors=["Application Effect"],
36
+ )
37
+
38
+ print(report.pdf_file)
39
+ ```
40
+
41
+ ## Async usage
42
+
43
+ ```python
44
+ from paive_agents import AsyncClient
45
+
46
+ client = AsyncClient(api_key="YOUR_API_KEY")
47
+ report = await client.generate_report(patent_id="US12093418B2")
48
+ ```
49
+
50
+ ## PDF upload instead of patent_id
51
+
52
+ ```python
53
+ report = client.generate_report(pdf_path="/path/to/patent.pdf")
54
+ ```
55
+
56
+ ## Errors
57
+
58
+ All errors subclass `paive_agents.PaiveError` and carry `.status_code` and `.response_body`:
59
+
60
+ - `AuthenticationError` — invalid/missing API key (401)
61
+ - `PermissionDeniedError` — user lacks permission (403)
62
+ - `InvalidRequestError` — bad request (400/404)
63
+ - `RateLimitError` — usage limit exceeded (429)
64
+ - `ServerError` — server-side failure (500+)
65
+ - `APIConnectionError` — network/connection failure
66
+
67
+ ## What this SDK does NOT change
68
+
69
+ This package only talks to the existing `/api/keys/generate_report` endpoint over HTTP,
70
+ using the same field names and the same `X-API-Key` auth your Django backend already expects.
71
+ No backend files were modified to build this SDK.
@@ -0,0 +1,18 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "paive-agents"
7
+ version = "0.1.0"
8
+ description = "Official Python SDK for the Paive patent intelligence report API"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "Proprietary" }
12
+ dependencies = [
13
+ "requests>=2.28",
14
+ "httpx>=0.24",
15
+ ]
16
+
17
+ [tool.setuptools.packages.find]
18
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,28 @@
1
+ from .client import Client, DEFAULT_BASE_URL
2
+ from .async_client import AsyncClient
3
+ from .models import Report
4
+ from .exceptions import (
5
+ PaiveError,
6
+ AuthenticationError,
7
+ PermissionDeniedError,
8
+ InvalidRequestError,
9
+ RateLimitError,
10
+ ServerError,
11
+ APIConnectionError,
12
+ )
13
+
14
+ __version__ = "0.1.0"
15
+
16
+ __all__ = [
17
+ "Client",
18
+ "AsyncClient",
19
+ "Report",
20
+ "DEFAULT_BASE_URL",
21
+ "PaiveError",
22
+ "AuthenticationError",
23
+ "PermissionDeniedError",
24
+ "InvalidRequestError",
25
+ "RateLimitError",
26
+ "ServerError",
27
+ "APIConnectionError",
28
+ ]
@@ -0,0 +1,61 @@
1
+ LIST_FIELDS = (
2
+ "revenue_types",
3
+ "funding_sources",
4
+ "suspicion_triggers",
5
+ "clp_factors",
6
+ "market_factors",
7
+ "licensing_factors",
8
+ )
9
+
10
+ SCALAR_FIELDS = (
11
+ "patent_id",
12
+ "name",
13
+ "email",
14
+ "company",
15
+ "patent_numbers",
16
+ "patent_type",
17
+ "role",
18
+ "trl_level",
19
+ "prototype_exists",
20
+ "commercialization_focus",
21
+ "revenue_status",
22
+ "traction_type",
23
+ "customer_discovery",
24
+ "pilots_trials",
25
+ "industry_interest",
26
+ "rpp_stage",
27
+ "rpp_deal",
28
+ "capital_raised",
29
+ "competing_technologies",
30
+ "primary_advantage",
31
+ "infringement_suspected",
32
+ "primary_objective",
33
+ "timeline_sensitivity",
34
+ "report_type",
35
+ "tech_sector",
36
+ "website",
37
+ "invention_disclosure",
38
+ )
39
+
40
+
41
+ def build_form_fields(input_type, api_key, **kwargs):
42
+ fields = []
43
+ fields.append(("input_type", input_type))
44
+ fields.append(("api_key", api_key))
45
+
46
+ for name in SCALAR_FIELDS:
47
+ value = kwargs.get(name)
48
+ if value is None:
49
+ continue
50
+ fields.append((name, str(value)))
51
+
52
+ for name in LIST_FIELDS:
53
+ values = kwargs.get(name)
54
+ if not values:
55
+ continue
56
+ if isinstance(values, (str, bytes)):
57
+ values = [values]
58
+ for item in values:
59
+ fields.append((name, str(item)))
60
+
61
+ return fields
@@ -0,0 +1,75 @@
1
+ import httpx
2
+
3
+ from ._payload import build_form_fields
4
+ from .exceptions import raise_for_status, APIConnectionError
5
+ from .models import Report
6
+ from .client import DEFAULT_BASE_URL, GENERATE_REPORT_PATH
7
+
8
+
9
+ class AsyncClient:
10
+ def __init__(self, api_key, base_url=None, timeout=60):
11
+ if not api_key:
12
+ raise ValueError("api_key is required")
13
+ self.api_key = api_key
14
+ self.base_url = (base_url or DEFAULT_BASE_URL).rstrip("/")
15
+ self.timeout = timeout
16
+
17
+ async def generate_report(
18
+ self,
19
+ patent_id=None,
20
+ pdf_path=None,
21
+ report_type="brief_IP_decision_support_intelligence",
22
+ tech_sector=None,
23
+ clp_factors=None,
24
+ market_factors=None,
25
+ licensing_factors=None,
26
+ revenue_types=None,
27
+ funding_sources=None,
28
+ suspicion_triggers=None,
29
+ **kwargs,
30
+ ):
31
+ if bool(patent_id) == bool(pdf_path):
32
+ raise ValueError("Provide exactly one of patent_id or pdf_path")
33
+
34
+ input_type = "patent_id" if patent_id else "pdf"
35
+
36
+ fields = build_form_fields(
37
+ input_type=input_type,
38
+ api_key=self.api_key,
39
+ patent_id=patent_id,
40
+ report_type=report_type,
41
+ tech_sector=tech_sector,
42
+ clp_factors=clp_factors,
43
+ market_factors=market_factors,
44
+ licensing_factors=licensing_factors,
45
+ revenue_types=revenue_types,
46
+ funding_sources=funding_sources,
47
+ suspicion_triggers=suspicion_triggers,
48
+ **kwargs,
49
+ )
50
+
51
+ url = self.base_url + GENERATE_REPORT_PATH
52
+ headers = {"X-API-Key": self.api_key}
53
+
54
+ files = None
55
+ file_bytes = None
56
+ if pdf_path:
57
+ with open(pdf_path, "rb") as f:
58
+ file_bytes = f.read()
59
+ files = {"pdf_file": (pdf_path.split("/")[-1], file_bytes, "application/pdf")}
60
+
61
+ async with httpx.AsyncClient(timeout=self.timeout) as client:
62
+ try:
63
+ response = await client.post(url, headers=headers, data=fields, files=files)
64
+ except httpx.HTTPError as exc:
65
+ raise APIConnectionError(f"Failed to reach {url}: {exc}") from exc
66
+
67
+ try:
68
+ body = response.json()
69
+ except ValueError:
70
+ body = {"error": response.text}
71
+
72
+ if response.status_code >= 400:
73
+ raise_for_status(response.status_code, body)
74
+
75
+ return Report.from_response(body)
@@ -0,0 +1,85 @@
1
+ import requests
2
+
3
+ from ._payload import build_form_fields
4
+ from .exceptions import raise_for_status, APIConnectionError
5
+ from .models import Report
6
+
7
+ DEFAULT_BASE_URL = "http://34.29.194.252:8000"
8
+ GENERATE_REPORT_PATH = "/api/keys/generate_report"
9
+
10
+
11
+ class Client:
12
+ def __init__(self, api_key, base_url=None, timeout=60):
13
+ if not api_key:
14
+ raise ValueError("api_key is required")
15
+ self.api_key = api_key
16
+ self.base_url = (base_url or DEFAULT_BASE_URL).rstrip("/")
17
+ self.timeout = timeout
18
+
19
+ def generate_report(
20
+ self,
21
+ patent_id=None,
22
+ pdf_path=None,
23
+ report_type="brief_IP_decision_support_intelligence",
24
+ tech_sector=None,
25
+ clp_factors=None,
26
+ market_factors=None,
27
+ licensing_factors=None,
28
+ revenue_types=None,
29
+ funding_sources=None,
30
+ suspicion_triggers=None,
31
+ **kwargs,
32
+ ):
33
+ if bool(patent_id) == bool(pdf_path):
34
+ raise ValueError("Provide exactly one of patent_id or pdf_path")
35
+
36
+ input_type = "patent_id" if patent_id else "pdf"
37
+
38
+ fields = build_form_fields(
39
+ input_type=input_type,
40
+ api_key=self.api_key,
41
+ patent_id=patent_id,
42
+ report_type=report_type,
43
+ tech_sector=tech_sector,
44
+ clp_factors=clp_factors,
45
+ market_factors=market_factors,
46
+ licensing_factors=licensing_factors,
47
+ revenue_types=revenue_types,
48
+ funding_sources=funding_sources,
49
+ suspicion_triggers=suspicion_triggers,
50
+ **kwargs,
51
+ )
52
+
53
+ url = self.base_url + GENERATE_REPORT_PATH
54
+ headers = {"X-API-Key": self.api_key}
55
+
56
+ files = None
57
+ opened_file = None
58
+ try:
59
+ if pdf_path:
60
+ opened_file = open(pdf_path, "rb")
61
+ files = {"pdf_file": (pdf_path.split("/")[-1], opened_file, "application/pdf")}
62
+
63
+ try:
64
+ response = requests.post(
65
+ url,
66
+ headers=headers,
67
+ data=fields,
68
+ files=files,
69
+ timeout=self.timeout,
70
+ )
71
+ except requests.RequestException as exc:
72
+ raise APIConnectionError(f"Failed to reach {url}: {exc}") from exc
73
+ finally:
74
+ if opened_file:
75
+ opened_file.close()
76
+
77
+ try:
78
+ body = response.json()
79
+ except ValueError:
80
+ body = {"error": response.text}
81
+
82
+ if not response.ok:
83
+ raise_for_status(response.status_code, body)
84
+
85
+ return Report.from_response(body)
@@ -0,0 +1,75 @@
1
+ class PaiveError(Exception):
2
+ def __init__(self, message, status_code=None, response_body=None):
3
+ super().__init__(message)
4
+ self.message = message
5
+ self.status_code = status_code
6
+ self.response_body = response_body
7
+
8
+
9
+ class AuthenticationError(PaiveError):
10
+ pass
11
+
12
+
13
+ class PermissionDeniedError(PaiveError):
14
+ pass
15
+
16
+
17
+ class InvalidRequestError(PaiveError):
18
+ pass
19
+
20
+
21
+ class RateLimitError(PaiveError):
22
+ pass
23
+
24
+
25
+ class ServerError(PaiveError):
26
+ pass
27
+
28
+
29
+ class APIConnectionError(PaiveError):
30
+ pass
31
+
32
+
33
+ def raise_for_status(status_code, response_body):
34
+ if status_code == 401:
35
+ raise AuthenticationError(
36
+ _extract_message(response_body, "Invalid or missing API key."),
37
+ status_code,
38
+ response_body,
39
+ )
40
+ if status_code == 403:
41
+ raise PermissionDeniedError(
42
+ _extract_message(response_body, "You do not have permission to perform this action."),
43
+ status_code,
44
+ response_body,
45
+ )
46
+ if status_code == 400:
47
+ raise InvalidRequestError(
48
+ _extract_message(response_body, "Invalid request."),
49
+ status_code,
50
+ response_body,
51
+ )
52
+ if status_code == 404:
53
+ raise InvalidRequestError(
54
+ _extract_message(response_body, "Resource not found."),
55
+ status_code,
56
+ response_body,
57
+ )
58
+ if status_code == 429:
59
+ raise RateLimitError(
60
+ _extract_message(response_body, "Usage limit exceeded."),
61
+ status_code,
62
+ response_body,
63
+ )
64
+ if status_code >= 500:
65
+ raise ServerError(
66
+ _extract_message(response_body, "Server error, please try again later."),
67
+ status_code,
68
+ response_body,
69
+ )
70
+
71
+
72
+ def _extract_message(response_body, default):
73
+ if isinstance(response_body, dict):
74
+ return response_body.get("error") or response_body.get("message") or default
75
+ return default
@@ -0,0 +1,17 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Optional, Dict, Any
3
+
4
+
5
+ @dataclass
6
+ class Report:
7
+ pdf_file: Optional[str] = None
8
+ escalation_report: Optional[str] = None
9
+ raw: Dict[str, Any] = field(default_factory=dict)
10
+
11
+ @classmethod
12
+ def from_response(cls, data):
13
+ return cls(
14
+ pdf_file=data.get("pdf_file"),
15
+ escalation_report=data.get("escalation_report"),
16
+ raw=data,
17
+ )
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: paive-agents
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for the Paive patent intelligence report API
5
+ License: Proprietary
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: requests>=2.28
9
+ Requires-Dist: httpx>=0.24
10
+
11
+ # paive-agents
12
+
13
+ Official Python SDK for the Paive patent intelligence report API.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install paive-agents
19
+ ```
20
+
21
+ ## Before publishing publicly
22
+
23
+ `src/paive_agents/client.py` currently defaults to a staging server:
24
+
25
+ ```python
26
+ DEFAULT_BASE_URL = "http://34.29.194.252:8000"
27
+ ```
28
+
29
+ This is a working staging link (plain HTTP, IP-based). Before publishing this package
30
+ anywhere public (PyPI, external customers), swap this for your real production domain
31
+ over HTTPS. Until then, this default is fine for internal testing.
32
+
33
+ ## Sync usage
34
+
35
+ ```python
36
+ from paive_agents import Client
37
+
38
+ client = Client(api_key="YOUR_API_KEY")
39
+
40
+ report = client.generate_report(
41
+ patent_id="US12093418B2",
42
+ tech_sector="Biotech / Therapeutics",
43
+ clp_factors=["Application Effect", "Benchmarking Data"],
44
+ market_factors=["Application Effect"],
45
+ licensing_factors=["Application Effect"],
46
+ )
47
+
48
+ print(report.pdf_file)
49
+ ```
50
+
51
+ ## Async usage
52
+
53
+ ```python
54
+ from paive_agents import AsyncClient
55
+
56
+ client = AsyncClient(api_key="YOUR_API_KEY")
57
+ report = await client.generate_report(patent_id="US12093418B2")
58
+ ```
59
+
60
+ ## PDF upload instead of patent_id
61
+
62
+ ```python
63
+ report = client.generate_report(pdf_path="/path/to/patent.pdf")
64
+ ```
65
+
66
+ ## Errors
67
+
68
+ All errors subclass `paive_agents.PaiveError` and carry `.status_code` and `.response_body`:
69
+
70
+ - `AuthenticationError` — invalid/missing API key (401)
71
+ - `PermissionDeniedError` — user lacks permission (403)
72
+ - `InvalidRequestError` — bad request (400/404)
73
+ - `RateLimitError` — usage limit exceeded (429)
74
+ - `ServerError` — server-side failure (500+)
75
+ - `APIConnectionError` — network/connection failure
76
+
77
+ ## What this SDK does NOT change
78
+
79
+ This package only talks to the existing `/api/keys/generate_report` endpoint over HTTP,
80
+ using the same field names and the same `X-API-Key` auth your Django backend already expects.
81
+ No backend files were modified to build this SDK.
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/paive_agents/__init__.py
4
+ src/paive_agents/_payload.py
5
+ src/paive_agents/async_client.py
6
+ src/paive_agents/client.py
7
+ src/paive_agents/exceptions.py
8
+ src/paive_agents/models.py
9
+ src/paive_agents.egg-info/PKG-INFO
10
+ src/paive_agents.egg-info/SOURCES.txt
11
+ src/paive_agents.egg-info/dependency_links.txt
12
+ src/paive_agents.egg-info/requires.txt
13
+ src/paive_agents.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ requests>=2.28
2
+ httpx>=0.24
@@ -0,0 +1 @@
1
+ paive_agents